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(RequiresSTM32duinocore and optionalSTM32_CANlibrary).
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', mcu='STM32F401RCT6')
# 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()
See examples/analog_read_example.py for the complete runnable script.
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', mcu='STM32F401RCT6')
# 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()
See examples/servo_control_example.py for the complete runnable script.
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', mcu='STM32F401RCT6')
# 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()
See examples/pwm_output_example.py for the complete runnable script.
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', mcu='STM32F401RCT6')
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()
See examples/i2c_read_example.py for the complete runnable script.
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', mcu='STM32F401RCT6')
# 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()
See examples/i2c_write_example.py for the complete runnable script.
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', mcu='STM32F401RCT6')
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()
See examples/spi_read_example.py for the complete runnable script.
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', mcu='STM32F401RCT6')
# 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()
See examples/spi_write_example.py for the complete runnable script.
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', mcu='STM32F401RCT6')
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()
See examples/uart_read_example.py for the complete runnable script.
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', mcu='STM32F401RCT6')
# 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()
See examples/uart_write_example.py for the complete runnable script.
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', mcu='STM32F401RCT6')
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()
See examples/can_read_example.py for the complete runnable script.
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', mcu='STM32F401RCT6')
# 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()
See examples/can_write_example.py for the complete runnable script.
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.
See examples/custom_mcu_example.py for a complete example showing custom pin maps and simple LED/Servo/Analog callback integration.
---
## 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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file roboreactor_firmata-0.1.2.tar.gz.
File metadata
- Download URL: roboreactor_firmata-0.1.2.tar.gz
- Upload date:
- Size: 10.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2822b091c6619a55868ba13ccfec0ec1737551e88b194f87bdc3a5307c65187c
|
|
| MD5 |
bff52e180dc3c4aaa2843352bac571e7
|
|
| BLAKE2b-256 |
fe4044ad49ca4e97f2919e8505203a965f489a51511f4de0946a352ee7f6962e
|
File details
Details for the file roboreactor_firmata-0.1.2-py3-none-any.whl.
File metadata
- Download URL: roboreactor_firmata-0.1.2-py3-none-any.whl
- Upload date:
- Size: 9.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dd20953cae2a3b1129f72c0f300c0083d96e653bd10a20c22e63f5f496c1a7f3
|
|
| MD5 |
3232e1dfaaf4b609b94ed94a97dba726
|
|
| BLAKE2b-256 |
817c8238e227107c60a206ad4280cb6641392fd5b62de3a69283cc179fe77231
|