IT security, FreeBSD, Linux, mail server hardening, post-quantum crypto, DNS, retro computing & hands-on hardware hacks. Privater Tech-Blog seit 2003.

Schlagwort: Embedded (Seite 1 von 2)

Billiger VGA-USB-Capture-Stick seziert: MS2109-Firmware, EDID-Hack und die 1080p-Lüge

Eigentlich wollte ich nur etwas ganz Simples: Aufnahmen von meinem alten DOS-Rechner machen. BIOS-POST, der Speichertest, ein paar DOS-Spiele, einmal das alles sauber als Video festgehalten. Dafür landete ein „VGA to USB 3.0 HD 1080P Video Capture Card“ in meinem Warenkorb, so ein billiger Dongle für ein paar Euro. Spoiler: in genau der Form hat das nicht geklappt. Und warum es nicht klappt, ist die eigentlich spannende Geschichte. Es geht um einen 8051 mit recyceltem Mask-ROM, eine EDID die der Quelle einen Monitor vorlügt, ein „1080p“ das horizontal gar keins ist, und eine Strings-Modifikation die ich bis heute nicht überlistet habe.

Das konkrete Gerät, falls es jemand nachvollziehen will, gibt es bei Amazon unter diesem Link. Es ist einer von hunderten optisch identischen Sticks, die alle den gleichen MacroSilicon-Chipsatz tragen. Die Erkenntnisse hier gelten also für eine ganze Geräteklasse, nicht nur dieses eine Exemplar.

Platine des VGA-USB-Capture-Sticks mit VGA-Stecker, USB-A-Buchse, Audio-Header und Silkscreen AFN_VGA_Captor
Die Platine des Sticks: VGA-Stecker, USB-A, 3-poliger Audio-Header und der Silkscreen AFN_VGA_Captor 2020/0615_V1.1.

Was steckt auf der Platine?

Aufgeschraubt zeigt sich eine winzige Platine mit Silkscreen-Aufdruck AFN_VGA_Captor 2020/0615_V1.1, einem VGA-Stecker, einer USB-A-Buchse und einem 3-poligen Audio-Header. Drei Halbleiter machen die eigentliche Arbeit:

RefChipFunktion
U3MacroSilicon MS21098051-basierte UVC-Bridge, USB 2.0 High-Speed
U7MacroSilicon MS9288AAnaloger VGA-Empfänger (PLL plus ADC plus Scaler)
U2HK / Holtek 24C16I²C-EEPROM, 2 KiB

Der MS2109 ist berühmt-berüchtigt. Er steckt in den meisten der spottbilligen HDMI-Capture-Sticks, die seit Jahren durchs Netz geistern. Hier sitzt derselbe Chip in einer VGA-Variante, mit dem MS9288A als analogem Frontend davor. Wie eng die beiden Welten verwandt sind, wird sich beim Mask-ROM-Dump zeigen: die Firmware ist nachweislich aus der HDMI-Variante recycelt.

Mikroskop-Makro des MacroSilicon MS2109, der 8051-basierten UVC-Bridge des Capture-Sticks
U3, der MacroSilicon MS2109. Der gleiche 8051-Chip wie in den billigen HDMI-Capture-Sticks, hier in der VGA-Variante.
Mikroskop-Makro des MacroSilicon MS9288A, des analogen VGA-Empfängers mit PLL und ADC
U7, der MacroSilicon MS9288A. Analoges Frontend mit PLL, ADC und Scaler, lockt das VGA-Signal und digitalisiert es.
Mikroskop-Makro des HK 24C16 I2C-EEPROM mit 2 KiB Kapazität auf der Capture-Platine
U2, der HK 24C16. 2 KiB I2C-EEPROM, hier liegen EDID, Vendor-Strings und die beiden 8051-Patch-Blöcke.

Wie meldet sich das Ding am USB?

Beim Anstecken kommt der erste Hinweis darauf, dass die Verpackung schwindelt. „USB 3.0″ steht drauf, der Kernel sieht aber ein High-Speed-Gerät, also USB 2.0:

usb 1-1.1: new high-speed USB device number 15 using xhci_hcd
usb 1-1.1: New USB device found, idVendor=534d, idProduct=2109, bcdDevice=21.00
usb 1-1.1: Manufacturer: MACROSILICON
usb 1-1.1: Found UVC 1.00 device <unnamed> (534d:2109)
hid-generic 0003:534D:2109.0009: hiddev4,hidraw8: USB HID v1.10 Device

Vendor 0x534d ist MacroSilicon, Produkt 0x2109 der nackte MS2109. Das Gerät enumeriert als UVC-1.00-Kamera plus USB-Audio plus ein vendor-spezifisches HID-Interface. Genau dieses HID-Interface ist später der Schlüssel: darüber kommt man an das EEPROM und sogar an den Arbeitsspeicher des 8051 heran, ganz ohne Lötkolben am I²C-Bus.

Das Werkzeug: ms-tools

Die zentrale Referenz für alles, was mit MS2109 zu tun hat, ist das Projekt ms-tools von Bertold Van den Bergh. Das ist eine kleine Goldgrube: EEPROM lesen und schreiben über die HID-Schnittstelle, Live-Zugriff auf den XDATA-Speicher zur Laufzeit (per eingeschleustem 8051-Patch-Code), das Werkzeug mshack zum Injizieren eigener 8051-Routinen, Ghidra-Skripte mit teildisassemblierter Firmware und ein dump-rom, das den kompletten 64-KiB-Mask-ROM ausliest.

Auf Ubuntu 24.04 ist das schnell gebaut:

sudo apt install golang-go libhidapi-dev libudev-dev
git clone https://github.com/BertoldVdb/ms-tools.git
cd ms-tools/cli && go build -o ../msctl .

Der EEPROM-Dump und eine erste Korrektur

Manche MS2109-Revisionen mögen das übliche RAM-Patching nicht, das ms-tools für komfortable Zugriffe nutzt. Mit --no-patch liest der Dump trotzdem sauber, weil dann der rohe HID-Pfad ohne vorgeschaltete Firmware-Manipulation genommen wird:

msctl --raw-path /dev/hidraw8 --no-patch read EEPROM 0 2048 --filename=dumps/eeprom-vga-raw.bin

Von den 2048 Bytes sind nur 962 belegt. Die Aufteilung sieht so aus:

OffsetGrößeInhalt
0x000 bis 0x00F16 BHeader: Magic a5 5a, dann Build-Datum 19 11 20 00 = 2019-11-20
0x010 bis 0x02F32 BVendor-Strings im Pascal-Format: AFN_Cap video, AFN_Cap audio
0x030 bis 0x07974 B8051-Patch-Code #1 (ROM-Hook-Routinen)
0x07A bis 0x179256 BVollständige EDID (128 Base plus 128 CTA-861-Extension)
0x17A bis 0x3C1584 B8051-Patch-Code #2, Keil-C51-kompiliert

Die ersten Bytes mit dem Hexeditor angeschaut, da steht die Geschichte schon drin:

0000  a5 5a 03 8e 09 10 ff ff ff ff ff ff 19 11 20 00   .Z............ .
0010  0e 41 46 4e 5f 43 61 70 20 76 69 64 65 6f ff ff   .AFN_Cap video..
0020  0e 41 46 4e 5f 43 61 70 20 61 75 64 69 6f ff ff   .AFN_Cap audio..
0030  90 de 07 ef f0 12 cd d6 90 de 07 e0 ff 02 cf 25   ...............%

Das 0e vor jedem String ist die Pascal-Längenangabe (14 Zeichen). Ab 0x30 beginnt der erste 8051-Patch-Block. Spannend ist die EDID-Sektion ab 0x07A. Mein erster Analyse-Versuch ging davon aus, der klassische EDID-Header 00 FF FF FF FF FF FF 00 sei wegoptimiert und werde erst zur Laufzeit ergänzt. Das war falsch. Nach dem Mask-ROM-Dump und einem genaueren Blick steht der Header sauber im EEPROM. Solche Korrektur-Momente sind mir lieber als ein zu glattes Narrativ, also schreibe ich sie hier auch hin.

Die EDID selbst enthält einen Monitor-Namen MACROSILICON (EDID-Descriptor mit Tag 0xFC), als erstes Detailed-Timing 1280×720 bei 60 Hz mit 74,25 MHz Pixeltakt, ein zweites Timing 1280×768, dazu eine CTA-861-Extension mit nativem VIC=4 (720p60) plus VICs für 1080p60, 1080i, 720p50, 480p und 576p. Es gibt sogar einen HDMI-VSDB-Block mit dem OUI 00:0C:03 von HDMI Licensing und einer Source Physical Address. Eine VGA-only-Platine, die HDMI-Strukturen in ihrer EDID trägt. Das ist schon der erste deutliche Fingerabdruck der gemeinsamen Codebasis.

Der Mask-ROM verrät die Herkunft

Der eigentliche Programmcode des 8051 liegt in einem nicht beschreibbaren Mask-ROM. dump-rom lädt dafür eigenen 8051-Code in den USERRAM, der per MOVC den ROM ausliest und über HID zurückschiebt:

msctl --raw-path /dev/hidraw8 --no-patch dump-rom dumps/maskrom-vga.bin

64 KiB komplette CODE-Memory, davon rund 36 KiB belegt im Bereich 0x0000 bis 0x8FFF und weitere 12 KiB ab 0xC000. Die Highlights:

  • 0x7738: eine zweite, im ROM fest verdrahtete Default-EDID, intakt mit Standard-Header, Hersteller-ID „HJW“ und Monitor-Name „HDMI TO USB“. Das ist der Beweis: diese Firmware wurde ursprünglich für den HDMI-Bruder geschrieben.
  • 0x77A9: der ASCII-String „HDMI TO USB“ noch einmal direkt.
  • 0x7087 und 0x709B: die USB-String-Descriptor-Fallbacks „USB Video“ und „USB Digital Audio“ in UTF-16LE. Diese beiden werden uns gleich noch ärgern.
  • 0x0000: der Reset-Vector 02 41 49, also LJMP 0x4149.
  • Ein LCALL 0xCC10 bei ROM-Adresse 0x478F: das ist der zentrale Einstieg vom Mask-ROM in den EEPROM-Patch-Code, der zur Laufzeit in den RAM kopiert wurde.

Der Bootloader kopiert dabei die EEPROM-Bytes ab Offset 0x30 in den USERRAM ab Adresse 0xCBD0. Die Strings-Sektion 0x10 bis 0x2F wird explizit nicht mitkopiert. Die Patch-Firmware liest die Strings stattdessen zur Laufzeit direkt per I²C aus dem EEPROM und baut daraus die USB-String-Descriptoren an festen RAM-Adressen zusammen. Diese Mapping-Tabelle ist der Kern, um den herum sich die ganze Bastelei dreht:

EEPROMCode-RAMWas
0x0300xCC00Patch #1, kleine Hook-Routinen
0x07A0xCC4AEDID-Header 00 FF FF FF FF FF FF 00
0x0800xCC50EDID-Body
0x0FA0xCCCACTA-861-Extension
0x17A0xCD4APatch #2, C51-Startup
0x1800xCD50MOV SP,#0x3B; LJMP 0xCD91
0x1C10xCD91main() der Patch-Firmware

Erkenntnis 1: Die EDID lügt der Quelle einen Monitor vor

Über die DDC-Leitungen am VGA-Stecker (Pins 12 und 15) präsentiert der Dongle dem Quell-PC eine EDID. Damit gibt sich das Gerät als Monitor namens „MACROSILICON“ mit 720p60 als nativer Auflösung aus. Genau deshalb liefert ein Quell-PC, an dem gar kein echter Monitor hängt, trotzdem ein sinnvolles Bild: er glaubt, ein 720p-Display gefunden zu haben. So weit, so clever.

Erkenntnis 2: Das „1080p“ ist Marketing

Die UVC-Frame-Tabelle im Mask-ROM listet zwar brav 1920×1080 mit 30 fps als MJPEG. Die Realität sieht anders aus. Mit v4l2-ctl lässt sich die Format-Liste auslesen:

$ v4l2-ctl -d /dev/video2 --list-formats-ext
[0]: 'MJPG' (Motion-JPEG, compressed)
  Size: Discrete 1920x1080    30/25/20/10/5 fps
  Size: Discrete 1280x720     60/50/30/20/10 fps
  Size: Discrete 1024x768     60/50/30/20/10 fps
[1]: 'YUYV' (YUYV 4:2:2)
  Size: Discrete 1920x1080    5 fps
  Size: Discrete 640x480      30/20/10/5 fps

Unkomprimiertes YUYV bei 1080p ist auf magere 5 fps gedeckelt. Das native Detailed-Timing der EDID ist 720p60, das 1080p wird intern hochskaliert. Und USB 3.0 ist nirgends, der Chip kann nur High-Speed. Drei Behauptungen auf der Verpackung, drei mal geschummelt. Auf die 5-fps-Grenze komme ich am Ende noch genauer zurück, die hat einen sehr konkreten technischen Grund.

Erkenntnis 3: Kein DOS, und das lässt sich nicht reparieren

Jetzt zum eigentlichen Frustpunkt, der Grund, warum mein DOS-Plan scheiterte. Die UVC-Frame-Tabelle enthält keine 70-Hz-Modi. Ein DOS-BIOS gibt aber im Standard-VGA-Textmodus 720×400 bei 70 Hz aus. Das analoge Frontend, der MS9288A, könnte dieses Signal vermutlich locken, der Horizontaltakt von 31,469 kHz ist derselbe wie bei 640×480 bei 60 Hz. Aber die MS2109-Firmware bietet schlicht keinen passenden UVC-Frame-Mode an, an dem ein Aufnahmeprogramm andocken könnte.

Und das Bittere: im EEPROM kann man das nicht reparieren. Die Frame-Tabelle liegt im nicht-flashbaren Mask-ROM. Das EEPROM steuert nur EDID, Strings und ein paar Patch-Routinen, nicht die Liste der angebotenen Auflösungen. Wer mit so einem Dongle echte DOS-Signale aufnehmen will, kommt um eine vorgeschaltete Scaler-Box nicht herum. Mehr dazu am Ende.

Was wir trotzdem geändert haben: die EDID

Wenn die Frame-Tabelle schon unantastbar ist, dann wenigstens die EDID anfassen. Ich habe das erste Detailed-Timing von 720p60 auf 1920×1080 bei 60 Hz umgeschrieben (148,5 MHz Pixeltakt, das Standard-CEA-861-1080p60-Timing), die EDID-Checksumme neu berechnet und das EEPROM zurückgeflasht. Das neue DTD #1 sieht so aus:

02 3a 80 18 71 38 2d 40 58 2c 45 00 00 00 00 00 00 1e

Nach einem Replug liefert das Gerät die modifizierte EDID. Zumindest dachte ich das. Ob sie auch wirklich bei einer Quelle ankommt, war eine ganz eigene Odyssee, dazu komme ich beim A/B-Test. Vorweggenommen: Die Mod tut technisch genau das, was sie soll, sie ändert nur am Ende nichts an dem, was aufgenommen wird. Eine reine „ich sage der Quelle, ich kann 1080p“-Kosmetik.

Was NICHT geklappt hat: die Strings

