Hast du dir schon einmal gewünscht, deinen Mikrocontroller bequem vom Sofa aus zu flashen? Ich hatte dasselbe Problem. Begleite mich auf meiner Reise, wie ich drahtloses Embedded Programming über das Netzwerk mithilfe eines Raspberry Pi und VirtualHere möglich gemacht habe.

Als Maker arbeite ich gerne mit Mikrocontrollern, doch eine Tatsache ist: Man braucht immer ein physisches USB-Kabel. Es verbindet deinen leistungsstarken Computer direkt mit der Hardware und ermöglicht das Flashen neuer Firmware oder das Debuggen nerviger Sensorprobleme.

Doch genau dieses Kabel schränkt meine Flexibilität enorm ein. Ich bevorzuge es, von unterschiedlichen Orten aus zu arbeiten – manchmal am Schreibtisch, manchmal gemütlich im Bett mit dem MacBook oder sogar draußen im Garten. Stell dir vor, du willst gerade neue Firmware flashen oder einen Sensor debuggen, aber dein Board steckt in der Werkstatt fest. Vielleicht bist du auch wie ich viel unterwegs mit einem mobilen Laptop und unterbrichst ständig deinen Workflow, weil du das Board ein- und ausstecken musst. Es fühlte sich an, als wäre ich an der Leine – ganz wie bei meinem SSD-Mount-Problem… lol.

Dieses Unannehmlichkeit beschäftigte mich: Wie komme ich davon los? Ich wollte unabhängig von meinem Standort arbeiten, unabhängig davon, wo sich die Hardware befand. Natürlich – wenn ich physisch Knöpfe drücke oder Kabel umstecke, muss ich neben dem Board sein. Aber bei vielen meiner Tätigkeiten – Sensordaten abfragen, Algorithmen optimieren, Low-Level-Treiber abstimmen – kann das Board theoretisch überall stehen. Also machte ich mich auf die Suche nach einer Lösung, um “Embedded Programmierung über das Netzwerk” für mein Setup Realität werden zu lassen.

In diesem Tutorial teile ich meine persönliche Reise samt Umwege und Sackgassen, damit du aus meinen Fehlern lernen und dein eigenes flexibles Remote-Labor aufbauen kannst.

Meine erste Idee: Die Hoffnung mit USB/IP

Mein erster Gedanke war – als Open-Source-Enthusiast – komplett auf freie Tools zu setzen. Ich las über usbip, ein spannendes Projekt, das direkt im Linux-Kernel integriert ist und USB-Geräte über das Netzwerk freigeben kann. „Perfekt!“, dachte ich. „Ich nehme einen Raspberry Pi als Server, mein MacBook als Client. Fertig.“

Was ist USB über IP überhaupt?

Ganz einfach gesagt: Es ist wie ein virtuelles USB-Verlängerungskabel. Du steckst dein USB-Gerät in einen Computer (den “Server”), und es erscheint so, als wäre es direkt mit einem anderen Computer (dem “Client”) verbunden – über WLAN oder Ethernet.

Vorbereitung des Raspberry Pi

Ich nahm also meinen Raspberry Pi und spielte mit dem Raspberry Pi Imager eine frische Version von Raspberry Pi OS Lite (64-bit) auf die SD-Karte. Super praktisch: Netzwerk, Hostname und SSH-Zugriff lassen sich direkt im Imager einrichten – perfekt für Headless-Setups.

Sobald der Pi einsatzbereit war, suchte ich die IP-Adresse im lokalen Netzwerk und verband mich via SSH. Dann installierte ich den usbip-Server mit:

sudo apt-get install usbip

Danach ging es weiter mit:

# Let's see what's connected locally first
usbip list --local

# Need to enable those kernel modules for usbip
sudo modprobe usbip_core
sudo modprobe usbip_host 

# Now, bind my dev board (make sure your busid matches your device!)
sudo usbip bind --busid 1-1.3 # (My specific device ID at the time)

