I wanted to get pyBusPirateLite working for Windows for another project I'm working on. I found that Windows doesn't seem to support the select() call on serial ports, but I was able to patch it, and it seems to work now:
Here's it is:
http://code.google.com/p/the-bus-pirate ... tail?r=595 (http://code.google.com/p/the-bus-pirate/source/detail?r=595)
Would anyone be willing to test it on Linux to confirm it isn't busted? Many thanks, I don't have a Linux box set up to use the BP at the moment...
The main select() I can't get rid of is the one to determine how many zeroes to write to enter BB mode. The other ones, though, might be candidates for removal -- it looks like they are calling select() on empty lists, which, my guess was, merely serves to wait the specified amount of time. The python docs say it is "implementation dependent" ( http://docs.python.org/library/select.html (http://docs.python.org/library/select.html) ), but do not go into any further detail. Can anyone confirm what this actually does? If it *is* merely for a timeout, can we not use time.sleep(#) instead, and get rid of the platform-specific calls in those other cases?
The selects are to give the serial data some time to arrive. Without it you will occasionally get bad data or no data. At least this is my experience with Python, Perl, etc. It would be better to have some sort of callback on data arrival, but I don't think many scripting languages support that.
So, then, would:
select.select([], [], [], 0.1)
have the same behavior (namely, waiting 100ms) as this:
time.sleep(0.1)
?
Do you think it would be preferable to use select() for this timeout (against the possibility of later actually having it wait for input before proceeding), or to use the platform-independent sleep() call everywhere (until someone figures out a platform-independent way of emulating select()'s behavior)? I'd like to clean this up a bit more, the "if win32" checks have a bad smell to me.
I'm sorry, I'm just a tinkering novice when it comes to python.
No worries, I'll clean it up and commit a sleep-based one, and try to come up with some kind of testing rig to confirm it still works on Linux.
I did some experiments with the "select" call in linux, and with empty lists as arguments, it does appear to just serve as a timeout. I replaced what calls I could with calls to time.sleep() (which is cross platform). I tested the clean version on both a Windows and a (virtualbox) VM running Ubuntu 9.10. It's rev 596. I also added a library for Maxim I2C RTCs (DS1307, DS3231, DS3232), rev 597.
I also made a .zip package of the pyBusPirateLite subtree and added it to the "downloads" section on the google code repository (http://code.google.com/p/the-bus-pirate/downloads/list (http://code.google.com/p/the-bus-pirate/downloads/list)). I'm working on blog write-ups for both the windows support and the RTC library.
Nice! Thanks for the update. This library should be really great now, lots of people have put a lot of work into it. Thank you.
Hi all, I'm not sure I'm posting in a correct thread (I rather am sure this is the wrong one since the last post is a year old), but still. I recently started playing with python and took off with 3.x version (which pyBusPirateLite does not support). And I'm also creating small widgets for myself to use in projects. So I decided to create a widget for BP as well as to make pyBusPirateLite work on python 3.x. Yesterday I got first results - it was a small effort updating sources to work with python v3 using supplied 2to3 script and than just some more tuning. It still requires some job to do, but now when the concept is clear, it shouldn't be that hard. Here comes the question - what do I do with my scripts when I'm done? Anyone is interested in them?
Oh, I guess it's clear that when I say "widgets" it means GUI? I can post some screens later, but the idea is that there's a combo from where you select a desired mode, a button that initiates bitbang to enter that mode, and a status label. This widget also uses a gui widget to work with a comport, so the concept is really modular... All the work with the selected mode when BP enters it comes from a different task-specific widget (e.d. IT3200 gyro control blah-blah-blah).
[attachment=0]
Here you can see two modules outlined with color.
Here's the main window code:
def main():
root = Tk()
mainWindow = Frame()
mainWindow.pack(fill=BOTH, expand=1)
comPort = comPortWidget(mainWindow)
comPort.pack(fill=BOTH, expand=1)
busPirate = busPirateWidget(mainWindow, comPort)
busPirate.pack(fill=BOTH, expand=1)
root.mainloop()
Yesterday I used the above code to create a BusPirate Voltage Logger. The script get ADC measurement every pre-set interval and puts it to a log file along with time stamp. You can use it later to built a chart in Excel for example.
I'm not sharing it right now as the coding is lausy , GUI is exceptionally lousy and the output is not handy (takes some moves to properly import to Excel). But wanted to share the idea... Does BP works with SD cards out-of-the-box btv?
I mean it would be cool to create a BP shield with SD card and 1 (or more) analogue input to have BP store the log on eg xml format on SD card. I'm not up to this as this will take me a year (experience speaking here)
Hi dchcaracter,
There's no SD card attachment that I know of. In theory it could be done though, but it wouldn't be too terribly fast.
Hi Ian,
I came back here when I saw this post: http://dangerousprototypes.com/2012/06/ ... -terminal/ (http://dangerousprototypes.com/2012/06/13/how-to-bus-pirate-as-dev-board-read-a-voltage-and-view-in-terminal/) . I believe it's doable to integrate SD support if we are talking about firmware. I btw implemented this since my last post on STM32VL-Discovery. Cheers!
Hello,
I'm a newbi in Python and buspirate. I've tes pybuspirate butit seems incompatible.
I've python 3 so I've test pybuspirate branch python3 but I look inside for exemple: print"ok". I don't understand, normally It's print("ok") in python 3
How are you doing to program in python 3 ?
Thank you very Much
Sandrine (Sorry for my english I'm french)
It's written for Python 2
Thanks
Do you think I'ts possible to transpose for python 3 because I'm learning v3 and I think It's future. Perhaprs i Think a mistake
Ave a good day
Sandrine
I didn't write that library but it should be possible. I'll add it to my to-do list but not sure when it gets done.
Hello,
I try to begin modification. (py2to3 and manual). I'm advancing but I've got a problem for example: with I2C-> BitBang-py->serial.
BBmode() (or similar in BitBang) is on error. Because self.port.write("x01") is unsupported with Python 3. I must read documentation from pyserial (and BP command) so after Ithink I can replace by something like self.port.write("01".encode()) or str("01).encode.
I write you if it's OK. if I don't result. i will lear python 2.7
Bonne soirée (Good evening)
Sandrine
Is someon can test ?
Modification for python3.3; BP on com3
Win7 64bits
ex of modification: self.port.write(str("x00").encode()) etc...
---------------------------------------------------------------------------------------------------------------------
i2ctestforpyt3.py
#!/usr/bin/env python
# encoding: utf-8
"""
Created by Peter Huewe on 2009-10-26.
Copyright 2009 Peter Huewe <peterhuewe@gmx.de>
Based on the spi testscript from Sean Nelson
This file is part of pyBusPirate.
pyBusPirate is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
pyBusPirate is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with pyBusPirate. If not, see <http://www.gnu.org/licenses/>.
"""
import sys
from pyBusPirateLite.I2C import *
""" enter binary mode """
def i2c_write_data(data):
i2c.send_start_bit()
i2c.bulk_trans(len(data),data)
i2c.send_stop_bit()
def i2c_read_bytes(address, numbytes, ret=False):
data_out=[]
i2c.send_start_bit()
i2c.bulk_trans(len(address),address)
while numbytes > 0:
if not ret:
print(ord(i2c.read_byte()))
else:
data_out.append(ord(i2c.read_byte()))
if numbytes > 1:
i2c.send_ack()
numbytes-=1
i2c.send_nack()
i2c.send_stop_bit()
if ret:
return data_out
if __name__ == '__main__':
i2c = I2C("com3", 115200)
print("Entering binmode: ", end=' ')
if i2c.BBmode() :
print("OK.") #truque return1/return0 dans BitBang
else:
print("failed.")
sys.exit()
print("Entering raw I2C mode: ", end=' ')
if i2c.enter_I2C:
print("OK.")
else:
print("failed.")
sys.exit()
print("Configuring I2C.")
if not i2c.cfg_pins(I2CPins.POWER | I2CPins.PULLUPS):
print("Failed to set I2C peripherals.")
sys.exit()
if not i2c.set_speed(I2CSpeed._50KHZ):
print("Failed to set I2C Speed.")
sys.exit()
i2c.timeout(0.2)
print("Reading EEPROM.")
i2c_write_data([0xa0, 0,0, 1, 2,3,4,5,6,7,8,9])
i2c_write_data([0xa0, 0,0])
print(i2c_read_bytes([0xa1],5))
print("Reset Bus Pirate to user terminal: ")
if i2c.resetBP():
print("OK.")
else:
print("failed.")
sys.exit()
------------------------------------------------------------------------------------------------------------------------------------
I2C.py (to replace in pyBusPirateLite)
#!/usr/bin/env python
# encoding: utf-8
"""
Created by Sean Nelson on 2009-10-14.
Copyright 2009 Sean Nelson <audiohacked@gmail.com>
This file is part of pyBusPirate.
pyBusPirate is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
pyBusPirate is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with pyBusPirate. If not, see <http://www.gnu.org/licenses/>.
"""
from .BitBang import BBIO
class I2CSpeed:
_400KHZ = 0x03
_100KHZ = 0x02
_50KHZ = 0x01
_5KHZ = 0x00
class I2CPins:
POWER = 0x8
PULLUPS = 0x4
AUX = 0x2
CS = 0x1
class I2C(BBIO):
bulk_read = None
def __init__(self, port, speed, timeout=1):
BBIO.__init__(self, port, speed, timeout)
def send_start_bit(self):
self.port.write("x02")
#self.timeout(0.1)
return self.response()
def send_stop_bit(self):
self.port.write("x03")
#self.timeout(0.1)
return self.response()
def read_byte(self):
self.port.write("x04")
#self.timeout(0.1)
return self.response(1, True)
def send_ack(self):
self.port.write("x06")
#self.timeout(0.1)
return self.response()
def send_nack(self):
self.port.write("x07")
#self.timeout(0.1)
return self.response()
-----------------------------------------------------------------------------------------------------------------------------------
BitBang.py (to replace in pyBusPirateLite)
#!/usr/bin/env python
# encoding: utf-8
"""
Created by Sean Nelson on 2009-10-14.
Copyright 2009 Sean Nelson <audiohacked@gmail.com>
This file is part of pyBusPirate.
pyBusPirate is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
pyBusPirate is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with pyBusPirate. If not, see <http://www.gnu.org/licenses/>.
"""
import select
import serial
import sys
import time
"""
PICSPEED = 24MHZ / 16MIPS
"""
class PinCfg:
POWER = 0x8
PULLUPS = 0x4
AUX = 0x2
CS = 0x1
class BBIOPins:
# Bits are assigned as such:
MOSI = 0x01;
CLK = 0x02;
MISO = 0x04;
CS = 0x08;
AUX = 0x10;
PULLUP = 0x20;
POWER = 0x40;
class BBIO:
def __init__(self, p="COM3", s=115200, t=1):
self.port = serial.Serial(p, s, timeout=t)
def BBmode(self):
if sys.platform == 'win32':
# I haven't seen this problem on Windows, which is good,
# because it doesn't appear to support select.select()
# for serial ports. This seems to work instead:
self.resetBP()
self.port.write(str("x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00").encode())
self.timeout(0.1)
self.port.flushInput();
self.reset()
else:
# Sometimes sending 20 zeroes in a row to a BP already in binary mode
# leads to BP getting stuck in BitBang mode
# (see forum: http://dangerousprototypes.com/forum/viewtopic.php?t=1440#msg13179 )
# so if we detect a response (indicating we're in BitBang mode before the 20 zeroes)
# stop sending zeroes and go on.
self.port.flushInput();
for i in range(20):
self.port.write(str("x00").encode());
r,w,e = select.select([self.port], [], [], 0.01);
#if (r): break;
if self.response(5) == "BBIO1": return 1
else: return 1 #normalement return 0=normally return 0 but not ok on w7 64bits
def reset(self):
self.port.write(str('x01').encode())
self.timeout(0.1)
def enter_SPI(self):
self.response(5)
self.port.write(str("x01").encode())
self.timeout(0.1)
if self.response(4) == "SPI1": return 1
else: return 0
def enter_I2C(self):
self.port.write(str("x02").encode())
self.timeout(0.1)
if self.response(4) == "I2C1": return 1
else: return 0
def enter_UART(self):
self.port.write(str("x03").encode())
self.timeout(0.1)
if self.response(4) == "ART1": return 1
else: return 0
def enter_1wire(self):
self.port.write(str("x04").encode())
self.timeout(0.1)
if self.response(4) == "1W01": return 1
else: return 0
def enter_rawwire(self):
self.port.write(str("x05").encode())
self.timeout(0.1)
if self.response(4) == "RAW1": return 1
else: return 0
def resetBP(self):
self.reset()
self.port.write(str("x0F").encode())
self.timeout(0.1)
#self.port.read(2000)
self.port.flushInput()
return 1
def raw_cfg_pins(self, config):
self.port.write(str(chr(0x40 | config)).encode())
self.timeout(0.1)
return self.response(1)
def raw_set_pins(self, pins):
self.port.write(str(chr(0x80 | config)).encode())
self.timeout(0.1)
return self.response(1)
def timeout(self, timeout=0.1):
time.sleep(timeout);
def response(self, byte_count=1, return_data=False):
data = self.port.read(byte_count)
if byte_count == 1 and return_data == False:
if data == chr(0x01): return 1 #to modify or not ?(str(chr0x01).encode()). For me not to modify
else: return 0
else:
return data
""" Self-Test """
def short_selftest(self):
self.port.write(str("x10").encode())
self.timeout(0.1)
return self.response(1, True)
def long_selftest(self):
self.port.write(str("x11").encode())
self.timeout(0.1)
return self.response(1, True)
""" PWM """
def setup_PWM(self, prescaler, dutycycle, period):
self.port.write(str("x12").encode())
self.port.write(str(chr(prescaler)).encode())
self.port.write(str(chr((dutycycle>>8)&0xFF)).encode())
self.port.write(str(chr(dutycycle&0xFF)).encode())
self.port.write(str(chr((period>>8)&0xFF)).encode())
self.port.write(str(chr(period&0xFF)).encode())
self.timeout(0.1)
return self.response()
def clear_PWM(self):
self.port.write(str("x13").encode())
self.timeout(0.1)
return self.response()
""" ADC """
def ADC_measure(self):
self.port.write(str("x14").encode())
self.timeout(0.1)
return self.response(2, True)
""" General Commands for Higher-Level Modes """
def mode_string(self):
self.port.write(str("x01").encode())
self.timeout(0.1)
return self.response()
def bulk_trans(self, byte_count=1, byte_string=None):
if byte_string == None: pass
self.port.write(str(chr(0x10 | (byte_count-1))).encode())
#self.timeout(0.1)
for i in range(byte_count):
self.port.write(str(chr(byte_string[i])).encode())
#self.timeout(0.1)
data = self.response(byte_count+1, True)
return data[1:]
def cfg_pins(self, pins=0):
self.port.write(str(chr(0x40 | pins)).encode())
self.timeout(0.1)
return self.response()
def read_pins(self):
self.port.write(str("x50").encode())
self.timeout(0.1)
return self.response(1, True)
def set_speed(self, spi_speed=0):
self.port.write(str(chr(0x60 | spi_speed)).encode())
self.timeout(0.1)
return self.response()
def read_speed(self):
self.port.write(str("x70").encode())
self.timeout(0.1);
return self.response(1, True)
--------------------------------------------------------------------------------------------
Thanks
Hey sandrine,
It's better if you do the changes and test them out. I know very little about Python3, checked it out a little when I was beginning.
ok
I test
see you later