SerialTalk documentation

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.

Goal

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.

Installation

The easiest way to install it is with the mpy-robot-tools installer.

Usage

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

  1. Copy the complete serialtalk directory to the OpenMV flash (not the whole repo, just the library)

  2. 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.
  1. On the SPIKE Prime Install mpy-robot-tools with the installer script. Note that the installer may seem unresponsive. Just have some patience.

  2. 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

SerialTalk modules

class serialtalk.SerialTalk(serial_device, timeout=1500, debug=False, **kwargs)

Bases: object

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.

Parameters:
  • 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.

Parameters:
  • 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.

Parameters:

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.

Parameters:
  • 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.

loop()

Start processing incoming commands until the repl is enabled remotely. (If repl is supported by the local device)

process()

Process incoming commands. Call this in your main loop. It will handle incoming commands, if any, reply to them, and return.

repl_activate()

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()

Parameters:
  • 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.

Parameters:
  • command (str) – The command to send.

  • argv – Any number arguments to send with the command.

class serialtalk.auto.SerialTalk(*args, **kwargs)

Bases: SerialTalk

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)

Bases: SocketSerial

Serial interface for python3 client sockets. Connects to a server host on a port.

For Micropython use usockets module. Harmonized behavior for SerialTalk.

Parameters:
  • host (str) – Hostname or IP address of the server

  • port (int) – Port number of the server

class serialtalk.sockets.SocketSerial(socket)

Bases: object

Serial interface for python3 sockets. For Micropython use usockets module. Harmonized behavior for SerialTalk.

Parameters:

socket (socket.socket) – Your server socket object

Roadmap, todo

  • test on esp8266 platform

  • test on bt comm channels

  • create pyserial/desktop channels