Odroid Go (ESP32) mit Arduino IDE programmieren

Neulich stieß ich im Internet auf den Odroid Go, den der Hersteller Hardkernel aus Südkorea von etwa einem Jahr auf den Markt gebracht hat. Eigentlich beschäftigt sich die Firma ja eher mit ESP32 und anderen Entwicklungsboards für Mikrocontroller, aber zum Zehnten Jubiläum hat man den Odroid Pro aus Do It yourself-Kit herausgebracht.

Da der Odroid nicht nur so etwas wie ein handlicher Gameboy ist, sondern gleichzeitig auch eine Plattform für Mikrocontroller-Bastelprojekte, war das genau das richtige Spielzeug für mich und ich legte mir einen zu. Allerdings war es gar nicht so einfach, an einen heranzukommen. Bei amazon war er gerade ausverkauft, bei Pollin stand er zwar im (Papier)-Katalog, war aber zur Zeit nicht lieferbar. Und bei eBay gingen die Preise teilweise bis 100 Euro. Das Teil schien also sehr gefragt zu sein. Ich ging das Risiko einer Wartezeit ein und bestellte bei Pollin um 40 Euro und bekam den Odroid dann doch erfreulicherweise schnell nach etwas über einer Woche. Glück gehabt.


Über die Hardware und den Zusammenbau des Do-it-yourself-Kits habe ich bereits einen Artikel geschrieben. Dort wird auch beschrieben, wie man darauf seine alten Gameboy-Spiele zum Laufen bekommt.

Heute will ich zeigen, wie man seine eigene Software dafür schreibt und zum Laufen bekommt. Wir nutzen dafür die Arduino IDE, die wir ja schon für den Arduino Nano, Uno und STM32 genutzt haben.

Im Prinzip geht das genauso wie beim Arduino, nur laden wir die fertige Firmware nicht per serieller Verbindung hoch, sondern speichern sie als *.fw-Datei auf der SD-Karte des Odroid-Go.

Der Odroid-Go verfügt nämlich über eine Art "Über"-Firmware, mit der wir Firmwares (eben diese *.fw-Files) flashen können. So kann man auch unterwegs zwischen den Firmwares umschalten, ohne den Odroid an den PC anschließen zu müssen. Wie das Flashen von Firmware geht, darüber habe ich ja bereits einen Artikel geschrieben.

Die Odroid Go Hardware

Warum man den Odroid-Go als Entwicklungsplattform hernehmen sollte statt ein "nacktes" ESP32-Entwicklungsboard, liegt auf der Hand. Der Odroid-Go bringt eine Menge an angebundener Hardware mit, die wir gut gebrauchen können: Der Custon ESP32 Wrover verfügt übrigens über folgende Daten: Wenn wir jetzt zum Beispiel eine Wetterstation realisieren wollen, brauchen wir lediglich noch einen Sensor wie den BMP280. Für die Werteausgabe haben wir gleich ein Display. Einen Alarm können wir über den Lautsprecher ausgeben. Zwischen den Ausgaben umschalten und durch ein Menü steuern könnten wir mit dem Steuerkreuz. Die Temperaturwerte könnten wir auf der SD-Karte protokollieren. Und selbst ein kleiner, über WLAN ansprechbarer Web-Server wäre möglich. Alles schon an Bord.

Integration der Odroid-Go-Libraries in die Arduino IDE

Für die Ansprache der Hardwarekomponenten des Odroid gibt es natürlich auch Libraries, die uns hier das Leben sehr vereinfachen.

