Skip to main content

A unified, dynamic Firmata control library supporting GPIO, I2C, SPI, UART, and CAN-bus on STM32 microcontrollers

Project description

roboreactor-firmata

A unified, dynamic Firmata client library for configuring and controlling GPIO, I2C, SPI, UART, and CAN-bus peripherals on STM32 microcontrollers.

Instead of being limited to hardcoded hardware pins, roboreactor-firmata allows you to dynamically assign peripheral pins at runtime from Python using a custom extended SysEx protocol.


Installation

pip install roboreactor-firmata

Firmware Flashing

Before running the Python client, flash the matching custom .ino sketch located inside the firmware/ directory to your microcontroller:

  • STM32: Flash StandardFirmataCustom_STM32.ino (Requires STM32duino core and optional STM32_CAN library).

Features & Quick Start Examples

1. Analog Input Read (Background Reporting)

Read analog inputs using physical named pins. Register callbacks to receive updates asynchronously.

import time
from roboreactor_firmata import STM32Board

board = STM32Board('/dev/ttyUSB0')

# Configure A0 analog channel on PA0
analog_in = board.get_gpio('PA0', mode='a')

# Callback receives value between 0.0 and 1.0
def analog_callback(value):
    print(f"Analog Read PA0: {value:.3f} | Voltage: {value * 3.3:.2f}V")

analog_in.register_callback(analog_callback)
analog_in.enable_reporting()

# Start messaging loop
board.samplingOn(50)

time.sleep(3)
board.exit()

2. Servo Motor Control

Configure a physical pin as a servo output to control angular position (0-180 degrees).

import time
from roboreactor_firmata import STM32Board

board = STM32Board('/dev/ttyUSB0')

# Configure PA9 as Servo
servo_out = board.get_gpio('PA9', mode='s')

# Set angles
print("Setting servo to 0 deg")
servo_out.write(0)
time.sleep(1)

print("Setting servo to 90 deg")
servo_out.write(90)
time.sleep(1)

print("Setting servo to 180 deg")
servo_out.write(180)
time.sleep(1)

board.exit()

3. PWM Output Control

Configure pins for PWM output to write duty cycles between 0.0 (0%) and 1.0 (100%).

import time
from roboreactor_firmata import STM32Board

board = STM32Board('/dev/ttyUSB0')

# Configure PA1 as PWM
pwm_out = board.get_gpio('PA1', mode='p')

# Set PWM duty cycle to 50%
pwm_out.write(0.5)
time.sleep(2)

# Turn off PWM
pwm_out.write(0.0)
board.exit()

4. Dynamic I2C Read

Route dynamic SDA/SCL pins and request read bytes from an I2C sensor via a response callback.

import time
from roboreactor_firmata import STM32Board

board = STM32Board('/dev/ttyUSB0')
board.samplingOn(50)

# Configure dynamic SDA/SCL pins
board.configure_custom_i2c(sda_pin="PB9", scl_pin="PB8")
board.i2c_config()

# Define read response callback
def on_i2c_reply(data):
    if len(data) >= 6:
        accel_x = (data[0] << 8) | data[1]
        print(f"MPU6050 Accel X: {accel_x}")

# Read 6 bytes starting from register 0x3B on MPU6050 (0x68)
board.i2c_read(0x68, register=0x3B, num_bytes=6, callback=on_i2c_reply)

time.sleep(2)
board.exit()

5. Dynamic I2C Write

Configure dynamic I2C pins and write command configuration bytes to configure an external device or driver register.

import time
from roboreactor_firmata import STM32Board

board = STM32Board('/dev/ttyUSB0')

# Configure dynamic SDA/SCL pins
board.configure_custom_i2c(sda_pin="PB9", scl_pin="PB8")
board.i2c_config()

# Wake up MPU6050 (0x68) by writing 0x00 to Power Management register (0x6B)
board.i2c_write(0x68, register=0x6B, data_bytes=[0x00])

time.sleep(0.5)
board.exit()

6. Dynamic SPI Read

Configure dynamic SPI clock, data, and CS pins to perform a read transaction using a response callback.

import time
from roboreactor_firmata import STM32Board

board = STM32Board('/dev/ttyUSB0')
board.samplingOn(50)

# Configure dynamic SPI lines
board.configure_custom_spi(mosi="PA7", miso="PA6", sclk="PA5", cs="PA4")

# Define SPI reply callback
def spi_callback(data):
    print(f"SPI Read Bytes: {list(data)}")

