Zum Hauptinhalt springen
LocoTV Video Handheld

LocoTV Video Handheld

··2580 Wörter·13 min·
Inhaltsverzeichnis

UPDATE 12.02.26:
Das Gehäuse wurde optimiert. Die SD-Karte kann nun ohne Auseinanderschrauben entnommen und neu mit Videomaterial bestückt werden. Gleichzeitig gibt es nun ein kleines Sichtloch, um den aktuellen Ladezustand des TP 4056 Batterielademoduls anzuzeigen: ROT = Batterie lädt, GRÜN = Batterie geladen.


Nachdem mein erster Neffe vor Jahren mit seiner eigenen Phoniebox beglückt wurde, war es an der Zeit seinem jüngeren Bruder eine kleine Freude zu machen.

Mein Neffe ist ein waschechter Pufferküsser mit einer ausgeprägten Begeisterung für Züge, insbesondere für alte Dampflokomotiven. Da er regelmäßig sämtliche Bildschirme einnimmt um Videos von Schienen­fahrzeugen zu konsumieren, habe ich mich ans Werk gesetzt und ihm ein kleines feines Gerät gebaut, mit dem er diese eigenständig schauen kann.

Initialer Funke für den Eigenbau war ein Video des Youtube Kanals thelastoutpostworkshop, das mir zufällig über den Weg lief:

Herausgekommen ist der LocoTV, ein kleiner Handheld im Hochkantformat, mit einem gedrucktem Gehäuse, einer Batterie und Ladeelektronik:

Ergebnis des Zusammenbaus

Der finale LocoTV

Hardware

Zentrale Rolle in diesem Projekt spielt das Cheap Yellow Display, kurz auch CYD genannt. Der Name ist etwas sonderbar, beschreibt aber anschaulich, worum es sich hierbei handelt: Es ist eine kompakte Displayplatine mit einer Auflösung von 320x240 Pixeln und Touch-Funktionalität mit diversen Zusatzkomponenten, bspw. einem Helligkeitssensor, einer LED und einem Micro SD-Kartenleser. Die Platine kommt in gelber Farbe daher. Angetrieben wird es durch einen ESP32 Microcontroller. Das Display ist in unzähligen Varianten erhältlich, die sich hauptsächlich in den Anschlüssen der Stromversorgung (Micro USB vs. USB-C), SPI-Taktung, aber auch in der eingesetzten Variante des ESP32 unterscheiden. Ich nutze für dieses Projekt die Version 2.0 des CYD mit USB-C Anschluss.

Die Materialkosten für die Hardware belaufen sich mit Versand auf ca. 30 €:

Funktion Bezeichnung Kosten
Display Cheap Yellow Display 2.8" 320x240 (ESP32-2432S028) 8,29 €
Spannungswandler MT3608 High Efficiency 1.2MHz 2A DC-DC Step Up Converter 1,89 €
Power Button Blue circle light, 16MM, Latching, 6V
Wichtig ist, dass es sich um einen Button mit Rastfunktion (latching switch) und keinen Drucktaster (momentary switch) handelt.
2,19 €
Batterielademodul TP4056 1A Standalone Linear Li-lon Battery Charger with Thermal Regulation in SOP-8 1,39 €
Batterie NCR18650B Pointed 18650 3400mAh 3.7V Li-ion 5,69 €
Batteriehalterung 18650 Battery Holder Case 4,97 €
JST-Connector JST 1.25mm MX1.25 4 Pin 2,89 €
SD-Karte Eine 8 GB SD-Karte flog bei mir noch rum. 0,00 €

Software

Wie bereits in der Einführung erwähnt, stammt der Code vom Autoren thelastoutpostworkshop. Das Repository esp32-2432S028_video_player ist bei Github verfügbar. Als Codebase für meinen Eigenbau habe ich jedoch den Fork cyd-video-player verwendet, da dieser Support für den Touchscreen ergänzt. Dies ermöglicht, mit einem kindgerechten Touch auf das Display, das nächste Video abzuspielen.

Alle meine Anpassungen sind im Repository schneekluth/locotv verfügbar:

Die benötigten Schritte zum Bezug der Software:

  1. Den Code als ZIP Datei herunterladen und entpacken.
  2. Den Ordnernamen von locotv-main in locotv umbenenen.
  3. Ein Doppelklick auf die Datei locotv.ino öffnet die Arduino IDE.

SD Karte vorbereiten

Im ersten Schritt muss die SD-Karte im FAT32-Dateisystem formatiert werden:

FAT32 Formatierung für die SD-Karte

Anschließend in den heruntergeladenen Ordner locotv/ ins Verzeichnis SD Content/ wechseln. Darin befindet sich ein Ordner mjpeg mit Beispielvideos. Dieser Ordner muss auf die SD-Karte kopiert werden:

Ordnerstruktur auf der SD-Karte

Die SD-Karte ist damit einsatzbereit und kann in den SD-Kartenleser vom Cheap Yellow Display gesteckt werden.

Das Cheap Yellow Display kann nun per USB mit dem Computer verbunden werden. Ab Werk begrüßt das Display den Nutzer mit einer Demo-Anwendung, mit der auch der Touchscreen ausprobiert werden kann.

Arduino IDE

Programmiert habe ich das Displayboard mit der Arduino IDE in Version 2.3.5. Dazu muss, sofern nicht bereits erfolgt, als erstes der ESP32 in der Arduino IDE als Board hinterlegt werden.

Dazu die Einstellungen der IDE mit CTRL+, aufrufen und auf den Button hinter dem Eingabefeld mit der Bezeichnung Additional board manager URLs klicken:

Preference Menü der Arduino IDE mit Button zum hinzufügen von zusätzlichen Boards

In das sich öffnende Textfeld muss die folgende URL eingetragen und anschließend mit OK bestätigt werden:

https://espressif.github.io/arduino-esp32/package_esp32_index.json
Texteingabe der zusätzlichen Board URL für den ESP32

Der ESP32 ist nun in allen gängigen Varianten mit der Arduino IDE nutzbar und steht im Board Manager zur Verfügung.

Board konfigurieren

Um den ESP32 als Board zuweisen zu können, muss zuerst der Board Manager unter Tools > Board > Board Manager… aufgerufen werden. Ins Suchfeld den Begriff esp32 eingeben und anschließen im Dropdown Menü die Version 3.2.0 auswählen und installieren:

ESP32 Board in Version 3.2.0 installieren

Weiterführend muss als Microcontroller der Eintrag ESP32 Dev Module ausgewählt und der korrekte Port des USB-Anschluss zugewiesen werden:

Board Selector in der Arduino IDE

Anschließend muss nur noch unter Tools > Upload Speed die Baudrate auf den Wert 115200 gesetzt werden und schon ist das Board programmierbereit.

Libraries installieren

Folgende Libraries müssen in den expliziten Version verwendet werden. Dazu, analog wie im Board Manager, in der Arduino IDE die jeweiligen Versionen im Library Manager unter Tools > Manage Libraries suchen und installieren:

Library/Framework Version
GFX Library for Arduino 1.6.0
JPGEGDEC 1.8.2
Installierte Library Versionen

Zusätzlich liegt in dem heruntergeladenen Ordner noch eine lokale Bibliothek TFT_Touch_v0.3.zip für die Touchscreen-Unterstützung bei. Diese muss in der Arduino IDE importiert werden. Dazu unter Sketch > Include Library > Import .ZIP Library… klicken und die Datei TFT_Touch_v0.3.zip auswählen.

Code Upload

Die Datei locotv.ino kann aus der Arduino IDE mit dem Shortcut CTRL+U kompiliert und auf das Cheap Yellow Display geladen werden:

Upload-Vorgang in der Arduino IDE

Treten beim Kompilieren keine Fehler auf, sollten nach dem Upload die zuvor auf die SD-Karte kopierten Beispielvideos auf dem Display erscheinen. Durch berühren des Displays wird zum nächsten Video gewechselt.

Code Anpassungen

