Arduino UNO Q - Communication Between Linux and MCU

The Arduino UNO Q has two processors: a STM32 MCU running Arduino sketches and a Qualcomm Linux MPU running Python. In this tutorial, you will learn how these two processors talk to each other using the Bridge — the key mechanism that makes Arduino UNO Q unique.

In this tutorial, you will learn:

Arduino UNO Q Linux MCU Communication

Hardware Preparation

1×Arduino UNO Q
1×USB Cable for Arduino Uno Q
1×Recommended: Screw Terminal Block Shield for Arduino Uno
1×Recommended: Sensors/Servo Expansion Shield for Arduino Uno
1×Recommended: Breadboard Shield for Arduino Uno
1×Recommended: Enclosure for Arduino Uno
1×Recommended: Prototyping Base Plate & Breadboard Kit for Arduino UNO

Or you can buy the following kits:

1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables .

How the Bridge Works

The Arduino UNO Q uses an internal serial link between the two processors — this is managed automatically by the Arduino_RouterBridge library. You never open this link directly in your code.

※ NOTE THAT:

/dev/ttyHS1 (on the Linux side) and Serial1 (on the MCU side) are reserved by the router bridge. Never open them in your code — doing so will break the Bridge communication.

The communication follows a request → response model — think of it like a phone call:

  • Linux (Python) always makes the call — it asks the MCU to do something or requests a value.
  • MCU always answers — it executes the requested function and can send a value back as the response.
  • The MCU never calls Linux on its own — it only responds when Linux asks.
Who What it does API
Linux (Python) Sends a request to the MCU Bridge.call("fn")
MCU (C/C++) Receives the request, runs the function, responds Bridge.provide_safe("fn", fn)

This means data can flow in both directions — but Linux always starts the conversation:

  • Linux → MCU: Linux sends a command (e.g. "turn LED on") and the MCU executes it.
  • MCU → Linux: Linux asks "what is the sensor value?" and the MCU replies with the data.

The MCU cannot start a conversation on its own. If the MCU needs to report something (e.g. a button was pressed), the workaround is polling: the MCU saves the event in a variable, and Python checks that variable by calling a Bridge.call("get_event") function at regular intervals.

About Monitor vs Serial

On Arduino UNO Q, there are two ways to print output from the MCU:

Method Visible in App Lab Console Requires library
Monitor.println() ✅ Yes Arduino_RouterBridge
Serial.println() ❌ No None (built-in)

Use Monitor.println() when you want to see MCU output in Arduino App Lab. Serial output goes to the UART pins only and is not visible in App Lab.

Example 1: Linux Calls the MCU (Linux → MCU)

This is the most common pattern. The Python script calls a function on the MCU — for example, to turn an LED on or off.

MCU Code

/* * This Arduino UNO Q code was developed by newbiely.com * * This Arduino UNO Q code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-uno-q/arduino-uno-q-communication-between-linux-and-mcu */ #include "Arduino_RouterBridge.h" #define LED_PIN LED_BUILTIN // Built-in RGB LED on Arduino UNO Q (LED3 on the board, lights up RED, active LOW) void set_led(int state) { // Active LOW: state 1 = on (LOW), state 0 = off (HIGH) digitalWrite(LED_PIN, state ? LOW : HIGH); Monitor.print("set_led called: state="); Monitor.println(state); } void setup() { Bridge.begin(); Monitor.begin(); pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, HIGH); // start with LED off Bridge.provide_safe("set_led", set_led); Monitor.println("Bridge ready"); } void loop() {}

Python Code

""" This Arduino UNO Q script was developed by newbiely.com This Arduino UNO Q script is made available for public use without any restriction For comprehensive instructions and wiring diagrams, please visit: https://newbiely.com/tutorials/arduino-uno-q/arduino-uno-q-communication-between-linux-and-mcu """ from arduino.app_utils import * import time def loop(): print("Turning LED ON...") result = Bridge.call("set_led", 1) print(result) time.sleep(1) print("Turning LED OFF...") result = Bridge.call("set_led", 0) print(result) time.sleep(1) App.run(user_loop=loop)

Detailed Instructions

