Freitag, 24. Juli 2026

USB2SerialMux - Weniger Kabelsalat beim Debuggen von Embedded-Systemen

USB2SerialMux - Weniger Kabelsalat beim Debuggen von Embedded-Systemen

USB2SerialMux ist ein kleines Hardware-/Firmware-Projekt, um mehrere USART-faehige Geraete ueber einen einzigen USB-Anschluss erreichbar zu machen.

USB2SerialMux PCB Top-Seite

Der konkrete Anlass war ein alter Embedded-Cluster. Darin liefen mehrere Orange Pis, und beim Booten wollte ich nicht nur einen einzelnen Knoten sehen, sondern zwischen den seriellen Konsolen der Boards umschalten koennen. Vorher bedeutete das: ein USB-Hub, mehrere USB-zu-Serial-Adapter, viele Kabel und am Ende trotzdem die Frage, welcher Adapter gerade zu welchem Board gehoert. Danach hing ein USB-Pigtail an meiner Platine und die Zielgeraete wurden per Multiplexer ausgewaehlt.

Das Projekt ist kein grosses Framework und auch kein universeller Console-Server. Es ist eine pragmatische Loesung gegen serielles Kabelchaos.

Was das Problem war

Bei Embedded-Boards ist die serielle Konsole oft der ehrlichste Debug-Ausgang. Gerade beim Booten sieht man dort Dinge, die spaeter ueber SSH oder Netzwerk nicht mehr sichtbar sind:

  • Bootloader-Ausgaben
  • Kernel-Start
  • fruehe Fehler vor dem Netzwerkstart
  • Login-Konsole
  • sporadische Ausgaben im Betrieb

Mit einem einzelnen Board ist das einfach: USB-Serial-Adapter anschliessen, screen, minicom oder picocom starten und mitlesen. Bei sieben oder acht Boards wird daraus aber schnell ein unuebersichtlicher Aufbau. Jeder Adapter erzeugt ein eigenes Device, die Reihenfolge kann sich aendern, der USB-Hub liegt irgendwo zwischen den Boards, und beim Mitschneiden muss man immer wissen, welcher Port gerade welches Geraet ist.

USB2SerialMux loest nicht alle Probleme gleichzeitig. Es reduziert das Setup bewusst auf eine klare 1-zu-1-Verbindung: ein USB-Anschluss am Rechner, ein gerade ausgewaehlter USART-Kanal auf der Zielseite.

Wie die Loesung aufgebaut ist

Die Platine basiert auf einem ATmega32U4 mit LUFA-Firmware. Am Rechner meldet sich das Geraet als USB-CDC-Device mit zwei virtuellen seriellen Interfaces:

  • ein Control-Interface fuer Kommandos wie Kanalwahl, Baudrate abfragen oder Baudrate setzen
  • ein Daten-Interface fuer den eigentlichen USART-Datenstrom

Auf der Hardwareseite schalten zwei 74HCT4051-Multiplexer die USART-Leitungen auf einen von acht Kanaelen. Die Firmware steuert die drei MUX-Select-Leitungen und leitet die Daten zwischen USB-CDC und UART weiter.

Das ist der wichtige Punkt: Es ist kein USB-Hub mit mehreren USB-Serial-Adaptern. Es ist auch kein paralleler Mehrkanal-Logger. Der Host sieht ein USB-Geraet, und die Platine verbindet dieses logisch mit genau einem ausgewaehlten USART-Ziel.

Bedienung

Nach dem Einstecken wird das Board als serielles USB-Geraet erkannt. Die Steuerung passiert ueber das Python-Tool im Projekt:

python tools/muxctrl.py -d /dev/ttyACM0 -l 3 -m

Damit wird zum Beispiel MUX-Kanal 3 ausgewaehlt und der aktuelle Kanal wieder abgefragt. Die Firmware unterstuetzt Kanaele von 0 bis 7.

Die Baudrate kann ebenfalls ueber das Tool gesetzt werden:

python tools/muxctrl.py -d /dev/ttyACM0 -s 115200 -b

Im Projekt liegt ausserdem ein kleines Shell-Skript, das den urspruenglichen Cluster-Anwendungsfall zeigt: tools/logClusterBootup.sh setzt Default-Werte, startet ein Logging-Skript und schaltet dann nacheinander durch die Kanaele 0 bis 7.

Warum das fuer den Cluster praktisch war

Vorher sah das Setup ungefaehr so aus:

  • mehrere Orange Pis
  • je Board ein USB-Serial-Adapter
  • ein USB-Hub
  • viele kurze Adapter- und Dupont-Kabel
  • manuelle Zuordnung von /dev/ttyUSB* oder /dev/ttyACM*

Nachher war der Aufbau deutlich ruhiger:

  • ein USB-Kabel zum Rechner
  • eine kleine Platine am Cluster
  • bis zu acht USART-Anschluesse auf der Zielseite
  • Umschalten per Kommandozeile