# And finally, kick off the daemon
sudo usbipd -D

Der Server lief! Doch beim Client – meinem MacBook – kam die Ernüchterung.

macOS Client-Problem: Warum ich auf VirtualHere umstieg

Ich benutze ein MacBook mit macOS und genau hier scheiterte der usbip-Plan. Nach kurzer Suche konnte ich einfach kein direktes, einfach zu installierendes usbip-Clientpaket oder keine Open-Source-Bibliothek finden, die zuverlässig unter macOS funktionierte. Ich las unzählige Forendiskussionen – viele Leute berichteten von Problemen oder teilten einfach ihren Frust. Es schien, als würde usbip auf der Clientseite Linux oder Windows bevorzugen.

Als pragmatischer Maker beschloss ich, nach Alternativen zu suchen. Ich stieß auf VirtualHere, ein kommerzielles Produkt, das auch „USB over IP“ unterstützt. Es gibt eine Testversion, und ich dachte mir: Warum nicht mal ausprobieren?

Mein erster Versuch war, den VirtualHere-Client auf meinem Mac zu verwenden, um eine Verbindung zu meinem bestehenden usbip-Server auf dem Raspberry Pi herzustellen. Ich verwendete die IP-Adresse und Port 3240 des Pi, und der Client zeigte tatsächlich das Remote-Gerät an! Sieht vielversprechend aus, dachte ich. Doch dann, nach nur wenigen Sekunden, verschwand es. Die automatische Erkennung erkannte es zwar wieder, verschwand aber nach etwa 10 Sekunden wieder. Das kam mir seltsam vor.

Ich grübelte. Mein erster Gedanke war, vielleicht ist das ein „Feature“ der Testversion oder ein Fehler. Später änderte sich meine Meinung jedoch: Was, wenn es nicht an der Client-App lag? Vielleicht lag es an meinem Server-Setup (meinem „usbip“ auf dem Pi), oder vielleicht waren die beiden einfach nicht für ein gutes Zusammenspiel ausgelegt und verwenden leicht unterschiedliche Ports für Kommunikation/Synchronisierung. Also entschied ich mich, sowohl für den Server als auch für den Client voll auf VirtualHere zu setzen. Und siehe da: Es hat funktioniert!

So habe ich den VirtualHere-Server auf meinem Raspberry Pi zum Laufen gebracht:

wget https://www.virtualhere.com/sites/default/files/usbserver/vhusbdarm 
# Stell sicher, dass du die richtige ARM-Version für dein Pi-Betriebssystem erhalten (32-Bit vs. 64-Bit!)

# Die vollständige Liste der Versionen findest du hier:
# https://www.virtualhere.com/usb_server_software

sudo chmod +x vhusbdarm
sudo ./vhusbdarm

Mit diesem letzten Befehl wurde der Server gestartet, und zum ersten Mal war eine stabile Verbindung vorhanden! Um sicherzustellen, dass sie auch nach einem Neustart bestehen blieb, musste ich sie mit „systemd“ als persistenten Dienst einrichten. Das ist wichtig für ein Remote-Labor, das man nach dem Motto „einrichten und vergessen“ nutzen kann.

Die Entwickler von VirutalHere bieten auch ein Installationsskript an, das die Installation und die Einrichtung von systemd vereinfachen soll, bei mir hat es aber nicht funktioniert. Probiere es gerne aus: https://github.com/virtualhere/script

curl https://raw.githubusercontent.com/virtualhere/script/main/install_server | sudo sh

Autostart mit systemd

Um sicherzustellen, dass VirtualHere bei jedem Booten meines Raspberry Pi gestartet wird, habe ich einen „systemd“-Dienst erstellt. Das klingt vielleicht etwas einschüchternd, wenn du noch wenig Erfahrung mit Linux-Diensten hast, aber glaube mir, es geht nur darum, ein paar Textzeilen in eine Datei zu kopieren und einzufügen.

