Nach der überraschenden Übernahme von Arduino durch Qualcomm war klar: Da kommt was. Und jetzt ist er da. Der erste große Wurf aus dieser neuen Kombi:
Der Arduino UNO Q

Was ist der Clou? Der UNO Q ist nicht einfach nur ein UNO mit neuem Namen. Das Ding hat zwei Gehirne!
Zum einen der Qualcomm Dragonwing QRB2210 Quad-Core ARM-Prozessor (MPU) als Linux-System für die cleveren Sachen und einen klassischen STM32U585 Mikrocontroller (MCU) für die Echtzeit-Spielereien.
Klingt erstmal wild – ist es auch. Aber genau das macht ihn spannend für alle, die beide Welten kombinieren wollen. Alle Details siehe UNO Q | Arduino-Dokumentation
In diesem ersten Beitrag möchte ich zeigen, dass die vertraute Arduino-Welt weiterhin besteht und neue sowie bestehende Projekte (fast) wie gewohnt in der Arduino IDE zum Laufen gebracht werden können. Außerdem erläutere ich, wie der UNO Q als Mini-PC eingesetzt werden kann und wie die neue Arduino App Lab Anwendung eine völlig neue Art der Entwicklung ermöglicht.
Getestete Hardware:
Derzeit konnte ich mir den Arduino UNO Q nur in der Version: „2 GB LPDDR4 RAM mit 16 GB eMMC Speicher vom Typ ABX00162“ kaufen. Die Variante 4 GB / 32 GB soll aber noch dieses Jahr auf den Markt kommen.
Als Netzteil habe ich das Raspberry Pi, USB-C 5V 5A verwendet
Das USB-C Hub mit HDMI Ausgang, SD Card Steckplatz, weiteren Typ A und C Schnittstellen, das extern mit Strom versorgt werden kann, ist das HODO USB C Hub
Erste Testreihe mit Arduino IDE:
Die vertraute Arduino-Welt: Arduino bleibt offen, bleibt bastelfreundlich, bleibt „Prilchen-kompatibel“.
Der UNO Q kommt im klassischen UNO-Formfaktor daher – gleiche Größe, gleiche GPIO-Anschlüsse, gleiche Pinbelegung. Das heißt: Deine alten Shields, Breakout-Boards und Breadboard-Setups passen weiterhin wie angegossen. Kein Umbau, kein Adapter-Zirkus. Einfach einstecken und mit der Arduino IDE loslegen.

Dann werde ich mal testen ob dem so ist.
Vorbereitung in der Entwicklungsumgebung Arduino IDE:
Library für das Board installieren

Nun den Uno Q per USB anschließen und in der IDE normal das Board und die Schnittstelle einstellen:

