""" pyboard interface This module provides the Pyboard class, used to communicate with and control the pyboard over a serial USB connection. Example usage: import pyboard pyb = pyboard.Pyboard('/dev/ttyACM0') pyb.enter_raw_repl() pyb.exec('pyb.Led(1).on()') pyb.exit_raw_repl() To run a script from the local machine on the board and print out the results: import pyboard pyboard.execfile('test.py', device='/dev/ttyACM0') """ import time import serial class PyboardError(BaseException): pass class Pyboard: def __init__(self, serial_device): self.serial = serial.Serial(serial_device) def close(self): self.serial.close() def enter_raw_repl(self): self.serial.write(b'\r\x01') # ctrl-A: enter raw REPL self.serial.write(b'\x04') # ctrl-D: soft reset data = self.serial.read(1) while self.serial.inWaiting() > 0: data = data + self.serial.read(self.serial.inWaiting()) time.sleep(0.1) if not data.endswith(b'raw REPL; CTRL-B to exit\r\n>'): print(data) raise PyboardError('could not enter raw repl') def exit_raw_repl(self): self.serial.write(b'\r\x02') # ctrl-B: enter friendly REPL def eval(self, expression): ret = self.exec('print({})'.format(expression)) ret = ret.strip() return ret def exec(self, command): command_bytes = bytes(command, encoding='ascii') for i in range(0, len(command_bytes), 32): self.serial.write(command_bytes[i:min(i+32, len(command_bytes))]) time.sleep(0.01) self.serial.write(b'\x04') data = self.serial.read(2) if data != b'OK': raise PyboardError('could not exec command') data = self.serial.read(2) timeout = 0 while True: if self.serial.inWaiting() > 0: data = data + self.serial.read(self.serial.inWaiting()) timeout = 0 elif data.endswith(b'\x04>'): break else: timeout += 1 if timeout > 100: break time.sleep(0.1) if not data.endswith(b'\x04>'): print(data) raise PyboardError('timeout waiting for EOF reception') if data.startswith(b'Traceback') or data.startswith(b' File '): print(data) raise PyboardError('command failed') return data[:-2] def execfile(self, filename): with open(filename) as f: pyfile = f.read() return self.exec(pyfile) def get_time(self): t = str(self.exec('pyb.time()'), encoding='ascii').strip().split()[1].split(':') return int(t[0]) * 3600 + int(t[1]) * 60 + int(t[2]) def execfile(filename, device='/dev/ttyACM0'): pyb = Pyboard(device) pyb.enter_raw_repl() output = pyb.execfile(filename) print(str(output, encoding='ascii'), end='') pyb.exit_raw_repl() pyb.close() def run_test(): device = '/dev/ttyACM0' pyb = Pyboard(device) pyb.enter_raw_repl() print('opened device {}'.format(device)) print('seconds since boot:', pyb.get_time()) pyb.exec('def apply(l, f):\r\n for item in l:\r\n f(item)\r\n') pyb.exec('leds=[pyb.Led(l) for l in range(1, 5)]') pyb.exec('apply(leds, lambda l:l.off())') ## USR switch test if True: for i in range(2): print("press USR button") pyb.exec('while pyb.switch(): pyb.delay(10)') pyb.exec('while not pyb.switch(): pyb.delay(10)') print('USR switch passed') ## accel test if True: print("hold level") pyb.exec('accel = pyb.Accel()') pyb.exec('while abs(accel.x()) > 10 or abs(accel.y()) > 10: pyb.delay(10)') print("tilt left") pyb.exec('while accel.x() > -10: pyb.delay(10)') pyb.exec('leds[0].on()') print("tilt forward") pyb.exec('while accel.y() < 10: pyb.delay(10)') pyb.exec('leds[1].on()') print("tilt right") pyb.exec('while accel.x() < 10: pyb.delay(10)') pyb.exec('leds[2].on()') print("tilt backward") pyb.exec('while accel.y() > -10: pyb.delay(10)') pyb.exec('leds[3].on()') print('accel passed') print('seconds since boot:', pyb.get_time()) pyb.exec('apply(leds, lambda l:l.off())') pyb.exit_raw_repl() pyb.close() if __name__ == "__main__": run_test()