# Transfer JEDEC ID command to read response
board.spi_transfer("PA4", [0x9F, 0x00, 0x00, 0x00], callback=spi_callback)

time.sleep(2)
board.exit()

7. Dynamic SPI Write

Configure SPI lines and write command or configuration payloads to a device without registering a callback.

import time
from roboreactor_firmata import STM32Board

board = STM32Board('/dev/ttyUSB0')

# Configure dynamic SPI lines
board.configure_custom_spi(mosi="PA7", miso="PA6", sclk="PA5", cs="PA4")

# Write Write Enable (WREN) command (0x06) to SPI flash chip
board.spi_transfer("PA4", [0x06])

time.sleep(0.5)
board.exit()

8. Dynamic UART Read

Configure dynamic RX/TX pins at a set baudrate, and receive serial streams asynchronously.

import time
from roboreactor_firmata import STM32Board

board = STM32Board('/dev/ttyUSB0')
board.samplingOn(50)

def uart_callback(data):
    print(f"UART Rx: {data}")

# Route RX=PA3, TX=PA2 at 9600 baud
board.configure_custom_uart(rx_pin="PA3", tx_pin="PA2", baudrate=9600, callback=uart_callback)

time.sleep(3)
board.exit()

9. Dynamic UART Write

Configure dynamic UART pins and write raw serial command packages/data to external devices.

import time
from roboreactor_firmata import STM32Board

board = STM32Board('/dev/ttyUSB0')

# Route RX=PA3, TX=PA2 at 9600 baud
board.configure_custom_uart(rx_pin="PA3", tx_pin="PA2", baudrate=9600)

# Write command string
board.uart_write(b"CMD_SET_SPEED:100\r\n")

board.exit()

10. Dynamic CAN-Bus Read

Configure dynamic CAN RX/TX pins and handle incoming standard or extended frames via a callback.

import time
from roboreactor_firmata import STM32Board

board = STM32Board('/dev/ttyUSB0')
board.samplingOn(50)

def can_callback(msg_id, payload, is_extended):
    print(f"CAN frame - ID: {hex(msg_id)} | Payload: {payload.hex()}")

# Configure CAN at 500kbps on PB12/PB13
board.configure_custom_can(rx_pin="PB12", tx_pin="PB13", baudrate=500000, callback=can_callback)

time.sleep(3)
board.exit()

11. Dynamic CAN-Bus Write

Configure dynamic CAN pins and transmit standard (11-bit ID) or extended (29-bit ID) frames.

import time
from roboreactor_firmata import STM32Board

board = STM32Board('/dev/ttyUSB0')

# Configure CAN at 500kbps on PB12/PB13
board.configure_custom_can(rx_pin="PB12", tx_pin="PB13", baudrate=500000)

# Send standard CAN frame
board.can_write(msg_id=0x123, data_bytes=[0x01, 0x02, 0x03], is_extended=0)

# Send extended CAN frame
board.can_write(msg_id=0x1F0000, data_bytes=[0xAA, 0xBB, 0xCC], is_extended=1)

board.exit()

12. Custom MCU Pin Mapping

For custom boards not natively supported in pin mappings, you can register and inject a custom virtual pin mapping at initialization.


License

This project is licensed under the MIT License - see the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

roboreactor_firmata-0.1.5.tar.gz (10.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

roboreactor_firmata-0.1.5-py3-none-any.whl (9.0 kB view details)

Uploaded Python 3

File details

Details for the file roboreactor_firmata-0.1.5.tar.gz.

File metadata

  • Download URL: roboreactor_firmata-0.1.5.tar.gz
  • Upload date:
  • Size: 10.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for roboreactor_firmata-0.1.5.tar.gz
Algorithm Hash digest
SHA256 f01c20f0f9a7b57b0b76e93740ba35d0b1fb77ecb2e7dbf2b58cd74a4af2259d
MD5 8f9afe7b5922cf77e0d12e2bb11a3045
BLAKE2b-256 5b9639c4f42925cc69fe89f5939f9a07b72dcf6dacc479e3a51534393e8b347b

See more details on using hashes here.

File details

Details for the file roboreactor_firmata-0.1.5-py3-none-any.whl.

File metadata

File hashes

Hashes for roboreactor_firmata-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 be2cb7bd13f0f874ce69bbb095e73f0e8c39e8d7be643d06c836071f7aaa8fd5
MD5 2cd8ada35a770d1f261bc807885e268b
BLAKE2b-256 77e5b2ad8d4d91f343caab5d703fb5fed36ad52e47e4235ecebfb1523b9a7c6c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page