Das Cheap Yellow Display existiert in zigfachen Ausführungen, die sich nicht immer gleich verhalten. Ich habe für meine Version und mein Vorhaben insgesamt drei Änderungen am Code vorgenommen:

  1. Die Farben des Displays invertieren:

    vorher
    gfx->fillScreen(RGB565_BLACK);
    // gfx->invertDisplay(true); // on some cheap yellow models, display must be inverted
    Serial.printf("Screeen size Width=%d,Height=%d\n", gfx->width(), gfx->height());
    nachher
    gfx->fillScreen(RGB565_BLACK);
    gfx->invertDisplay(true); // on some cheap yellow models, display must be inverted
    Serial.printf("Screeen size Width=%d,Height=%d\n", gfx->width(), gfx->height());
  2. Zusätzlich muss für meine gewählte Einbaurichtung im Gehäuse der Portraitmodus des Displays gespiegelt werden, indem die Werte setRotation() und touch.setRotation() angepasst werden:

    vorher
    gfx->setRotation(0);
    touch.setRotation(0);
    nachher
    gfx->setRotation(2);
    touch.setRotation(2);
  3. Das Display mit 80 Mhz statt 40 Mhz Taktung per SPI betreiben:

    vorher
    // Some model of cheap Yellow display works only at 40Mhz
    //#define DISPLAY_SPI_SPEED 80000000L // 80MHz
    #define DISPLAY_SPI_SPEED 40000000L // 40MHz
    
    nachher
    // Some model of cheap Yellow display works only at 40Mhz
    #define DISPLAY_SPI_SPEED 80000000L // 80MHz
    //#define DISPLAY_SPI_SPEED 40000000L // 40MHz
    

Eigene Videos erstellen

Ideale Quelle für Videos von Lokomotiven sind YouTube Shorts. Diese sind, dem spinösen Zeitgeist verschuldet, im Hochkantformat vorhanden und somit optimales Ausgangsmaterial, wenn das Display in dieser Ausrichtung betrieben wird.

Im Folgenden gilt es Videos herunterzuladen und ins Motion Jpeg Format Format zu konvertieren. Das Format MJPEG wird gewählt, da der ESP32 hardwareseitig die Funktion besitzt JPEG-Dateien zu Encoden und Decoden.

Für den Download und die Konvertierung der Videos nutze ich zwei Kommandozeilen-Tools:

  • yt-dlp: Zum Herunterladen der Videos
  • ffmpeg: Zum Konvertieren der Videos

Beide Tools können unter Windows 11 einfach über die Paketverwaltung winget installiert werden. Dazu das Terminal öffnen und den Einzeiler eintippen:

winget install yt-dlp.yt-dlp Gyan.FFmpeg

Nach der Installation muss das Terminal geschlossen und erneut geöffnet werden.

Einzelkonvertierung

Als Beispiel für die einzelne Konvertierung eines Videos dient dieser Short. Seine URL lautet: https://www.youtube.com/shorts/cKKkR6O_jYQ.

Zum Herunterladen kann nun yt-dlp im Terminal verwendet werden:

cd ~\Desktop
yt-dlp "https://www.youtube.com/shorts/cKKkR6O_jYQ" -o test

Und schon befindet sich das Video mit dem Dateinamen test.webm auf dem Desktop.

Zur Konvertierung sind im Repository des ursprünglichen Autoren diverse ffmpeg Kommandos gelistet. Diese skalieren Videos jedoch nur auf die benötigte Bildschirmauflösung von 320x240 Pixel. Dies ist ein Problem, da YouTube Shorts in der Regel hochkant im Format 16:9 aufgenommen werden. Das Display besitzt jedoch ein Bildschirmverhältnis von 4:3. Ich habe das Kommando angepasst, dass mit ffmpeg im ersten Schritt ein Zoom in das Video und anschließend ein Zuschnitt auf die 320x240 Pixel erfolgt. Somit gehen in der Höhe zwar Teile des Videos verloren, jedoch entstehen so keine schwarzen Balken auf der linken und rechten Seite neben dem Video.

Das folgende optimierte Kommando wird zur Konvertierung der heruntergeladenen Datei test.webm in das mjpeg Format verwendet:

cd ~\Desktop
ffmpeg -y -i .\test.webm -pix_fmt yuvj420p -q:v 7 -vf "fps=24,crop=in_w:in_w*4/3:0:(in_h-in_w*4/3)/2,scale=240:-1:flags=lanczos" test.mjpeg

Die generierte Datei test.mjpeg liegt ebenfalls auf dem Desktop und kann so direkt auf die SD-Karte kopiert und auf dem Display abgespielt werden.

Batchkonvertierung

Da das einzelne Herunterladen und Konvertieren mühsam ist, macht es Sinn dies im Batch zu erledigen. Dazu in das Verzeichnis locotv/script wechseln. Darin liegen zwei Dateien:

./locotv/script
  ├── 00_convert.ps1
  └── 00_videos.txt

In der Datei 00_videos.txt können nun zeilenweise Links zu YouTube Shorts mit einem Texteditor hinterlegt werden:

00_videos.txt | Beispieleinträge
https://www.youtube.com/shorts/cKKkR6O_jYQ
https://www.youtube.com/shorts/S3O2S8ZE8ec
https://www.youtube.com/shorts/-1p6VCfEhfw
https://www.youtube.com/shorts/lFymosFJC1c
https://www.youtube.com/shorts/QhkMK151dy8
https://www.youtube.com/shorts/X2mo7eP74u4
https://www.youtube.com/shorts/tXyq57_Cvc0
https://www.youtube.com/shorts/Q2YHydMnHRQ
https://www.youtube.com/shorts/hI4E1KZAd84
https://www.youtube.com/shorts/Ou3pGGidRgM
https://www.youtube.com/shorts/nM4f9Vzdo4Y
https://www.youtube.com/shorts/6WNYhWgIdS4
https://www.youtube.com/shorts/ewbTSRsFC-0
https://www.youtube.com/shorts/af9Om_3LcQk
https://www.youtube.com/shorts/mKP9dpXhcx0
https://www.youtube.com/shorts/tfQvw7QjGa8

Die Datei 00_convert.ps1 enthält den Code für die Konvertierung der Videos ins MJPEG-Format. Es liest zeilenweise den Inhalt der Datei 00_videos.txt ein, lädt die darin hinterlegten Videos herunter, konvertiert sie und löscht die Ursprungsdateien.

In diesem Ordner einen Rechtsklick machen und den Eintrag In Terminal öffnen auswählen:

Anschließend kann das Skript über diesen Befehl gestartet werden:

.\00_convert.ps1

Das Skript 00_convert.ps1 macht im Detail folgendes in dieser Reihenfolge:

  • Erstellt einen Ordner locotv/script/mjpeg.
  • Lädt sämtliche Videos aus der Datei 00_videos.txt in den Ordner locotv/script/ herunter.
  • Prüft mit ffprobe, ob das Video im Hochkant- oder Querformat aufgenommen wurde.
  • Konvertiert das Video in MJPEG-Format. Für Hochkant- und Querformate werden unterschiedliche ffmpeg Kommandos angewandt, um keine schwarzen Balken in den Videos vorzufinden.
  • Die konvertierten Dateien werden im Ordner locotv/script/mjpeg abgelegt. Ein Dateinamenpräfix portrait_ (Hochkantformat) und landscape_ (Querformat) wird angewandt.
  • Die Ursprungsvideos werden gelöscht. Lediglich die konvertierten Videos bleiben erhalten.
Ordnerstruktur, die vom PowerShell Skript angelegt wird und in der die konvertierten Videos abgelegt werden.

Wer nicht regelmäßig mit PowerShell auf dem eigenen Computer arbeitet, muss in der Regel noch die notwendigen Rechte zur Ausführung von Skripten setzen:

Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned

MAX_FILES anpassen

UPDATE 12.02.26:
Der Wert MAX_FILES scheint nur eine Rolle zu spielen, wenn mehr Videos auf der SD-Karte existieren, als in MAX_Files definiert ist. Der Wert kann beliebig hoch gesetzt werden und trotzdem starten die Videos erneut von vorne, wenn das letzte Video erreicht ist.

Der Arduino Code in der Datei locotv.ino hat per Default einen Counter, der nach jedem abgespielten Video um das Inkrement 1 erhöht wird. Die maximale Anzahl an abzuspielenden Videodateien ist leider hardgecoded und wird nicht dynamisch ermittelt. Standardmäßig steht der Wert bei 20 Dateien. Hat man mehr als 20 Dateien werden also trotzdem nur die ersten 20 Dateien abgespielt. Der Wert sollte also, gemäß der vorhandenen Anzahl an Videodateien auf der SD-Karte, angepasst werden:

#define MAX_FILES 20 // Maximum number of files, adjust as needed

Das vorgestellte PowerShell Skript zur Batch-Konvertierung mehrerer Videos ermittelt die Anzahl der Dateien und gibt diesen Wert, nach dem Konvertierungsvorgang, im Terminal aus:

Terminal-Ausabe zur ermittelten Anzahl an gefundenen Video-Dateien

Wichtig: Eine Anpassung des Codes erfordert stets auch einen neues Kompilieren und einen erneuten Upload über die Arduino IDE.

Gehäuse drucken

Ich habe in Autodesk Inventor ein simples Gehäuse, bestehend aus Ober- und Unterseite, entworfen. Die Gehäusehälften werden mittels Schrauben und passender Hülsenmuttern zusammengehalten. Die ermöglicht ein zukünftiges verschleißfreies Auseinanderbauen.

In der Unterseite finden Batteriehaltertung, Ladeelektronik und der Spannungs­wandler platz. In der oberen Gehäusehälfte sind das Display und der Ein-Aus-Schalter verbaut. Aussparungen für die SD-Karte und den USB-C Anschluss zum Laden der Batterie sind enthalten.

Isometrische Ansicht vom 3D gedruckten Gehäuse

Verwendet wird das gröbste Druckprofil Draft im Cura Slicer mit einer Druckstärke von 0,3 mm auf meinem in die Jahre gekommenen Anycubic i3 Mega.

Die STL-Dateien der Gehäusehälften sind im Ordner locotv/stl zum Nachdrucken vorhanden.

Spannungswandler einstellen

Für diesen Schritt wird ein Multimeter benötigt. Als Vorbereitung für den Zusammenbau muss vorerst der Spannungswandler so eingestellt werden, dass bei 3,7 V Eingangsspannung eine Ausgangsspannung von 5 V erreicht wird, die das Display für seinen Betrieb erfordert. Dazu wird die Justierschraube auf dem MT3608 verwendet. Videos dazu gibt es im Weltnetz zu Hauf:

Die 18650er-Batterie in das Batteriegehäuse stecken, das rote Kabel an den VIN+ und das schwarze Kabel an den VIN- Kontakt anschließen. Das kann mit Krokodilsklemmen, geschickter Positionierung oder über ein temporäres Löten erfolgen. Anschließend das Multimeter auf Gleichstrommessung stellen und analog das rote Kabel des Multimeters an VOUT+ und das schwarze an VOUT- halten. Nun muss die Justierschraube des MT3608 so eingestellt werden, dass 5 V Ausgangs­spannung auf dem Multimeter angezeigt wird:

Justierung der Ausgangsspannung an der Stellschraube des Spannungswandlers

Verdrahtung

Schematische Verdrahtung der Elektronik

Zusammenbau

Für den Zusammenbau des Gehäuses und der Verdrahtung der elektronischen Bauteile werden, neben Lötkolben und Kabelage, folgende Bauteile benötigt:

Bauteil Anzahl Bezeichnung
M2x5 4 Schrauben zur Befestigung des Displays an der oberen Gehäusehälfte.
M4 4 Tellerkopfschrauben + Hülsenmutter, oft auch im Set als Möbelverbinder bezeichnet, mit Klemmweite von 34,2 mm zur Befestigung der oberen und unteren Gehäusehälfte.
Heißkleber 1 Zur Fixierung des Spannungsreglers, des Batteriehalters und der Ladeelektronik in der unteren Gehäusehälfte.

Gehäuseoberseite

Im ersten Schritt wird das Display mit den M2x5 Schrauben befestigt. Es empfiehlt sich die Schrauben vorher ohne Display vorsichtig in die dafür vorgesehenen Löcher zu schrauben, um das Gewinde im PLA zu formen. Dabei immer wieder vor- und zurückschrauben, bis die benötigte Tiefe erreicht ist.

Im zweiten Schritt muss der JST-Connector auf einer Seite, direkt hinter dem Stecker, mit einem Seitenschneider abgetrennt werden. Von den vier verfügbaren Pins werden nur die beiden Äußeren in den Farben Rot und Grün verwendet. Die Mittleren können ebenfalls abgetrennt werden:

Vorbereitung des JST-Connectors

Der JST-Connector kann nun an dem vorhandenen Anschluss am Displayboard gesteckt werden.

Als finaler Schritt wird der Power Button eingesetzt. Den Feststellring habe ich aus Platzgründen entfallen lassen, da der Button auch ohne ihn gut fixiert platziert war. Theoretisch ist der Platz aber vorhanden, falls er beim Nachbau platziert werden muss.

Zusammenbau der oberen Gehäusehälften mit Power Button und verschraubtem Display

Die Oberseite ist damit fertig bestückt und Einsatzbereit.

Gehäuseunterseite

Die Gehäuseunterseite ist anspruchsvoller. Ich habe zuerst alle Komponenten darin platziert und dann die Kabellängen markiert und zugeschnitten. Danach habe ich alle Bauteile wieder herausgeholt und zuerst alle Bauteile verlötet, die in der Unterseite platziert werden. Danach legt/stellt man die Vorderseite so nah es geht daneben und lässt für diese die Kabel länger, damit die Verbindungen nicht reißen, wenn das Gehäuse mal geöffnet werden muss:

Batterielademodul, Spannungswandler und die Batteriehalterung habe ich anschließend mit Heißkleber in der unteren Gehäusehälfte fixiert:

Klebeflächen der elektronischen Komponenten in der Gehäuseunterseite

Klebeflächen in roter Farbmarkierung

Hochzeit

Nachdem beide Gehäusehälften montiert und verdrahtet sind, können sie zusammengefügt werden. Dabei darauf achten, dass die Kabel nicht zu sehr unter Spannung sind oder Schaden beim Schließvorgang nehmen.

Die beiden Gehäusehälften werden durch Hülsenmuttern und Schrauben der Gewindegröße M4 zusammengehalten. Das hat den Vorteil, dass nicht selber ins Druckmaterial geschraubt werden muss und eine zukünftige verschleißfreie Öffnung des Gehäuse gegeben ist. Hülsen- und Schraubenlänge kann variiert werden, solange die errechnete ideale Klemmweite von 34,2 mm erreicht wird:

Schnittansicht des CAD-Modells für die Klemmweite von 34,2 mm

Für meinen Eigenbau habe ich eine M4x18 Tellerkopfschraube und eine Hülsenmutter mit M4 Innengewinde einer Länge von 25 mm verwendet. Diese stammen aus einem IKEA Pax Schrank und haben bei IKEA die Teilenummern 100644 und 100402:

Schraube und Hülsenmutter

Resultat

Das Ergebnis ist ein kleines, neckische, portables Brikett, das auch in der Zukunft mit Videomaterial aller Art bespielt werden kann. Es dient nur dem Zweck der Video­wiedergabe, hat keine nervige Sound-Ausgabe und der abgespielte Content liegt zu 100% in eigener Hand:

Ergebnis des Zusammenbaus

Betätigt man den Power-Button, rastet dieser ein, der LED-Ring des Buttons beginnt zu leuchten und ca. eine Sekunde später beginnt die Videowiedergabe:

Animiertes gif der Funktionsweise

Ist die Batterie einmal leer gesaugt, kann sie mit einem handelsüblichen USB-C Ladegerät wieder aufgeladen werden.

Neue Videos hinterlegen

Es wird notgedrungen immer wieder zu der Situation kommen, dass neue Videos auf der SD-Karte hinterlegt werden müssen. Da das CYD in zig Varianten existiert, ist der sicherste weg den JST-Connector, vor einem erneuten Code Upload zu trennen, bevor der USB-C anschluss mit dem Computer verbunden wird, um Voltage Backfeeding zu vermeiden.

Generell empfiehlt es sich den Wert für MAX_FILES relativ hoch, bspw. 300 anzusetzen, da so nur kein neuer Code Upload erfoderlich ist, wenn die reale anzahl der gespeicherten Video den Wert in der Variable MAX_FILES überschreitet.