Entweder ein Beispiel Sketch wählen, das mit der Library installiert wurde oder
dieser Test Quellcode für Laufschrift auf Matrix:
#include "ArduinoGraphics.h"
#include "Arduino_LED_Matrix.h"
ArduinoLEDMatrix matrix;
void setup() {
matrix.begin();
// Matrix vorbereiten
matrix.beginDraw();
matrix.stroke(0xFFFFFFFF); // Weiß
matrix.textScrollSpeed(25); // Scrollgeschwindigkeit
matrix.endDraw();
}
void loop() {
displayScrollingText(" Willkommen bei Prilchen tueftelt ");
delay(2000); // Pause zwischen Durchläufen
}
void displayScrollingText(String text) {
matrix.beginDraw();
matrix.stroke(0xFFFFFFFF);
matrix.textScrollSpeed(99); // Optional: schnellerer Lauftext
matrix.textFont(Font_5x7); // Standard-Schriftart
matrix.beginText(0, 1, 0xFFFFFF); // X, Y, Farbe (weiß)
matrix.println(text);
matrix.endText(SCROLL_LEFT);
matrix.endDraw();
delay(1000); // Wartezeit für das Laufband
}
Nach dem Upload läuft der Text ohne Reset und Wartezeit sofort über die Matrix los. 🙂 Prima!
Test mit angeschlossenen Sensor an den GPIO Schnittstellen.
Da habe ich den CO₂-Sensor aus dem schon beschriebenen Projekt mit dem funktionierende Sketchen für Arduino UNO und UNO R4 Wifi ausprobiert:
Arduino-Projekt: Werte der Luftqualität mit ENS160 und AHT21 messen und auswerten
Im ersten Sketch wurde gezeigt wie der Senor die Daten beider Sensoren ausliest und im Seriellen Monitor anzeigte. Abweichend von meiner alten Anleitung änderte ich den I2C Anschluss von A4 auf SDA D20 und von A5 auf SCL D21.
Ausführung: Ein Upload war ohne Probleme möglich
Problem: aber im Seriellen Monitor wurde nichts angezeigt? Schade
Status: Das Problem ist bekannt und wird bereits im Arduino-Forum diskutiert. Ein entsprechendes Update zur Behebung ist in Arbeit und soll in Kürze veröffentlicht werden.
Was kannst du tun? Bis zum Update kannst du alternativ die LED-Matrix zur Visualisierung mit diesem funktionierenden Sketch nutzen:
#include <Wire.h>
#include <SparkFun_ENS160.h>
#include <Adafruit_AHTX0.h>
#include "ArduinoGraphics.h"
#include "Arduino_LED_Matrix.h"
// Sensoren und Matrix initialisieren
SparkFun_ENS160 ens160;
Adafruit_AHTX0 aht;
ArduinoLEDMatrix matrix;
void setup() {
Wire.begin();
matrix.begin();
displayScrollingText("Starte Sensorcheck...");
// ENS160 starten
if (!ens160.begin()) {
displayScrollingText("ENS160 nicht gefunden!");
while (1);
}
ens160.setOperatingMode(SFE_ENS160_RESET);
delay(100);
ens160.setOperatingMode(SFE_ENS160_STANDARD);
// AHT21 starten
if (!aht.begin()) {
displayScrollingText("AHT21 nicht gefunden!");
while (1);
}
displayScrollingText("Sensoren bereit!");
}
void loop() {
// AHT21-Daten
sensors_event_t humidity, temp;
aht.getEvent(&humidity, &temp);
float temperature = temp.temperature;
float humidityVal = humidity.relative_humidity;
// ENS160-Daten
if (ens160.checkDataStatus()) {
int co2 = ens160.getECO2();
int voc = ens160.getTVOC();
// Anzeigen auf Matrix
displayScrollingText("Temp: " + String(temperature, 1) + " C");
displayScrollingText("Feuchte: " + String(humidityVal, 1) + " %");
displayScrollingText("CO2: " + String(co2) + " ppm");
displayScrollingText("VOC: " + String(voc) + " ppb");
} else {
displayScrollingText("ENS160 keine Daten!");
}
delay(2000); // Pause
}
void displayScrollingText(String text) {
matrix.beginDraw();
matrix.stroke(0xFFFFFFFF);
matrix.textScrollSpeed(75);
matrix.textFont(Font_5x7);
matrix.beginText(0, 1, 0xFFFFFF);
matrix.println(text);
matrix.endText(SCROLL_LEFT);
matrix.endDraw();
delay(1000);
}
Funktioniert:

Status und Werte auf der Matrix als Laufschrift zu sehen
Zweite Testreihe: Arduino mit neuer Entwicklungsumgebung App Lap
Eine neue Entwicklungsumgebung ist gleichzeitig mit erschienen. Dazu kommt nun auch noch das neue Arduino App Lab, eine Entwicklungsumgebung die dir Einzelzugriff oder auch Zugriff auf beide „Gehirne“ gibt – den klassischen Mikrocontroller und das Linux-System.
Du kannst dann Projekte nahtlos kombinieren. Somit trifft Echtzeitsteuerung dann auf High-Level-Intelligenz. Mal sehen wie das geht.
Jetzt aber erst mal Updates und dann eine erste App nur mit MCU
Erster Start:
Linux Update:
Erster Start der App Lab und schon wird auf externes Linux Update per Flasher aufgefordert. Also raus aus der App Lab und diese gut dokumentierte Anleitung ausgeführt:
Linux Update: Flashing a New Image to the UNO Q | Arduino Dokumentation
Applikationen werden installiert:
Zweiter Start der App Lab. Wieder Tastatur Sprache und Wifi.
Danach Applikationsupdate. (Auch App Lab erhällt ein Upgrade)

Den Lese und Schreibzugriff zeigt das Board, blinkend an der zweiten blauen QRB LED
App Lab Desktob Oberfläche:
Also dritter Start der App Lab und Passwort setzen. Dabei wird klar das lokaler Single Board User und App Lab User getrennt verwendet werden.
Eine Desktop Oberfläche erscheint mit 4 Reiter:

Hier die Ansicht der Beispiele
Die My Apps ist noch ohne Inhalt.
Aber kaum öffnet sich die Bricks-Ansicht, macht das Makerherz Luftsprünge – so viel Potenzial auf einen Blick 🙂 Mal schauen was damit alles möglich ist:

und zum Kennenlernen einige Tutorials

Jetzt kann die Testreihe beginnen. Unter MyApps erstelle ich meine erste App:

Den unveränderten Sketch aus der IDE wird nun unter Files/sketch.ino eingefügt.

Dann die fehlenden Bibliotheken:

Und gestartet wird mit Klick auf

Funktioniert wie mit der Arduino IDE. 🙂
Nun MCU und MPU verbinden und nutzen:
Unter der Haube werkelt jetzt eine brauchbare MPU: Neben dem gewohnten Mikrocontroller (für die Echtzeit-Spielereien) sitzt eine Quad-Core ARM CPU mit integrierter GPU, die eine abgespeckte Linux Distribution auf einem eMMC-Flashspeicher bereitstellt – Geschätzte Lesegeschwindigkeit: Bis zu 250 MB/s.
Damit kannst du nicht nur Python skripten, sondern auch KI-Modelle ausführen, Bildverarbeitung machen oder Webserver hosten. Und das alles direkt auf dem Board, ohne externe Rechner oder Cloud-Gedöns.
Um nun mal zu testen, wie ich jetzt die mit der MCU ausgelesenen CO2 Werte, dann an einem von der MPU erstellten Webserver zu übergeben, sollte man wissen, das hier so eine Art Brücke zwischen den beiden Welten erstellt werden muss.
Damit das gemeinsam funktioniert, wird eine Arduino Bridge RPC-Bibliothek benötigt.

Das muss dann in etwa so in den bereits funktionierenden Sketch hinzugefügt werden:

und so in etwa sieht dann das benötigte Python Skript aus, damit es auf der MPU läuft:

So arbeiten C++ und Python Hand in Hand.
Da ich die Ausgabe der CO2 Werte in jedem Browser meines Netzwerkes als Webseite sehen möchte,
installiere ich als erstes das Brick WebUI-HTML. Bricks sind modulare Bausteine in der neuen Entwicklungsumgebung, mit denen du deinem Projekt gezielt Funktionen hinzufügen kannst – ganz ohne komplexe Konfiguration oder manuelles Setup. So zu mindestens der zukünftige Plan.

