Repository that implement the UNO Q DoubleBridge.
mkdir -p /home/arduino/ArduinoApps/DoubleBridge && \
curl -L https://github.com/ffich/UNOQ_DoubleBridge/archive/refs/heads/main.tar.gz \
| tar -xz --strip-components=2 -C /home/arduino/ArduinoApps/DoubleBridge UNOQ_DoubleBridge-main/DoubleBridge
This project provides a robust and extensible control infrastructure for Arduino UNO Q, based on:
- Node-RED for automation logic and UI/dashboard
- Python (App Lab) as a TCP control server
- Bridge for communication with the MCU sketch
- JSON line-based protocol over TCP
The goal is to create a clean, scalable, and production-ready bridge between high-level automation (Node-RED) and low-level hardware control (UNO Q).
- Node-RED
- Builds JSON commands
- Sends them via TCP
- Python App Lab Server
- Receives and validates JSON
- Dispatches commands to the Bridge
- Sends structured JSON responses back
- UNO Q Sketch
- Executes hardware operations (GPIO, ADC, LED Matrix)
- Transport: TCP
- Format: JSON
- Message termination: newline (
\n) -- mandatory - Model: request → response
{"cmd":"set_io","pin":"D13","value":true}(with \n appended at the end)
Command:
{ "cmd": "set_io", "pin": "D13", "value": true }Python Action:
Bridge.call("set_pin_by_name", pin, True)Response:
{
"ok": true,
"event": "io_updated",
"pin": "D13",
"value": true
}Command:
{ "cmd": "get_io", "pin": "D13" }Python Action:
Bridge.call("get_pin_by_name", pin)Response:
{
"ok": true,
"event": "io_status",
"pin": "D13",
"value": true
}This command allows enabling or disabling all digital outputs at once.
Command:
{ "cmd": "set_all_io", "value": false }Python Action:
Bridge.call("set_all_io", False)Response:
{
"ok": true,
"event": "io_all_updated",
"value": false
}The UNO Q LED Matrix is driven using the standard Arduino UNO R4 LED Matrix library.
{
"cmd": "led_matrix_print",
"text": "HELLO UNO Q"
}Bridge.call("led_matrix_print", text){
"ok": true,
"event": "led_matrix_updated",
"text": "HELLO UNO Q"
}Analog inputs are read using a Bridge function implemented on the MCU:
int get_an_pin_by_name(String pin);{ "cmd": "get_an", "pin": "A0" }Bridge.call("get_an_pin_by_name", pin){
"ok": true,
"event": "an_value",
"pin": "A0",
"value": 734
}This feature allows configuring the direction of a GPIO pin (input/output) at runtime.
{ "cmd": "set_io_dir", "pin": "D13", "value": true }Where:
pinis the pin name (string)valueis the direction:true→ OUTPUTfalse→ INPUT
Bridge.call("set_pin_direction_by_name", pin, value){
"ok": true,
"event": "io_dir_updated",
"pin": "D13",
"value": true
}The Python TCP server is designed to be fault-tolerant and production-safe:
- Handles:
- Invalid JSON
- Missing newline termination
- Socket timeouts
- Bridge runtime errors
- Never blocks indefinitely
- Always returns structured error responses
{ "ok": false, "error": "Invalid JSON" }{ "ok": false, "error": "Timeout waiting for complete line" }{ "ok": false, "error": "Bridge call set_all_io failed: ..." }Each command is encapsulated inside dedicated subflows:
- ✅ Set IO via TCP
- ✅ Get IO via TCP
- ✅ Set All IO via TCP
- ✅ LED Matrix Print via TCP
- ✅ Get Analog via TCP
Each subflow:
- Uses an environment variable
PIN_NAMEwhen needed - Automatically builds:
{ "cmd": "...", ... }- Sends data through a
tcp requestnode
A Node-RED sample control panel is also provided:

This architecture allows you to easily add:
- PWM outputs
- DAC control
- I²C / SPI via Bridge
- Advanced LED effects
- State synchronization
- Safe boot modes
- Remote diagnostics
To add a new feature:
- Implement the function in the MCU sketch
- Add a new branch in
handle_command(Python) - Create a new Node-RED subflow
This project provides a clean, scalable, and industrial-grade control bridge between:
- Automation layer: Node-RED
- Control layer: Python App Lab
- Hardware layer: Arduino UNO Q
It is designed to be:
- ✅ Reliable
- ✅ Scalable
- ✅ Maintainable
- ✅ Ready for dashboards and remote control