1. On the UNO Q board, there is a four-core MPU (Mcroprocessor Unit, QRB2210, Fig-1) and a single-core MCU (Microcontroller Unit, STM32U585, Fig-1). By definition, an MPU does not contain memory in the same pacakge/die; whereas, an MCU does contain memory in the same package/die.
Figure-1: (at my coneptual level)
2. On the UNO Q board, there are four RGB leds which are marked as: QRB/1 2 (connected with MPU) and STM/3 4 (connected with MCU). The symbolic DPin (digital pin) numbers for these leds are respectively: (numerical values/Port-pins for these DPin numbers are shown in Fig-2)
LED1_R, LED1_G, LED1_B
LED2_R, LED2_G, LED2_B
LED3_R, LED3_G, LED3_B
LED4_R, LED4_G, LED4_B
Figure-2:
3. Arduino Sketch to blink LED3_R (Fig-1) at 2 sec interval using IDE 2.3.7. (tested ok)
void setup()
{
pinMode(LED3_R, OUTPUT); //numerical value of LED3_R is not known to me
}
void loop()
{
digitalWrite(LED3_R, LOW); // turn on led; in UNO Q the logic is active low
delay(1000); // wait for a second
digitalWrite(LED3_R, HIGH); // turn led off by making the logic HIGH
delay(1000); // wait for a second
}
4. Arduino Sketch to do color modulation/mixing for LED3_R/G/B (Fig-1).
... looks like analogWrite() function does not work!
5. Python Script to blink LED1_G (Fig-1) at 2 sec interval (1 sec On and 1 sec Off) (tested ok)
(1) Open App Lab, click on Examples, click on Blink LED icon, click on Copy and edit app, change the name to Blink LED1_G, and then click on Create new. You have got your new application.
(2) Goto the Editor window, open python file, and click on main.py. A window appears with a default script which is to be deleted. Now, copy and paste the following script which I have taken from this document: https://docs.arduino.cc/tutorials/uno-q/user-manual/#from-serial-to-monitor (To know what the python lines are doing -- place them line-by-line to ChatGPT who will explain and be careful to accept their opinon.)
import time
LED1_R = "/sys/class/leds/red:user/brightness"
LED1_G = "/sys/class/leds/green:user/brightness"
LED1_B = "/sys/class/leds/blue:user/brightness"
LED2_R = "/sys/class/leds/red:panic/brightness"
LED2_G = "/sys/class/leds/green:wlan/brightness"
LED2_B = "/sys/class/leds/blue:bt/brightness"
def set_led_brightness(led_file, value):
try:
with open(led_file, "w") as f:
f.write(f"{value}\n")
except Exception as e:
print(f"Error writing to {led_file}: {e}")
def main():
# turn off all LEDs
set_led_brightness(LED1_R, 0)
set_led_brightness(LED1_G, 0)
set_led_brightness(LED1_B, 0)
set_led_brightness(LED2_R, 0)
set_led_brightness(LED2_G, 0)
set_led_brightness(LED2_B, 0)
while True:
#blink the LED 1 GREEN segment
set_led_brightness(LED1_G, 1)
time.sleep(1)
set_led_brightness(LED1_G, 0)
time.sleep(1)
if __name__ == "__main__":
main()
(3) Run the applicaton and check that LED1_G is blinking.
6. Passing ADC data from MCU to MPU using Router bridge
Figure-3:
Python Script for MPU (tested)
from arduino.app_utils import *
import time
last_print = 0
interval = 0.1 # seconds between loop checks
# A container to hold the latest ADC value
latest_adc = None
# This function will be called automatically when MCU sends notify
def on_adc(value):
global latest_adc
latest_adc = value
# Subscribe to MCU notifications
Bridge.provide("adc_data", on_adc)
def loop():
global last_print, latest_adc
current_time = time.time()
# Check every 100ms if there is new data
if latest_adc is not None and current_time - last_print >= 1:
voltage = latest_adc * (3.3 / 1023.0)
print(f"ADC: {latest_adc}, Voltage: {voltage:.3f} V") #shows on: Python console
last_print = current_time
App.run(user_loop=loop)
Arduino Sketch for MCU (tested)
#include "Arduino_RouterBridge.h"
void setup()
{
analogReadResolution(10);
Monitor.begin();
Bridge.begin();
}
void loop()
{
int adc = analogRead(A0);
Bridge.notify("adc_data", adc);
Monitor.println("Seding data to MPU."); //shows on: Serial Monitor of IDE and Console
delay(1000);
}
7. Serial Communication Ports of STM32U585 MCU
(1) USART1
(2) USART2
(3) USART3
(4) UART4
(5) UART5
(6) LPUART1
(7) LPUART2
Q1: Which Serial port of the above is connected with
DPin-0 (RX) and DPin-1 (TX) pins of UNO Q?
Q2: What are the corresponding C++ object names for the above hardware ports. For example: Serial1 for UART1, .....
Q3: Which UART port is used by the Arduino_RouterBridge.h Library for inter-communication between MCU and MPU? I have read in the diagram of #4 of this thread that it is : LPUART1 (Serial1 at Bd = 115200).
8. The C++ compiler and the Python interpreter are pre-stored in eMMC storage media, then they are loaded into RAM, then executed by the MPU to generate the corresponding executable files, and then te sketch is flashed into MCU and the script remains in RAM for runtime execution. To be a bit more precise all those components are part of the pre-loaded Debian image of the UNO Q. ref: #21 #22.
As a result, the execution of the sketch in the MCU tends to begin earlier but is delayed until the MPU has started execution, which is have guaranteed in by including the following codes at the setup() function of the MCU sketch:
#include "Arduino_RouterBridge.h"
int data = 0;
void setup() {
Bridge.begin();
delay(2000);
boolean start = false;
// Wait until the python is started
while(!start)
{
Bridge.call("linux_started").result(start);
}
}
void loop() {
data++;
Bridge.notify("python_func", data);
delay(1000);
}
from arduino.app_utils import *
import time
#used only for sync purposes
def linux_started():
return True
def python_func (data: int):
print(data)
Bridge.provide("linux_started", linux_started)
Bridge.provide("python_func", python_func)
def loop():
time.sleep(1)
App.run(user_loop=loop)
9. SPI port operation of UNO Q and 74HC595 shift register
(1) 1. Connection diagram between Arduino UNO Q and 74HC595 shift register using SPI port.
(2) Reeceive Newline terminated string of decimal digits from InputBox of APp Lab Console.Serial Monitor, extract the single-valued decimal number, save it and then transmits to 74C595 shift register over SPI port. The received number would also be shown on Console.python.
Sketch:
#include <Arduino_RouterBridge.h>
#include <SPI.h>
const int storePin = 10; // ST_CP
char myData[10];
void setup()
{
Bridge.begin();
Monitor.begin();
pinMode(storePin, OUTPUT);
SPI.begin();
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
digitalWrite(storePin, LOW); // Prepare latch
//--------------------
SPI.transfer(0b10101010); // 0xAA
digitalWrite(storePin, HIGH); // Output appears on Q0–Q7
delayMicroseconds(5);
digitalWrite(storePin, LOW);
}
void loop()
{
byte n = Monitor.available();
if (n != 0)
{
byte m = Monitor.readBytesUntil('\n', myData, sizeof myData - 1);
myData[m] = '\0';
byte y = atoi(myData);
Monitor.println(y, BIN);
Bridge.notify("data_sm", y);
//--------------------
SPI.transfer(y); // 0xAA
digitalWrite(storePin, HIGH); // Output appears on Q0–Q7
delayMicroseconds(5);
digitalWrite(storePin, LOW);
}
}
Script:
from arduino.app_utils import *
import time
# This function will be called automatically when MCU sends notify
def data_sm(value):
print(value)
# Subscribe to MCU notifications
Bridge.provide("data_sm", data_sm)
def loop():
time.sleep(1)
App.run(user_loop=loop)
10. Troubleshooting Tips
If it happens that you cannot run any application from App Lab that involves Bridge.provide()/call()/notify(), then carryout the following tasks:
(1) From linux terminal (>_) of App Lab, type the following and then press Enter key.
arduino-app-cli system cleanup
(2) Then type the following and then press Enter key.
docker network prune
10. Electrical Characteristics of an IO Pin
11. Negative Logic to turn on LED_BUILTIN of UNO Q Board
UNO Q represents a remarkable migration from the UNO R3 platform. However, in the UNO Q board design, the onboard LED (LED_BUILTIN = LED3_R, lebeled STM-3) is implemented using active-LOW (negative) logic, meaning the LED turns ON when its cathode terminal is pulled LOW (Fig-1).
In contrast, on the UNO R3, the LED_BUILTIN is implemented using active-HIGH (positive) logic, where the cathode is permanently grounded and the LED turns ON when a HIGH level is applied to its anode terminal.
Since LED_BUILTIN on the UNO Q is not driven from header pin D13, the board designers likely had valid architectural or electrical reasons for choosing an active-LOW configuration in this case. It is worth noting that all header GPIO pins on the UNO Q continue to follow positive logic, consistent with the behavior of the UNO R3 header pins.
12. Procedures to update software (Linux, Compiler, Interpreter, Zephyr) into UNO Q
I have carried out the following steps from this Arduino Documents https://docs.arduino.cc/tutorials/uno-q/update-image/) to update software (Debian Linux Operating System and others) in my UNO Q board :
(1) I have downloaded Arduino Flasher CLI software and have unziped it under the same folder where the zip file is saved. I have copied this folder: arduino-flasher-cli-0.5.3-windows-amd64> from unzipped path under C drive.
(2) I have unplugged the board from PC.
(3) I have shorted the following two-pins (red wire, Fig-1) to bring the board into OS updating mode.
Figure-1:
(4) I have connected back the UNO Q board with PC.
(5) From the Start icon of the PC, I have executed cmd.exe to get text screen.
(6) I have changed the directory to:
C:\arduino-flasher-cli-0.5.3-windows-amd64>
(7) From the command prompt of Step-6, I have executed the following command:
arduino-flasher-cli
(8) After a while, the prompt has come back and then I have executed the folloiwng command from the prompt:
arduino-flasher-cli flash latest
(9) That statred the downloading of the Debian image of size 2.4 GB.
(10) I have waited until the image is completely downloaded and then have entered yes in response to queries.
(11) Ulltimately, the image was flashed into UNO Q board with the following message:
The board has been successfully flashed. You can now power-cycle the board (unplug and re-plug). Remember to remove the jumper.
(12) I have taken out the board from PC, removed the jumper, and connected back the board with PC.
(13) I have launced the App Lab and then have clicked on Blink LED icon and then on Run button. After a while, the led-3 has started blinking.
13. Scrpt and Script Loading in MPU and MCU
(1) IDE 2.3.7 based sketch is compiled in the PC. The application file (in Intel-Hex format) is transmitted to the MPU which extracts the binary codes and then writes them into Flash or RAM (Tools ---> Flash mode: Flash or RAM) of the MCU using boot loader based ISP Programmer (Fig-1).
(2) App Lab based sketch is compiled in the MPU using a pre-installed C++ compiler. After that the MPU writes the binary codes of the sketch into RAM (no option for Flash like IDE based sketch) of the MCU using boot loader based ISP Programmer.
(3) When we create a new app (application) in App Lab (My Apps ---> Create new app+ ---> + Create New App ---> Test-1 (Insert title) ---> Create new) for an application (sketch+ script), the following two components appear in the espective Edit Window by default.
(My Apps ---> Test-1 ---> Files ---> sketch ---> sketch)
Sketch:
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
}
(My Apps ---> Test-1 ---> Files ---> pyhon ---> main.py)
Script:
import time
from arduino.app_utils import App
print("Hello world!")
def loop():
"""This function is called repeatedly by the App framework."""
# You can replace this with any code you want your App to run repeatedly.
time.sleep(10)
# See: https://docs.arduino.cc/software/app-lab/tutorials/getting-started/#app-run
App.run(user_loop=loop)
(4) We enter our Arduino codes into Editor>>sketch.ino window. For example, the following codes to blink the LED_BUILTIN (LED3_R) led.
#include <Arduino_RouterBridge.h>
void setup() {
Bridge.begin();
Monitor.begin();
delay(5000);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, LOW); // active LOW; turn LED on
delay(1000); //1000 ms
digitalWrite(LED_BUILTIN, HIGH); // active low,LED off
delay(1000); // wait for a second
}
(5) We do not do anything with the default script of Editor>>main.py window.
(6) When we click on the RUN button, the source codes of both the sketch and the script are transferred to the MPU (which one goes firts?); where, the script is interpreted by a pre-installed Python Interpreter and the application codes are written into the 2 GB RAM space. Here, the python script does not do anything useful except suspending the loop() thread in every 10 sec with the help of the resident Linux OS.
(7) The source codes of the sketch are compiled by the MPU with the assistance of a pre-installed C++ compiler, the binary codes are written into RAM of MCU, and then the LED_BUILTIN starts blinking at every 2 sec intervals.
14. What are "IDE: Serial Monitor Console", "IDE: Serial Monitor", "App Lab: Serial Monitor Console", "App Lab: Python Console"
I have prepared this tutorial to explain and clarify the definitions of the objects mentioned in the title. I would greatly appreciate feedback to correct any misconceptions if any from my part.
With the advent of UNO Q Board, we have the following monitoring/communicating windows (Fig-1):
-
Arduino IDE: Serial Monitor Console (Monitor object driven console window frpm Arduino skech)
-
Ardino IDE: Serial Monitor (Serial object driven console window from Arduino Sketch)
-
App Lab: Serial Monitor Console (Monitor object driven console window Arduino sketch)
-
App Lab: Python Console (print driven console window from Python script)
Figure-1:
//====================================================
1. Arduino IDE: Serial Monitor Console
This console window communicates with the MCU of UNO Q board in the followin path (Fig-1)
Arduino IDE 2.3.7 ----> Serial Monitor Console <----> virtual COMX Port in PC <----> USB-A Port of PC <----> USB-C Port of UNO Q <----> MPU <----> Router Bridge <-----> flash of MCU
Test Sketch: Hello message appears on Serial Monitor Console
Use IDE 2.3.7 to upload the following sketch into the flash of MCU and check the message Hello appears on the Serial Monitor Console.
#include <Arduino_RouterBridge.h>
void setup() {
Bridge.begin();
Monitor.begin(); //creates Serial Monitor Console
delay(5000);
}
void loop() {
Monitor.println("Hello");
delay(1000); // wait for a second
}
//=====================================================
2. Arduino IDE: Serial Monitor
This console window communicates with the MCU of UNO Q board in the following path (Fig-1). From this IDE, it is not possible to upload sketch into flash of MCU.
Arduino IDE 1.8.19 ---> Serial Monitor <----> virtaul COMX Port in PC <----> USB-A Port of PC<----> USB to TTL Converter <----> RX/TX Pins of Header of UNO Q (MCU's UART1 Port) <-----> flash of MCU
Test sketch: Welcome message appears on Serial Monitor
(a) Connect UNO Q, PC, TTL<--->USB Converter as per Fig-2 (tested).
Figure-2:
(b) Use IDE 2.3.7 to upload the following sketch into flash of MCU.
#include <Arduino_RouterBridge.h>
void setup() {
Bridge.begin();
Monitor.begin();
delay(5000);
Serial.begin(9600); //creates Serial Monitor
}
void loop() {
Monitor.println("Hello");
Serial.println("welcome");
delay(1000); // wait for a second
}
(c) Open IDE 1.8.19 and open Serial Monitor at Bd = 9600. Check that Welcome message appears on the Serial Monior.
//========================================================
3. App Lab: Serial Monitor Console
This window communicates with MCU of UNO Q board in this way (Fig-1):
Arduino IDE 2.3.7 ----> Serial Monitor Console <----> virtual COMX Port in PC <----> USB-A Port of PC <----> USB-C Port of UNO Q <----> MPU <----> Router Bridge <-----> (after compilation) flash of MCU
Test Sketch: MCU message appers on Serial Monitor Console of App Lab.
(a) Close IDE2.3.7 and IDE 1.8.19
(b) Open App Lab and then My Apps ----> create new app + -----> +Create New App -----> serailTest ----> Create new
(c) Editor ---> sketch ----> sketch and delete whatever is there.
(d) Copy and paste the following sketch.
#include <Arduino_RouterBridge.h>
void setup() {
Bridge.begin();
Monitor.begin(); //creates Serial Monitor Console
delay(5000);
}
void loop() {
Monitor.println("MCU");
delay(1000); // wait for a second
}
(e) Click on Run button.
(f) Go to: Console ----> Serial Monior (this is App Lab: Serial Moitor Console)
(g) works OK!
//========================================================
4. App Lab: Python Console
The window communicates with the MPU in this way (Fig-1).
App Lab ----> USB-A Port of PC ----> USB-C Port of UNO Q ----> (after interpretation) RAM MPU
Python Console <---- USB-A Port of PC <---- USB-C Port of UNO Q <---- RAM MPU
Teast Sketch: MPU message appers on Python Console
(a) App Lab ----> My Apps ----> serialTest --- > python ---> main.py ----> delete watever is there and then paste the following codes:
import time
def main():
while True:
print("UNO Q")
time.sleep(1)
if __name__ == "__main__":
main()
(b) Click on Run button
(c) Go to: Console ----> Python (this is the Python Console) and check that UNO Q message appears here.
//===========================================================
15. ???
... in progress













