An open-source Modbus RTU slave for MicroPython, with a working example on the IoTextra Octal2 digital I/O module. Your IoTsmart or IoTbase PICO board answers a PLC, SCADA system, Node-RED or any other Modbus master over RS485. The code is MIT licensed and has no external Modbus dependencies.
This is an example you can copy and adapt: the register map is written by hand in the example script.
Octal2 has 4 digital inputs and 4 digital outputs. In the example they appear to the Modbus master as follows:
| Modbus table | Address | Octal2 |
|---|---|---|
| Discrete inputs (FC02) | 0–3 | Digital inputs 0–3 |
| Coils (FC01, FC05, FC0F) | 0–3 | Digital outputs 4–7 (LED 1–4) |
A PC master script from the same repository switches the outputs on and off one by one and shows input changes. Analog modules are not covered.
Tested with an external isolated Waveshare UART-RS485 adapter, one slave on the bus, slave address 1, 8N1.
| Board | UART | TX / RX | 9600 | 115200 |
|---|---|---|---|---|
| IoTsmart RP2040 | UART0 | GPIO0 / GPIO1 | pass | pass |
| IoTbase PICO with Raspberry Pi Pico 2 W (RP2350) | UART0 | GPIO0 / GPIO1 | pass | pass |
| IoTsmart ESP32-S3 | UART1 | GPIO43 / GPIO44 | pass | pass* |
Each board: 500 of 500 consecutive reads at both baud rates, 0% errors. Masters used: pymodbus, QModMaster and minimalmodbus. IoTsmart RP2350A and multi-drop buses (several slaves on one line) have not been tested yet.
* On ESP32-S3 at 115200, detach the MicroPython REPL from the Modbus UART first: import os; os.dupterm(None).
modbus_slave.py from the repository to the board (for example into lib/).examples/octal2/ (except octal2_master.py) to the board and run main_octal2.py, or save it as main.py.pip install -r requirements.txt, then python examples/octal2/octal2_master.py --port YOUR_PORT --baud 115200.modbus-rtu-slave-example on GitHub — the engine, the Octal2 example, PC test scripts and the full bring-up report with wiring and timing results.