First time with Arduino UNO Q? Follow the Getting Started with Arduino UNO Q tutorial before proceeding.

  • Connect: Plug the USB-C cable into the Arduino UNO Q.
  • Open Arduino App Lab: Launch Arduino App Lab and wait until it detects your board.
  • Create a new App: Click the Create New App button.
Create New App in Arduino App Lab on Arduino UNO Q
  • Give the App a name, for example: LinuxMcuComm1
  • Click Create to confirm.
Arduino App Lab App folders and files on Arduino UNO Q
  • Paste the MCU sketch: Copy the MCU code above and paste it into sketch/sketch.ino.
  • Paste the Python code: Copy the Python code above and paste it into the Python file in the App.
  • Install the library: Click the Add sketch library button (the open book icon with a + sign) in the left sidebar.
Add sketch library in Arduino App Lab on Arduino UNO Q
  • Search for Arduino_RouterBridge created by Arduino and click the Install button.
My Apps / DIYables Apps
Run
Bricks
No bricks added...
Sketch Libraries
No sketch libra...
Files
python
sketch
.gitignore
README.md
app.yaml
sketch.ino
Add sketch library
Arduino_RouterBridge Arduino

This library provides a simple RPC bridge for Arduino UNO Q boards, allowing communication between the board and other devices using MsgPack serialization.

0.4.1
Install
More Info
  • Upload: Click the Run button in Arduino App Lab.
Click Run button in Arduino App Lab on Arduino UNO Q

App Lab Console Output

DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
Message (Enter to send a message to "Newbiely" on usb(2820070321))
New Line
9600 baud
[2026-05-07 09:00:01] Bridge ready [2026-05-07 09:00:02] set_led called: state=1 [2026-05-07 09:00:03] set_led called: state=0 [2026-05-07 09:00:04] set_led called: state=1 [2026-05-07 09:00:05] set_led called: state=0
DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
[2026-05-07 09:00:01] Turning LED ON... [2026-05-07 09:00:02] OK [2026-05-07 09:00:03] Turning LED OFF... [2026-05-07 09:00:04] OK

How It Works

  • The MCU registers a function set_led via Bridge.provide_safe().
  • The Python script calls Bridge.call("set_led", 1) — this sends an RPC request to the MCU.
  • The MCU executes set_led(1) and prints a confirmation via Monitor.println().
  • Bridge.call() returns "OK" when the function completes.

Example 2: MCU Sends Data to Linux (MCU → Linux via return value)

In this pattern, the Python side requests a sensor reading from the MCU. The MCU reads the sensor and returns the value back to Python via the Bridge.

MCU Code

/* * This Arduino UNO Q code was developed by newbiely.com * * This Arduino UNO Q code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-uno-q/arduino-uno-q-communication-between-linux-and-mcu */ #include "Arduino_RouterBridge.h" const char* get_value() { int raw = analogRead(A0); // read analog sensor on A0 static char buf[8]; itoa(raw, buf, 10); Monitor.print("get_value called — returning "); Monitor.println(buf); return buf; } void setup() { Bridge.begin(); Monitor.begin(); Bridge.provide_safe("get_value", get_value); Monitor.println("Bridge ready"); } void loop() {}

Python Code

""" This Arduino UNO Q script was developed by newbiely.com This Arduino UNO Q script is made available for public use without any restriction For comprehensive instructions and wiring diagrams, please visit: https://newbiely.com/tutorials/arduino-uno-q/arduino-uno-q-communication-between-linux-and-mcu """ from arduino.app_utils import * import time def loop(): result = Bridge.call("get_value") print("MCU returned:", result) time.sleep(2) App.run(user_loop=loop)

App Lab Console Output

DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
Message (Enter to send a message to "Newbiely" on usb(2820070321))
New Line
9600 baud
[2026-05-07 09:00:01] Bridge ready [2026-05-07 09:00:02] get_value called — returning 42 [2026-05-07 09:00:04] get_value called — returning 43 [2026-05-07 09:00:06] get_value called — returning 41
DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
[2026-05-07 09:00:02] MCU returned: 42 [2026-05-07 09:00:04] MCU returned: 43 [2026-05-07 09:00:06] MCU returned: 41

