class ArduinoHelper(object): portName = 'COM4' def __init__(self): self.arduino = Arduino(self.portName) it = util.Iterator(self.arduino) it.start() self.start_time = time.time() self.input_pin = self.arduino.get_pin( 'a:0:i') #analog, input to the computer self.output_pin = self.arduino.get_pin( 'd:6:p') #digital, PWM mode, from the computer self.switch_pin = self.arduino.get_pin( 'd:9:i') #digital, input to the computer (switch-state) # make sure the PWM pin (6) is off, wait a number of seconds # (gives enough time so everything is ready to be read - otherwise it may read "None") time.sleep(2) self.update_duty_cycle(0) def read_input_pin(self): return self.read_voltage(self.input_pin) def read_voltage(self, pin): """ Returns the voltage of the pin passed in (between 0 and 5 Volts) It takes a number of measurements, then averages them to reduce noise """ outputs = [] for i in range(10): time.sleep(.1) outputs.append(pin.read()) return 5.0 * np.average(outputs) def read_voltage_fast(self, pin): """ Returns the voltage of the pin passed in (between 0 and 5 Volts) It takes a single of measurement """ return 5.0 * pin.read() def write_to_lcd(self, *args): message = '' for arg in args: message += str(arg) print(message) self.arduino.send_sysex(STRING_DATA, util.str_to_two_byte_iter(str(message))) def is_switch_on(self): switch_voltage = self.read_voltage_fast(self.switch_pin) return switch_voltage > 1 def update_duty_cycle(self, DC): self.output_pin.write(DC)
class ArduinoInterface: def __init__(self, config): self.config = config self.button_status_handler = None @staticmethod def _autodiscover_device(): device_list = ['/dev/ttyACM{}'.format(i) for i in range(10)] devices = [dev for dev in device_list if os.path.exists(dev)] return devices[0] def connect(self): device = None try: device = self.config['device'] except KeyError: device = self.__class__._autodiscover_device() self.board = Arduino(device, baudrate=57600, timeout=100) Iterator(self.board).start() self.board.add_cmd_handler(STRING_DATA, self._button_status_handler) def send_alert_update(self, alert=True): self.board.send_sysex(0x01, bytes([alert])) def request_button_status(self): self.board.send_sysex(0x02, bytes([])) def _button_status_handler(self, *string): status = None try: status = int(chr(string[0])) except ValueError: print('Empty button status received: {}'.format(string)) else: self.button_status_handler(status) def attach_button_status_handler(self, func): self.button_status_handler = func
class Board: def __init__(self, port, hello_msg="hello, world!"): try: self.board = Arduino(port) self.print(hello_msg) except SerialException: print("Error: couldn't open port " + port) def print(self, text, gui=False): try: if text: if gui: gui.set_data_str(text) self.board.send_sysex(STRING_DATA, util.str_to_two_byte_iter(text)) except TypeError: self.board.send_sysex(STRING_DATA, util.str_to_two_byte_iter('Error')) def print_2d_data(self, data, gui): for row in data: time.sleep(TIME_LAG) self.print("".join(row), gui)
from pyfirmata import Arduino, util import time board = Arduino('/dev/ttyUSB0') it = util.Iterator(board) it.start() print('✔ board ready!') def handle_read_write(*data): print(data[0]) board.send_sysex(0x01, [12, data[0]]) board.add_cmd_handler(0x03, handle_read_write) while True: board.send_sysex(0x03, [18]) time.sleep(0.01)
class Arduino_Interface(object): ## ## ## CONSTANTS ## ## ## ## ## PING = 0x01 TEST_DATA = 0x02 ## ## ## Initalization ## ## ## ## ## def __init__(self, port, log_handler): ## Initalize logging logging.basicConfig(level=logging.DEBUG) self.logger = logging.getLogger('Arduino_Interface') self.logger.addHandler(log_handler) # Add Tk log handler self.logger.debug('__init__') ## Board Initalization self.board = Arduino(port) self.board.add_cmd_handler(pyfirmata.START_SYSEX, self.handleIncomingSysEx) self.board.add_cmd_handler(pyfirmata.STRING_DATA, self.handleIncomingString) ## Data Buffer Initalization self.incoming_data = [] ## Callback holder self.callback_holder = dict() ## ## ## Runtime Functions ## ## ## ## ## def begin_scanning(self): self.board.iterate() ## ## ## Senders ## ## ## ## ## def ping(self, pingCallback): self.logger.debug('----Sending Ping----') ## Attach callback self.callback_holder[Arduino_Interface.PING] = pingCallback byte_array = bytearray() byte_array.append(Arduino_Interface.PING) self.sendSysEx(byte_array) def requestTestData(self, testDataCallback): self.logger.debug('----Requesting Test Data----') ## Attach callback self.callback_holder[Arduino_Interface.TEST_DATA] = testDataCallback byte_array = bytearray() byte_array.append(Arduino_Interface.TEST_DATA) self.sendSysEx(byte_array) def sendSysEx(self, byteArray): self.logger.debug('----sendSysEx----') self.logger.debug('SEND Data: {}'.format(binascii.hexlify(byteArray))) self.board.send_sysex(pyfirmata.START_SYSEX, byteArray) self.begin_scanning() def sendString(self, stringToSend): pass #self.board.send_sysex # for byte in dataArray: # self.incoming_data.append(chr(byte)) # print self.incoming_data ## ## ## Handlers ## ## ## ## ## def handleIncomingString(self, *string): self.logger.debug('handling Incoming String') ## Flush incoming_data self.incoming_data = [] for byte in string: self.incoming_data.append(chr(byte)) recieved_string = ''.join(self.incoming_data) print recieved_string def handleIncomingSysEx(self, *byteArray): self.logger.debug('----Incoming SysEx----') ## Flush incoming_data array self.incoming_data = [] self.incoming_data = self.filterSysEx(byteArray) ## Get header header = byteArray[0] self.logger.debug('header: {}'.format(header)) if (header == Arduino_Interface.PING): self.logger.debug('PING Response recieved') ## Ping response recieved. Return True self.callback_holder[Arduino_Interface.PING](True) elif (header == Arduino_Interface.TEST_DATA): self.logger.debug('Test Data recieved') self.callback_holder[Arduino_Interface.TEST_DATA](self.incoming_data) ## ## ## Utilities ## ## ## ## ## def filterSysEx(self, byteArray): self.logger.debug('filterSysEx') incoming_data = [] for idx, byte in enumerate(byteArray): if idx == 0: continue incoming_data.append(byte) self.logger.debug('SysEx Data:') self.logger.debug(incoming_data) return incoming_data
from pyfirmata import Arduino, util, STRING_DATA board = Arduino('COM6') board.send_sysex(STRING_DATA, util.str_to_two_byte_iter('Hello!')) def msg(text): if text: board.send_sysex(STRING_DATA, util.str_to_two_byte_iter(text))
from pyfirmata import Arduino, util import msvcrt speed = 5 initial_angle = 90 board = Arduino('COM11') print("press left or right arros to move the servo:") print("press e to terminate the program:") data = initial_angle while True: c = ord(msvcrt.getch()) if c != 224: if c == 101: print("program terminated.") break print() if c == 75: data -= speed if data < 0: data = 0 if c == 77: data += speed if data > 180: data = 180 board.send_sysex(0x71, util.str_to_two_byte_iter(f"{data}\0"))
print(data) board.add_cmd_handler(0x02, handle_write) def writePwmValue(pin, value): datasToWrite = [] datasToWrite.append(pin) datasToWrite.append(0) datasToWrite.append(15) datasToWrite.append(10) v = divmod(value, 127) for i in range(1, v[0]): datasToWrite.append(127) if (v[0] >= 1): datasToWrite.append(v[1]) else: datasToWrite.append(value) return datasToWrite while True: board.send_sysex(0x04, writePwmValue(19, 1023)) time.sleep(0.01)
class Collector(): """ Handles the communication to arduino SensorReader The arduino firmware publishes messages using firmata once per second with sensor readings. This class is responsible for collection and persistance of readings. AttachTo: "" """ NAME = "Collector" def __init__(self, port): ''' Constructor. Adds the callback handler to accept firmata messages from the arduino board connected to the sensors. ''' self.last_rain_reading_saved = None self.last_sky_temperature_reading_saved = 0 self.last_ambient_temperature_reading_saved = 0 self.last_reading_saved_time = time.time() self.board = Arduino(port) # start an iterator thread so that serial buffer doesn't overflow it = util.Iterator(self.board) it.start() self.board.add_cmd_handler(pyfirmata.pyfirmata.STRING_DATA, self._messageHandler) def _messageHandler(self, *args, **kwargs): ''' Calback method envoked by the firmata library. Handles the string message sent from the arduino. Grabs the sensor data from the message and persists in the DB table. :param args: :param kwargs: :return: ''' readings = json.loads(util.two_byte_iter_to_str(args)) sky_temperature = readings['sky'] ambient_temperature = readings['ambient'] rain = readings['rain'] if self.should_persist_sensor_reading(sky_temperature, ambient_temperature, rain): conn = sqlite3.connect('weather_sensor.db') c = conn.cursor() print('inserting observation') c.execute( "INSERT INTO weather_sensor (rain,sky_temperature,ambient_temperature) VALUES (?,?,?)", (rain, sky_temperature, ambient_temperature)) c.execute( "DELETE FROM weather_sensor WHERE date_sensor_read <= date('now','-365 day')" ) print('inserted') # new_id = c.lastrowid conn.commit() self.last_rain_reading_saved = rain self.last_sky_temperature_reading_saved = sky_temperature self.last_ambient_temperature_reading_saved = ambient_temperature self.last_reading_saved_time = time.time() c.close() def update(self): super(Collector, self).update() def writeData(self, data): self.board.send_sysex(pyfirmata.pyfirmata.STRING_DATA, data) def dispose(self): super(Collector, self).dispose() try: self.board.exit() except AttributeError: print('exit() raised an AttributeError unexpectedly!') def should_persist_sensor_reading(self, sky_temperature, ambient_temperature, rain): ''' Returns true if the sensor data should be persisted in the DB. The rules are if any temp change is more than 1 degree, or the rain state changes or 60sec have elapsed since the last save :param sky_temperature: :param ambient_temperature: :param rain: :return: ''' if abs(sky_temperature - self.last_sky_temperature_reading_saved) > 1 or abs( ambient_temperature - self.last_ambient_temperature_reading_saved ) > 1 or rain != self.last_rain_reading_saved or time.time( ) - self.last_reading_saved_time > 60: return True else: return False
from pyfirmata import Arduino, util import time board = Arduino('/dev/ttyUSB0') it = util.Iterator(board) it.start() print('✔ board ready!') def handle_read(*data): print(data) board.add_cmd_handler(0x02, handle_read) while True: board.send_sysex(0x02, [32]) time.sleep(0.01)
from pyfirmata import Arduino, util board = Arduino('/dev/ttyUSB0') it = util.Iterator(board) it.start() print('✔ board ready!') while True: board.send_sysex(0x01, [12, 1])
class Arduino_Interface(object): ## ## ## CONSTANTS ## ## ## ## ## PING = 0x01 TEST_DATA = 0x02 ## ## ## Initalization ## ## ## ## ## def __init__(self, port, log_handler): ## Initalize logging logging.basicConfig(level=logging.DEBUG) self.logger = logging.getLogger('Arduino_Interface') self.logger.addHandler(log_handler) # Add Tk log handler self.logger.debug('__init__') ## Board Initalization self.board = Arduino(port) self.board.add_cmd_handler(pyfirmata.START_SYSEX, self.handleIncomingSysEx) self.board.add_cmd_handler(pyfirmata.STRING_DATA, self.handleIncomingString) ## Data Buffer Initalization self.incoming_data = [] ## Callback holder self.callback_holder = dict() ## ## ## Runtime Functions ## ## ## ## ## def begin_scanning(self): self.board.iterate() ## ## ## Senders ## ## ## ## ## def ping(self, pingCallback): self.logger.debug('----Sending Ping----') ## Attach callback self.callback_holder[Arduino_Interface.PING] = pingCallback byte_array = bytearray() byte_array.append(Arduino_Interface.PING) self.sendSysEx(byte_array) def requestTestData(self, testDataCallback): self.logger.debug('----Requesting Test Data----') ## Attach callback self.callback_holder[Arduino_Interface.TEST_DATA] = testDataCallback byte_array = bytearray() byte_array.append(Arduino_Interface.TEST_DATA) self.sendSysEx(byte_array) def sendSysEx(self, byteArray): self.logger.debug('----sendSysEx----') self.logger.debug('SEND Data: {}'.format(binascii.hexlify(byteArray))) self.board.send_sysex(pyfirmata.START_SYSEX, byteArray) self.begin_scanning() def sendString(self, stringToSend): pass #self.board.send_sysex # for byte in dataArray: # self.incoming_data.append(chr(byte)) # print self.incoming_data ## ## ## Handlers ## ## ## ## ## def handleIncomingString(self, *string): self.logger.debug('handling Incoming String') ## Flush incoming_data self.incoming_data = [] for byte in string: self.incoming_data.append(chr(byte)) recieved_string = ''.join(self.incoming_data) print recieved_string def handleIncomingSysEx(self, *byteArray): self.logger.debug('----Incoming SysEx----') ## Flush incoming_data array self.incoming_data = [] self.incoming_data = self.filterSysEx(byteArray) ## Get header header = byteArray[0] self.logger.debug('header: {}'.format(header)) if (header == Arduino_Interface.PING): self.logger.debug('PING Response recieved') ## Ping response recieved. Return True self.callback_holder[Arduino_Interface.PING](True) elif (header == Arduino_Interface.TEST_DATA): self.logger.debug('Test Data recieved') self.callback_holder[Arduino_Interface.TEST_DATA]( self.incoming_data) ## ## ## Utilities ## ## ## ## ## def filterSysEx(self, byteArray): self.logger.debug('filterSysEx') incoming_data = [] for idx, byte in enumerate(byteArray): if idx == 0: continue incoming_data.append(byte) self.logger.debug('SysEx Data:') self.logger.debug(incoming_data) return incoming_data