Bastelspaß mit Sensoren, Raspberry Pi und Kotlin/Native

News-Bote

Ich bring die Post
Bastelspaß mit Sensoren, Raspberry Pi und Kotlin/Native

Wir basteln uns Spaß mit Sensoren, Raspberry Pi und Kotlin/Native


Ein Raspberry Pi, ein paar Sensoren von Pimoroni, alles durch ein wenig Kotlin/Native Quelltext zusammengefügt und fertig ist das neuste Mitglied in unserer Reihe “Dr. Windows bastelt”: KPi.Enviro. Doch bis dahin war es für mich kein leichter Fußmarsch, aus unerwarteten Gründen erwiesen sich der BMP280- und TCS3472-Sensor für mich als Neuling wenig kooperativ.

Erklärung: Unterschied Kotlin/Native zu Kotlin​


Kotlin/Native (K/N)ist eine Variante des allseits bekannten Kotlin, die darauf abzielt, Quelltext in native Binärdateien zu kompilieren. Diese Dateien können ohne eine (Java) virtuelle Maschine (JVM) direkt ausgeführt werden – wie eine *.exe.

Angesichts dessen eignet sich K/N für Geräte, auf denen keine VM vorhanden ist, wie Embedded Geräte oder auch iOS und iPadOS. Der Dreh- und Angelpunkt von K/N ist die einfache, dafür verpflichtende, Einbettung von C-Bindings. In unserem Beispiel ermöglichen diese Bindings etwa den Zugriff auf die GPIO-Pins.

Was ich bisher unter Kotlin verstehe, ist Kotlin/JVM. Hier greift das größte Ökosystem von Kotlin, Java, Groovy und Co. gemeinsam und sorgt mit einem reichhaltigen Angebot an Bibliotheken und Frameworks für nichts, was man nicht mit Kotlin lösen könnte. Server- und Android-Programmierung, Minecraft und Abertausende weitere Produkte stützen sich hierbei auf die JVM Variante.

Sehnsucht nach Windows 10 IoT Core​


Bereits im letzten Teil unserer “Kotlin/Native”-Reihe zum Thema “Blinkt HAT” führte ich aus, wieso ich weg von dem sonst üblichen Windows 10 IoT Core und C# gegangen bin. Bei der Entwicklung von KPi.Enviro dachte ich des Öfteren wieder zurück an die goldene Zeit, in der sich Microsoft noch um Nischen wie Bürobastler und Co. gekümmert hat. Denn eines sei hier gesagt, im .NET-Umfeld ist der Einstieg für Anfänger wie mich in die Low Level Sensor-Ausleserei deutlich einfacher, da von .NET mehr bereits vorgefertigt mitgeliefert wird. Bei K/N setze ich weiter auf die Bibliothek ktgpio, welche aber anscheinend leider nicht mehr betreut wird.

Was mich am Ende davon abgehalten hat, war, dass es einerseits kein Windows 11 IoT existiert und dass die Entwicklung des Tooling rund um die IoT-Variante von Windows 10 allem Anschein nach einfach mitten im Prozess abgebrochen wurde. Ja, ich trauere um die Windows 10 IoT Zeit, dennoch werde ich diese bedauerlicherweise nicht wiederbeleben können.

Was basteln wir dieses Mal?​


Nachdem wir zuletzt ein paar LEDs zum Leuchten gebracht haben, geht es dieses Mal etwas tiefer in die Materie. Wir wollen Sensoren auslesen! Im Genaueren handelt es sich hierbei um Temperatur-, Druck- und Höhenwerte eines BMP280 (Bosch Datenblatt) und um eine gewisse Umgebungsfarberkennung mittels eines TCS3472 Chips (Datenblatt).

Alles zusammen ist bequem auf einem mittlerweile eingestellten Pimoroni pHAT platziert, welcher wiederum auf einem in die Jahre gekommen, aber noch immer voll ausreichenden Raspberry Pi 3B mit einem 64Bit Raspbian Betriebssystem gesteckt wird.

Schaubild

Am Ende sollen die ausgelesenen Werte mithilfe einer rudimentären Webseite vom überall aus dem lokalen Netzwerk auslesbar sein.

Lessons learned aus Blinkt!​


Alles hätte keinen Sinn, würden wir nicht aus Fehlern lernen. Im Falle von KPi.Enviro eben von im Nachhinein gelernten möglichen Verbesserungen des Vorgänger KPi.Blinkt!

Raspberry Pi Betriebssystem​


Klingt im Nachhinein offensichtlich, dennoch war die Wahl der Architektur des Betriebssystems des Raspberry Pis letztens eine Hürde. Da mein Host-System 64Bit ARM ist und Visual Studio Code Remote-Host-Extentions nur auf ein 64Bit System zugreifen kann, fiel die Wahl auf ein 64Bit Linux, obwohl ein Raspberry Pi 3B mit einem ein Gigabyte Arbeitsspeicher sich unter 32Bit wohlfühlen würde.

Simplere Softwarearchitektur​


Software-architektonisch war die Verbindung von Webseite und Sensoren immens verbesserungs- und vor allem vereinfachungswürdig. Deswegen habe ich für dieses Wochenendprojekt auf das Pattern von “Emit & subscribe” verzichtet. Sprich, die App verwendet nicht die aus Compose bekannten SharedFlows, Emitters und Collectors. Dies ist kein Entwicklungsmuster für eine produktive App. Zum Lernen von Grundlagen, welche genau nicht das reaktive Programmieren betreffen, wie ich es anstrebe, kann es ruhig hemdsärmelig sein. Wer hierzu Kenntnisse beisteuern kann, dieser Person sei mein Wohlwollen gewiss.

Beenden ohne Reue​


Neben diesem war auch der Punkt eines “gracefully shutdown” der Chip-Controller und des Webservers etwas, das ich aus Blinkt! Mitnehme. Low-Level GPIO-Pins haben es nicht gern, einfach ab- und wieder angeschaltet werden. Alte Verbindungen könnten noch aktiv sein und deswegen durch einen Neustart der App bedingte frische Verbindungen vom System abgelehnt werden.

Projektstruktur & wichtige Abschnitte​


Die App ist in vier Teile separiert, welche alle unter dem Schirm von Enviro.kt zusammenlaufen. Bmp280.kt, Tcs3472.kt und LEDs.kt kümmern sich um die Kommunikation mit den Platinenbestandteilen, wohingegen Server.kt für das Webinterface und die inhaltliche Verbindung zu den zuvor genannten Codestellen verantwortlich zeichnet.

LEDs.kt​


Dies ist mit Abstand der einfachste Bereich der App. Auf dem Enviro pHAT sind beide LEDs unter dem gleichen GPIO-Pin 4 ansteuerbar. Anders als bei Blinkt! lassen sich diese auch nicht einfärben oder dimmen. Alles schön straight forward.

BMP280.kt​


Diese Kotlin-Klasse misst die jeweils vom vorherigen Wert abhängigen Informationen Temperatur, Luftdruck und Höhe über Null aus dem via I2c angesteuerten Chip.

Wie aus dem Datenblatt von Bosch zu entnehmen, sind Daten zur Kalibrierung des Temperatursensors nötig, ohne welche die Berechnung aus den Ufern laufen würde.

Anschließend kann mittels des aus dem Datenblatt stammenden C-Algorithmus die eigentliche Berechnung stattfinden.

TCS3472.kt​


Dieser durch I2c kommunizierende Lichtsensor gab mir Rätsel auf, dennoch war die Implementierung der vom Modul erfasst Roten, Grünen, Blauen und Clear Werten überraschend einfach. Die Herausforderung bei dieser Berechnung lag im richtigen Bitmaskieren der Speicherregister mit logischen Verknüpfungen. Die “Treiber”-Klasse benutzt hierbei den einfachsten Weg und verzichtet aus Gründen der Wartbarkeit auf weitere Stellschrauben wie Gain oder Sampling.


Eine Aussage über die Sinnhaftigkeit hauptsächlich des klaren Wertes kann ich nicht treffen. Bei direktem Taschenlampenlicht wird der größtmögliche Wert von 2 Byte Datentypen mit 65’535 angeben. Ein Wert von 100 ist dennoch hell genug, um als Mensch noch Gegenstände ohne Probleme zu erkennen.

Server.kt​


Wie anfangs erwähnt, läuft hier der Einfachheit halber alles zusammen. Dies ermöglicht eine simple Einbettung erfasster Sensordaten in das Html-Seiten-Template. Da unter Kotlin native Dateizugriffe nicht vergleichbar einfach wie unter Kotlin innerhalb einer JVM realisierbar sind, ist das das Webseitengrundgerüst auch bei Kpi.Enviro als einfacher String in das Programm eingebunden. An den entsprechenden Stellen sind Platzhalter untergebracht, welche vor dem Senden des Textes an den Browsers durch einfach “Replace”-Methoden mit den eigentlichen Informationen ausgetauscht werden.

Dinge, die ich dieses Mal lernte​


Wie auch beim letzten Mal habe ich wieder viel gelernt während der Bastelei rund um den Enviro pHAT. Allein deswegen sind für mich solch Wochenendbasteleien es wert, die Zeit hierfür zu verwenden.

Nehme nichts als gegeben an!​


Die Entwicklung unter Kotlin/Native hat mir eine Sache gezeigt: Nehme nichts als gegeben an, was du bisher immer gewöhnt warst zu besitzen! Dateizugriffe, String.format() oder andere Helferlein, welche jedem Hochsprachenentwickler als obligatorisch vorkommen, sucht man in dieser Form unter Kotlin Native vergeblich – logisch da keine JVM, sondern C-Bindings, was ja wiederum die Stärke dieser Kotlin Art ist.

Andersherum fühlen sich hier Embedded- und Low-Level-Entwickler zu Hause und können sich unter Umständen auch von ihrem geliebten C oder Rust verabschieden.

Lerne die Größe deiner Datentypen​


Ein Integer ist größer als ein Word ist größer als ein Byte und über Short, Unsigned Bytes und dessen Arrays brauchen wir erst gar nicht zu reden. Während der Programmierung von KPi.Enviro wurde ich wieder feinfühliger, was den Umgang mit Datentypen anbelangt. In modernen Apps sind Integer, Double, String sowie deren Listen allgegenwärtig und man macht sich oft keine Gedanken, ob man wirklich eine 64Bit genaue Datenrepräsentation benötigt.

Beim Ansprechen von Sensoren macht es dagegen einen gewaltigen Unterschied. Fragt man ein, zwei oder vier Bytes ab, können von einem richtigen Wert nur noch Fragmente übrig bleiben. Auch das Wissen darüber, wie und wann bestimmte Typen einen Bit-Overflow produzieren, also die in ihnen gespeicherte Zahl zu groß wird, schadet auf keinen Fall. Vor allem, wenn dies ein gewünschtes Verhalten seitens des Bauteils ist.

Ich vermisse eine lebhafte Community!​


Oft fühlte ich mich allein – metaphorisch gesprochen. Kotlin Native an sich ist schon eine Nische, welche jedoch durch das immer bekannter werdende Kotlin Mobile Multiplattform und den iOS-Geräten einen gewissen Zulauf verspürt. Geht man jedoch weg von diesen Architekturen hin zu Rapsberry Pi und Co., wird es düster. Möchte man dann noch mittels GPIO-Pins andere Geräte ansprechen, ist selbst die dunkelste Nacht noch heller. Dies könnte mir jedoch auch zeigen, dass ich mich, was Kotlin Native anbelangt, von meiner Denkweise umstellen muss. Weg vom großen JVM-Ökosystem eben zurück zu C-Bindings und dass man viele Dinge einfach selbst in die Hand nehmen muss, ohne die Magie von externen Bibliotheken.

Fazit​


Hat es sich gelohnt? Allemal! Werde ich weitermachen und andere Raspberry Pi HATs ansprechen? Aber sowas von! Fühle ich mich wohl? Nope.

So lässt sich meine Bastelei eventuell zusammenfassen. Ich bin nach all dem Kopfzerbrechen froh, dass das Projekt in grob der gesteckten Zeit fertig wurde. Es zeigte mir dennoch auf, dass die großen Communities und die daraus entstehenden Hilfen von Experten im Vergleich zu JVM oder auf Windows 10 IoT Geräten noch sehr mager ist, was hauptsächlich mir als Anfänger manchmal mehr Sorgen bereitete, als ich vermutet hätte.

Dennoch ist es für mich in meinen Augen alternativlos. Ich möchte kein Python, Rust oder C einsetzen, ich möchte die Freiheit haben, das Betriebssystem meines Hosts frei auszusuchen und ich möchte absolut keine JVM auf einem armen Pi verwenden. Daher hat mir Kpi.Enviro gezeigt, was ich an Kotlin Native mag und im gleichen Punkt auch gezeigt, was ich in der Vergangenheit beispielsweise im .NET-Umfeld an Gemeinschaftsgefühl empfand.

Der Quelltext ist wie immer auf GitHub frei verfügbar.

zum Artikel...
 
Oben