Fuer meinen Zweck war das genau die richtige Vereinfachung. Beim Booten konnte ich Kanal fuer Kanal mitloggen oder gezielt auf den gerade interessanten Knoten schalten. Im laufenden Betrieb war die serielle Konsole weiterhin erreichbar, ohne jedes Mal Kabel oder Adapter umzustecken.

Warum ueberhaupt eine eigene Platine?

Damals haette ich das Problem natuerlich auch mit mehreren USB-zu-Serial-Adaptern loesen koennen. Technisch waere das vollkommen ausreichend gewesen.

Mich reizte jedoch die Idee, dafuer eine eigene Hardware zu entwickeln. Zum einen entstand dadurch ein wesentlich aufgeraeumterer Aufbau. Zum anderen bot das Projekt die Moeglichkeit, Mikrocontroller-Firmware, USB-Kommunikation, Leiterplattenentwicklung und Embedded-Hardware in einem kleinen, ueberschaubaren Projekt miteinander zu verbinden.

Rueckblickend war genau das vermutlich der eigentliche Grund, warum dieses Projekt entstanden ist.

Hardware

Aus den Projektdateien ist dieser Aufbau ableitbar:

  • Mikrocontroller: ATmega32U4-A
  • USB-Anschluss: USB Mini-B
  • Multiplexer: 2 x 74HCT4051
  • Firmware-Basis: LUFA CDC
  • Takt: 16 MHz laut Firmware-Makefile
  • Ziel: acht umschaltbare USART-Kanaele

Die Platine ist als Shared Project bei OSH Park verfuegbar: USB2SerialMux bei OSH Park.

Das groesste praktische Problem war nicht die Firmware, sondern die Platine: moeglichst klein bleiben und trotzdem so viele USART-Anschluesse wie moeglich sauber herausfuehren. Genau an der Stelle wird so ein Projekt mechanisch und layoutseitig interessant. Die reine Idee ist simpel, aber auf engem Raum mit USB, Mikrocontroller, Multiplexern und Anschluessen wird es schnell ein echtes PCB-Projekt.

Firmware

Die Firmware ist ein angepasstes LUFA-CDC-Beispiel. Im Quellcode ist der Stand mit 08/2016 und Version v0.1 kommentiert; auf der Platine steht USB2SerialMux v0.2.

Sie stellt auf der USB-Seite zwei CDC-Interfaces bereit: eines fuer die Steuerung und eines fuer den eigentlichen seriellen Datenstrom. Die Firmware nimmt die Kommandos des Python-Tools entgegen, schaltet darueber den aktiven MUX-Kanal und reicht die UART-Daten zwischen Host und ausgewaehltem Zielgeraet weiter. Die Baudrate wird dabei im EEPROM gespeichert, und fuer Firmware-Updates kann das Board per Kommando in den Bootloader springen.

Das Makefile ist fuer atmega32u4 ausgelegt und nutzt dfu-programmer zum Flashen. Vor dem Programmieren kann das Board ueber muxctrl.py in den Bootloader geschickt werden.

Was es nicht kann

USB2SerialMux ist bewusst kein Mehrkanal-Logger. Es kann nicht zwei oder mehr USART-Geraete gleichzeitig mitschneiden. Es gibt immer genau eine aktive Verbindung zwischen USB-Seite und einem Zielkanal.

Das ist keine versteckte Einschraenkung, sondern die eigentliche Designentscheidung. Fuer paralleles Logging aller Boards waere ein anderes Design noetig: mehrere UARTs, groesserer Controller, anderes Buffering, anderes Host-Protokoll. Fuer meinen Anwendungsfall war das nicht der Punkt. Ich wollte das serielle Chaos am Cluster reduzieren und bei Bedarf sauber umschalten koennen.

Repository

USB2SerialMux auf Okoyono-Gitea

Fazit

USB2SerialMux ist ein typisches Werkstattprojekt: ein konkretes Problem, eine kleine Platine, etwas Firmware und am Ende weniger Kabelsalat. Es ersetzt keinen Console-Server und keinen Log-Aggregator, aber es macht einen bestimmten Embedded-Alltag deutlich angenehmer: viele USART-Geraete, ein USB-Anschluss, Umschalten per Kommandozeile.

Fuer mich war das der Punkt, an dem aus sieben oder acht USB-Serial-Adaptern an einem Hub eine kleine eigene Platine wurde.

Keine Kommentare:

Kommentar veröffentlichen

USB2SerialMux - Weniger Kabelsalat beim Debuggen von Embedded-Systemen

USB2SerialMux - Weniger Kabelsalat beim Debuggen von Embedded-Systemen USB2SerialMux ist ein kleines Hardware-/Firmware-Projekt, um mehrer...