Diese müssen wir unserer Arduino IDE beibringen. Das tun wir mit dem Kommando und dem Pfad, in dem wir unsere Arduino-Libraries speichern. Das ist im Normalfall git clone https://github.com/hardkernel/ODROID-GO.git %USERPROFILE%\Documents\Arduino\libraries\ODROID-GO Kann aber auch abweichen wie z. B. bei mir: git clone https://github.com/hardkernel/ODROID-GO.git D:\Arduino\libraries\ODROID-GO in der Eingabeaufforderung. Dadurch werden die Libraries heruntergeladen und in den Library-Ordner Odroid-Go kopiert: Cloning into 'C:\Users\admin/Documents/Arduino/libraries/ODROID-GO'... remote: Enumerating objects: 37, done. remote: Counting objects: 100% (37/37), done. remote: Compressing objects: 100% (24/24), done. remote: Total 726 (delta 12), reused 27 (delta 10), pack-reused 689 Receiving objects: 98% (712/726), 4.48 MiB | 4.47 Mi Receiving objects: 100% (726/726), 5.59 MiB | 4.77 MiB/s, done. Resolving deltas: 100% (281/281), done.
Danach können wir unter Werkzeuge unter Board das Board ODROID ESP32 auswählen.

Nun weiß die Arduino IDE, für welche Umgebung wir unseren Source kompilieren wollen.

Sketch kompilieren

Testen wir es, indem wir dieses kleine Progrämmchen eingeben #include void setup() { // put your setup code here, to run once: GO.begin(); GO.lcd.print("Hello, ODROID-GO from Doc Cool"); } void loop() { // put your main code here, to run repeatedly: } und mit dem Haken oben links im Arduino-Fenster (Überprüfen, CTRL+R) kompilieren.


Erhalten wir eine Fehlermeldung "odroid_go.h: No such file or directory" wie rechts gezeigt, dann haben wir den falschen Pfad angegeben und müssen das Git-Paket noch einmal an der richtigen Stelle installieren.

Das erste Kompilieren kann ein wenig dauern und sollte dann mit einer Meldung wie Kompilieren abgeschlossen. Der Sketch verwendet 383241 Bytes (29%) des Programmspeicherplatzes. Das Maximum sind 1310720 Bytes. Globale Variablen verwenden 16788 Bytes (5%) des dynamischen Speichers, 310892 Bytes für lokale Variablen verbleiben. Das Maximum sind 327680 Bytes. erfolgreichen Vollzug vermelden.

Odroid-Firmware (*.fw) erstellen

1. Binary suchen und finden

Einen seriellen Port brauchen wir unter Werkzeuge gar nicht für unseren Odroid-Go angeben, denn wir wollen ja nicht die Über-Firmware überschreiben, sondern diese nutzen, unsere Firmware zu flashen.

Dazu braucht es ein *.fw-File, dass auf die SD-Karte des Odroid unter s:\odroid\firmware\ kopiert werden kann und dann mit der "B halten und Einschalten"-Tastenkombination installiert werden kann.

Um ein .fw-File zu generieren, brauchen wir erst einmal das Kompililat, das bin-File, sozusagen die binäre .exe für unseren Microcontroller. In diesem speziellen Fall die odroid-go-hello.ino.bin

Diese können wir entweder mit einem Programm wie Everything von Voidtools tun:



oder wir geben in den Voreinstellungen der Arduino IDE an, dass die Kompilierungsausgaben ausführlicher sein sollen und kompilieren erneut, was eine elend lange Ausgabe im unteren Fensterabschnitt erzeugt:



... "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_426218\\libraries\\WiFiClientSecure\\ssl_client.cpp.o" "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_cache_597133\\core\\core_8f6099509d1b2cd6223729101f529923.a" -lgcc -lesp32 -lphy -lesp_http_client -lmbedtls -lrtc -lesp_http_server -lbtdm_app -lspiffs -lbootloader_support -lmdns -lnvs_flash -lfatfs -lpp -lnet80211 -ljsmn -lface_detection -llibsodium -lvfs -ldl_lib -llog -lfreertos -lcxx -lsmartconfig_ack -lxtensa-debug-module -lheap -ltcpip_adapter -lmqtt -lulp -lfd -lfb_gfx -lnghttp -lprotocomm -lsmartconfig -lm -lethernet -limage_util -lc_nano -lsoc -ltcp_transport -lc -lmicro-ecc -lface_recognition -ljson -lwpa_supplicant -lmesh -lesp_https_ota -lwpa2 -lexpat -llwip -lwear_levelling -lapp_update -ldriver -lbt -lespnow -lcoap -lasio -lnewlib -lconsole -lapp_trace -lesp32-camera -lhal -lprotobuf-c -lsdmmc -lcore -lpthread -lcoexist -lfreemodbus -lspi_flash -lesp-tls -lwpa -lwifi_provisioning -lwps -lesp_adc_cal -lesp_event -lopenssl -lesp_ringbuf -lfr -lstdc++ -Wl,--end-group -Wl,-EL -o "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_426218/odroid-go-hello.ino.elf" "C:\\Users\\admin\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\1.0.4/tools/gen_esp32part.exe" -q "C:\\Users\\admin\\AppData\\Local\\Arduino15\\packages\\esp32\\hardware\\esp32\\1.0.4/tools/partitions/default.csv" "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_426218/odroid-go-hello.ino.partitions.bin""C:\\Users\\admin\\AppData\\Local\\Arduino15\\packages\\esp32\\tools\\esptool_py\\2.6.1/esptool.exe" --chip esp32 elf2image --flash_mode dio --flash_freq 80m --flash_size 16MB -o "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_426218/odroid-go-hello.ino.binspan>" "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_426218/odroid-go-hello.ino.elf" esptool.py v2.6 Mehrere Bibliotheken wurden für "odroid_go.h" gefunden Benutzt: d:\Arduino\libraries\ODROID-GO Mehrere Bibliotheken wurden für "SPI.h" gefunden Benutzt: C:\Users\admin\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\libraries\SPI Mehrere Bibliotheken wurden für "FS.h" gefunden Benutzt: C:\Users\admin\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\libraries\FS Mehrere Bibliotheken wurden für "SD.h" gefunden Benutzt: C:\Users\admin\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\libraries\SD Nicht benutzt: D:\Program Nicht benutzt: d:\Arduino\libraries\SD Mehrere Bibliotheken wurden für "WiFiServer.h" gefunden Benutzt: C:\Users\admin\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\libraries\WiFi Nicht benutzt: D:\Program Mehrere Bibliotheken wurden für "WiFiClientSecure.h" gefunden Benutzt: C:\Users\admin\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\libraries\WiFiClientSecure Bibliothek ODROID-GO in Version 1.0.0 im Ordner: d:\Arduino\libraries\ODROID-GO wird verwendet Bibliothek SPI in Version 1.0 im Ordner: C:\Users\admin\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\libraries\SPI wird verwendet Bibliothek FS in Version 1.0 im Ordner: C:\Users\admin\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\libraries\FS wird verwendet Bibliothek SD in Version 1.0.5 im Ordner: C:\Users\admin\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\libraries\SD wird verwendet Bibliothek WiFi in Version 1.0 im Ordner: C:\Users\admin\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\libraries\WiFi wird verwendet Bibliothek WiFiClientSecure in Version 1.0 im Ordner: C:\Users\admin\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\libraries\WiFiClientSecure wird verwendet "C:\\Users\\admin\\AppData\\Local\\Arduino15\\packages\\esp32\\tools\\xtensa-esp32-elf-gcc\\1.22.0-80-g6c4433a-5.2.0/bin/xtensa-esp32-elf-size" -A "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_426218/odroid-go-hello.ino.elf" Der Sketch verwendet 383241 Bytes (29%) des Programmspeicherplatzes. Das Maximum sind 1310720 Bytes. Globale Variablen verwenden 16788 Bytes (5%) des dynamischen Speichers, 310892 Bytes für lokale Variablen verbleiben. Das Maximum sind 327680 Bytes. Wichtig ist aber nur, dass wir wissen, wo unser kompiliertes Binärfile steckt, in diesem Falle C:\Users\admin\AppData\Local\Temp\arduino_build_426218\odroid-go-hello.ino.bin. Entweder kopieren wir alles aus dem Fenster heraus (CTRL+A), kopieren es in einen Texteditor und suchen nach ".ino.bin" (obere gelbe Markierung) oder wir schauen ganz am Ende (untere gelbe Markierung) und ersetzen das ".elf" durch ".bin". Außerdem müssen wir doppelte Backslashes zu einfachen machen.

Kopieren wir das Binary in einen extra Ordner d:\Odroid-Go\eigene_fw\: copy C:\Users\admin\AppData\Local\Temp\arduino_build_426218\odroid-go-hello.ino.bin d:\Odroid-Go\eigene_fw\

2. Grafik für Firmware-Eintrag erstellen

Wir erstellen uns ein Logo für die Firmware, die dann später in dem Flashing-Menü der Über-Firmware erscheinen soll. Dazu nehmen wir uns eine 86 mal 48 Pixel große Grafik und speichern sie als PNG-Datei.

Dann benutzen wir ffmpeg (gibt es auch für Windows), um aus dem PNG ein RAW zu machen, dass ist das seltene Grafik-Format, was die Firmware-Software benötigt: d:\tools\ffmpeg\bin\ffmpeg.exe -i d:\grafik\c-o-o-l-86x48.png -f rawvideo -pix_fmt rgb565 d:\Odroid-Go\eigene_fw\fw-gfx.raw ffmpeg version N-94892-g0993327939 Copyright (c) 2000-2019 the FFmpeg developers built with gcc 9.1.1 (GCC) 20190807 configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enabl e-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enab le-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enabl e-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 - -enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enabl e-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-ffnvcode c --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt --e nable-amf libavutil 56. 35.100 / 56. 35.100 libavcodec 58. 56.101 / 58. 56.101 libavformat 58. 32.104 / 58. 32.104 libavdevice 58. 9.100 / 58. 9.100 libavfilter 7. 58.102 / 7. 58.102 libswscale 5. 6.100 / 5. 6.100 libswresample 3. 6.100 / 3. 6.100 libpostproc 55. 6.100 / 55. 6.100 Input #0, png_pipe, from 'd:\grafik\c-o-o-l-86x48.png': Duration: N/A, bitrate: N/A Stream #0:0: Video: png, rgb24(pc), 86x48 [SAR 2835:2835 DAR 43:24], 25 tbr, 25 tbn, 25 tbc Stream mapping: Stream #0:0 -> #0:0 (png (native) -> rawvideo (native)) Press [q] to stop, [?] for help [swscaler @ 00000000005bcd80] full chroma interpolation for destination format 'rgb565le' not yet implemented Output #0, rawvideo, to 'd:\Odroid-Go\eigene_fw\fw-gfx.raw': Metadata: encoder : Lavf58.32.104 Stream #0:0: Video: rawvideo (RGB[16] / 0x10424752), rgb565le, 86x48 [SAR 1:1 DAR 43:24], q=2-31, 1651 kb/s, 25 fps, 25 tbn, 25 tbc Metadata: encoder : Lavc58.56.101 rawvideo frame= 1 fps=0.0 q=-0.0 Lsize= 8kB time=00:00:00.04 bitrate=1651.2kbits/s speed=13.7x video:8kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000000%

3. Binary und Grafik zu Firmware linken

Um unser Firmware-Binary und die Grafik zusammenzubringen und in das ganz spezielle *.fw-Format für die Über-Firmware des Odroid-Go zu bringen, benötigen wir das Tool mkfw (kurz für Make Firmware) von OtherCrashOverride, das wir auf GitHub finden. An eine Version von mkfw für Windows heranzukommen, ist nicht ganz einfach. Darum habe ich kurzum meine eigene Windows-Exe kompiliert. Diese kann hier heruntergeladen werden. Entpackt das .zip und kopiert die mkfw.exe auch in euer "eigene_fw"-Verzeichnis.

Danach ruft ihr sie mit den Parametern für Anwendungsname ("hello_world"), der Grafik (*.raw) und dem Binary (*.ino.bin) auf: mkfw.exe hello_world d:\Odroid-Go\eigene_fw\fw-gfx.raw 0 16 1048576 app d:\Odroid-Go\eigene_fw\odroid-go-hello.ino.bin Der Output sollte in etwa so aussehen: d:\Odroid-Go\eigene_fw >> mkfw.exe hello_world d:\Odroid-Go\eigene_fw\fw-gfx.raw 0 16 1048576 app d:\Odroid-Go\eigene_fw\odroid-go-hello.ino.bin HEADER='ODROIDGO_FIRMWARE_V00_01' FirmwareDescription='hello_world' tile: wrote 8256 bytes. [0] type=0, subtype=16, length=1048576, label=app part=0, length=383360, data=d:\Odroid-Go\eigene_fw\odroid-go-hello.ino.bin main: checksum=0x2b31e639 Das Verzeichnis sollte danach folgende Files beeinhalten: Verzeichnis von d:\Odroid-Go\eigene_fw 19.12.2019 15:14 <DIR> . 19.12.2019 15:14 <DIR> .. 19.12.2019 15:15 391.716 firmware.fw 19.12.2019 13:26 8.256 fw-gfx.raw 19.12.2019 15:10 <DIR> mkfw 19.12.2019 15:10 51.630 mkfw.exe 19.12.2019 12:31 383.360 odroid-go-hello.ino.bin MmkFw hat uns die neue Firmware in das File firmware.fw geschrieben. Diese kopieren wir nach hello_world.fw auf s:\odroid\firmware auf der Odroid-SD-Karte. Fertig.

Wer möchte, kann sich den Prozess mit einer Batch-Datei, etwa make-firmware.cmd in d:\Odroid-Go\eigene_fw genannt, vereinfachen. Hier der Code meiner Batch-Datei. Die Pfade, Username etc. müssen natürlich noch an die eigenen Bedürnisse angepasst werden.

Ich muss so nur noch die 6-stellige, sich jedesmal ändernde Nummer des temporären Verzeichnisses angeben (Aufruf z. B. make-firmware.cmd 456789) und die SD-Karte in meinen Reader stecken, Return drücken, ein paar Sekunden warten, die SD-Karte wieder in den Odroid stecken und schon kann ich die neue Firmware flashen und testen. Dem endgültigen Produkt gibt man dann natürlich händisch doch noch einen eigenen Namen und Icon. Aber für die Testphase ist es doch nur nervig, alles immer wieder per Hand zu machen.

make-firmware.cmd @echo off if "%1"=="" goto fehler1 dir /B C:\Users\admin\AppData\Local\Temp\arduino_build_%1\*.ino.bin if not exist C:\Users\admin\AppData\Local\Temp\arduino_build_%1\*.ino.bin goto fehler2 xcopy /Y C:\Users\admin\AppData\Local\Temp\arduino_build_%1\*.ino.bin d:\Odroid-Go\eigene_fw\firmware.ino.bin mkfw.exe OWN_FIRMWARE d:\Odroid-Go\eigene_fw\fw-gfx.raw 0 16 1048576 app d:\Odroid-Go\eigene_fw\firmware.ino.bin copy firmware.fw s:\odroid\firmware\_own_firmware.fw goto fertig :fehler1 echo als 1. Parameter die 6-stellige Build Nr. angeben goto :EOF :fehler2 echo unter Build %1 konnte keine *.ino.bin gefunden werden goto :EOF :fertig echo Fertig. Batch beendet.

Firmware flashen

Wie man eine solche Eigen-Firmware mit der Überfirmware flasht, hatte ih ja bereits an anderer Stelle erläutert.

Aber hier noch einmal in aller Kürze:

1. B halten und Odroid-Go einschalten und eigene Firmware mit dem D-Pad suchen und mit A auswählen:



START drücken und Firmware flashen lassen (verify, erase, write):



Danach erfolgt automatisch ein Reset und die eigene Firmware wird gestartet:



Erfolg!

Die Firmware macht was sie soll. Das ist zugegebenenmaßen zur Zeit nicht gerade viel, aber hier ging es erstmal nur um das Vorbereiten und Flashen einer eigenen Firmware für den Odroid-Go, die mit der Über-Firmware geflasht werden kann. Mit gedrücktem B und einschalten können wir jetzt wieder eine andere Firmware auswählen und flashen und wieder z. B. Gameboy spielen

Welche Befehle es sonst noch in den Odroid-Go-Libraries gibt und wie man sie anwendet, wird Thema eines weiteren Artikels sein.