Skip to content
Snippets Groups Projects
Commit 80a90118 authored by Quentin Bolsee's avatar Quentin Bolsee
Browse files

rename module

parent fac16ac5
No related branches found
No related tags found
No related merge requests found
......@@ -26,10 +26,10 @@ The following Python code on the host computer lets you instantiate the device a
```python
# test_led.py (Python)
import mpy_bridge
import mpybridge
# instantiate the device on serial port COM1
d = mpy_bridge.Device("COM1")
d = mpybridge.Device("COM1")
# prints available functions
print(d)
......@@ -63,10 +63,10 @@ A host program can send Python objects, and receive some in return. In this case
```python
# test_pins.py (Python)
import mpy_bridge
import mpybridge
# instantiate the device on serial port COM5
d = mpy_bridge.Device("COM5")
d = mpybridge.Device("COM5")
# setup 3 pins at once
d.setup_inputs([2, 6, 15])
......@@ -95,13 +95,13 @@ Exceptions on the MicroPython side are turned into Python exceptions, which can
```python
# test_exceptions.py (Python)
import mpy_bridge
import mpybridge
d = mpy_bridge.Device("COM5")
d = mpybridge.Device("COM5")
try:
d.read_inputs()
except mpy_bridge.MicroPythonError as e:
except mpybridge.MicroPythonError as e:
print(f"Error on the device: {e}")
```
......@@ -111,10 +111,10 @@ This module includes a basic tool to update the main file on the MicroPython dev
```python
# test_upload.py (Python)
import mpy_bridge
import mpybridge
# instantiate device, skip init in case main file is missing
d = mpy_bridge.Device("COM34", init=False)
d = mpybridge.Device("COM34", init=False)
# upload main file
d.upload("embedded/main.py", "main.py")
......
import mpy_bridge
import mpybridge
import time
def main():
# open device, read functions
d = mpy_bridge.Device("COM39")
d = mpybridge.Device("COM39")
# print out functions
print(d)
......
import datetime
import mpy_bridge
import mpybridge
import numpy as np
import matplotlib.pyplot as plt
def main():
d = mpy_bridge.Device("COM39")
d = mpybridge.Device("COM39")
n_exp = 1024
results = []
......
import mpy_bridge
import mpybridge
def main():
# Open device, skip reading its functions (the main file might be absent)
d = mpy_bridge.Device("COM39", init=False)
d = mpybridge.Device("COM39", init=False)
# Upload main file
d.upload("micropython/main.py", "main.py")
......
......@@ -8,6 +8,7 @@
# warranty is provided, and users accept all liability.
import os.path
import serial
import serial.tools.list_ports
import time
import re
import ast
......@@ -17,61 +18,77 @@ class MicroPythonError(RuntimeError):
pass
class MicroPythonFileError(MicroPythonError):
pass
class Device:
init_delay = 0.1
init_delay = 0.15
timeout_delay = 2.0
def __init__(self, port, main_filename="main.py"):
self.ser_obj = serial.Serial(port)
def __init__(self, port, main_filename="main.py", show_prints=True, init=True):
self.ser_obj = serial.Serial(port, timeout=self.timeout_delay)
self.function_args = {}
self.function_callable = {}
self.main_filename = main_filename
self.main_module = main_filename.replace(".py", "")
# initialize
self.show_prints = show_prints
self.reset()
if init:
self.init()
self.read_functions()
def init(self):
def reset(self):
s = self.ser_obj
s.write(b'\x04')
s.write(b'\r\n\x03\r\n')
s.write(b'\x01')
time.sleep(self.init_delay)
# clean slate
s.flushInput()
# wipe out previous state
for name in self.function_args:
delattr(self, name)
self.function_args = {}
self.function_callable = {}
def init(self):
# read functions
self.read_functions()
# make sure main file is imported
self.run(f'import {self.main_module}')
def run(self, cmd, show=False, end="\n"):
def run(self, cmd, end="\n", ignore_error=False):
s = self.ser_obj
s.write((cmd+end).encode("utf-8"))
s.write(b'\x04') # ^d reset
# >OK<RETURN>\x04
txt_ret = s.read_until(b"\x04")[3:-1].decode("utf-8")
# OK<RETURN>\x04
txt_ret = s.read_until(b"\x04")[2:-1].decode("utf-8")
# <ERROR>\x04
txt_err = s.read_until(b"\x04")[:-1].decode("utf-8")
# <ERROR>\x04>
txt_err = s.read_until(b"\x04>")[:-2].decode("utf-8")
if len(txt_err) > 0:
if len(txt_err) > 0 and not ignore_error:
raise MicroPythonError(txt_err)
if show:
print(f"RETURN: '{txt_ret.rstrip()}'")
return txt_ret.rstrip()
def run_func(self, func_name, *args, **kwargs):
args_list = list(repr(x) for x in args)
kwargs_list = list(f"{a}={repr(b)}" for a, b in kwargs.items())
cmd_txt = f"print(repr({self.main_module}.{func_name}({','.join(args_list+kwargs_list)})))"
ret_txt = self.run(cmd_txt)
return ast.literal_eval(ret_txt)
cmd_txt = f"_ret = {self.main_module}.{func_name}({','.join(args_list+kwargs_list)})"
ret_print = self.run(cmd_txt)
if self.show_prints and len(ret_print) > 0:
print(f"MPY_PRINT@{self.ser_obj.port}:{ret_print}")
ret_val = self.run(f"print(repr(_ret))")
return ast.literal_eval(ret_val)
def read_functions(self):
# open file
try:
self.run(f'f=open("{self.main_filename}","rb")')
except MicroPythonError:
raise FileNotFoundError(f"Could not find {self.main_filename} on device!")
except MicroPythonError as e:
raise MicroPythonFileError(str(e))
# read main txt file
main_txt = ast.literal_eval(self.run('print(f.read())')).decode("utf-8")
......@@ -86,6 +103,13 @@ class Device:
self.function_callable[name] = func
setattr(self, name, func)
def testREPL(self):
# reduce waiting time for this simple test
txt = self.run("print(6*7)")
if len(txt) == 0:
return False
return ast.literal_eval(txt) == 42
def __str__(self):
txt = f"MicroPython Device at {self.ser_obj.port}, available functions:\n"
if len(self.function_args) == 0:
......@@ -102,17 +126,12 @@ class Device:
self.close()
def update(self):
for name in self.function_args:
delattr(self, name)
self.function_args = {}
self.function_callable = {}
self.init()
self.read_functions()
def upload_main(self, filename):
self.upload(filename, self.main_filename)
def upload(self, filename, destination=None, update=True):
def upload(self, filename, destination=None, init=True):
if destination is None:
_, destination = os.path.split(filename)
with open(filename, "r") as f:
......@@ -120,8 +139,9 @@ class Device:
self.run(f'f = open("{destination}", "wb")')
self.run(f'f.write({repr(file_txt)})')
self.run(f'f.close()')
if update:
self.update()
self.reset()
if init:
self.init()
def remove(self, filename):
self.run('import os')
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment