CLUE - ein Clou von Adafruit?
Spätestens seit dem Erfolg von Arduino und Raspberry Pi ist offensichtlich, dass man mit „Schulungscomputern“ aller Herren Couleur Geld verdienen kann. Die BBC schickte im Jahr 2016 mit dem micro:bit einen Einplatinencomputer ins Rennen, der statt eines vollwertigen Linux-fähigen Prozessors „nur“ ein Bluetooth-SoC aus dem Hause Nordic Semiconductor mitbrachte.
Der Rest ist eine für den Autor dieser Zeilen nicht wirklich verständliche Geschichte: Mittlerweile gibt es z.B. in der Slowakei Unternehmen, die sich ausschließlich über den Vertrieb des micro:bit-Ökosystems ernähren [1].
Der alte Kalauer, dass man an einem „gut gefüllten“ Topf nicht allzu lang alleine frisst, gilt auch im Bereich des Prozessrechnerwesens. Die Weiterentwicklung im Bereich der Bluetooth-SoCs hat dazu geführt, dass der mit 16 MHz arbeitende Prozessor des micro:bit (insbesondere auch mit seinen nur 16 KB SRAM) heute wie ein Methusalem aussieht. Zudem ist das aus 5×5 Leuchtdioden bestehende Display für die Ausgabe komplizierterer Grafiken nicht geeignet.
Attacke von Adafruit
Spätestens als Nordic Semiconductor den nRF52840 vorstellte - ebenfalls ein einkerniges Bluetooth-SoC, dessen ARM-Prozessor allerdings bis zu 64 MHz erreicht und 256 KB RAM hat - war der „Angriffsvektor“ klar. Die Bilder 1 und 2 zeigen das Resultat - ein System, das dem BBC micro:bit durchaus ähnlich sieht.
Neben dem auf diesen Fotos nicht direkt erkennbaren SoC fällt auf der Vorderseite der wesentlich größere Bildschirm auf - statt den Leuchtdioden bekommen wir es mit einem 240 × 240 Pixel großen Farbdisplay zu tun, das allerdings nicht auf organischer, sondern auf klassischer IPS-LCD-Technologie basiert.
Ein „netter Touch“ des Moduls ist der auf der Rückseite befindliche und in Bild 3 gezeigte Steckverbinder. Er exponiert im hauseigenen Format einen I2C-Bus, über den sich unbürokratisch weitere Sensoren anschließen lassen. Zudem gibt es einen Adapter auf das von Seeed betriebene Grove-Format, für das verschiedene fair bepreiste Sensoren im Handel angeboten werden.
Beachten Sie, dass der CLUE nur teilweise mit dem großen Vorbild kompatibel ist. Der Konnektor auf der Unterseite ist physikalisch identisch - ob der Nutzung eines anderen Displays gilt allerdings, dass der „Gutteil“ der Gehäuse für den BBC micro:bit nicht auf den Adafruit CLUE passt.
Der Autor testete diese Hypothese mit dem unter [2] bereitstehenden ThingiVerse-Gehäuse von domw. Die Vorderseite passte offensichtlich nicht, da das Display des CLUE wesentlich größer war als die LED-Matrix des Originals der BBC. Besonders überraschend empfand der Autor in diesem Zusammenhang, dass die Rückwand des Gehäuses trotz der zusätzlichen Stecker problemlos passte - dies lag allerdings daran, dass das Gehäusedesign vergleichsweise großzügig gestaltet war. Hat Ihr Gehäusedesigner „knapper“ konzipiert, so wäre wahrscheinlich schon an dieser Stelle komplettes Ende.
Eine Frage der Programmierung
Als „Ausbildungssystem“ ist der micro:bit fernab von klassischen Embedded-Entwicklungsumgebungen wie ARM Keil angesiedelt - dies mag für Embedded-Puristen ärgerlich sein, ist in der Praxis aber notwendig, weil an vielen Hochschulen nicht ausreichend kompetentes Personal zum Debuggen von C++-Programmfehlern zur Verfügung steht (glauben Sie dem Autor: Kadetten finden die magisch debilsten Wege).
Stattdessen wird im Allgemeinen auf ein Quadriumvirat aus Arduino IDE, CircuitPython, MakeCode und Scratch gesetzt. Im Fall des CLUE gilt, dass nur zwei der Systeme zur Verfügung stehen: An MakeCode wird ohne Liefertermin gearbeitet; zu Scratch gibt es keine Informationen.
Wichtig ist, dass Adafruit den CLUE mit einem seriellen Bootloader ausstattet, um das „Deployment“ von Code - ganz analog zum Raspberry Pi Pico - zu ermöglichen.
Für einen ersten kleinen Versuch wollen wir CircuitPython zum Laufen bringen.
Verbindet man ein jungfräuliches Board über den auf der Rückseite befindlichen MicroUSB-Connector mit dem Rechner, so zeigt das Display eine Statusseite (Bild 4), die Informationen über den Betriebszustand anbietet.
Doppeltes Drücken des auf der Rückseite befindlichen Reset-Buttons sorgt im ersten Schritt dafür, dass die Bildschirmanzeige ob des im Displaycontroller enthaltenen Framebuffers einfriert. Die angeschlossene Workstation (beim Autor läuft sie unter Linux) sieht das Aufscheinen eines neuen USB-Laufwerks, auf dem sich Kompilate ablegen lassen.
Interessanterweise ist der Adafruit CLUE für den Rechner „immer“ sichtbar - ist er nicht im Bootloader-Modus, so erkennt ihn dmesg folgendermaßen:
. . .
[28292.202193] usb 1-2.7: Manufacturer: Adafruit LLC
[28292.202195] usb 1-2.7: SerialNumber: 7687A137B6FDB874
[28292.204040] cdc_acm 1-2.7:1.0: ttyACM0: USB ACM device
Nach dem Doppel-Druck auf den Button sehen wir stattdessen nach folgendem Schema ein USB-Laufwerk:
. . . .
[28371.624193] sd 10:0:0:0: Attached scsi generic sg6 type 0
Wichtig ist, dass dieses Laufwerk nicht „ewig“ aktiviert bleibt - die Firmware setzt sich nach etwa 30 Sekunden Totzeit wieder in den normalen Betrieb zurück.
Dateien suchen
Wir besuchen im ersten Schritt die URL https://circuitpython.org/board/clue_nrf52840_express/, um die Datei adafruit-circuitpython-clue_nrf52840_express-en_US-6.1.0.uf2 herunterzuladen. Sie enthält die Runtime, die Sie auf dem USB-Laufwerk ablegen.
Interessant ist in diesem Zusammenhang, dass Sie im Laufwerk zudem eine Datei namens CURRENT.UF2 finden - sie erlaubt das einfache Abernten des Kompilats, dass gerade im Speicher des Prozessrechners liegt.
Lustigerweise wird die Runtime nicht mit einem vollständigen Bibliotheks-Set ausgeliefert, das alle enthaltenen Sensoren abdeckt. Wir müssen stattdessen die URL https://circuitpython.org/libraries aufrufen, wo wir uns das Archiv adafruit-circuitpython-bundle-6.x-mpy-20210329.zip herunterladen und es in einen bequemen Ordner im Dateisystem extrahieren.
Spätestens an dieser Stelle sollten Sie einen weiteren Blick auf den Bildschirm des CLUE werfen - die Runtime gibt die Inhalte der Konsole permanent am Bildschirm aus. Ein netter Touch ist, dass das Gerät auf dem PC - wie in Bild 5 gezeigt - den internen Speicher der Python-Arbeitsumgebung exponiert.
Wichtig ist, dass Sie im Libs-Ordner einerseits die folgenden Ordner aus dem Archiv unterbringen:
adafruit_bus_device
adafruit_display_shapes
adafruit_display_text
adafruit_lsm6ds
adafruit_register
Als wäre dies noch nicht genug der Arbeit, mutet Adafruit den Käufern auch noch das Zusammensuchen der folgenden Einzeldateien zu - warum man nicht ein „schlüsselfertiges“ Archiv anbietet, ist dem Rezensenten nicht klar:
adafruit_clue.mpy
adafruit_lis3mdl.mpy
adafruit_sht31d.mpy
adafruit_slideshow.mpy
neopixel.mpy
Code-Beispiel
Für einen ersten kleinen Gehversuch mit der Python-Umgebung bietet sich das unter https://learn.adafruit.com/adafruit-clue/clue-spirit-level bereitstehende Beispiel an - es realisiert einen Lagemesser, nutzt dabei aber eine Reihe CLUE-spezifischer Idiome.
Die erste Amtshandlung des Codes besteht darin, eine Gruppe von Bibliotheken zu inkludieren:
import displayio
from adafruit_display_shapes.circle import Circle
from adafruit_clue import clue
Neben dem clue-Objekt, das diverse boardbezogene Funktionen zur Verfügung stellt, ist hier auch der Import der Circle-Klasse interessant. Der GUI-Stack erlaubt nicht nur das „direkte“ Zeichnen in einen Framebuffer, sondern unterstützt auch die Arbeit mit Objekten, die von der Firmware in am Bildschirm erscheinende Elemente umgesetzt werden.
Im nächsten Akt kümmert sich die Firmware darum, einen Verweis auf das Display zu verschaffen und ein Display-Group-Objekt zusammenzustellen:
clue_group = displayio.Group(max_size=4)
Das clue_group-Objekt ist insofern interessant, als es ein an einen DOM-Baum erinnerndes Eltern-Element generiert, dem unser Code danach mehr oder weniger beliebige Objekte für die Anzeige einschreibt.
Aus der Logik folgt, dass die nächste Amtshandlung des Programms darin besteht, drei für die Darstellung der Stärke der Auslenkung zuständigen Kreise zu erzeugen und für die Ausgabe anzumelden:
middle_circle = Circle(120, 120, 75, outline=clue.YELLOW)
inner_circle = Circle(120, 120, 35, outline=clue.GREEN)
clue_group.append(outer_circle)
clue_group.append(middle_circle)
clue_group.append(inner_circle)
Als Nächstes folgen noch einige weitere Housekeeping-Tasks, deren Sinn sich am einfachsten beim Blick auf das im Artikel weiter unten gezeigte Beispiel-Rendering erschließt:
bubble_group = displayio.Group(max_size=1)
level_bubble = Circle(int(x + 120), int(y + 120), 20, fill=clue.RED, outline=clue.RED)
bubble_group.append(level_bubble)
clue_group.append(bubble_group)
display.show(clue_group)
Zu guter Letzt benötigen wir eine Arbeitsschleife, die die von der Adafruit-Bibliothek über das Attribut acceleration ausgegebenen Lagewerte analysiert und in die Koordinaten-Eigenschaften des „Ziel-Objekts“ weiterschreibt:
x, y, _ = clue.acceleration
bubble_group.x = int(x * -10)
bubble_group.y = int(y * -10)
Der bequemste Weg zur „schnellen“ Ausführung vom Code am CLUE ist die in Bild 5 gezeigte Datei code.py. Sie wird von der CircuitPython-Firmware automatisch im Rahmen jedes Starts ausgeführt. Bild 6 zeigt, was Sie sich erwarten dürfen.
Ob des Vorhandenseins eines Bluetooth-Transmitters ist das System auch zur Kommunikation mit dem Rechner befähigt. Unter [3] stellt Adafruit ein sehr lustiges Beispiel zur Verfügung, das die Verwendung einer in Google Chrome implementierten Web-Bluetooth-API illustriert.
Und jetzt mit C
Python mag ein schneller Weg sein, um „unbürokratisch“ Ergebnisse aus einem Prozessrechner zu bekommen. Die maximale Performance erreicht man durch C.
Insbesondere auf einem Einkern-Funksystem ist das Realisieren von kommunikativem Code schwierig, wenn es nicht zu Timing-Problemen kommen soll. Damit zwingt Adafruit Entwicklern die Nutzung der Arduino-IDE mehr oder weniger auf. Im Hintergrund arbeitet dann ein Echtzeit-Betriebssystem, das sich um die Zuweisung von Rechenleistung an die verschiedenen Aufgaben kümmert.
Unter Linux ist im ersten Schritt ein Erweiterungspaket erforderlich, das der Arduino IDE (ab Version 1.8.6) die Kommunikation mit dem nicht-standardisierten Bootloader des CLUE ermöglicht:
Collecting adafruit-nrfutil
. . .
Successfully installed adafruit-nrfutil-0.5.3.post13
Als Nächstes müssen wir im Board Manager die URL https://www.adafruit.com/package_adafruit_index.json einpflegen, um das Board-Package Adafruit nRF52 zum Download verfügbar zu machen. Nach getaner Arbeit steht das Board unter Tools > Board > Adafruit CLUE zur Verfügung.
Wie im Fall von CircuitPython gilt leider auch hier, dass die Einrichtung von Bibliothek und Co. ein arbeitsamer Prozess ist. Weitere Informationen dazu finden sich unter [4].
Lohnt es sich?
Wer den CLUE in die Hand nimmt, bekommt eine durchaus attraktive Evaluationsplattform, die - insbesondere dank des Bildschirms - im Bereich Interfacing angenehm zu bedienen ist. Andererseits steht der im Vergleich zum BBC micro:bit vergleichsweise hohe Preis - das „Original“ kostet wesentlich weniger. Als wäre dies noch nicht genug, ist der CLUE eben doch nicht zu 100% mit dem micro:bit kompatibel - die traurige Lebenserfahrung lehrt, dass ein „insignifikantes Detail“, das von 99% der Anwendungen nicht tangiert wird, genau im vorliegenden Projekt für Probleme sorgt.
Wer eine „saubere“ Nordic-basierte Plattform realisieren möchte, ist mit einem klassischen Evaluationsboard besser bedient. Unterm Strich ist der CLUE also ein liebenswertes Produkt für jene, die einer kompatiblen Kleinstserie von BBC micro:bit-Projekten zu mehr Leistungsfähigkeit verhelfen wollen.
(210395-01)
Sie haben Fragen oder Kommentare?
Haben Sie Fragen oder Anmerkungen zu diesem Artikel? Senden Sie eine E-Mail an editor@elektor.com.
Übersetzung: Vasileios Laskaridis