How It Works

  • The MCU function reads a sensor (here simulated with analogRead(A0)) and returns the value as a string.
  • On the Python side, Bridge.call("get_value") returns that string — Python can then parse and use it.
  • This is the standard pattern for reading any MCU sensor from the Linux side.

Example 3: Passing Arguments from Linux to MCU

The Python side can pass arguments to the MCU function. This is useful for commands that include parameters — for example, setting a target angle, a threshold, or a speed value.

MCU Code

/* * This Arduino UNO Q code was developed by newbiely.com * * This Arduino UNO Q code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/arduino-uno-q/arduino-uno-q-communication-between-linux-and-mcu */ #include "Arduino_RouterBridge.h" #define LED_PIN LED_BUILTIN // Built-in RGB LED on Arduino UNO Q (LED3 on the board, lights up RED, active LOW) void set_brightness(int value) { // analogWrite simulates brightness (0 = off, 255 = full on) // Note: active LOW — invert for LED_BUILTIN analogWrite(LED_PIN, 255 - value); Monitor.print("set_brightness called: value="); Monitor.println(value); } void setup() { Bridge.begin(); Monitor.begin(); pinMode(LED_PIN, OUTPUT); Bridge.provide_safe("set_brightness", set_brightness); Monitor.println("Bridge ready"); } void loop() {}

Python Code

""" This Arduino UNO Q script was developed by newbiely.com This Arduino UNO Q script is made available for public use without any restriction For comprehensive instructions and wiring diagrams, please visit: https://newbiely.com/tutorials/arduino-uno-q/arduino-uno-q-communication-between-linux-and-mcu """ from arduino.app_utils import * import time def loop(): for brightness in [0, 64, 128, 192, 255]: print(f"Setting brightness to {brightness}...") result = Bridge.call("set_brightness", brightness) print(result) time.sleep(1) App.run(user_loop=loop)

App Lab Console Output

DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
Message (Enter to send a message to "Newbiely" on usb(2820070321))
New Line
9600 baud
[2026-05-07 09:00:01] Bridge ready [2026-05-07 09:00:02] set_brightness called: value=0 [2026-05-07 09:00:03] set_brightness called: value=64 [2026-05-07 09:00:04] set_brightness called: value=128 [2026-05-07 09:00:05] set_brightness called: value=192 [2026-05-07 09:00:06] set_brightness called: value=255
DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
[2026-05-07 09:00:01] Setting brightness to 0... [2026-05-07 09:00:02] Done [2026-05-07 09:00:03] Setting brightness to 64... [2026-05-07 09:00:04] Done [2026-05-07 09:00:05] Setting brightness to 128... [2026-05-07 09:00:06] Done

How It Works

  • Arguments are passed as additional parameters to Bridge.call("function_name", arg1, arg2, ...).
  • On the MCU side, the registered function receives arguments as int (or const char * for strings) parameters.
  • The MCU can return a result string back to Python as the function return value.

Summary

Pattern MCU side Python side
Linux calls MCU Bridge.provide_safe("fn", fn) Bridge.call("fn")
MCU returns a value return "value" result = Bridge.call("fn")
Linux passes arguments void fn(int a, int b) Bridge.call("fn", a, b)
MCU console output Monitor.println("...") *(visible in App Lab console)*

※ NOTE THAT:

All Bridge functions must be non-blocking — do not use delay() inside a Bridge-registered function. The Bridge will time out if the MCU function takes too long.

Troubleshooting

Bridge.call() returns an error or empty string:

  • Check that the function name in Bridge.call("name") exactly matches the name used in Bridge.provide_safe("name", fn) on the MCU side — it is case-sensitive.
  • Make sure Bridge.begin() is called in setup() before Bridge.provide_safe().

MCU output does not appear in App Lab:

  • Use Monitor.println() — not Serial.println(). Only Monitor output appears in the App Lab console.
  • Make sure Monitor.begin() is called in setup().

The board stops responding after a while:

  • Do not open /dev/ttyHS1 (Linux) or Serial1 (MCU) in your code — these are reserved for the Bridge router.
  • Avoid using delay() inside Bridge-registered functions.

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!