Das ist der lehrreichste Teil des Projekts, gerade weil er bis heute offen ist. Ich wollte die USB-Function-Strings ändern, aus dem hässlichen „AFN_Cap video“ sollte ein sauberes „VGA Capture HD“ werden. Das EEPROM-Schreiben verifiziert sauber per Readback-Hash. Die EDID-Mod aus demselben Reflash funktioniert. Aber die Strings fallen nach dem Replug auf die ROM-Defaults „USB Video“ und „USB Digital Audio“ zurück. Irgendetwas in der Firmware sagt „nein“.

Also empirisch rangegangen, drei Single-Byte-Tests in der Strings-Region 0x10 bis 0x2F: einmal ein ASCII-Zeichen geändert, einmal ein FF-Padding-Byte, einmal das Längen-Byte. Jeder einzelne dieser Eingriffe löst den Fallback aus. Egal welches Byte, egal welcher Inhalt. Das ist eine klare Indikation für ein Content-Gate über die gesamte 32-Byte-Region, nicht für eine simple Längen- oder Inhaltsprüfung an einer Stelle.

Ein Gegencheck zur eigenen Analyse hat ein paar Punkte geschärft. Die Bytes 0x02 und 0x03 (03 8E) sind verifiziert die Payload-Länge und keine Checksumme: 910 Bytes ab 0x30 reichen bis 0x3BD, exakt bis vor den End-Marker. Der Verdacht: ein lokales Validierungs-Gate auf den 32-Byte-Strings-Slots, wahrscheinlich ein Hash oder ein Exact-Content-Compare in einem ROM-Helper, nicht im Patch-Code selbst. Ein Quervergleich mit dem usbkvm-Projekt zeigt dasselbe Header-Muster bei verwandter Hardware.

Der spannendste Nebenbefund kam aus einem XDATA-Boot-Trace bei 0xC630 bis 0xC67F: die „AFN_Cap“-Strings landen gar nicht dauerhaft im RAM. Was dort steht, ist die Fallback-Variante. Die echten Strings werden erst zur Laufzeit beim USB-GetDescriptor aus dem EEPROM gebaut, und genau in diesem Moment greift offenbar das Gate. Wer das knacken will, müsste den USB-Control-Transfer mit usbmon und Wireshark während der Enumeration mitschneiden, die ROM-Helper bei 0x6345 und Nachbarn disassemblieren, oder mit mshack einen Bypass-Patch auf den Fallback-Branch setzen. Der schnellste Weg wäre allerdings, ein vom offiziellen MacroSilicon-Windows-Tool editiertes EEPROM byteweise gegen mein eigenes zu diffen. Dieses Tool schreibt vermutlich versteckte Metadaten mit, die das öffentliche Reverse-Engineering noch nicht dokumentiert hat. Das ist mein heißester Kandidat fürs Strings-Mysterium, aber bisher unbewiesen.

Der A/B-Test, oder: die Suche nach einer ehrlichen VGA-Quelle

Ich wollte zwei Dinge empirisch klären. Erstens: Kommt die modifizierte 1080p-EDID überhaupt bei der Quelle an? Zweitens: Löst das Ding echtes 1080p auf oder ist das hochskalierter Matsch? Beides braucht eine VGA-Quelle, die ihre DDC-Leitung auch wirklich ausliest. Das war schwerer zu finden als gedacht.

Erster Anlauf, ein Notebook mit „VGA-Out“. Plot-Twist: der VGA-Anschluss lief über einen aktiven DisplayPort-auf-VGA-Adapter und tauchte als DP-4 auf. Der Adapter liefert ein eigenes synthetisches EDID („NVD“, „LCD_VGA“, 1280×1024). Das ist nicht das EDID aus dem Dongle. Der EDID-Pfad vom Dongle bis zur GPU ist also unterbrochen. Erste Lehre: aktive DP-auf-VGA-Adapter verhalten sich wie eine eigene EDID-Quelle und maskieren alles dahinter.

Zweiter Anlauf, ein ThinkPad L560 mit echter VGA-Buchse hinten. Wieder gescheitert, und zwar aus einem prinzipiellen Grund. Ab Haswell und Skylake hat Intel den analogen RAMDAC komplett aus der GPU geworfen. Die physische VGA-Buchse hängt an einem Onboard-DP-auf-VGA-Bridge-Chip. Der Kernel verrät es selbst:

$ xrandr --verbose | grep -i subconnector
        subconnector: VGA
$ cat /sys/class/drm/card1-DP-2/edid | wc -c
0

Null Byte EDID. Die Bridge reicht das DDC vom Dongle nicht durch, der Connector bietet nur die VESA-Default-Modi an. Exakt dasselbe Problem wie beim ersten Notebook, nur diesmal onboard statt als Dongle. Auf beiden getesteten Bridge-Pfaden kam die EDID des Capture-Sticks nicht zur Quelle durch. Als Trend lässt sich sagen: neuere Intel-Notebooks haben den analogen RAMDAC verloren (der fiel etwa um Haswell und Broadwell, also rund 2013 bis 2015) und führen „VGA“ über DP-Bridges, die DDC abschneiden. Das als „kein Notebook taugt je“ zu verkaufen wäre übertrieben, es ist ein Trend, kein Beweis.

Ein netter Nebenbefund vom L560, den ich erst für einen kaputten Aufbau hielt: nach jedem Auflösungswechsel liefert der Dongle erstmal 1 bis 6 Sekunden ein komplett schwarzes Bild, bis die MS9288A-PLL wieder eingerastet ist. Ich hatte reihenweise schwarze Frames gegrabbt und schon den Analogpfad für tot erklärt. In Wirklichkeit hatte ich nur immer ins Re-Lock-Fenster reingeschossen. Mit 4 bis 6 Sekunden Settle-Zeit kommt das Bild stabil. Passt zur dokumentierten Sync-Trägheit des Chips.

Der A/B-Test selbst

Trotz blockiertem DDC habe ich den A/B durchgezogen, einfach um es schwarz auf weiß zu haben. Als Quelle ein 1920×1080-Testbild mit vier Quadranten aus 1-Pixel-Gittern: Schachbrett, vertikale Linien, horizontale Linien, Diagonale. Dazu grüne Eck-Marker, um sicher zu sein, dass der ganze Frame ankommt.

1920x1080-Testbild mit vier Quadranten aus 1-Pixel-Gittern und grünen Eck-Markern für den A/B-Test
Das Quell-Testbild: vier Quadranten mit 1px-Schachbrett, Vertikal-, Horizontal- und Diagonalgittern, dazu Eck-Marker.

Erst der Befund, der mich am meisten interessiert hat: 1px-Vertikallinien und Schachbrett kollabieren zu flachem Grau, das horizontale Feindetail ist weg. 1px-Horizontallinien und Diagonale zeigen schwache Resttextur. Die vertikale Auflösung kommt also weitgehend durch (jede Scanline ist eine eigene analoge Zeile), die horizontale ist deutlich begrenzt. Wichtiges Ehrlichkeits-Caveat: das ist die komplette Analogkette, also Bridge-DAC im L560, Kabel und MS9288A-ADC zusammen. Mit diesem Aufbau lässt sich nicht sauber trennen, wieviel davon der Dongle ist.

Dann der eigentliche EEPROM-A/B. EEPROM gegen das Original-Backup getauscht, Readback-Hash jedes Mal verifiziert. Etwas, das ich erst lernen musste: nach dem Flashen muss der Dongle einmal physisch ab- und wieder angesteckt werden. Ein reiner USB-Bus-Reset reicht nicht, der 8051 läuft einfach weiter und liest das neue EEPROM gar nicht ein. Software-seitig ging das nicht (kein schaltbarer Port), also von Hand. Die Zahlen, ImageMagick MAE auf einer Skala von 0 bis 1:

VergleichMAEpro 255
Rauschen mod3 (zwei Aufnahmen, gleiches EEPROM)0,00411,05
Rauschen Original0,00431,10
mod3 gegen Original0,00711,82

Der Cross-Wert liegt nur minimal über dem Rauschpegel. Das maximal verstärkte Differenzbild zeigt keine strukturierte Änderung, nur MJPEG-Blockrauschen in den hochfrequenten Quadranten. Die kleine Differenz ist Re-Lock- und AGC-Varianz zwischen den Sessions, nicht das EDID.

Maximal verstärktes Differenzbild mod3-EDID gegen Original-EDID, nur MJPEG-Blockrauschen, keine strukturierte Änderung
Maximal verstärkte Differenz: mod3-EDID gegen Original-EDID. Nur Blockrauschen, keine Struktur. Die EDID-Mod ändert am Bild nichts.

Fazit des A/B: Die EDID-Mod von 720p auf 1080p verändert das aufgenommene Bild exakt null. Aus erstem Prinzip war das klar, die EDID ist das, was das Gerät der Quelle anbietet, sie steuert nicht den Aufnahmepfad. Aber jetzt steht es empirisch da.

Endlich eine echte Analog-Quelle, und zwei dicke Befunde

Dritter Anlauf, diesmal ein Desktop mit einer NVIDIA GeForce GT 630 (Kepler). Kepler hat noch einen echten analogen RAMDAC, über einen passiven DVI-I-auf-VGA-Adapter kommt echtes analoges VGA raus. Endlich die Hardware, die den Notebooks fehlte.

Befund 1: Die EDID-Mod ist sogar grundsätzlich für die Katz. Der NVIDIA-Treiber cached die analoge EDID hartnäckig (analoges VGA hat kein Hotplug), also einmal lightdm neugestartet für einen frischen Read. Das Ergebnis im Xorg-Log:

(--) NVIDIA(GPU-0): CRT-0: connected
(WW) NVIDIA(0): CRT-0 does not have an EDID

Der Dongle liefert auf seinem VGA-Eingang gar keine DDC und keine EDID. Sauber belegt: derselbe Adapter hat vorher die EDID eines echten Monitors gelesen (ein Fujitsu P24-9, mit 1920×1080 und physischen Maßen), der Adapter reicht DDC also durch. Es ist der Dongle, der nichts treibt. Das kippt eine Annahme aus meinen eigenen Notizen, wo stand, das Patch-Modul beantworte „wahrscheinlich“ DDC-Reads. Dieses „wahrscheinlich“ war nie gemessen.

Ehrlich bei der Konfidenz bleiben: hoch dafür, dass in diesem GT-630-Test keine lesbare EDID vom Dongle kam. Nur mittel für das universelle „keine Quelle sieht die EDID je“. Restzweifel, die ich noch nicht ausgeräumt habe: NVIDIA-Eigenheiten bei analogem DDC, ob die Dongle-DDC die 5 Volt auf VGA-Pin 9 braucht, oder ob der DDC-Responder erst nach Sync-Lock aufwacht. Ein Pin-9-Check plus Logic-Analyzer auf den Pins 12 und 15 (mit dem Fujitsu als Positiv-Kontrolle) würde es hart machen. Arbeitshypothese: auf dem getesteten echten Analogpfad präsentierte der Dongle keine lesbare EDID, vermutlich weil der VGA-DDC-Pfad in der geteilten HDMI/VGA-Codebasis schlicht nicht verdrahtet ist. HDMI hat HPD und DDC, VGA hier offenbar nicht.

Befund 2: Das „1080p“ ist vertikal echt, horizontal Fake. Mit echtem RAMDAC konnte ich endlich den Dongle-Anteil am Blur isolieren (eigene xorg.conf mit UseEDID false und forciertem 1080p-Modeline, NVIDIA lehnt xrandr-Modelines ab). Testbild: reine 1px-Schwarz-Weiß-Gitter per xsetroot. Das Resultat, gemessen als Standardabweichung der Luma (ein ideales Gitter liegt bei rund 128, flaches Grau bei 0):

1px-Gitter bei echtem Analog-1080pStd-Abw.Bedeutung
horizontale Linien119vertikal sauber aufgelöst
vertikale Linien0,6horizontal komplett verschmiert
Schachbrett0,55weg
Zweifach-Zoom dreier Ausschnitte: vertikales Gitter grau verschmiert, horizontales Gitter scharf, Schachbrett grau
Echte Analog-Quelle (GT 630): links das vertikale 1px-Gitter zu Grau verschmiert, mittig horizontale Linien gestochen scharf, rechts das Schachbrett weg.

Der Dongle hat also echte 1080 Zeilen vertikal, aber horizontal kommt weit weniger als 1920 Pixel an. Und weil hier kein Bridge mehr dazwischen sitzt: der Blur ist der Dongle selbst, nicht das billige Notebook. Das ist die belastbare Aussage.

Den Mechanismus habe ich auf einen Vorschlag aus dem Gegencheck hin gleich nachgemessen, ein Phasen- und Balkenbreiten-Test. Das 1px-Gitter ist bei Phase 0 und Phase 1 gleich grau (Std-Abw. 0,18 gegen 0,19), ein PLL- oder Phasen-Mislock ist damit ausgeschlossen, sonst würde der 1px-Versatz den Kontrast kippen. Und der Kontrast steigt sauber mit der Balkenbreite: 1px liegt bei rund 0, 2px bei 35, 3px bei 61, 4px bei 79 (Ideal rund 128). Das ist die klassische Tiefpass-Signatur, also ein echtes Horizontal-Auflösungs-Limit und kein Lock-Artefakt. Ob das an der ADC-Abtastrate oder an einem internen Rescale liegt, kann ich noch nicht trennen, aber beides heißt: der Dongle begrenzt die Horizontalauflösung.

Auflösungs-Rampe von 1px bis 4px Balkenbreite, der Kontrast steigt von flachem Grau zu klaren Streifen
Balkenbreiten-Rampe: 1px bleibt grau, ab 2px wird Kontrast sichtbar. Klassische Tiefpass-Signatur, ein echtes Horizontal-Limit.

Warum YUYV bei 1080p nur 5 fps macht

Zum Schluss noch die berüchtigte 5-fps-Grenze, diesmal gemessen statt aus der Tabelle abgeschrieben (Quelle GT 630 bei 1080p60, v4l2-ctl --stream-mmap):

Format bei 1920×1080gemessen
MJPEG29 fps (Tabelle: 30)
YUYV (unkomprimiert)exakt 5,0 fps

Meine erste Erklärung mit „ungefähr 40 MB/s USB-2.0-Bandbreite“ war zu schludrig. Der genaue Grund ist das Payload-Limit des isochronen UVC-Endpoints. Das größte Altsetting des Video-Endpoints ist 3 mal 1024 Bytes pro Microframe, also 24,576 MB/s (steht so im lsusb -v). Unkomprimiertes YUYV bei 1080p sind 1920 mal 1080 mal 2 Bytes, also 4,15 MB pro Frame. Die Firmware-Frametabelle ist genau so gewählt, dass die YUYV-Raten knapp darunter passen:

  • 1080p mal 5 fps = 20,7 MB/s
  • 720p mal 10 fps = 18,4 MB/s
  • 480p mal 30 fps = 20,7 MB/s

Also keine generische „USB-2.0-Bandbreite“, sondern der High-Speed-Isoch-Endpoint plus die fest verdrahteten Frametabellen. MJPEG komprimiert vorher, deshalb bleiben dort 30 fps bei 1080p und bis zu 60 bei 720p und darunter. Klare Ansage: am MS2109 ist MJPEG bei hoher Auflösung Pflicht. Und „USB 3.0″ auf der Verpackung ist und bleibt gelogen, das Ding enumeriert als USB-2.0-High-Speed, ohne SuperSpeed.

Stabiles Device-Naming per udev