1. Dienstdatei erstellen:

sudo nano /etc/systemd/system/virtualhere.service

2. Den Inhalt einfügen: (Passe „ExecStart“ und „WorkingDirectory“ an, wenn sich deine „vhusbdarm“-Datei an einer anderen Stelle befindet oder anders heißt!)

[Unit]
Description=VirtualHere USB Server
After=network-online.target

[Service]
ExecStart=/home/pi/vhusbdarm -b # My path, check yours!
WorkingDirectory=/home/pi/ # My working directory
User=pi
Group=pi
Restart=always
RestartSec=5s

[Install]
WantedBy=multi-user.target

Eine kurze Erläuterung zur Bedeutung:

  • Description: Nur eine benutzerfreundliche Bezeichnung für meinen Dienst.
  • After=network-online.target: Dies weist den Pi an: „Warte, bis das Netzwerk vollständig betriebsbereit ist, bevor du versuchst, VirtualHere zu starten.“
  • ExecStart: Dies ist der Befehl zum Starten des VirtualHere-Servers. -b bedeutet, dass er im Hintergrund läuft.
  • WorkingDirectory: Hier befindet sich die ausführbare Datei des Servers.
  • User=pi und Group=pi: Ich weise ihn an, unter dem Standardbenutzer pi zu laufen, was für diese Art von Setup normalerweise in Ordnung ist.
  • Restart=always: Sollte VirtualHere aus irgendeinem Grund abstürzen (was zum Glück selten vorkommt), versucht systemd nach 5 Sekunden automatisch, es neu zu starten. Super praktisch!

3. Speichern und beenden: Drücke Strg+O, dann Eingabetaste und anschließend Strg+X. 4. Dienst aktivieren: Nun folgen die letzten Befehle, um „systemd“ über unseren neuen Dienst zu informieren und ihn zu starten:

sudo systemctl daemon-reload # Weist systemd an, unsere neue Datei zu lesen.
sudo systemctl enable virtualhere.service # Lässt es beim Booten starten.
sudo systemctl start virtualhere.service # Startet es jetzt.

5. Überprüfe, ob es ausgeführt wird: Du kannst jederzeit überprüfen, ob es aktiv ist:

systemctl status virtualhere.service

Du solltest „aktiv (läuft)“ sehen. Um sicherzugehen, dass Verbindungen abgehört werden, kannst du Port 7575 (den Standardport von VirtualHere) überprüfen:

netstat -tuln | grep 7575

Suche nach einem Eintrag wie tcp 0 0 0.0.0.0:7575 0.0.0.0:* LISTEN. Das bedeutet, es ist einsatzbereit!

Hardware-Check: Was ich verwendet habe

Für dieses Setup habe ich mich an Standardgeräte gehalten:

1. Raspberry Pi 4 (2 GB RAM):
Diesen habe ich verwendet, und er ist dafür hervorragend geeignet. Er liefert ausreichend Leistung, und die USB-3.0-Anschlüsse sorgen für stabile Verbindungen. Ein Pi 3B+ würde wahrscheinlich auch gut funktionieren, insbesondere für weniger anspruchsvolle Boards. Vom originalen Pi Zero W würde ich aufgrund seiner begrenzten Leistung und des einzelnen Micro-USB-Anschlusses abraten, aber ein Zero 2 W könnte für ein superkleines Setup interessant sein, wenn du abenteuerlustig bist (denke nur an den USB-Adapter).
2. Pi Essentials:
Ein zuverlässiges 5-V-USB-C-Netzteil (ich habe ein 3-A-Netzteil für meinen Pi 4 verwendet) ist für die Stabilität unerlässlich. Eine ordentliche 16-GB-microSD-Karte reichte für Raspberry Pi OS Lite und VirtualHere völlig aus. Ich habe meinen Pi außerdem in ein kleines Gehäuse gepackt.
3. Mein Entwicklungsboard:
Das Coole daran ist: Diese Lösung funktioniert mit praktisch jedem Entwicklungsboard, das über USB angeschlossen wird! Ich habe es ausgiebig mit meinem Nucleo-F411RE-Board und STM32CubeIDE getestet, aber ich habe auch festgestellt, dass es mit ESP32, ESP8266 und sogar Arduino-Boards einwandfrei funktioniert. Solange dein Board als Standard-USB-Gerät (z. B. ein serieller Port, ein Debugger oder ein DFU-Gerät) angezeigt wird, ist alles in Ordnung.
4. Netzwerk:
Ich habe für meinen Raspberry Pi hauptsächlich Ethernet verwendet, da es die stabilste und latenzarme Verbindung bietet, was sich hervorragend zum Debuggen eignet. WLAN funktioniert auch, allerdings kann die Verbindungsqualität etwas schwanken, insbesondere wenn dein WLAN-Signal nicht besonders stark ist.