Problem: Das notwendige Verzeichnis assets wurde nicht beim hinzufügen des WebUI Brick hinzugefügt.
Dann lege ich nun manuell mit dem File Manager ein assets Verzeichnis an, um gleich eine index.html Datei darin hinein zulegen.
Vollständiger C++ sketch.ino in das Sketch Verzeichnis legen:
#include <Wire.h>
#include <SparkFun_ENS160.h>
#include <Arduino_RouterBridge.h>
SparkFun_ENS160 ens160;
void setup() {
Wire.begin();
Bridge.begin();
ens160.begin();
ens160.setOperatingMode(SFE_ENS160_RESET);
delay(100);
ens160.setOperatingMode(SFE_ENS160_STANDARD);
}
void loop() {
if (ens160.checkDataStatus()) {
int co2 = ens160.getECO2();
int voc = ens160.getTVOC();
Bridge.notify("record_air_quality", co2, voc);
}
delay(2000);
}Vollständiges Python Skript main.py in das python Verzeichnis legen:
from arduino.app_utils import App, Bridge, Logger
from arduino.app_bricks.web_ui import WebUI
import time
# Logger initialisieren
logger = Logger("air-quality-dashboard")
logger.info("Starte Luftqualitäts-App...")
# WebUI starten
web_ui = WebUI()
# Globale Datenstruktur für aktuelle Werte
latest_data = {
"co2": None,
"voc": None,
"timestamp": None
}
# REST-API-Endpunkt für JSON-Abruf
web_ui.expose_api("GET", "/air_quality", lambda: latest_data)
logger.info("API-Endpunkt /air_quality bereitgestellt")
# WebSocket: sende Daten bei Verbindung
def on_client_connect(sid):
logger.debug(f"Client verbunden: {sid}")
web_ui.send_message("air_quality", latest_data)
web_ui.on_connect(on_client_connect)
# Bridge-Funktion vom Mikrocontroller
def record_air_quality(co2: int, voc: int):
logger.debug(f"Empfangen: CO₂={co2} ppm, VOC={voc} ppb")
latest_data["co2"] = co2
latest_data["voc"] = voc
latest_data["timestamp"] = time.time()
try:
web_ui.send_message("air_quality", latest_data)
logger.debug("Werte an WebUI gesendet")
except Exception as e:
logger.warning(f"WebUI-Sendung fehlgeschlagen: {e}")
# Bridge registrieren
Bridge.provide("record_air_quality", record_air_quality)
logger.info("Bridge-Funktion 'record_air_quality' registriert")
# App starten
App.run()Vollständiger HTML-Code für index.html Datei:
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>CO₂- und VOC-Werte</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
margin-top: 50px;
background: #f4f4f4;
}
.card {
display: inline-block;
background: white;
padding: 20px 40px;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 { color: #0077cc; }
.value { font-size: 2em; margin: 10px 0; }
.timestamp { color: #888; font-size: 0.9em; }
</style>
</head>
<body>
<div class="card">
<h1>💨 Luftqualität</h1>
<div>CO₂: <span id="co2" class="value">–</span> ppm</div>
<div>VOC: <span id="voc" class="value">–</span> ppb</div>
<div class="timestamp" id="time"></div>
</div>
<script>
async function updateData() {
try {
const response = await fetch("/air_quality");
const data = await response.json();
document.getElementById("co2").textContent = data.co2;
document.getElementById("voc").textContent = data.voc;
const date = new Date(data.timestamp * 1000);
document.getElementById("time").textContent =
"Zuletzt aktualisiert: " + date.toLocaleTimeString();
} catch (err) {
console.error("Fehler beim Abrufen der Daten:", err);
}
}
updateData();
setInterval(updateData, 5000); // alle 5 Sekunden neu laden
</script>
</body>
</html>Jetzt wieder mit

hochladen und starten und dann kann in jedem Browser meines Netzwerkes die Luftqualität abgerufen werden:

Und hiermit sieht man, das die Übergabe vom Controller zum Prozessor funktionieren.
Dritte Testreihe: Arduino als Mini-PC
Wie inzwischen nun verstanden, werkelt unter der Haube jetzt eine brauchbare MPU.
Neben dem gewohnten Mikrocontroller (für die Echtzeit-Projekte) sitzt eine Quad-Core ARM CPU mit integrierter GPU für die grafische Ausgabe, die eine abgesteckte Linux Distribution auf einem eMMC-Flashspeicher bereitstellt. (Geschätzte Lesegeschwindigkeit: Bis zu 250 MB/s)
Damit kannst du nicht nur Python skripten, sondern auch KI-Modelle ausführen, Bildverarbeitung machen oder Webserver hosten. Und das alles direkt auf dem Board, ohne externe Rechner oder Cloud-Gedöns.
Auch hier ist die Entwicklungsumgebung App Lab Lokal zu finden und kann nach dem Booten, direkt gestartet werden.
Um jetzt dieses kleine Board als Mini-PC zu verwenden, wird noch ein USB-C Dongle mit externer Stromversorgung benötigt, damit ich Tastatur, Maus und Monitor per HDMI anschließen kann. Für die Stromversorgung habe ich dieses Netzteil verwendet.

Erster Start beginnt mit Eingabeaufforderung für User „arduino“ mit Erzeugen eines neuen Passwortes.

Danach Tastatur Sprache abgefragt und mit dem lokalen kabellose Netzwerk WiFi verbunden.
Und schon kann die grafische Oberflache von Debian Linux verwendetet werden.

Die Debian Linux Umgebung ist wie ein kleiner Singleboard Computer der als eigenständige Lösung betrieben werden kann.
Während dieser Arbeit mit dem Single Board Computer, konnte ich gleichzeitig vom PC mich remote über die App Lab mit dem Board verbinden und habe Testweise den Sketch Blink erfolgreich ausgeführt.

Per SSH aus dem Windows Terminal / Eingabeaufforderung
mit User/Board-name (ssh arduino@prilchensq.local) oder mit IP-Adresse geht auch:

Informationsquelle:
UNO Q Benutzerhandbuch | Arduino Dokumentation
Youtube – Video:
