This is a library for robust, near real-time communication between two UART devices. We developed it on python 3.9 with LEGO EV3, SPIKE Prime and other MicroPython (ESP/STM32) modules. The library is available on github: UartRemote on GitHub. The library has the following properties:
It is fast enough to read sensor data at 30-50Hz.
It is fully symmetrical, so master and slave can have the same import.
It includes a RAW REPL mode to upload code to a slave module. This means you can develop code for both modules in one file.
It is implemented in MicroPython and Arduino/C code. With Arduino code, much higher sensor reading speeds are possible, but flashing is a bit less user friendly.
The library has a command loop to wait and listen for calls. That loop is customizable and non-blocking so you can add your own code to it.
The python-struct-like encoding is included in the payload, so the other side always knows how to decode it.
Compatable with most RS232-TTL 3.3v/5v converter board to further expand i/o possibilities.
Remote module importing
Usage: you can use all of the parts of this library for your own projects. Please give us credits at least. We put a lot spare time in this. You are also welcome to contribute. Please fork and PR.
The package aims to facilitate communication between devices like Robots and peripheral embedded systems or monitors over a serial communication line. Sounds abstract? Think connecting an OpenMV camera to a LEGO SPIKE Prime Robot. Or linking up two pyboards.
The easiest way to install it is with the mpy-robot-tools installer.
When you want default UART for the platform you’re running on, just go:
from serialtalk.auto import SerialTalk
When you want special channels like sockets or Bluetooth, do it like this:
from serialtalk import SerialTalk from serialtalk.sockets import ClientSocketSerial ser = SerialTalk(ClientSocketSerial("127.0.0.1",8080)) ser.call('echo','read?')
Example with OpenMV H7
Copy the complete serialtalk directory to the OpenMV flash (not the whole repo, just the library)
Create a main.py with this code. It is an adaptation of the OpenMV Hello world
import sensor, image, time from serialtalk.auto import SerialTalk sensor.reset() # Reset and initialize the sensor. sensor.set_pixformat(sensor.RGB565) # Set pixel format to RGB565 (or GRAYSCALE) sensor.set_framesize(sensor.QVGA) # Set frame size to QVGA (320x240) sensor.skip_frames(time = 2000) # Wait for settings take effect. clock = time.clock() # Create a clock object to track the FPS. st = SerialTalk() # Create UART comm object def fps(): # Create function to call from uart return clock.fps() st.add_command(fps,"repr") # Add function to callable uart commands while(True): clock.tick() # Update the FPS clock. img = sensor.snapshot() # Take a picture and return the image. st.process_uart() # Process aurt calls print(clock.fps()) # Note: OpenMV Cam runs about half as fast when connected # to the IDE. The FPS should increase once disconnected.
On the SPIKE Prime Install mpy-robot-tools with the installer script. Note that the installer may seem unresponsive. Just have some patience.
Run this script on SPIKE Prime:
from projects.mpy_robot_tools.serialtalk import SerialTalk from projects.mpy_robot_tools.mshub import MSHubSerial st = SerialTalk(MSHubSerial('F')) print(st.call('echo','Hello there OpenMV!')) print(st.call('fps'))
This should be the result: Spike result
- class serialtalk.SerialTalk(serial_device, timeout=1500, debug=False, **kwargs)
Symmetrical communication library for Micropython devices: use the same SerialTalk class on both sides of the serial connection. This library allows you to call functions on a remote device. Use call(‘some_function’, arg1, arg2, …) for this. You can also listen for commands on a local device. Use add_command() to add functions to listen for.
serial_device – The serial device to use for communication. It should have a write(), read() and any() method.
timeout – The timeout in milliseconds to wait for a reply, default 1500.
debug – If True, print debug messages, default False.
- add_command(command_function, return_format='', name=None)
Add a function or method to the list of commands that can be called from a remote instance of SerialTalk.
command_function (function or method) – The function to add.
return_format (struct.pack format string or "repr" for returning Python objects.) – The format of the return value, default “” for no return value.
name (str) – The name of the command, default None for the function name.
- add_module(module: str)
Load a module on the remote device and execute add_commands(serialtalk_instance) within that module to add the module’s commands to the remote command list.
module (str) – The name of the module to load.
- call(command: str, *args, wait=False)
Send a command to a remote host that is processing serialtalk commands. Wait until an answer comes or until self.timeout. Return the answer, or (err, …) if there was a problem.
command (str) – The command to send.
args – Any number arguments to send with the command.
wait – If True, wait for a reply forever, default False.
Start processing incoming commands until the repl is enabled remotely. (If repl is supported by the local device)
Process incoming commands. Call this in your main loop. It will handle incoming commands, if any, reply to them, and return.
Cajole the other side into a raw REPL with a lot of ctrl-c and ctrl-a.
- repl_run(command: str, reply=True, raw_paste=True)
Execute MicroPython remotely via raw repl. RAW repl must be activated first! with repl_activate()
command (str) – The micropython code to execute
reply (bool) – If True, return the result of the command, if False, return None, default True.
raw_paste (bool) – If True, use raw paste. Turn off for more compatility, default True.
- send_command(command: str, *argv, flush=True)
Send a command to a remote host that is processing serialtalk commands. Does not wait for an answer.
command (str) – The command to send.
argv – Any number arguments to send with the command.
- class serialtalk.auto.SerialTalk(*args, **kwargs)
SerialTalk class that automatically detects the platform and uses the correct SerialTalk implementation also sets the correct default values for the platform.
- class serialtalk.sockets.ClientSocketSerial(host, port)
Serial interface for python3 client sockets. Connects to a server host on a port.
For Micropython use usockets module. Harmonized behavior for SerialTalk.
host (str) – Hostname or IP address of the server
port (int) – Port number of the server
- class serialtalk.sockets.SocketSerial(socket)
Serial interface for python3 sockets. For Micropython use usockets module. Harmonized behavior for SerialTalk.
socket (socket.socket) – Your server socket object
test on esp8266 platform
test on bt comm channels
create pyserial/desktop channels