Clientseitige Verbindung herstellen

1. VirtualHere USB-Client für macOS:

Ich besuchte direkt die offizielle VirtualHere-Website (virtualhere.com) und lud den macOS-Client herunter. Die Datei ist in der Regel eine DMG-Datei – die Installation ist kinderleicht: Ziehe einfach die App in den Anwendungsordner.

Screenshot der Download-Webseite des VirtualHere-Clients

2. Starten und Verbinden:

Nach der Installation startete ich den VirtualHere-Client. Der große Moment kam, als mein Raspberry Pi, auf dem der VirtualHere-Server lief, automatisch erkannt wurde. Er erschien einfach. Sollte dies bei deinem Raspberry Pi aus irgendeinem Grund nicht der Fall sein (vielleicht hast du ein komplexes Netzwerk oder eine Firewall), kannst du jederzeit mit der rechten Maustaste in das Client-Fenster klicken und „USB-Server angeben…“ → „Hinzufügen…“ auswählen und anschließend die IP-Adresse deines Raspberry Pi eingeben.

Sobald der Server angezeigt wurde, habe ich ihn erweitert. Dort war mein Nucleo-Board aufgelistet und wartete nur darauf, verwendet zu werden. Ich habe mit der rechten Maustaste darauf geklickt (es wurde als „STMicroelectronics ST-LINK/V2“ angezeigt) und auf „Dieses Gerät verwenden“ geklickt.

VirtualHere screenshot activation

Ich habe in meinem Terminal unter „/dev/“ die angeschlossenen Geräte überprüft, und auch im Finder war das neue Gerät sichtbar. Es war, als wäre das Board direkt an mein MacBook angeschlossen.

Der Moment der Wahrheit: Remote-Flashen und -Debuggen

Hier kommt die Flexibilität voll zum Tragen. Sobald die VirtualHere-Verbindung aktiv ist, sehen deine Entwicklungstools das Remote-Board wie ein lokales USB-Gerät. In der IDE sind größtenteils keine speziellen Konfigurationen erforderlich.

1. Schließe dein Entwicklungsboard an den Raspberry Pi an:
Stelle zunächst sicher, dass dein Nucleo-F411RE (oder ein anderes Board) an einen der USB-Ports des Raspberry Pi angeschlossen ist. Überprüfe, ob der VirtualHere-Client auf deinem MacBook läuft und das Gerät aktiv nutzt.

2. Öffnen deinen Code Editor oder IDE:
Ich habe STM32CubeIDE auf meinem MacBook gestartet und mein aktuelles Projekt für den Nucleo, das Drohnen-Telemetriesystem, geöffnet.