Damit das Gerät im Alltag immer unter demselben Pfad auftaucht, eine udev-Regel. Die Regeln stehen bewusst jeweils auf einer Zeile, weil mehrzeilige Fortsetzungen mit Backslash schnell zur Fehlerquelle werden:

# /etc/udev/rules.d/70-vga-capture-ms2109.rules
SUBSYSTEM=="video4linux", ENV{ID_VENDOR_ID}=="534d", ENV{ID_MODEL_ID}=="2109", ENV{ID_V4L_PRODUCT}=="*AFN_Cap*", ATTR{index}=="0", SYMLINK+="video-vga"
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="534d", ATTRS{idProduct}=="2109", ATTRS{product}=="USB3.0 Capture", GOTO="ms2109_vga_end"
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="534d", ATTRS{idProduct}=="2109", SYMLINK+="hidraw-vga", MODE="0660", GROUP="plugdev"
LABEL="ms2109_vga_end"

Die GOTO-Konstruktion ist nötig, weil ATTRS{product}!="..." nicht so funktioniert, wie man denkt. udev sperrt die Attribut-Suche auf einen Parent-Device-Walk, und „Fehlen eines Attributs“ verhält sich anders als ein echtes Ungleich. Deshalb der Umweg über ein positives Match plus Sprungmarke.

Fazit, und der Workaround der wirklich hilft

Was bleibt? Der Dongle ist ein nettes Studienobjekt, aber für mein ursprüngliches Ziel, alte DOS-Signale aufnehmen, ist er unbrauchbar. Es gibt keine 70-Hz-Modi, und reparieren lässt sich das nicht, weil die Frame-Tabelle im Mask-ROM festgebrannt ist. Das „1080p“ ist horizontal Marketing, „USB 3.0″ eine glatte Lüge, und die EDID-Mod ist auf dem getesteten Analogpfad wirkungslos, weil der Dongle gar keine EDID treibt. Drei Korrektur-Momente gegenüber meinen ersten Annahmen, alle drei lehrreicher als wenn alles gleich funktioniert hätte.

Wer wirklich exotische VGA-Signale wie DOS-Textmodi sauber aufnehmen will, schaltet eine externe Scaler-Box vor. Mein Tipp ist GBS-Control, eine offene Firmware für die rund 20 Euro teuren GBS-8200-Boards. Sie nimmt das krumme Quellsignal, lockt sauber und gibt ein normgerechtes Bild aus, das jeder Capture-Stick frisst. Die andere Liga ist der Open Source Scan Converter, dessen Firmware-Update ich hier schon beschrieben habe. Wer es noch günstiger mag, fängt einen gebrauchten Extron-Scaler aus einer Konferenzraum-Ausmusterung.

Offen bleibt das Strings-Mysterium (ohne das Vendor-Tool komme ich an den Gate-Algorithmus nicht ran), die Disassembly des zweiten Patch-Blocks in Ghidra, ein Latenz-Benchmark für den Einsatz als KVM-Console-Viewer, und der finale DOS-Test mit GBS-Control davor. Material für einen zweiten Teil ist also reichlich da.

Siehe auch:

Habt ihr selbst schon so einen MS2109-Stick auseinandergenommen oder das Strings-Gate geknackt? Dann lasst es mich gerne wissen, ihr dürft mich jederzeit fragen.

LCR-T4-Plus v2: m-firmware flashen, Display-Tuning und die 8-MHz-Quartz-Falle

Vor ein paar Wochen habe ich hier den TC1 Multifunction Tester mit der quelloffenen m-firmware geflasht. Seitdem liegt ein zweiter Bauteiltester aus genau dem gleichen Dunstkreis bei mir auf dem Tisch: ein LCR-T4-Plus mit gelber Platine, eingebautem ZIF-Sockel und Beschriftung „91make.taobao.com“ auf der Rückseite. Das billige Gegenstück zum TC1, vom selben Hersteller-Cluster, gleiche Firmware-Familie. Eigentlich ein gemütlicher Folge-Sonntag, dachte ich.

Aufgeklappter LCR-T4-Plus v2 mit ZIF-Sockel, blauem Start-Button und ISP-Header mit vertauschten Silkscreen-Labels
Ausgangslage: aufgeklapptes Display, ZIF-Sockel, blauer Start-Button. Rechts vom Button der ISP-Header mit den (falsch beschrifteten) Silkscreen-Labels.

Zur Vorgeschichte gehört ein erster T4-Plus, den ich vor Jahren mal gekauft hatte. Das Gerät arbeitet bis heute, sein Display allerdings ist tot. Der COG-Controller unter dem Epoxy-Klecks auf dem ST7565R hat aufgegeben, der MCU lebt noch, aber zeigen kann er nichts mehr. Vor ein paar Wochen habe ich aus einer Resterampe ein zweites Exemplar geordert, gleicher Aufdruck, gleiche PCB-Revision. Plan: einmal Backup-Flash und dann beide Geräte parallel mit m-firmware betreiben, eines als Bastelreserve.

Aus „schnell mal das gleiche Flash-Profil wie beim ersten T4-Plus drüberbügeln“ wurde ein ganzer Nachmittag mit komplett schwarzem Display, abgeschnittenem Cursor, einem Tester der sich beim Loslassen des Buttons sofort wieder ausschaltet und am Ende der Erkenntnis, dass die zentrale Falle nicht in der Firmware steckt, sondern in einem winzigen Bauteil neben dem MCU.

Was steckt im T4-Plus v2?

Anders als der TC1 mit seinen zwei Chips (ATmega plus STC für das Power-Management) ist der T4-Plus ein Single-MCU-Design. Auf der Rückseite klebt genau ein nennenswerter Halbleiter, der Rest ist Spannungsteiler, drei Transistoren für die Power-Latch-Schaltung und der Quartz.

PCB-Rückseite des T4-Plus v2 mit ATmega328P, 8-MHz-Quartz und 9V-Block-Anschluss
Rückseite des PCB mit dem ATmega328P, dem silbernen Quartzblock daneben (8 MHz, nicht 16 wie beim ersten Exemplar!) und dem 9V-Block-Anschluss.
Mikroskop-Closeup auf den ATmega328P-U-TH mit Date-Code 2009SG8
Close-up unter der Lupe: ATMEL MEGA328P-U-TH, Date-Code 2009SG8. Originalsilizium von Atmel/Microchip, kein LGT8F328-Klon wie auf manchen jüngeren Boards.

U1: ATmega328P-U-TH im TQFP-32-Gehäuse, Signatur 0x1e950f, 32 KB Flash, 2 KB SRAM, 1 KB EEPROM. Der Date-Code 2009SG8 stammt aus 2020, Production-Code-Pattern passt zu echtem Microchip-Silizium. Auf gefälschten Klonen sieht das Lasermarkings-Pattern deutlich anders aus, das Schriftbild ist hier sauber, also passt das.

Der Display-Controller sitzt unter dem schwarzen Epoxy-Blob auf dem LCD selbst und ist ein ST7565R mit 128 mal 64 Pixel monochromem STN-Panel, gelb-grüne Hintergrundbeleuchtung. Klassische COG-Bauform. Daten kommen seriell über vier GPIO-Leitungen rein. Kein I2C, sondern SPI-Bitbang vom MCU getrieben.

Stromversorgung läuft über einen 9V-Block mit Spannungsteiler 10k zu 3.3k auf einem ADC-Pin. Bedienelement: ein einziger blauer Start-Button, kein Drehgeber, kein IR-Empfänger, kein USB. Das Ding ist ein Wegwerf-Standalone im besten Sinne, nichts dran was schiefgehen kann.

Und dann ist da noch dieser kleine silberne Quartzblock direkt neben dem MCU. 8.000 steht da. Acht Megahertz. Beim ersten T4-Plus von vor Jahren habe ich 16 MHz im Hinterkopf, ich notiere mir die 8 MHz pflichtbewusst, denke aber „nett, anderer Quartz“ und mache ansonsten erstmal weiter. Spoiler: genau dieser Eintrag wird Stunden später zum Schlüssel.

ISP-Header finden, und der Aufdruck lügt

Der ISP-Header sitzt versteckt unter der Display-Platine, ein simples 2×3-Pad-Grid ohne aufgelötete Stiftleiste. Auf der Rückseite finden sich Silkscreen-Hinweise: mis, mosi, sck, reset, plus die beiden Stromversorgungspads. Lustig: bei diesem Board sind die beiden Datenleitungen vertauscht beschriftet. Was als mis markiert ist, trägt physisch MOSI; das mosi-Pad ist tatsächlich MISO.

Aufgefallen ist mir das beim ersten Signatur-Read mit dem Arduino Uno als ISP-Programmer. Wenn man stur nach Silkscreen verkabelt, antwortet der Chip mit lauter 0x00. Sobald die Leitungen getauscht werden, kommt eine saubere Signatur. Heißt für die Praxis: bei diesem Board nicht auf den Aufdruck verlassen, sondern Pin für Pin mit dem Durchgangsprüfer gegen die Chip-Pins verifizieren. Standard-ISP-Pinout auf dem ATmega328P im TQFP-32 ist Pin 17 MOSI, Pin 18 MISO, Pin 19 SCK, Pin 29 /RESET.

Arduino Uno als ISP-Programmer am ISP-Header des T4-Plus v2
Arduino Uno mit ArduinoISP-Sketch als Programmer. Display zur Seite geklappt, vier Datenleitungen plus 5V und GND. Genauso wie beim TC1, gleiche Hardware, gleiche Flag-Kombination.

Verkabelung an den richtigen Pads (Arduino-seitig), gilt für beide T4-Plus-Boards:

Arduino D10  ->  RESET   (T4-Plus Pad RESET)
Arduino D11  ->  MOSI    (T4-Plus Pad „mis"   bei diesem Klon!)
Arduino D12  ->  MISO    (T4-Plus Pad „mosi"  bei diesem Klon!)
Arduino D13  ->  SCK     (T4-Plus Pad SCK)
Arduino 5V   ->  VCC
Arduino GND  ->  GND

Sobald die Signatur sauber kommt, ist die halbe Miete drin:

$ avrdude -c avrisp -p m328p -P /dev/ttyACM0 -b 19200 -B 32 -v 2>&1 | grep -i sig
avrdude: Device signature = 0x1e950f (probably m328p)

Backup der Original-Firmware

Beim TC1 ging das Backup nicht, weil die Lock-Bits auf 0xC0 standen und das Auslesen geblockt haben. Beim T4-Plus v2 habe ich Glück: Lock-Byte ist 0xFF, also komplett offen. Vor dem ersten Flash zieht man sich also bitte unbedingt das Original einmal komplett herunter, Flash und EEPROM:

avrdude -c avrisp -p m328p -P /dev/ttyACM0 -b 19200 -B 32 
        -U flash:r:t4plus2-original-flash.hex:i 
        -U eeprom:r:t4plus2-original-eeprom.hex:i 
        -U lfuse:r:-:h -U hfuse:r:-:h -U efuse:r:-:h -U lock:r:-:h

Fuses kamen so zurück: lfuse=0xF7, hfuse=0xD9, efuse=0xFD, lock=0xFF. Hat man das im Kasten, kann man auch beruhigt herumprobieren. Notfalls geht es per avrdude -U flash:w: jederzeit wieder auf den Auslieferungszustand zurück.

Erster Flash und ein völlig schwarzes Display

Quelle für die neue Firmware ist wie beim TC1 die m-firmware von madires, aktuell Version 1.56m. Im Repo liegt unter Software/Firmware/m-firmware/ der Source mit allen Config-Templates für die diversen MCU-Varianten. Für den ATmega328P ist das config_328.h, gemeinsame Optionen in config.h, build-Flags im Makefile.

Mein erster Anlauf orientierte sich an dem, was beim ersten T4-Plus damals funktioniert hatte. Display ST7565R aktivieren, BAT_DIVIDER mit 10k zu 3.3k, Short-Circuit-Menu an, MCU auf atmega328 (ohne das nachgeschobene P, sonst greift der #if defined(__AVR_ATmega328__)-Guard in config_328.h nicht und der Build wirft undefinierte BUTTON_PIN-Symbole), Frequenz pflichtbewusst auf FREQ = 16 wie beim ersten Board.

Make, flash, einschalten, und dann das hier:

Komplett dunkles ST7565R-Display nach erstem Flash mit Default FLAG_RATIO_65
Display nach erstem Flash mit Default-FLAG_RATIO_65: komplett dunkel. Klassisches Symptom eines zu hoch eingestellten internen LCD-Spannungsteilers.

Komplett schwarz. Kein Boot-Banner, keine Kontrast-Stufe, einfach nur eine schwarze Fläche. Mein erster Gedanke war natürlich: Display kaputt, gleicher Spaß wie beim ersten T4-Plus. Aber die Backlight-LEDs leuchten, und im Streiflicht erkennt man, dass die Pixel-Anordnung sichtbar ist, nur eben in „alle Pixel an“-Stellung. Das ist kein toter Controller, das ist ein lebender Controller mit zu hohem internem LCD-Bias.

Im m-firmware-Source liegt direkt ein Clones-Verzeichnis mit Hinweisen zu bekannten Klon-Variationen. Für den verwandten LCR-T5 steht dort genau dieser Workaround: bei manchen ST7565R-Panels ist der per Software gesetzte Bias zu hoch, der typische Default-Befehl CMD_V0_RATIO | FLAG_RATIO_65 muss runter auf FLAG_RATIO_55 oder sogar FLAG_RATIO_45. Geändert wird das in ST7565R.c in der Funktion LCD_Init():

/* set contrast: resistor ratio 5.5 */
LCD_Cmd(CMD_V0_RATIO | FLAG_RATIO_55);    /* statt FLAG_RATIO_65 */

Mit dieser einen Zeile ändert sich alles. Neuer Build, flashen, und siehe da, plötzlich sind tatsächlich Pixel sichtbar.

Display-Tuning: Orientierung, Kontrast und der abgeschnittene Cursor

„Pixel sichtbar“ heißt noch lange nicht „lesbar“. Was da auf dem Display erscheint, sind erstmal Hieroglyphen kopfüber, spiegelverkehrt, mit komischen Pixel-Mustern an Stellen, an denen eigentlich Zeichen stehen sollten. Das ist die klassische ST7565R-Inbetriebnahme: drei Defines steuern Orientierung und Kontrast, alle drei muss man am eigenen Panel kalibrieren.

//#define LCD_FLIP_X                /* horizontale Spiegelung */
//#define LCD_FLIP_Y                /* vertikale Spiegelung   */
#define LCD_CONTRAST     22         /* 0..63, 22 passt hier   */

Bei meinem Panel sind beide FLIP-Defines aus, was unintuitiv klingt aber stimmt. Der Kontrast landet final bei 22. Nach ein paar Build-Iterationen sieht das so aus:

Display mit korrektem Kontrast aber rechts abgeschnittenem Cursor-Symbol durch LCD_OFFSET_X
Zwischenstand: Orientierung und Kontrast passen, „1-||-3 .15pF“ gut lesbar. Aber das blinkende Cursor-Symbol rechts ist abgeschnitten, weil LCD_OFFSET_X den gesamten Inhalt um vier Pixel nach rechts schiebt.

Klassischer Fall: bestimmte ST7565R-Panel-Varianten brauchen einen X-Offset von vier Pixel, weil deren sichtbarer Bereich rechts beginnt. Andere wiederum nicht. Das Define LCD_OFFSET_X erzwingt genau diese Verschiebung. Mein Panel will sie nicht, also raus damit:

//#define LCD_OFFSET_X            /* deaktiviert: kein +4 Pixel Shift */
Display korrekt zentriert nach Deaktivierung von LCD_OFFSET_X
Nach dem Auskommentieren sitzt der Bildinhalt zentriert, der Cursor ist vollständig sichtbar. Erste komplette Messung lesbar: ein simpler Widerstand.

An dieser Stelle wäre die Geschichte normalerweise vorbei. Display tut, Buttons drücken, Messen, fertig. Wäre da nicht das Problem mit dem Einschalten.

Das Power-Latch-Drama

Der T4-Plus hat einen blauen Druckknopf. Den drückt man, der Tester bootet, misst, schaltet sich nach Inaktivität von alleine wieder ab. So weit der Plan. Mein frisch geflashtes Board allerdings macht etwas Ärgerliches: Knopf drücken, Display bootet kurz an, Knopf loslassen, sofort wieder aus. Das ist kein „Auto-Power-Off nach Timeout“, das ist „MCU verliert beim Loslassen die Stromversorgung“. Klassischer Power-Latch-Bug.

Erster Reflex: irgendein POWER_CTRL-Pin in der Config ist falsch. Die m-firmware hat einen Define für den Pin, an dem der MCU nach dem Boot ein HIGH-Signal anlegen muss, um sich selbst am Leben zu halten. Auf den meisten Boards heißt der Pin PD6 oder ähnlich. Also durchprobiert: PD6, PD7, PD4, PD3, alles was an freien Pins noch übrig ist. Kein Erfolg. Egal welcher Pin, sobald der Finger den Button verlässt, ist Schluss.

Zeit für die Multimeter-Tour über die Latch-Schaltung. Auf der Platine sitzen drei Transistoren um den Power-Knopf herum: Q1 ist ein S9015 (PNP), schaltet die 9V auf die Versorgung. Q2 und Q3 sind beide S9014 (NPN) und treiben gemeinsam mit dem Button-Kontakt die Basis von Q1. Durchgangsmessungen ergeben:

Pin 29 (/RESET) --- 27 kOhm --- Basis Q3
Basis Q3 --- Button-Kontakt --- GND
Kollektor Q3 --- Basis Q1 (über Pull-up)
Q1 schaltet 9V auf den 5V-Regler

Das ist also gar kein „Firmware schaltet POWER_CTRL HIGH“-Design. Die Latch-Schaltung ist passiv über die /RESET-Leitung des MCU aufgebaut. Solange der ATmega läuft, liegt /RESET auf HIGH (intern hochgehalten), und über den 27k zur Basis von Q3 bleibt der Transistor durchgesteuert, Q1 hält die Versorgung an. Drückt man den Button, zieht der Q3-Basis kurz auf GND-Potenzial Richtung positiv und triggert das Hochfahren über einen leicht anderen Pfad. Aber sobald der Boot durch ist und der MCU /RESET HIGH hält, läuft das Ganze von alleine.

Heißt: an meinem Board sollte das auch ohne firmware-seitiges POWER_CTRL funktionieren. Tut es aber nicht. Spannungsmessung unter Strom zeigt: Q3-Basis bleibt dauerhaft bei 0V, der Transistor schaltet nie sauber durch. Aber warum, wenn doch /RESET nach erfolgreichem Boot eigentlich HIGH sein müsste?

An dieser Stelle saß ich gefühlte zwei Stunden an dem Tisch und habe mit dem Multimeter zwischen MCU-Pinout, Transistor-Basen und 9V-Schiene hin- und hergemessen. Mein Verdacht war zwischendurch ein toter Transistor, ein kalter Lötpunkt, ein verkokelter Trace unter dem schwarzen Lötstopplack. Alles falsch.

Der Aha-Moment im Makefile eines fremden Forks

Irgendwann habe ich aus Verzweiflung angefangen, fremde Firmware-Forks für genau dieses Board zu lesen. Es gibt eine zweite quelloffene Linie neben der m-firmware: die k-firmware (das „k“ steht für Karl-Heinz Kübbeler, den Original-Autor), und davon wiederum diverse Forks. Einer davon ist Palingenesis‘ Fork mit einem dedizierten T4-v2-Build-Profil. Ich öffne dessen Makefile, und der Blick fällt auf eine einzelne Zeile:

OP_MHZ = 8

Acht. Megahertz. Genau die Zahl, die ich Stunden vorher auf dem Quartz gelesen und in mein Notizfeld geschrieben hatte. Genau die Zahl, deren Bedeutung ich nicht richtig zu Ende gedacht hatte. Mein Build der m-firmware lief mit FREQ = 16, weil ich davon ausgegangen war, dass das T4-Plus-Board immer 16 MHz Quartz hat. Tut es eben nicht. Beim zweiten Exemplar ist ein 8-MHz-Quartz drauf.

Was das praktisch bedeutet: wenn die Firmware glaubt, sie laufe auf 16 MHz, aber tatsächlich nur 8 MHz Takt verfügbar sind, läuft jede Operation effektiv mit halber Geschwindigkeit. Jedes Timer-Tick, jede Schleife, jede ADC-Konversion dauert doppelt so lang. Im Falle der Initialisierungssequenz heißt das: bis der MCU im Bootcode an der Stelle ist, an der POWER_CTRL HIGH gesetzt wird (oder bis /RESET stabil HIGH ausgegeben wird), ist das Zeitfenster, in dem der Button noch gedrückt ist, schon längst vorbei. Der Latch greift nicht, der Tester schaltet sich beim Loslassen ab.

Drei Buchstaben im Makefile geändert:

FREQ = 8

Neu kompiliert, geflasht. Knopf gedrückt. Display kommt. Knopf losgelassen. Display bleibt an. Der Tester hält sich selbst am Leben. Zwei Stunden Diagnose-Drama wegen einer einzigen Zahl im Makefile, die mit der eigentlichen Hardware nichts zu tun hatte, außer dass die Hardware halt ein anderer Quartz war als gedacht. Genau eine dieser Stellen, an denen man kurz aufsteht und sich was zu trinken holt.

Self-Adjustment und Werte ins Flash schreiben

Nach dem Power-Latch-Fix ist der Tester quasi nutzbar, aber die m-firmware meldet beim Boot „Checksum failure“ für die Adjustment-Werte im Flash. Das ist erwartbar, weil dort ja noch nie eigene Kalibrierwerte gespeichert wurden. Heilmittel: das Service-Menü aufrufen, Self-Adjustment durchlaufen, Werte abspeichern.

Voraussetzung ist, dass UI_SHORT_CIRCUIT_MENU in config.h aktiviert ist. Damit kommt man ins Menü, indem man beim Start alle drei Probes (1, 2, 3) miteinander kurzschließt. Der Tester erkennt das und blendet das Service-Menü ein:

Service-Menü des T4-Plus v2 via 3-Probe-Kurzschluss erreicht
Service-Menü via 3-Probe-Kurzschluss: PWM, IR detector, Opto Coupler, Test, Adjustment, Contrast, Save. Genau das, was man für eine saubere Inbetriebnahme braucht.

Erster Punkt ist „Test“, ein Selbsttest mit allen drei Probes. Anschließend „Adjustment“, da braucht man dann einen 1 µF-Kondensator zwischen Probe 1 und Probe 3. Der Tester misst seinen eigenen internen Ri-Wert, die Eingangskapazität, eine Referenzspannung. Am Ende „Save“, und die Werte landen via DATA_FLASH als Block im Programmspeicher (Self-Programming). Beim TC1 war das genauso, der einzige Unterschied: dort kommen die Daten in den 1 KB EEPROM. Beim T4-Plus reicht der Flash-Bereich und ich nutze DATA_FLASH stattdessen, weil das Self-Programming auf dem ATmega328P stabiler läuft als die EEPROM-Erase-Write-Sequenz.

Self-Adjustment-Ergebnis mit Ri-, Ri+, C0, R0, Vref, Vcc, AComp Werten
Self-Adjustment-Ergebnis: Ri- 20.8 Ω, Ri+ 23.4 Ω, C0 36 pF, R0 0.31 Ω, Vref 1097 mV, Vcc 5130 mV, AComp 0 mV. Werte ins Flash gespeichert, Checksum-Fehler beim nächsten Boot weg.

Diese Werte unterscheiden sich übrigens leicht von Board zu Board. Die Ri-Werte hängen an den konkreten Innenwiderständen der MCU-Ausgangsstufen, C0 und R0 an den Probe-Leitungslängen, Vref am internen Bandgap. Wer die Hex eines anderen Geräts mit dessen Flash-Region 1:1 auf sein eigenes flasht, übernimmt also fremde Kalibrierdaten, die zu falscher Mess-Anzeige führen können. Lieber einmal selbst kalibrieren.

3D-gedrucktes Gehäuse statt nackte Platine

Das Original-T4-Plus kommt ohne Gehäuse, nur die nackte Platine. Für den TC1 gab es ja damals zumindest noch eine billige Plastik-Halbschale, hier ist nicht mal das dabei. Auf Makerworld liegt ein passendes Modell von „LeoNerd“ mit der ID 1891431, „Case for LCR-T4 Component Tester“. Drei Teile: Unterschale, Frontblende mit ZIF-Sockel-Ausschnitt und Display-Fenster, Batterie-Klappe.

3D-gedruckte PETG-Gehäuseteile direkt von der Druckplatte für den LCR-T4-Plus
PETG, 0.2 mm Schichthöhe, fertig auf der Druckplatte. Drei Teile, kein Support nötig.

Ich habe das auf meinem Bambu Lab X1 Carbon in PETG ausgedruckt. PLA ginge auch, aber PETG ist hier ein bisschen weniger spröde, der Tester wird ja immer wieder mal in die Hand genommen. Maße passen direkt, das PCB sitzt sauber zwischen den Stegen, das Display fluchtet, der Button schaut zentrisch durch die Öffnung. Den 9V-Block fixiert die Klappe von hinten.

Finaler Funktionstest im Gehäuse

Fertig zusammengebauter T4-Plus v2 im 3D-Gehäuse mit Boot-Banner Component Tester v1.56m
Boot-Banner „Component Tester v1.56m“ im 3D-gedruckten PETG-Gehäuse. Knopf drücken, Display bleibt an, alles, was es braucht.
Boot-Screen mit korrekter Batteriespannungs-Anzeige Bat 9.61V ok
„Bat 9.61V ok / Probing…“, der BAT_DIVIDER mit 10k zu 3.3k stimmt und eine frische 9V-Batterie wird korrekt erkannt.

Ein paar Testmessungen mit Bauteilen aus der Schublade: 10k-Widerstände, ein paar 100 nF Kondensatoren, ein BC547 und ein paar LEDs. Alle Werte plausibel, BC547 wird mit korrekter Pin-Zuordnung als NPN-Transistor erkannt, hFE in der erwarteten Größenordnung. Damit ist das Gerät einsatzbereit.

Die finale Konfiguration zum Mitnehmen

Damit andere mit dem gleichen 91make-Klon nicht die gleichen drei Tage verbrennen müssen, hier alle Änderungen relativ zur unveränderten m-firmware 1.56m an einer Stelle gesammelt.

Makefile (Auszug, nur die geänderten Zeilen):

MCU    = atmega328       # NICHT atmega328p, sonst greift der Include-Guard nicht
FREQ   = 8               # 8 MHz Quartz auf der v2-Variante, nicht 16
PARTNO = m328p           # avrdude-Part bleibt m328p

config.h (gemeinsame Optionen, aktive Defines):

#define HW_REF25                   /* interne 2.5V-Bandgap-Referenz */
#define UI_AUTOHOLD                /* nach Messung auf Tastendruck warten */
#define UI_SHORT_CIRCUIT_MENU      /* Service-Menue via 3-Probe-Short */
#define POWER_OFF_TIMEOUT 60       /* Auto-Off nach 60 Sekunden Idle */
#define BAT_DIVIDER                /* externer 10k/3.3k-Teiler */
#define BAT_R1     10000
#define BAT_R2     3300
#define BAT_WEAK   7400            /* 7.4V Warnschwelle */
#define BAT_LOW    6400            /* 6.4V Abschaltschwelle */
#define DATA_FLASH                 /* Kalibrierdaten ins Programm-Flash */

config_328.h (ST7565R-Section, alles relevante an einem Stueck):

#define LCD_ST7565R
#define LCD_GRAPHIC
#define LCD_SPI
#define LCD_PORT     PORTD
#define LCD_DDR      DDRD
#define LCD_RESET    PD0
#define LCD_CS       PD5
#define LCD_A0       PD1
#define LCD_SCL      PD2
#define LCD_SI       PD3
#define LCD_DOTS_X   128
#define LCD_DOTS_Y   64
//#define LCD_OFFSET_X            /* AUS, sonst +4 Pixel Verschiebung */
//#define LCD_FLIP_X              /* AUS */
//#define LCD_FLIP_Y              /* AUS */
#define LCD_START_Y  0
#define LCD_CONTRAST 22
#define FONT_8X8_VF
#define SYMBOLS_24X24_VFP
#define SPI_BITBANG

ST7565R.c (genau eine Zeile in LCD_Init()):

/* set contrast: resistor ratio 5.5 */
LCD_Cmd(CMD_V0_RATIO | FLAG_RATIO_55);     /* war FLAG_RATIO_65 */

Flash-Befehl, identisch zum TC1 (nur die Hex-Datei ist eine andere):

avrdude -c avrisp -p m328p -P /dev/ttyACM0 -b 19200 -B 32 
        -U flash:w:ComponentTester.hex:i

Was ich aus dem Nachmittag mitnehme

Vier Punkte, die ich beim nächsten Klon-Tester sofort prüfen werde, statt wieder Stunden in der Diagnose zu verbringen:

  • Quartz mit der Lupe lesen bevor man die Frequenz im Makefile setzt. Identische PCB-Bezeichnung garantiert nicht den gleichen Takt. Bei diesem T4-Plus ist es 8 MHz, bei meinem ersten waren es 16 MHz. Zwei Boards, derselbe Aufdruck, verschiedene Bestückung.
  • ST7565R komplett schwarz nach erstem Flash ist fast immer ein zu hoher Bias und kein toter Controller. Erst FLAG_RATIO_65 auf FLAG_RATIO_55 oder FLAG_RATIO_45 ändern, dann weiter denken.
  • Silkscreen-Labels glauben, aber verifizieren. Auf dem v2-Board sind mis und mosi physisch vertauscht. Einmal Durchgangsprüfung gegen den MCU-Pin spart eine Stunde Frustration.
  • Vermeintliche Hardware-Fehler sind manchmal Build-Parameter. Ein Tester, der sich beim Loslassen ausschaltet, sieht aus wie eine kaputte Latch-Schaltung. War aber in Wirklichkeit nur die falsche CPU-Frequenz im Makefile, was den Boot-Code langsamer laufen ließ, als das mechanische Button-Zeitfenster es zuließ.

Repo und Quellen

Wie beim TC1 habe ich auch hier ein kleines Repo mit der fertigen Hex, den Config-Patches und einer README mit Schritt-für-Schritt-Anleitung gepackt: github.com/Kernel-Error/t4plus-v2-firmware-update. Lizenz folgt der m-firmware (EUPL v1.2), die Config-Patches sind als unified diff gegen die unveränderte 1.56m beigelegt.

Quellen, ohne die das nicht funktioniert hätte:

Siehe auch: TC1 Multifunction Tester mit Open-Source-Firmware (der Vorgänger-Beitrag, gleiche Firmware-Familie, mehr Drama bei der STC-Variante), Multifunktionstester für Elektronikbauteile (mein erster Eindruck von dieser Tester-Klasse 2019), xum1541-Firmware-Bug gefunden und gefixt (anderes Mikrocontroller-Firmware-Drama), OSSC Firmware-Update 1.21 (Firmware-Update an Open-Source-Hardware), Preciva 992D+ Lötstation (für alle die nach diesem Beitrag selber löten wollen).

Fragen, eigene T4-Plus-Klon-Varianten oder noch krummere Silkscreen-Vertauschungen gesehen? Gerne über die fragen-Seite oder als Issue im Repo.

TC1 Multifunction Tester: Open-Source Firmware flashen, kalibrieren und die Stolperfallen dabei

TC1 Multi-function Tester mit originaler M-Tester Firmware auf dem Display

Es gibt diese kleinen Bauteiltester aus China, die für 15 bis 20 Euro auf AliExpress oder Amazon rumschwirren. Der TC1, auch bekannt als LCR-TC1. Transistoren, Widerstände, Kondensatoren, MOSFETs, Dioden. Bauteil in den ZIF-Sockel stecken, Knopf drücken, fertig. Für den Preis eigentlich erstaunlich brauchbar. Aber die originale Firmware ist halt, sagen wir mal, solide Mittelklasse. Die Messgenauigkeit geht in Ordnung, aber nicht mehr, und die Zahl der erkannten Bauteile ist überschaubar. In der Open-Source-Welt gibt es zwei Firmware-Varianten für diese Tester: Die k-firmware als stabiles Original und die m-firmware von madires als aktiv weiterentwickelter Rewrite. Präzisere Messungen, mehr erkannte Bauteile, bessere IR-Protokollunterstützung, flexiblere Konfiguration und ein sauberes Menü mit Kalibrierung. Also habe ich mich drangesetzt.

Was als „schnell mal neue Firmware drauf“ geplant war, wurde ein mehrtägiger Abstieg in die Untiefen von STC-Microcontrollern, falschen Pinouts und parasitärer Stromversorgung. Aber der Reihe nach.

Was steckt im TC1?

PCB-Rueckseite des TC1 mit ATmega324PA Hauptprozessor und STC15L104W Power-Management-Chip

Auf der Rückseite der Platine sitzen zwei Chips, die man kennen muss:

Nahaufnahme des ATmega324PA-U-TH Chips auf der TC1-Platine

U1: ATmega324PA — der Hauptprozessor. Ein Atmel AVR im TQFP-44 Gehäuse, 32 KB Flash, 2 KB SRAM, 1 KB EEPROM. Hier läuft die eigentliche Tester-Firmware. Wird über ISP (In-System Programming) geflasht, also braucht man einen Programmer.

Nahaufnahme des STC15L104W (U4) Power-Management-Chips im SOP-8 Gehaeuse

U4: STC15L104W — ein winziger 8051-kompatibler Mikrocontroller im SOP-8 Gehäuse von STC Micro. Der macht das Power-Management: Einschalten per Tastendruck, automatisches Abschalten nach Timeout. Klingt trivial, ist aber der Chip, der mir die meisten Kopfschmerzen bereitet hat.

Beide Chips brauchen neue Firmware. Die m-firmware liefert die Hex-Dateien für beide: ComponentTester.hex für den ATmega und u4.hex für den STC. Klingt einfach. War es nicht.

Erster Versuch: Backup der Original-Firmware

Bevor man irgendwas überschreibt, will man natürlich ein Backup. Gute Idee, klappt nur nicht. Die Lock Bits des ATmega sind auf 0xC0 gesetzt. Das bedeutet: Lesen des Flash-Inhalts ist gesperrt. Man kann die Firmware löschen und neu schreiben, aber nicht auslesen. Kein Backup möglich. Also Augen zu und durch.

U4 flashen: Der schwierigste Teil

Der STC15L104W hat einen eingebauten UART-Bootloader. Klingt praktisch. Man braucht theoretisch nur einen USB-TTL Adapter, sendet das Hex-File und der Chip programmiert sich selbst. Theoretisch. In der Praxis muss der Chip für den Bootloader einen sauberen Power-Cycle bekommen, also Strom weg, Strom wieder an. Und genau hier fängt das Drama an.

Im eingelöteten Zustand liegt VCC des STC über den Button-Schaltkreis auf GND. Der Bootloader startet schlicht nicht. Der Chip muss raus.

Atten ST-862D Heissluft-Rework-Station zum Ausloeten des STC15L104W
Sugon T3602 Dual-Channel Loetstation mit Temperaturanzeige auf dem Arbeitsplatz

Also Atten ST-862D Heißluftstation raus, SOP-8 Chip bei 280°C vorsichtig von der Platine gehoben, Pads sauber gemacht. Zum späteren Wiedereinlöten dann die Sugon T3602. Für solche SMD-Arbeiten will man vernünftiges Werkzeug, mit einem 15-Euro-Lötkolben aus dem Baumarkt wird das nichts.

Der CH341 und seine 5V-Lüge

Erster Versuch: CH341 USB-TTL Adapter. Steht „3.3V“ drauf, also sollte das passen. Der STC15L104W ist ein 3.3V-only Chip, 5V auf den Datenleitungen wären sein Todesurteil. Also Multimeter dran, TX-Pin messen und… 5V. Auf dem TX-Pin. Trotz „3.3V“-Stellung. Der CH341 hat zwar einen 3.3V Spannungsregler für VCC, aber die Logikpegel auf TX bleiben bei 5V. Das steht nirgendwo auf dem Board, nirgendwo im Datenblatt des Adapters. Man muss es wissen oder messen.

Hätte ich nicht nachgemessen, wäre der STC jetzt Elektroschrott. Lektion gelernt: Immer nachmessen, nie dem Aufdruck vertrauen.

FT232RL USB-TTL Adapter mit Jumper auf 3.3V fuer das STC15L104W Flashing

Also einen FT232RL USB-TTL Adapter bestellt. Der hat einen echten 3.3V/5V Jumper, der tatsächlich auch die Logikpegel umschaltet. Nachgemessen: TX bei 3.3V. Endlich.

Das Pinout-Desaster

Jetzt wirds peinlich. Ich habe stundenlang versucht, den STC über Pin 1 (P3.4) und Pin 3 (P3.5) anzusprechen. Keine Reaktion. Kein Bootloader. Nichts. Irgendwann habe ich nochmal das Datenblatt studiert und festgestellt: P3.4 und P3.5 sind GPIO-Pins. Die UART-Pins (RXD/TXD) liegen auf P3.0 und P3.1, also Pin 5 und Pin 6. Das SOP-8 Pinout:

       ┌──────────┐
Pin 1  │● P3.4    │  Pin 8  (P3.3)
Pin 2  │  VCC     │  Pin 7  (P3.2)
Pin 3  │  P3.5    │  Pin 6  ← TXD (P3.1)
Pin 4  │  GND     │  Pin 5  ← RXD (P3.0)
       └──────────┘

Stunden. Am falschen Pin. Das sind so Momente, in denen man kurz aufstehen und was trinken gehen sollte. Keine Ahnung, warum ich die falschen Pins unbedingt wollte… Ich hab auf das Datenblatt geschaut und… na, vielleicht war die Brille dreckig, keine Ahnung. „Leider“ kamen da auch sinlose Daten bei zustande, was erst nach einer falschen Baudrate ausgesehen hat; vielleicht ist das eine gute Ausrede, warum ich da so lange hängen geblieben bin?!

Parasitäre Stromversorgung und der Breadboard-Aufbau

Ausgeloeteter STC15L104W auf Breadboard verkabelt mit FT232RL Adapter zum Flashen

Das nächste Problem: Der STC-Bootloader braucht einen Power-Cycle zum Starten. Also VCC abziehen, Flash-Tool starten, VCC wieder anlegen. Sollte klappen. Tat es aber nicht zuverlässig. Warum? Der Chip versorgt sich über die TX/RX-Datenleitungen parasitär mit Strom. Selbst wenn VCC getrennt ist, reicht der Strom über die Schutzdioden in den I/O-Pins, um den Chip am Leben zu halten. Kein sauberer Power-Cycle, kein Bootloader.

Die Lösung: Beim Power-Cycle ALLE Drähte trennen, nicht nur VCC. Erst das Flash-Tool starten (wartet auf den Chip), dann alle Leitungen gleichzeitig einstecken. Dazu ein 220 Ohm Serienwiderstand auf der TX-Leitung als Schutz und ein 100nF Stützkondensator zwischen VCC und GND für eine stabile Versorgung.

Geflasht habe ich unter Linux mit stcgal:

stcgal -P stc15 -p /dev/ttyUSB1 -l 2400 -b 4800 -t 12000 u4.hex

Der Trick ist die niedrige Baudrate (-l 2400 für die initiale Kommunikation, -b 4800 zum Flashen) und das erhöhte Timeout (-t 12000). Zur Verifikation habe ich das Ganze nochmal mit STC-ISP v6.96S unter Windows (VirtualBox) gegengeprüft. Beides erfolgreich. Chip wieder eingelötet, weiter gehts.

U1 flashen: Der einfache Teil

Arduino Uno als ISP-Programmer mit Dupont-Kabeln an den Digital-Pins
Arduino Uno Power-Seite mit VCC und GND Verkabelung fuer ISP-Programmierung

Der ATmega324PA wird über ISP programmiert. Als Programmer dient ein ganz normaler Arduino Uno mit dem ArduinoISP-Sketch. Den lädt man in der Arduino IDE über File → Examples → ArduinoISP auf den Uno. Dann die Pins verbinden: MOSI (D11), MISO (D12), SCK (D13), RESET (D10) vom Arduino an den J4-Header auf der TC1-Rückseite, plus VCC und GND.

ISP-Kabel am J4-Header auf der TC1-Platinenrueckseite angeschlossen
Seitenansicht des TC1 mit angeschlossenem ISP-Kabel am J4-Header

Auf der TC1-Platine gibt es ein J4-Pad für ISP. Ich habe da einen Pin-Header aufgelötet, das macht das Leben bei zukünftigen Updates deutlich einfacher. Dann mit avrdude:

avrdude -c avrisp -p m324pa -P /dev/ttyACM0 -b 19200 -U flash:w:ComponentTester.hex:i

Das ging durch. Erster Versuch. Nach dem STC-Drama fühlte sich das fast verdächtig einfach an.

„Kas Rh- _BB“ — Was zur Hölle?

Nach dem Flashen das Display eingeschaltet und… „Kas Rh- _BB“ statt „Bat 3.83V ok“. Die Zeichen sahen aus wie ein kaputtes Font-Rendering. Stundenlang habe ich nach SPI-Fehlern gesucht, den Display-Treiber hinterfragt (ST7735 vs. SEMI_ST7735), die Pin-Belegung dreimal geprüft. Nichts half.

Die Lösung war so simpel wie ärgerlich: „Kas“ ist der Anfang von „Kaseikyo“, einem IR-Protokollnamen. Die m-firmware speichert Strings standardmäßig im EEPROM (DATA_EEPROM in der config.h). Aber ich hatte nur die .hex-Datei geflasht, nicht die .eep-Datei fürs EEPROM. Die Firmware las also zufällige alte Daten aus dem EEPROM und interpretierte sie als Text.

Der Fix: In der config.h DATA_FLASH statt DATA_EEPROM setzen. Dann werden alle Strings direkt im Flash-Speicher abgelegt und man braucht kein separates EEPROM-Flashing. Nochmal kompiliert, nochmal geflasht. Uff… Bis ich darauf gekommen bin *kopfschüttel*. Zugegeben, darüber nachgedacht habe ich aber ich war mir fast sicher das in einem mit geflashed zu haben. Fast sicher halt. Eine Nacht darüber schlafen hat geholfen, klassisch also im Problem festgefressen.

Batteriespannung: 19V aus einer LiPo-Zelle?

Nächstes Problem: Das Display zeigte 19V Batteriespannung an. Der TC1 läuft mit einer einzelnen LiPo-Zelle, das sind 3,7 bis 4,2V. Die Standard-Konfiguration der m-firmware geht von einem Spannungsteiler auf der Batterieleitung aus (BAT_DIVIDER mit R1=10k, R2=3.3k für einen 9V-Block). Der TC1 hat aber keinen Spannungsteiler, die Batteriespannung geht direkt an den ADC.

Fix: BAT_DIRECT statt BAT_DIVIDER in der config.h. Dazu die Schwellwerte anpassen: BAT_WEAK=3400 und BAT_LOW=3100 (in mV) für eine einzelne LiPo-Zelle.

TC1 Display zeigt Bat 3.83V ok und Probing nach korrekter BAT_DIRECT Konfiguration

So soll das aussehen. 3.83V, alles ok.

Menü und Kalibrierung

TC1 Menue mit Adjustment-Option fuer die Kalibrierung nach Firmware-Flash

Noch ein Stolperstein: Das Menü war nicht erreichbar. Die m-firmware hat verschiedene Wege, das Menü aufzurufen. Beim TC1 funktioniert das über UI_SHORT_CIRCUIT_MENU: Alle drei Probe-Pins im ZIF-Sockel kurzschließen und Start drücken. Dann öffnet sich das Menü mit Optionen für PWM, IR-Detector, Opto Coupler, Test und eben Adjustment.

Die Kalibrierung selbst ist einfach: Adjustment auswählen, mit leerem ZIF-Sockel starten, dann wenn gefordert einen Kurzschluss zwischen 123 einstecken. Die Firmware misst die internen Referenzen und speichert die Korrekturdaten. Dann den Kurzschluss wieder raus und es wird die Gegenprobe gemessen.

Die vollständige Konfiguration

Für alle, die das selbst machen wollen, hier die kompletten Änderungen gegenüber der Standard-Konfiguration der m-firmware (ComponentTester v1.56m):

Makefile:

MCU = atmega324p
FREQ = 16

config.h:

#define DATA_FLASH              /* Strings im Flash statt EEPROM */
#define UI_AUTOHOLD             /* Messergebnis halten bis Tastendruck */
#define UI_SHORT_CIRCUIT_MENU   /* Menü über Kurzschluss aller Probes */
#define BAT_DIRECT              /* Kein Spannungsteiler auf Batterie */
#define BAT_WEAK    3400        /* Warnung unter 3.4V */
#define BAT_LOW     3100        /* Abschaltung unter 3.1V */

config_644.h (Hardware-Mapping für den TC1):

/* Display: ST7735 über SPI Bit-Bang */
#define LCD_ST7735
#define LCD_RES     PB4
#define LCD_DC      PB5
#define LCD_SDA     PB6
#define LCD_SCL     PB7
#define LCD_FLIP_X
#define LCD_ROTATE
#define LCD_OFFSET_X    2
#define LCD_OFFSET_Y    1
#define LCD_LATE_ON
#define SPI_BITBANG         /* SDA auf PB6 statt Hardware-MOSI PB5 */

/* Probe-Widerstände auf PORTC statt PORTD */
/* PC0-PC5 für die drei Probe-Paare */

/* Power und Button */
#define POWER_PORT  PORTD
#define POWER_PIN   PD2
#define BUTTON_PIN  PD1

/* ADC-Pins vertauscht gegenüber Default */
#define TP_ZENER    PA4
#define TP_REF      PA3

Das Ergebnis

TC1 Startbildschirm zeigt Component Tester v1.56m nach erfolgreichem Flash

Component Tester v1.56m. Läuft.

TC1 mit m-firmware zeigt korrekt gemessenen 220 Ohm Widerstand an
TC1 erkennt MOSFET N-ch enh. mit Vth, Cgs und Rds Werten nach Firmware-Update

Widerstände, MOSFETs, alles wird sauber erkannt. Die Werte passen.

MOSFET-Messung auf dem TC1 nach Kalibrierung mit praezisen Vth und Rds Werten

Nach der Kalibrierung werden die Messwerte nochmal präziser. Vth 2065mV, Cgs 11.27nF, Rds 0.03 Ohm. Für einen 20-Euro-Tester absolut brauchbar.

Fazit und Quellen

War das ganze Prozedere nötig? Die originale Firmware funktioniert ja grundsätzlich. Aber wenn man sich auf die Messwerte verlassen will und nicht bei jedem unbekannten Bauteil rätseln möchte, lohnt sich der Aufwand. Die m-firmware liefert präzisere Ergebnisse, erkennt deutlich mehr Bauteile und hat ein richtiges Menü mit Kalibrierung. Und der J4-Header ist jetzt drauf, das nächste Firmware-Update ist dann tatsächlich in fünf Minuten erledigt.

Die fertige Firmware mit allen Config-Anpassungen für den TC1 und eine Schritt-für-Schritt-Anleitung habe ich auf GitHub gepackt. Da liegt auch die U4-Firmware (tc1-u4, GPL v3) und ein Verweis auf die m-firmware (EUPL v1.2).

Wer sich tiefer einlesen will:

Siehe auch:, Multifunktionstester für Elektronikbauteile: Schnell & günstig prüfen​

Fragen zum TC1 oder eigene Erfahrungen beim Flashen? Dann kannst du mich gerne fragen.

Eigener ADS-B Feeder: Flugzeuge tracken mit Raspberry Pi, RTL-SDR und selbstgebauter Antenne

Flugzeuge senden permanent ihre Position, Höhe und Geschwindigkeit auf 1090 MHz. Einfach so, unverschlüsselt, für jeden empfangbar. Das Ganze nennt sich ADS-B (Automatic Dependent Surveillance-Broadcast) und ist seit Jahren Standard in der Luftfahrt. Man braucht nur einen günstigen SDR-Empfänger und eine passende Antenne, um das Signal zu dekodieren. Und weil Dienste wie Flightradar24 auf Daten von freiwilligen Feedern angewiesen sind, bekommt man als Gegenleistung einen Business-Account, der sonst knapp 500 Euro im Jahr kostet.

Beitragsbild zum ADS-B-Feeder: Raspberry Pi mit RTL-SDR-Dongle und selbstgebauter 1090-MHz-Groundplane-Antenne, kombiniert mit einer Karte von Mitteleuropa mit zahlreichen Flugzeugsymbolen und einem Flightradar24-Dashboard-Overlay.

Ich wollte das schon länger mal ausprobieren. Ein Raspberry Pi lag noch herum, ein billiger RTL-SDR-Stick war schnell bestellt, und die Antenne habe ich selbst gebaut. Nach längerem Betrieb kann ich sagen: Das Projekt macht erstaunlich viel Spaß und liefert faszinierende Ergebnisse. Bis zu 335 km Reichweite mit einer Antenne aus Kupferdraht und einer N-Buchse für unter 10 Euro.

Was ist ADS-B eigentlich?

ADS-B steht für Automatic Dependent Surveillance-Broadcast. Jedes moderne Verkehrsflugzeug sendet damit periodisch seine GPS-Position, Flughöhe, Geschwindigkeit, ICAO-Kennung und Squawk-Code auf 1090 MHz. Das Signal ist nicht verschlüsselt und nicht authentifiziert. Jeder mit einem passenden Empfänger kann es dekodieren. Der Empfang ist legal und rein passiv, man sendet nichts.

Die Reichweite hängt von der Sichtlinie (Line of Sight) ab. Flugzeuge in großer Höhe sind über hunderte Kilometer empfangbar. Tieffliegende Maschinen oder Flugzeuge hinter Bergen dagegen nicht. Topografie spielt eine große Rolle.

Warum ein eigener Feeder?

Flightradar24 lebt von den Daten freiwilliger Feeder weltweit. Je mehr Stationen, desto besser die Abdeckung. Als Gegenleistung gibt es einen kostenlosen Business-Account. Der kostet regulär knapp 500 Euro pro Jahr und bietet unter anderem erweiterte Filter, historische Flugdaten und eine werbefreie Oberfläche. Für Hardware im Wert von 100 bis 150 Euro ein ziemlich guter Deal.

Geöffneter Filterdialog einer Flightradar24-App. Der Empfänger T-EDKB55 ist ausgewählt, Filterung ist aktiviert und ein benutzerdefinierter Filter (ICH) gesetzt. Unten Schaltfläche zum Hinzufügen weiterer Filter.

Nebenbei kann man die empfangenen Daten auch parallel an andere Dienste wie FlightAware oder ADS-B Exchange schicken. Und natürlich ist es einfach ein tolles Bastelprojekt mit sofort sichtbarem Ergebnis. Man sieht in Echtzeit auf einer Karte, welche Maschinen gerade über einem fliegen.

Hardware

Das Setup ist überschaubar:

KomponenteModellHinweis
EinplatinencomputerRaspberry Pi 4 Model B4 GB RAM, 64 GB SD-Karte
BetriebssystemPi24 (offizielles FR24-Image)Debian Bookworm, Kernel 6.12
SDR-DongleRealtek RTL2838 (RTL-SDR)Günstiger DVB-T-Stick als SDR-Empfänger
GPS-DongleVK-162 (u-blox 7)USB, 3D-Fix, ~10 Satelliten
AntenneEigenbau: λ/4-GroundplaneFür 1090 MHz, siehe Abschnitt Antennenbau

Der Raspberry Pi 4 ist für die Aufgabe eigentlich überdimensioniert. Ein Pi 2 oder 3 würde ebenfalls reichen. Das Pi24-Image von Flightradar24 bringt alles mit: Betriebssystem, den Feeder-Client fr24feed, den ADS-B-Decoder dump1090 und ein lokales Web-Interface. SD-Karte flashen, WLAN oder Ethernet konfigurieren, fertig.

Der RTL-SDR-Dongle ist ein umfunktionierter DVB-T-Stick. Die Dinger kosten zwischen 10 und 25 Euro und können in einem breiten Frequenzbereich empfangen. Für ADS-B braucht man 1090 MHz, das schaffen die meisten RTL2832U-basierten Sticks problemlos.

Standort

Mein Feeder steht im Raum Bonn/Hangelar (Siegburg-Umgebung). Nicht gerade der ideale Standort für maximale Reichweite. Die Eifel im Süden blockiert einen Teil des Empfangs, und die Antenne steht aktuell nur am Fenster. Trotzdem sind die Ergebnisse beeindruckend, dazu gleich mehr.

Meine Radar-ID bei Flightradar24: T-EDKB55.

Antennenbau: λ/4-Groundplane für 1090 MHz

Die mitgelieferten DVB-T-Antennen sind für den Frequenzbereich um 500 MHz ausgelegt. Für ADS-B auf 1090 MHz sind sie schlicht ungeeignet. Ich habe drei verschiedene gekaufte DVB-T-Antennen getestet. Alle performten schlechter als die Original-Stummelantenne. Das war frustrierend, aber auch lehrreich.

Die Lösung: Selbst bauen. Nach einer hervorragenden Anleitung von weberblog.net habe ich eine λ/4-Groundplane-Antenne gebaut. Das ist im Prinzip ein vertikaler Strahler mit vier Radialen, abgestimmt auf 1090 MHz.

Die Physik dahinter ist simpel: Die Wellenlänge bei 1090 MHz beträgt λ = c / f ≈ 27,5 cm. Ein Viertel davon (λ/4) ergibt 68 mm. Das ist die Länge jedes Antennenelements.

Material:

  • N-Einbaubuchse (N-Flanschbuchse)
  • 2,5 mm² Kupferdraht (massiv)
  • Koaxialkabel (RG213 oder Satellitenkabel)
  • M4-Schrauben zur Montage
  • Adapter je nach SDR-Stick (MCX, SMA oder BNC)

Aufbau: Ein Strahler (68 mm Kupferdraht) wird vertikal am Center-Pin der N-Buchse angelötet. Vier Radiale (ebenfalls 68 mm) werden an der Masse befestigt und ca. 45 Grad nach unten gebogen. Alle Elemente exakt auf 68 mm kürzen, das ist wichtig. Optional kann man einen Wetterschutz drüber stülpen, ein altes CD-Spindelgehäuse oder ein Stück PVC-Rohr tut es.

Laut der Bauanleitung von weberblog.net bringt die selbstgebaute Antenne im Indoor-Test +61% mehr erkannte Flugzeuge (39 → 63 Aircraft). Andere Bastler berichten von bis zu 160 NM Reichweite mit acht Radialen und Mastmontage. Meine Erfahrung bestätigt das. Der Unterschied zur Stummelantenne war sofort sichtbar.

Software

Das Pi24-Image bringt alles mit. fr24feed ist der offizielle Feeder-Client von Flightradar24. Er startet intern dump1090-mutability als ADS-B-Decoder und schickt die empfangenen Daten per UDP an die FR24-Server. Dazu läuft ein lighttpd für die lokalen Web-Interfaces.

Die Konfiguration liegt in /etc/fr24feed.ini:

receiver=dvbt
fr24key=<sharing-key>
path=/usr/lib/fr24/dump1090
bs=no
raw=no
mlat=yes
mlat-without-gps=yes
lat=50.578167
lon=6.948833
alt=1261

Lokal gibt es drei Web-Interfaces: Die FR24 Status-GUI unter http://<IP>/, den JSON-Monitor unter http://<IP>:8754/monitor.json und die dump1090-Karte unter http://<IP>:8080/. Die Karte zeigt in Echtzeit alle empfangenen Flugzeuge auf einer OpenStreetMap-Karte. Das alleine ist schon faszinierend.

Ersteinrichtung

Nach dem Flashen des Pi24-Images musste ich noch ein paar Dinge anpassen:

  1. Hostname geändert: pi24-bookwormflightradar24
  2. Statische IP konfiguriert via NetworkManager (DHCP → feste Adresse)
  3. GPS-Koordinaten in fr24feed.ini eingetragen
  4. dump978-fr24 deaktiviert (UAT 978 MHz wird in Europa nicht verwendet)
  5. Bluetooth deaktiviert (nicht benötigt, erzeugte unnötige Fehlermeldungen)
  6. OS-Update: 232 Pakete aktualisiert, Kernel von 6.6.21 auf 6.12.62
  7. Boot-Fix: Bind-Mount /boot/boot/firmware (Pi24-Image-Kompatibilität)

Reichweite und Ergebnisse

Nach drei Wochen Betrieb, noch mit der Antenne am Fenster:

MetrikWert
Flugzeuge aktuell getrackt (Snapshot)74 (34 ADS-B + 40 Non-ADS-B)
Flugzeuge gesamt gesehen1.541
Nachrichten verarbeitet~8,9 Millionen
Maximale Reichweite~335 km (~181 NM)
Signal (Durchschnitt)-20,9 dBFS
SNR~14,8 dB
CPU-Temperatur47,2 °C
Uptime20 Tage
Dashboard eines privaten Flightradar24-Empfängers (T-EDKB55) mit Status online, IP-Adresse und Betriebsdaten. Angezeigt werden Kennzahlen wie Anzahl erfasster Flugzeuge, gemeldete Positionen und Treffer sowie Diagramme zur täglichen Verfügbarkeit, Reichweite (Polar-Plot), Ranking und Histogramme.

335 Kilometer Reichweite. Mit einer Indoor-Antenne aus Kupferdraht für unter 10 Euro. Das war ein Norwegian-Flug (NOZ1802) über der Nordsee auf FL360. Das hätte ich vorher nicht für möglich gehalten.

Die Hauptabdeckung geht nach Norden und Nordwesten. KLM-Flüge über den Niederrhein und die Niederlande sind in 250 bis 335 km Entfernung problemlos sichtbar. Nach Nordosten reicht es bis ins Münsterland und den Raum Osnabrück. Nach Süden ist die Abdeckung durch die Eifel-Topografie eingeschränkt, aber Flüge bis in den Raum Trier/Luxemburg (~100 km) kommen noch durch. Lokal sieht man natürlich alles, was sich im Raum Bonn/Hangelar bewegt, Privatflieger, Kleinflugzeuge, Hubschrauber.

Kartenansicht von Mitteleuropa mit zahlreichen gelben Flugzeugsymbolen, die aktuellen Flugverkehr anzeigen. Hohe Dichte über Nordrhein-Westfalen, Benelux und den Niederlanden; einzelne Flugzeuge auch über Norddeutschland und Südwestdeutschland verteilt.

Ein paar Beispiele vom Snapshot:

CallsignAirlineHöheEntfernung
NOZ1802NorwegianFL360~335 km
BTI859airBaltic10.600 ft~249 km
KLM96EKLM14.725 ft~232 km
SIA314Singapore AirlinesFL360~25 km
BAW169British AirwaysFL330~16 km
UAE62TEmiratesFL380~42 km

Singapore Airlines, Emirates und British Airways über dem Rheinland. Das hat was.

Bug: NTP-Client in fr24feed 1.0.55-0

Achtung, Falle: Version 1.0.55-0 von fr24feed ist defekt. Der Feeder bleibt in einer Endlosschleife mit [time][e]Failed to synchronize time hängen und geht nie online. Nicht nur MLAT funktioniert nicht, das gesamte Feeding ist tot.

Ich habe das mit strace und tcpdump analysiert. Der statisch kompilierte interne NTP-Client löst pool.ntp.org per DNS korrekt auf, sendet aber nie UDP-Pakete auf Port 123. Der Client ist schlicht kaputt. Kein Workaround hat funktioniert: weder Root-Rechte, noch CAP_NET_RAW, noch ein lokaler NTP-Server, noch nftables DNAT-Umleitung.

Die Lösung ist ein Downgrade:

# Downgrade auf funktionierende Version
sudo apt install fr24feed=1.0.54-0
# Version pinnen gegen Auto-Update
sudo apt-mark hold fr24feed

Ich habe den Bug direkt an den FR24-Support gemeldet, mit strace-Nachweis, tcpdump-Capture und der kompletten Liste getesteter Workarounds. Die Antwort war ernüchternd: Man könne den Bug nicht reproduzieren, vermutet aber eine Library-Regression durch einen Wechsel des Build-Systems. Der Bug ist seit Januar 2026 auch im FR24-Forum bekannt (Threads #186163 und #231707). Da fr24feed proprietär und Closed Source ist, kann man leider keinen Pull Request einreichen.

Das bedeutet auch: MLAT (Multilateration) funktioniert bei mir aktuell nicht. MLAT würde es ermöglichen, auch Flugzeuge ohne ADS-B-Transponder zu erfassen, indem mehrere Feeder-Stationen die Signallaufzeiten triangulieren. Dafür braucht der Feeder aber eine exakte Zeitbasis, und genau die liefert der kaputte NTP-Client nicht. Sobald FR24 eine gefixte Version veröffentlicht, werde ich das aktivieren.

Kosten

PostenKosten
Raspberry Pi 4 (4 GB)~60–75 EUR
RTL-SDR USB-Dongle~10–25 EUR
Antenne (Eigenbau) / Kabel~5–10 EUR
GPS-Dongle VK-162~15 EUR
SD-Karte 64 GB~10 EUR
Netzteil, Kabel, Gehäuse~15–20 EUR
Gesamt~115–155 EUR

Für 115 bis 155 Euro bekommt man einen funktionierenden ADS-B-Feeder und einen Flightradar24 Business-Account im Wert von knapp 500 Euro pro Jahr. Das Projekt amortisiert sich also ziemlich schnell.

Was noch kommt

  • MLAT aktivieren, sobald FR24 den NTP-Bug fixt
  • Outdoor-Montage der Antenne mit Wetterschutz, das sollte die Reichweite nochmals deutlich verbessern
  • Parallel-Feeding an FlightAware, ADS-B Exchange und andere Dienste

Siehe auch:

Fragen, eigene Erfahrungen mit ADS-B oder Verbesserungsvorschläge? Gerne über das Kontaktformular.

Dallas DS80C400: 8051-Ethernet-Mikrocontroller neu entdeckt

Vor ziemlich genau 20 Jahren habe ich in einem Unternehmen gearbeitet, in dem Teile einer eigens entwickelten Lösung eine Zeit lang auf einem DALLAS DS80C400 basierten.

Dallas TINI400 evaluation board with DS80C400 microcontroller

Der DALLAS DS80C400 ist ein hochintegrierter, netzwerkfähiger Mikrocontroller, der auf der Architektur des klassischen 8051 basiert. Entwickelt wurde er von Dallas Semiconductor (später Maxim Integrated) und war besonders für eingebettete Systeme geeignet, die eine Ethernet-Konnektivität benötigten.

Ja, klingt nicht weiter spannend, ich weiß – aber wir schreiben ja auch das Jahr 2025 und nicht 2005. Viele werden sich erinnern, dass der Raspberry Pi (Model B) im Februar 2012 veröffentlicht wurde. Arduino gab es zwar bereits seit 2005, aber ein einfach nutzbares TCP/IP-Netzwerk? Das war damals noch nicht so selbstverständlich. Der DS80C400 war mit seinem integrierten Netzwerkstack also ein ziemlich guter Mikrocontroller seiner Zeit.

Ich hatte ihn damals fertig montiert auf den Entwicklerboards von MAXIM in den Fingern. Das DSTINIM400 Embedded-Modul hatte 1 MB Flash, 1 MB SRAM, konnte 10/100 Mbit/s Ethernet, hatte zwei serielle RS232-Schnittstellen und noch ein paar andere nette Features. Dieses Modul steckte dann auf einem DSTINIS400, das – na ja, nennen wir es Hostboard – also eine Platine, die das DSTINIM400 aufnimmt und die verschiedenen Schnittstellen bereitstellt (Maxim TINI s400 Evaluation Board Socket).

Genau so ein Teil habe ich nun beim Aufräumen meiner „da muss ich noch mal nachschauen“-Elektronikkiste gefunden. Wirklich etwas damit tun wollte ich nicht, aber aus nostalgischen Gründen wollte ich es zumindest einmal booten sehen. Meine Erinnerung daran, wie das alles genau funktionierte, ist allerdings ziemlich verblasst. Irgendwas war da mit einer der beiden RS232-Schnittstellen und einem Terminalprogramm … also los.

Die mit Loader – Serial 0 beschriftete RS232-Schnittstelle war es, meine ich. Also habe ich mein Breakout-Board angeschlossen und ein bisschen herumgemessen. Sah soweit richtig aus – zumindest zeigte mein Oszilloskop beim Booten Aktivität auf den Datenleitungen. Die Pin-Belegung ist 1:1.

DSTINIm400 (DB9, DCE)PC (DB9, DTE)Funktion
2 (TXD)2 (RXD)Senden → Empfangen
3 (RXD)3 (TXD)Empfangen ← Senden
5 (GND)5 (GND)Gemeinsame Masse

Die Konfiguration der RS232 ist 9600 Baud, also 9,6 kbps. Dann noch 8N1:

  • 8 Datenbits (8 Bits pro Zeichen)
  • N Paritätsbit (keine Parität)
  • 1 Stoppbit

Da wirklich nur diese drei Leitungen benötigt werden, habe ich den Rest direkt beim Aufruf meiner Terminalemulation deaktiviert:

screen /dev/ttyUSB1 9600,cs8,-dtr,-rts

Hm … es passiert etwas, aber leider kommt nur Zeichensalat. Das spricht eher dafür, dass ich eine falsche Baudrate eingestellt habe. Also habe ich unterschiedliche Geschwindigkeiten ausprobiert – leider mit mehr oder weniger dem gleichen Ergebnis.

Vielleicht ist das auch der Grund, warum das Teil überhaupt in dieser Kiste gelandet ist?!

Ich wollte schon aufgeben, da fiel mir auf der Rückseite etwas auf: Ein MAX560CAI, ein Low-Dropout-Voltage-Regulator. In seiner direkten Nachbarschaft fehlen zwei Kondensatoren – C33 und C34. Klingt so, als wenn dort ein Keramik- oder Tantal-Kondensator für 10V und irgendwas zwischen 1 µF bis 10 µF hingehört. Und das könnte durchaus problematisch sein, denn einige Leitungen führen direkt bis zur RS232-Schnittstelle.

Um die richtigen Werte für die Kondensatoren zu finden, musste ich dann doch ein bisschen im Internet suchen. Dabei bin ich zumindest schon mal auf ein paar PDFs gestoßen, die ich hier mit euch teilen möchte.

DSTINIS-005-DSTINIS400.pdf
TINI_GUIDE.pdf
DSTINIm400.pdf
DSTINIm400EVKit.pdf

Im DSTINIS-005-DSTINIS400.pdf bin ich dann zum Glück fündig geworden:

  • C10, C31, C32, C34-C361 µF
  • C3310 nF

Passende SMD-Bauteile hatte ich zwar nicht (nicht gefunden), aber THT sollte für einen Test reichen. Für C33 habe ich einfach ebenfalls einen 1 µF-Kondensator genommen – das war mir passend genug für einen Versuch.

Noch ein Test mit 115200 Baud und … ha, er bootet!

TINI Slush OS v1.17 – man, man, man … lange nicht gesehen!

Siehe auch: PDS OSIcom-Office Box: Retro-PC mit JUMPtec SBC & SUSE Linux​

FRITZ!Box 7590: Fiepen, Spannungsregler-Probleme und WLAN-Ausfälle​

Eigentlich sollte die Überschrift heißen: Ärgere ich mich gerade über mich selbst oder über AVM?

PCB der FritzBox 7590 mit Zoom auf den MP1477 Spannungsregler

Zuhause arbeitete eine FRITZ!Box 7590 KA, die zu Beginn mit einem Frixtender erweitert wurde. Nach knapp zwei Jahren habe ich bemerkt, dass die FRITZ!Box angefangen hat zu fiepen. Eine Funktionseinschränkung konnte ich jedoch nicht feststellen. Da es aber knapp vor dem Ablauf der Garantie war, habe ich Kontakt mit dem AVM-Support aufgenommen.

Dem AVM-Support habe ich in einer kurzen E-Mail geschildert, dass meine Box plötzlich fiept und ob ihnen in diesem Zusammenhang vielleicht Probleme, beispielsweise mit Spulen oder Spannungsreglern, bekannt sind. Die Antwort vom AVM-Support ließ nicht lange auf sich warten und lautete zusammengefasst: „Nein, uns sind keine Probleme bekannt, aber du kannst deine Box gerne zur Überprüfung/Austausch einschicken.“

Jetzt kommen wir zum Punkt, warum ich mich ärgere und unschlüssig bin, ob ich mich über mich selbst oder über AVM ärgere. Für meine Arbeit benötige ich eine funktionsfähige Internetverbindung. Wenn ich die Box einschicke, muss ich für eine Alternative sorgen. Wenn AVM die Box vorsorglich gegen eine neue tauscht, wäre das zwar schön, aber es gibt schon zu viel Elektroschrott. Elektronik darf Geräusche machen. Spulen könnt ihr euch oft wie eine Art Schwungrad vorstellen. Es braucht etwas, um anzulaufen, läuft dann aber auch noch einige Zeit weiter, selbst wenn es niemand mehr antreibt. Das hängt mit den aufkommenden Magnetfeldern zusammen und ist so gewollt. Magneten kennt ihr, und dass dort Kräfte an den Bauteilen ziehen, könnt ihr euch jetzt ebenfalls vorstellen. Eine Spule kann also mit der Zeit anfangen, leichte Geräusche zu machen, und das ist auch okay. Für Spannungsregler gilt das ebenfalls. Stellt euch einfach euren Wasserhahn vor: Wenn ihr ihn voll aufdreht, kommen da vielleicht 5 Liter in der Minute heraus. Wenn ihr weniger Wasser wollt, macht ihr den Hahn ganz schnell an und wieder aus. Wie schnell ihr das Wasser ein- bzw. ausschalten müsst, um beispielsweise nur 1 Liter pro Minute fließen zu lassen, messt ihr mit euren Augen. Ganz grob funktionieren Schaltnetzteile so. Je nach Last kann man da also schon mal etwas hören, und das ist okay.

So ist ein weiteres Jahr ins Land gegangen, bis mir in einem meiner Newsticker die Meldung über sterbende FRITZ!Boxen vom Typ 7590 aufgefallen ist. Hier wird von anfänglichem Fiepen, schlechter werdendem 2,4-GHz-WLAN bis hin zum Totalausfall des WLANs und der Box berichtet. Bääähhhhh. Das klang verdächtig nach dem von mir beobachteten Fehlerbild. Nun ist meine Box aus jeglicher Garantie und Gewährleistung heraus. Den AVM-Support brauche ich also nicht mehr zu bemühen, sondern kann mich vielmehr mit dem Gedanken anfreunden, eine neue Box zu kaufen, um auf einen Ausfall vorbereitet zu sein. Zeitgleich haben bei uns im Ort die Arbeiten am Glasfaserausbau begonnen. Diese gehen so schnell und gut voran, dass ich damit rechnen kann, bis zum Ende dieses Jahres von DSL auf Glasfaser wechseln zu können. Mit diesem Wechsel kommt vom Anbieter auch eine neue FRITZ!Box. Tjo… Also Risiko eingehen oder eine Box kaufen, die in 5 oder 6 Monaten dann wohl irgendwo im Regal Staub fängt?

Bevor es eine Antwort auf diese Frage gibt, noch schnell zum Punkt mit dem Ärgern: Ich habe AVM bewusst gefragt, ob es bekannte Probleme mit der Box gibt und speziell auf die aus meiner Sicht verdächtigen Bauteile hingewiesen. Die Antwort war ein klares Nein. Das muss ich jetzt einfach so glauben, aber ich werde den Beigeschmack nicht los, dass es zum Zeitpunkt meiner Supportanfrage schon einige Reklamationen wegen dieses Problems gegeben haben müsste. Daher wohl mein möglicher Ärger über AVM – und dass ich auf die Möglichkeit eines Austauschs verzichtet habe – und der Ärger über mich selbst.

Habe ich jetzt eine neue Box gekauft oder nicht? Nein, habe ich natürlich nicht. Ich habe meine Box von der Wand genommen, aufgeschraubt und durchgemessen. Ja, Geräusche und etwas zu hohe Spannung für das 2,4-GHz-WLAN habe ich gemessen bzw. zuordnen können. Alles aber noch im Rahmen, sodass ich gehofft habe, dass es noch ein paar Monate gutgeht. War leider nicht so. Vor ein paar Wochen ist die Box an der Wand „geplatzt“ und ich musste in den sauren Apfel beißen und eine neue für den Übergang kaufen. Jetzt habe ich wohl ein Backup für die Zukunft. Woohoo 🙁 Manchmal lerne ich nicht so schnell dazu, oder? Naja, manchmal kommt halt eins zum anderen.

Ob meine alte Box wirklich mit genau dem beschriebenen Problem ausgefallen ist, wollte ich dennoch herausfinden. Die Sichtprüfung war noch immer gut, aber es war keine Spannung mehr zu messen. Daher habe ich mir von Aliexpress ein paar MP1477 (die genaue Bezeichnung ist MP1477GTF-Z) zuschicken lassen. Ich habe direkt alle drei verbauten Chips ausgetauscht und siehe da, die Box lebt wieder. Oft sollen dabei wohl noch die RF FRONT ENDs 055F als Folge der zu hohen Spannung sterben, aber diese haben es bei mir zum Glück überlebt.

PCB der FritzBox 7590 mit Zoom auf den MP1477 Spannungsregler

Nun habe ich also auch noch ein Backup für das zukünftige Backup. Super…

Da ich bei Aliexpress insgesamt 10 Stück bestellt habe, liegen hier jetzt noch ein paar herum. Ich wäre bereit, sie gegen ein Snickers zu tauschen, falls jemand von euch vor einem ähnlichen Problem steht. Uhh, und bedenkt bitte, dass die Dinger ECHT klein sind. Ich habe euch mal einen auf ein 1-Cent-Stück gelegt. Ohne Heißluftstation und etwas SMD-Löterfahrung solltet ihr das vielleicht lieber nicht angehen.

Größenvergleich zwischen dem MP1477 Spannungsregler und einem Euro-Cent-Stück

Die Messpunkte und die erwarteten Spannungen findet ihr im folgenden Bildchen.

PCB der FritzBox 7590 mit eingezeichneten Messpunkten und Messwerten des MP1477 Spannungsreglers

Wenn ihr dann noch Fragen habt, fragt einfach 🙂

Siehe auch: Bosch Geschirrspülmaschine E-21 beheben

Fragen? Einfach melden.

FNIRSI GC-01 Upgrade: Akku, Zählrohr & Rad Pro Firmware installieren​

Bei meinen letzten Einkaufstouren auf AliExpress ist mir immer wieder ein FNIRSI GC-01 Nuclear Radiation Detector vorgeschlagen worden — ein Geigerzähler für knapp 30 €. Irgendwann lag das Ding im Einkaufswagen. Nach ein paar Spielereien ging mir aber schnell die Batterielaufzeit auf die Nerven — das Teil war im Grunde immer leer. Also aufschrauben und schauen, was man verbessern kann.

Was steckt drin?

PCB des FNIRSI GC-01: Spannungswandler, Multiplier und MCU sichtbar.

Das Gerät kam mit einem J613 Geiger-Müller-Zählrohr — Beta- und Gammastrahlung, Betriebsspannung 300–400 V, ganz brauchbar für niedrige Strahlungsniveaus. Die Platine ist simpel aufgebaut:

  1. Spannungswandler — baut vom USB-C-Anschluss oder 3,7-V-Akku ca. 130 V AC auf.
  2. 3-Stage Multiplier — vervielfacht die Spannung auf die nötigen ~400 V für das Zählrohr.
  3. CH32F103 MCU — je nach Revision auch ein ARM-Controller. Steuert Display, Piezo-Tongeber und Messlogik.

Dazu eine CR1220 Knopfzelle für Uhrzeit und Messwertespeicher und ein 3,7-V-Akku mit mageren 1.100 mAh (~4 Wh) — das erklärt die kurze Laufzeit. Nahe der MCU sind vier Löcher mit der Beschriftung JP1. Das ist ein ST-Link-Anschluss: von links nach rechts +3,3 V, SWDIO, SWCLK, GND.

ST-Link-Anschluss (JP1) auf dem FNIRSI GC-01 PCB mit angeloeteter Stiftleiste.

Aufgefallen ist mir auch, dass nicht jedes Teilchen ein hörbares Knacken auslöst. Die rote LED über dem Display blinkt bei jedem Impuls, aber der Piezo-Tongeber wird ausschließlich per Firmware angesteuert — und die Entwickler haben da anders entschieden.

Hardware-Upgrades: Akku und Zählrohr

Die CR1220 kam schon verbraucht an — ausgetauscht. Für den Akku hat sich ein passender Ersatz mit 2.200 mAh gefunden, der ins Gehäuse passt. Das sollte die Laufzeit fast verdoppeln.

FNIRSI GC-01 mit ausgetauschtem 2200-mAh-Akku.

Das J613 ist solide, aber ich hatte noch ein SBM-20-1 aus einem früheren Projekt in der Schublade. Das SBM-20-1 braucht 380–450 V, erfasst ebenfalls Beta- und Gammastrahlung und hat eine ähnliche Bauform. Wenn man die beiden Haltepfosten des J613 auslötet, passt die SBM-20-1 rein — ein Tropfen Heißkleber hält sie an Ort und Stelle.

FNIRSI GC-01 mit eingebautem SBM-20-1 Zaehlrohr anstelle des originalen J613.

Das SBM-20-1 ist bei geringer Strahlung nicht ganz so empfindlich wie das J613 und das Fenster für Betastrahlung ist etwas kleiner. Aber das Ding ist fast unkaputtbar — und wenn die Firmware das Zählrohr kennt, kann sie die Unterschiede per Kalibrierung ausgleichen. Sowohl auf der Röhre als auch auf dem PCB sind +/−-Markierungen — Polarität beim Einbau beachten.

Rad Pro — alternative Firmware

Die Stock-Firmware konnte wenig. Kein Datalogger, keine Hintergrundstrahlung filtern, kein Einfluss auf den Stromverbrauch. Bei der Recherche bin ich schnell auf Rad Pro gestoßen — eine Open-Source-Firmware für den GC-01 und andere Geigerzähler. Die kann alles, woran ich gedacht habe, und mehr.

Die Installationsanleitung ist überschaubar. Der Weg über das USB-Laufwerk hat bei mir nicht funktioniert — am Ende habe ich eine Stiftleiste auf JP1 gelötet und die Firmware über ST-Link geflasht. Fühlt sich zuverlässiger an.

Update auf Rad Pro 3.x

Mittlerweile ist Rad Pro bei Version 3.x angekommen — ein deutlicher Sprung. Installation wieder über ST-Link, wieder auf Anhieb sauber:

kernel@ErrorWork:~/radpro/fnirsi-gc01_ch32f103r8$ sudo ./install.sh
Available language codes: bg cs da de el en es fi fr hr hu it nl ...
Enter language code for Rad Pro installation: de
** Programming Started **
** Programming Finished **

Nach dem Flashen lief das Gerät sofort stabil. Alle Einstellungen wurden übernommen, nur den Zählrohrtyp musste ich neu setzen.

Die wichtigsten Neuerungen in 3.x gegenüber den 2.x-Versionen:

  • 27 Sprachen — Deutsch, Englisch und 25 weitere.
  • History bis zu einem Jahr — deutlich erweiterte Aufzeichnung.
  • Power-Management — Auto-Shutdown, überarbeitete Akku-Logik, kein versehentliches Einschalten bei USB-Power.
  • Messgenauigkeit — längere Mittelungsintervalle, größere Sensitivitätsspanne, verbesserte Dead-Time-Kompensation.
  • UI — Skalierung, sekundäre Einheiten, visuelle Alarm- und Warnzonen.
  • Weitere Geräte — u. a. GQ GMC-800.

Den vollständigen Changelog gibt es bei den Rad Pro Releases auf GitHub.


Ein paar Bilder vom Gerät mit der Rad Pro Firmware — die einzelnen Menüs und Anzeigen:

Fazit

Für 30 € plus ein paar Euro für Akku und Zählrohr hat man einen brauchbaren Geigerzähler mit Open-Source-Firmware, Datalogger, konfigurierbaren Alarmen und ordentlichem Power-Management. Dass beim GC-01 weiterhin der Weg über ST-Link nötig ist, bleibt unschön — liegt aber an der Hardware, nicht an Rad Pro.

Wer sich für Messtechnik und Physik-Hardware interessiert — im Quantis-USB-Beitrag geht es um einen Hardware-Quantenzufallsgenerator, ein ähnlich spannendes Bastelprojekt.

Viel Spaß beim Basteln — bei Fragen einfach melden.

Arduino und die jammernde Pflanze: Technik trifft Humor

Auf irgendeinem CCC Event bin ich über eine lustige Projektidee einer jammernden Pflanze gestoßen. Die hat mir und auch meiner größeren Tochter so gut gefallen, dass wir sie zusammen nachbauen wollten.

Geöffnetes Gehäuse mit der gesamten Technik für das Arduino-Projekt: Die jammernde Pflanze

Die Idee

Ein kleines Gerät misst den Feuchtigkeitsgehalt der Blumenerde. Ist der Wert zu trocken, spielt ein MP3-Player eine Audiodatei ab. Ein Bewegungsmelder sorgt dafür, dass die Pflanze sich nur beschwert, wenn auch jemand da ist. Ist die Erde trocken und es wird eine Bewegung erkannt, jammert die Pflanze los.

Die Bauteile

Da es das erste Projekt dieser Art für meine Tochter ist, sollte es übersichtlich und einfach bleiben. Ein Arduino Nano (fast die gleichen Möglichkeiten wie der UNO, aber deutlich kleiner), ein DFPlayer-Modul als MP3-Player, ein HC-SR312 Bewegungsmelder und ein kapazitiver Feuchtigkeitssensor.

Aufbau und Entwicklung

Gestartet haben wir mit einem Breadboard, um die Verschaltung Modul für Modul zu setzen und die Ansteuerung mit dem Arduino anhand der Beispiele zu testen. Beim DFPlayer haben wir per TTS Texte in MP3s umgewandelt und auf der SD-Karte im Ordner mp3 gespeichert. Diese werden zufällig abgespielt, wenn die Erde zu trocken ist und eine Bewegung erkannt wurde.

Als die Verschaltung zusammen mit dem Code funktionierte, haben wir mit KiCad eine Platine designt und fertigen lassen. So hat man weniger Kabelsalat und alles ist platzsparend aufgehoben.

Elektrischer Schaltplan für die jammernde Pflanze

Das Gehäuse haben wir in FreeCAD designt und mit dem 3D-Drucker gedruckt. Die Teile sind mit einem Tropfen Sekundenkleber fixiert.

FreeCAD-Design des Gehäuses für die jammernde Pflanze

Im Einsatz

Das Teil steckt in der Blume und meldet sich zuverlässig, wenn es Zeit zum Gießen ist. Da es von den MP3s auf dem Player abhängt, was die Pflanze „sagt“, sind lustige Reaktionen garantiert. Die Pflanze kann dich im Vorbeigehen voll jammern, um Wasser betteln oder anfangen zu schimpfen.

Meine Tochter wird nach dem Projekt nicht alles alleine wiederholen können, aber die einzelnen Schritte sind klar. Wie so ein Gerät entsteht, was nötig ist. Schnell findet man Verbesserungsmöglichkeiten: Den Feuchtigkeitssensor von der Elektronik trennen, mit einem NodeMCU ESP8266 WLAN-Statusdaten senden, oder mit Li-Ion-Akkus und einem BMS vom Stromnetz unabhängig werden.

Quellcode

Für den DFPlayer wird die DFRobotDFPlayerMini Library benötigt (lokal unter ~/Arduino/libraries ablegen).

#include <Arduino.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>

/* --- Pins ---------------------------------------------------- */
const uint8_t PIN_DF_RX   = 10;
const uint8_t PIN_DF_TX   = 11;
const uint8_t PIN_PIR     = 7;
const uint8_t PIN_SENSOR = A0;

/* --- Parameter ----------------------------------------------- */
const int schwellwert = 380;
const unsigned long PLAY_COOLDOWN_MS = 15000;
const uint8_t TRACK_JAMMERN = 1;

/* --- Objekte ------------------------------------------------- */
SoftwareSerial dfSerial(PIN_DF_RX, PIN_DF_TX);
DFRobotDFPlayerMini dfPlayer;

/* --- Laufzeitstatus ------------------------------------------ */
unsigned long lastPlay = 0;

/* ------------------------------------------------------------- */

void setup() {
  pinMode(PIN_PIR, INPUT);

  Serial.begin(115200);
  dfSerial.begin(9600);

  Serial.println(F("Initializing DFPlayer ..."));

  if (!dfPlayer.begin(dfSerial)) {
    Serial.println(F("DFPlayer init failed"));
    while (true);
  }

  dfPlayer.volume(20);
  dfPlayer.outputDevice(DFPLAYER_DEVICE_SD);
  dfPlayer.EQ(DFPLAYER_EQ_NORMAL);
  dfPlayer.setTimeOut(500);

  Serial.println(F("DFPlayer Mini online"));
}

/* ------------------------------------------------------------- */

void loop() {
  /* DFPlayer Events immer zuerst abholen */
  if (dfPlayer.available()) {
    handleDFPlayerEvent(dfPlayer.readType(), dfPlayer.read());
  }

  int messwert = analogRead(PIN_SENSOR);
  bool bewegung = digitalRead(PIN_PIR) == HIGH;
  bool trocken = messwert > schwellwert;

  unsigned long now = millis();

  if (trocken && bewegung) {
    if (now - lastPlay >= PLAY_COOLDOWN_MS) {
      Serial.println(F("Bewegung + Erde trocken -> spiele Sound"));
      dfPlayer.play(TRACK_JAMMERN);
      lastPlay = now;
    }
  } else {
    logStatus(trocken, bewegung, messwert);
  }

  delay(100);  // leichte Entlastung – kein Logik-Delay
}

/* ------------------------------------------------------------- */

void logStatus(bool trocken, bool bewegung, int messwert) {
  if (!bewegung && trocken) {
    Serial.print(F("Keine Bewegung, Erde trocken: "));
  } else if (bewegung && !trocken) {
    Serial.print(F("Bewegung, Erde ok: "));
  } else if (!bewegung && !trocken) {
    Serial.print(F("Keine Bewegung, Erde ok: "));
  }
  Serial.println(messwert);
}

/* ------------------------------------------------------------- */

void handleDFPlayerEvent(uint8_t type, int value) {
  if (type == DFPlayerPlayFinished) {
    Serial.print(F("Track "));
    Serial.print(value);
    Serial.println(F(" beendet"));
  }
}

Downloads

3D-Druck: STL Gehäuse | STL Deckel
Platine: Gerber-Dateien

Einkaufsliste

Optional: Breadboard mit Kabeln, Multimeter, Lötkolben

Fragen? Einfach melden.

DIY Feinstaubsensor bauen: Luftqualität selbst messen mit ESP8266​

Bild vom DIY Feinstaubsen und Luftqualitätsensor beim Aufbau.

Es gibt ein ganz spannendes Projekt, welches sich mit dem Messen und Sammeln von Umweltdaten beschäftigt. So gibt es vom Projekt einige Bauanleitungen inkl. Software zum Messen der Luftqualität, Temperatur, Luftfeuchtigkeit, Lärm usw… Die Webseite findet ihr hier: https://luftdaten.info/

Im einfachsten Fall basiert so ein Sensor am Ende auf folgenden Komponenten:
NodeMCU ESP8266, CPU/WLAN
SDS011 Feinstaubsensor (früher PPD42NS)
DHT22, Temperatur & Luftfeuchtigkeit (optional)

Die Daten werden offen gesammelt und können auf verschiedene Weise eingesehen werden. So gibt es zum Beispiel:
– eine Karte:  https://maps.sensor.community
– Grafana: Temperatur / Feinstaub

Die Bauanleitung ist extrem einfach, die Teile bekommt jeder und kosten kaum Geld. Selbst der Softwareteil ist ohne jeden Aufwand. Man muss nicht mal löten! Fast jeder sollte in der Lage sein so einen Sensor zu bauen und ihn mit seinem WLAN zu verbinden. Vielleicht ein schönes Projekt mit seinen Kindern oder um sich im Unterricht mit so etwas zu beschäftigen?!?

Fragen? Dann fragen!

Siehe auch: DHT22 am Raspberry Pi

Fragen? Einfach melden.

Riden RD6006 Labornetzteil: Zusammenbau und erster Eindruck

RIDEN RD6006 DC POWER SUPPLY Labornetzteil

Vor gut 20 Jahren habe ich mir ein Labornetzteil gebaut. Elektronik lernen und verstehen war das Ziel. Das Gerät liefert 30 V bei 3 A, ist kurzschlussfest und hält Strom und Spannung auch unter Last sauber. Komplett analog, mit zwei dreistelligen Segmentanzeigen. Ein treuer Begleiter, aber mit klaren Grenzen: Mehr als 30 V oder 3 A geht nicht. Feine Einstellungen brauchen ein zusätzliches Messgerät. Verlaufskurven speichern, vorgespeicherte Werte abrufen oder schnell zwischen Werten wechseln? Keine Chance. Dazu die hohe Verlustleistung des alten Trafos.

Warum das RD6006

Ein Highend-Gerät brauche ich nicht. Meine Anwendungen sind zu simpel dafür. Preis und Leistung müssen stimmen. So bin ich auf das Riden RD6006 gestoßen. Ein Modul von AliExpress aus China. Ja, von dort kommt auch viel Schrott. Aber die Eckdaten klangen gut genug, um es zu probieren: 60 V, 6 A, USB-Anbindung, Firmware-Updates, Akku-Ladefunktion, vorprogrammierbare Werte.

Zusammenbau

Nach knapp drei Wochen waren alle Teile da. Das Handbuch gibt es als PDF in Chinesisch und Englisch, das Nötigste ist beschrieben. Der Zusammenbau ist unkompliziert: Schaltnetzteil ins Gehäuse, RD6006-Modul einsetzen, verkabeln, fertig.

Was nicht so gut läuft

Das WLAN-Modul funktioniert nicht so, wie ich es erwarten würde. Der Temperatursensor zur Akkuüberwachung beim Laden muss irgendwie aus dem Gehäuse geführt werden. Und die Schutzerde habe ich zusätzlich ans Gehäuse geklemmt, das war mir so lieber.

Fazit

Davon abgesehen: Das Ding ist gut. Es tut was es soll und erweitert meine Möglichkeiten erheblich gegenüber dem alten Analognetzteil. Für den Preis eine klare Empfehlung, wenn man kein Keysight braucht. Wer es nachbauen will: Riden RD6006 auf AliExpress.

Siehe auch: Multifunktionstester für Bauteile

Fragen? Einfach melden.

« Ältere Beiträge

© 2026 -=Kernel-Error=-RSS

Theme von Anders NorénHoch ↑