3. Firmware flashen:
Ich habe die Build-Einstellungen meines Projekts aufgerufen (normalerweise die Konfigurationen „Ausführen“ oder „Debuggen“). Die IDE erkannte den virtuellen ST-LINK/V2-Programmierer problemlos über die VirtualHere-Verbindung. Es war, als wäre ich lokal verbunden. Ich drückte die Schaltfläche „Ausführen“ (Flash) und beobachtete, wie meine Firmware kompiliert und über das Netzwerk auf das Nucleo-Board hochgeladen wurde.
Der Fortschrittsbalken lief schnell, und wenige Augenblicke später wurde mein Board mit der neuen Firmware zurückgesetzt. Erfolg!

4. Remote-Debugging:
Hier liegt für mich die wahre Stärke. Ich startete die Debugging-Sitzung und überprüfte die Live-Expressions-Variable, die vom Sensor über den ST-LINK/V2 kam – alles von meinem MacBook aus.

Screenshot von STMCubeIDE

Diese Lösung ist übrigens nicht nur für STM32 geeignet. Wenn du beispielsweise ein ESP32-Board mit PlatformIO in VS Code verwenden, erkennt esptool.py (das Flash-Tool von PlatformIO) automatisch den virtuellen seriellen Port. Du kannst die Firmware flashen und die serielle Ausgabe genau so überwachen, als wäre der ESP32 lokal angeschlossen. Gleiches gilt für die Arduino IDE; sie listet den Remote-COM-Port auf, als wäre er direkt vorhanden.

Fehlerbehebung und meine Best Practices

Selbst mit einer scheinbar magischen Lösung wie VirtualHere kann es gelegentlich zu Problemen kommen. Ich bin selbst schon auf einige Probleme gestoßen und habe Folgendes über die Fehlerbehebung und einen reibungslosen Betrieb gelernt:

Das Verschwinden:

  • Was passiert: Manchmal, insbesondere wenn dien Entwicklungsboard während eines Flash-Vorgangs zurückgesetzt wird (wodurch die USB-Verbindung kurzzeitig getrennt wird) oder wenn dein Netzwerk nicht besonders stabil ist, kann das Gerät kurzzeitig von deinem Client verschwinden.

  • Meine Lösung: Der VirtualHere-Client verbindet sich recht gut automatisch wieder. Falls nicht, genügt ein einfacher Rechtsklick auf das Gerät im VirtualHere-Client und die Auswahl von „Dieses Gerät verwenden“, um es wiederherzustellen. Deshalb lege ich Wert auf ein starkes WLAN-Signal oder idealerweise eine Ethernet-Verbindung für den Raspberry Pi – das trägt entscheidend zur Stabilität bei.

„Client kann Server nicht sehen“:

  • Was passiert: Dein MacBook-Client zeigt den Raspberry Pi-Server einfach nicht an.

  • Meine Lösung:

  • Ist der Pi überhaupt eingeschaltet?

  • Melde dich per SSH beim Pi an und prüfe, ob der VirtualHere-Server läuft: systemctl status virtualhere.service. Falls nicht, versuche sudo systemctl start virtualhere.service.

  • Befindet sich das MacBook im selben Netzwerk? Ist die IP-Adresse des Pi korrekt, wenn du ihn manuell hinzufügen?

  • Überprüfe deine Firewall! In seltenen Fällen blockiert der Router oder sogar die Firewall des Pi (falls du eine eingerichtet haben) Port 7575 (den Standardport von VirtualHere).

„Gerät wird verwendet“-Fehler:

  • Was passiert: Gelegentlich, nach einer unvorhergesehenen Verbindungsunterbrechung oder einem unerwarteten Absturz, kann der VirtualHere-Server dein Gerät weiterhin als „in Verwendung“ betrachten, obwohl dies nicht der Fall ist.

  • Meine Lösung: Ich starte einfach den VirtualHere-Dienst auf dem Raspberry Pi neu: sudo systemctl restart virtualhere.service. Das behebt das Problem normalerweise sofort.

Leistungserwartungen:

Dieses Setup eignet sich zwar hervorragend für die meisten eingebetteten Programmieraufgaben, aber bei USB-Geräten mit extrem hoher Bandbreite (wie hochauflösenden Webcams, die du dafür wahrscheinlich nicht verwenden würden!) oder bei Szenarien, die eine absolute Zeitmessung im Nanosekundenbereich erfordern, kann es im Vergleich zu einer direkten USB-Verbindung zu einer sehr geringen Latenz kommen. Für das Flashen von Firmware und typisches Debugging war es für mich ehrlich gesagt völlig akzeptabel.

Meine Best Practice: Im Ernst, wenn möglich, schließe deinen Raspberry Pi mit einem Ethernet-Kabel an deinen Router oder Switch an. Es ist einfach von Natur aus stabiler und hat eine geringere Latenz als WLAN, insbesondere wenn das WLAN-Netzwerk überlastet ist.

Sicherheit (Ein kurzer Gedanke):

Denk daran, dass jeder andere in diesem Netzwerk potenziell auf USB-Geräte zugreifen kann, wenn diese über dein Netzwerk zugänglich sind. Für mein Heimlabor mache ich mir keine allzu großen Sorgen.

Meine Best Practice: Richte dies nur in einem vertrauenswürdigen lokalen Netzwerk ein. Ich würde meinen Raspberry Pi (oder den VirtualHere-Server) ohne umfassende Netzwerksicherheit (wie z. B. ein robustes VPN) nicht direkt dem Internet aussetzen.

VirtualHere-Testversion:

Nur ein Hinweis: Die kostenlose Testversion von VirtualHere beschränkt die Nutzung auf jeweils ein USB-Gerät. Für meine Hobbyprojekte ist das kein Problem. Wenn du später mehrere Entwicklungsboards gleichzeitig anschließen möchten (z. B. für einen großen Testaufbau), benötigst du eine Vollversion. Diese wird in der Regel einmalig pro Server erworben, was aber nicht weiter schlimm ist, wenn du sie für wertvoll erachten.

Mehr als nur die Grundlagen: Wie geht es weiter?

Sobald dein Setup reibungslos läuft, träumst du vielleicht von größeren Dingen, genau wie ich:

  • Mehrere Boards: Mit einer VirtualHere-Volllizenz kannst du einen USB-Hub an deinem Raspberry Pi anschließen und eine unbegrenzte Anzahl an Entwicklungsboards verbinden. Stellst du dir eine „Remote-Gerätefarm“ vor, in der du vom Schreibtisch aus zwischen den Boards wechseln können.

  • Automatisierung: Für ganz Abenteuerlustige könntest du sogar das Verbinden und Trennen von Geräten mit dem VirtualHere-Befehlszeilen-Client skripten und so deinen Workflow weiter automatisieren.

  • Kommerzielle Lösungen: Dieser DIY-Ansatz ist zwar großartig, aber es gibt auch industrietaugliche Lösungen wie Digi AnywhereUSB. Diese sind für die Verwaltung von Hunderten von USB-Geräten in Unternehmen oder der Industrie konzipiert und bieten hohe Zuverlässigkeit und zentrale Verwaltung, sind aber deutlich teurer. Es gibt zwar auch High-End-Debug-Sonden mit integriertem Ethernet/WLAN, diese sind aber in der Regel auf bestimmte Mikrocontroller-Architekturen zugeschnitten.

Für mich war die Kombination aus Raspberry Pi und VirtualHere bahnbrechend. Sie ist erschwinglich, relativ einfach einzurichten und bietet genau das, was ich brauchte: echte Flexibilität in meinem Embedded-Programmier-Workflow. Ich kann mich jetzt von dem lästigen USB-Kabel verabschieden und mich der kabellosen Entwicklung widmen.

Probiere dieses Setup selbst aus und teile in den Kommentaren deine Erfahrungen, wie es läuft. Wenn dir dieses Tutorial geholfen hat, sich zu befreien, abonniere gerne meinen Newsletter oder Podcast für weitere praktische Maker-Anleitungen und Abenteuer rund um Embedded Systems!