AZ-ONEBoard in MicroPython - Teil 2 - Raumklima mit SHT30 - AZ-Delivery
Diesen Beitrag gibt es auch als PDF-Dokument.

Im ersten Beitrag zum Thema AZ-Oneboard hatten wir uns um das Breakout-Board mit dem BH1750 gekümmert und den Zugang zu den vom System nicht genutzten GPIOs geschaffen. Heute geht es um die Programmierung eines Moduls für den Zugriff auf das SHT30-Board, mit dem Temperatur und relative Luftfeuchte erfasst werden können. Grundlage dafür ist das Datenblatt von Sensirion. Der Chip kann Temperaturen von 0°C bis 65°C erfassen und wird, ähnlich wie der BH1750, über Kommandos gesteuert. Allerdings sind das hier 16-Bit-Words, dargestellt durch zwei Bytes. Wir werden für den SHT30 eine eigene Exception-Klasse bauen, eine CRC-Test-Routine programmieren und die Erkenntnisse über Decorators erneut nutzen. Außerdem gibt es einen Tipp zum bequemen Testen von Modulen. Genaueres erfahren Sie in dieser neuen Folge aus der Reihe

MicroPython auf dem ESP32, ESP8266 und Raspberry Pi Pico

heute

Das AZ-Oneboard und der SHT30

Die Steckleiste des Breakout-Boards mit dem SHT30 hat dieselbe Pinfolge wie der BH1750 und kann daher auch an eine beliebige der drei Buchsenleisten angesteckt werden.

Abbildung 1: AZ-Oneboard mit zwei Satelliten

Abbildung 1: AZ-Oneboard mit zwei Satelliten

Die Hardware

Das sonst übliche Board mit dem Controller, hier ein ESP8266, wird durch das AZ-Oneboard ersetzt. An der Hardwareliste aus der ersten Episode hat sich nichts geändert. Das SHT30-Board ist ja bereits in dem Kit enthalten.

1 AZ-ONEBoard Entwicklungsboard inklusive Extensionboards SHT30, BH1750 & SGP30
1 0,91 Zoll OLED I2C Display 128 x 32 Pixel
1 Mini Breadboard 400 Pin mit 4 Stromschienen
1 Jumper Wire Kabel 3 x 40 STK. je 20 cm M2M/ F2M / F2F
optional Logic Analyzer

Abbildung 2: Anschluss des SHT30-Boards

Abbildung 2: Anschluss des SHT30-Boards

Die Software

Fürs Flashen und die Programmierung des Controllers:

Thonny oder

µPyCraft

Signalverfolgung:

Saleae Logic 2

Verwendete Firmware für den ESP8266:

v1.23.0 (2024-06-02) .bin

Die MicroPython-Programme zum Projekt:

timeout.py: Nichtblockierender Software-Timer

oled.py: OLED-API

ssd1306.py: OLED-Hardwaretreiber

bh1750.py: Hardwaretreiber-Modul

bh1750_test.py: Demoprogramm

bh1750_kal.py: Programm zum Kalibrieren der Lux-Werte

sht30.py: Hardwaretreiber-Modul

sht30_test.py: Demoprogramm

MicroPython - Sprache - Module und Programme

Zur Installation von Thonny finden Sie hier eine ausführliche Anleitung (english version). Darin gibt es auch eine Beschreibung, wie die Micropython-Firmware (Stand 18.06.2022) auf den ESP-Chip gebrannt wird. Wie Sie den Raspberry Pi Pico einsatzbereit kriegen, finden Sie hier.

MicroPython ist eine Interpretersprache. Der Hauptunterschied zur Arduino-IDE, wo Sie stets und ausschließlich ganze Programme flashen, ist der, dass Sie die MicroPython-Firmware nur einmal zu Beginn auf den ESP32 flashen müssen, damit der Controller MicroPython-Anweisungen versteht. Sie können dazu Thonny, µPyCraft oder esptool.py benutzen. Für Thonny habe ich den Vorgang hier beschrieben.

Sobald die Firmware geflasht ist, können Sie sich zwanglos mit Ihrem Controller im Zwiegespräch unterhalten, einzelne Befehle testen und sofort die Antwort sehen, ohne vorher ein ganzes Programm kompilieren und übertragen zu müssen. Genau das stört mich nämlich an der Arduino-IDE. Man spart einfach enorm Zeit, wenn man einfache Tests der Syntax und der Hardware bis hin zum Ausprobieren und Verfeinern von Funktionen und ganzen Programmteilen über die Kommandozeile vorab prüfen kann, bevor man ein Programm daraus strickt. Zu diesem Zweck erstelle ich auch gerne immer wieder kleine Testprogramme. Als eine Art Makro fassen sie wiederkehrende Befehle zusammen. Aus solchen Programmfragmenten entwickeln sich dann mitunter ganze Anwendungen.

Autostart

Soll das Programm autonom mit dem Einschalten des Controllers starten, kopieren Sie den Programmtext in eine neu angelegte Blankodatei. Speichern Sie diese Datei unter main.py im Workspace ab und laden Sie sie zum ESP-Chip hoch. Beim nächsten Reset oder Einschalten startet das Programm automatisch.

Programme testen

Manuell werden Programme aus dem aktuellen Editorfenster in der Thonny-IDE über die Taste F5 gestartet. Das geht schneller als der Mausklick auf den Startbutton, oder über das Menü Run. Lediglich die im Programm verwendeten Module müssen sich im Flash des ESP32 befinden.

Zwischendurch doch mal wieder Arduino-IDE?

Sollten Sie den Controller später wieder zusammen mit der Arduino-IDE verwenden wollen, flashen Sie das Programm einfach in gewohnter Weise. Allerdings hat der ESP32/ESP8266 dann vergessen, dass er jemals MicroPython gesprochen hat. Umgekehrt kann jeder Espressif-Chip, der ein kompiliertes Programm aus der Arduino-IDE oder die AT-Firmware oder LUA oder … enthält, problemlos mit der MicroPython-Firmware versehen werden. Der Vorgang ist immer so, wie hier beschrieben.

Die Vorbereitung des AZ-Oneboards

Das Board kommt mit einem fertig programmierten ESP8266. Das Programm demonstriert die Möglichkeiten der drei Sensoren. Abbildung 3 zeigt die Ausgabe des Programms mit dem Terminalprogramm Putty.

Abbildung 3: Ausgabe mit der Demosoftware

Abbildung 3: Ausgabe mit der Demosoftware

Wir wollen aber unser eigenes Programm in MicroPython schreiben und laufen lassen. Der erste Schritt zum Ziel ist, dass wir einen entsprechenden MicroPython-Kern auf den ESP8266 brennen, der das Demoprogramm überschreibt. Laden Sie also erst einmal die Firmware herunter und folgen Sie dann bitte dieser Anleitung. Der ESP8266 meldet sich dann im Terminal von Thonny etwa so:

Die Programmierung des Moduls

Am AZ-Oneboard sind jetzt angesteckt: das SHT30-Board, das BH1750-Board und das OLED-Display. Wir starten wieder mit der händischen Überprüfung der Devices. Eingaben in REPL werden in diesem Skript fett formatiert, die Antworten vom ESP8266 kursiv.

Die 35 = 0x23 kennen wir aus der letzten Folge als Geräteadresse des BH1750. 60 = 0x3C kommt vom OLED-Display. Also ist 68 = 0x44 die Hardwareadresse des SHT30 und alle drei Peripherie-Geräte funktionieren so weit, also legen wir los.

Ein paar Dinge importieren.

Eine eigene Exception-Klasse

MicroPython hat zur Fehlerabsicherung die Basisklasse Exception mit einer großen Anzahl von Unterklassen, die bestimmte Bereiche abdecken. Wir wollen heute eine eigene Ausnahmeklasse für die Behandlung von Fehlern erstellen, die speziell den SHT30 betreffen. Sie soll SHTError heißen und muss von Exception erben.

Folgende Fehlerarten können auftreten. Wir weisen den Bezeichnern Konstanten zu.

Wie bei jeder Klasse brauchen wir einen Konstruktor, dem beim Aufruf eine der Konstanten übergeben wird. Den Wert weisen wir dem Instanz-Attribut code zu und initialisieren die Top-Klasse Exception, der wir eine Referenz auf die Methode message() übergeben. Diese wird sich um die Fehlermeldungen kümmern.

Starten wir jetzt das Programm schon einmal im Editorfenster von Thonny – F5.

Mit der folgenden Zeile lösen wir eine Fehlermeldung aus, welche die genaue Position und die Art des Fehlers mitteilt.

Als Nächstes gehen wir ans Ende des Programms. Durch den folgenden Trick können wir das Modul, welches wir gleich erstellen werden, ganz einfach testen, ohne dass wir die Datei nach jeder Änderung auf den ESP8266 hochladen müssen. Das erspart eine Menge Zeit und Umstände. Ergänzen wir das Programm also durch folgende Zeilen.

Wird das Modul als Hauptprogramm im Editorfenster gestartet, weist MicroPython dem Attribut name den String "main" zu. Wird eine Klasse dagegen regelrecht importiert, dann bekommt name den Namen der Klasse zugewiesen. Wenn wir unser bisheriges Programm abspeichern und auf den ESP8266 hochladen, können wir uns durch folgende Eingaben davon überzeugen.

Mit der Funktionstaste F5 wird das Modul im Editorfenster als Hauptprogramm gestartet.

Wir importieren somit die Klasse SoftI2C und instanziieren ein I2C-Bus-Objekt, so wie wir es in einem Hauptprogramm tun würden. Sobald die ersten Methoden unserer Klasse SHT3X existieren, können wir die unterste Zeile entkommentieren und haben damit nach einem Druck auf F5 unmittelbaren Zugriff auf die Routinen.

Die Klasse SHT3X

Beim BH1750 hatten wir die Kommandos durch Konstanten definiert. Prinzipiell ginge das hier auch mit Hilfe von 16-Bit-Worten. Dennoch habe ich einen anderen Weg gewählt. Wie wir aus dem vorangegangenen Beitrag wissen, können über den I2C-Bus nur Bytes-Objekte oder Bytearrays übertragen werden, weil diese Datentypen das Buffer-Protokoll unterstützen. Die Kommandos für den SHT30 setzen sich grundsätzlich aus zwei Bytes zusammen. Warum also nicht gleich Bytes-Objekte für die Festlegung verwenden? Das erspart auch noch die Umwandlung. Der Definitionsblock sieht damit aus wie folgt.

Ein paar weitere Definitionen folgen.

Damit sind wir mit init() auch schon beim Konstruktor der Klasse SHT3X. Obligatorisch wird beim Aufruf ein I2C-Bus-Objekt übergeben.

Nach der Festlegung einiger Instanzattribute prüfen wir, ob sich die Hardware-Adresse des SHT30 in der Liste befindet, die scan() zurückgibt. Ist das nicht der Fall, werfen wir eine SHTBoardError-Exception. Das aufrufende Programm kann darauf mit try – except reagieren. Tut es das nicht, erfolgt der Programmabbruch. Dann setzen wir das Statusregister im SHT30 zurück und definieren das Attribut status.

Der Methode sendCommand() übergeben wir den Kommando-Code, der mittels i2c.writeto() nach der Hardware-Adresse über den I2C-Bus gesendet wird.

Jetzt können wir die Methode clearStatus() definieren, die auf sendCommand() zurückgreift.

Aufmerksame Leser stellen hier fest, dass das Kommando SHTCMD_CLEAR_STATUS zusammen mit dem Klassenbezeichner referenziert wird. Beim BH1750 war das nicht so. Der Grund ist, dass die Kommandos hier als Bytes-Objekte definiert sind und nicht als Konstanten. Konstanten werden direkt im Programmcode abgelegt, bei Variablen ist das nicht möglich. Würde man alle Kommandodefinitionen als Konstanten von Bytes-Objekten definieren, dann könnte SHT3X wegbleiben. Als Konstanten werden einige Basistypen akzeptiert, also zum Beispiel Ganzzahlen, Fließkommazahlen, Bytes-Objekte und String-Literale.

Jetzt können wir die letzte Zeile im Programm entkommentieren.

Als Nächstes soll eine Routine entstehen, die einen Einzelschuss triggert und anschließend die Messwerte einliest. Die Tabelle in Abbildung 4 zeigt uns die Möglichkeiten auf. Repeatability übersetzt Onkel Google als Wiederholgenauigkeit. So heißt es auf Seite 2 im Kleingedruckten, dass es sich dabei um den dreifachen Wert der Standardabweichung von mehreren Messungen handelt. Erreicht wird das wohl durch mehrfaches Sampeln der Messgrößen aus denen dann ein Mittelwert berechnet wird. Das würde auch die verschiedenen Messzeiten der einzelnen Modi erklären, die zwischen 4,5ms (Low) und 15,5ms (High) liegen

Abbildung 4: Singleshot Modi

Abbildung 4: Singleshot Modi

Clockstretching enabled bedeutet im I2C-Bus-Protokoll, dass ein Peripheriegerät die Taktleitung auf 0 ziehen kann, wenn es gerade beschäftigt ist und keine Daten senden kann. Beim SHT30 verhält sich das ähnlich. Wenn nach einem empfangenen Kommando der Wandlerprozess getriggert wurde und gleich danach eine Leseanfrage vom ESP8266 gesendet wird, antwortet der SHT30 darauf mit einem Acknowledge-Bit (ACK), legt aber die Taktleitung so lange auf 0, bis der Prozess beendet ist und Messdaten vorliegen. Dann gibt er die Taktleitung frei und sendet die Datenbytes mit dem wiedereinsetzenden Takt vom ESP8266. Die Blöcke links in Abbildung 5 entsprechen dem Senden des Kommandos und einer Leseanfrage, die der SHT30 aber nicht bedienen kann, weil noch keine Daten vorliegen. Die Wandlung dauert etwa 12ms. Danach werden die Daten übertragen. Die Abbildung 6 und 7 zeigen die Details.

Abbildung 5: Clock-Stretching im Überblick

Abbildung 5: Clock-Stretching im Überblick

Abbildung 6: Clock-Stretching – Kommando 0x2C06 und Leseanfrage

Abbildung 6: Clock-Stretching – Kommando 0x2C06 und Leseanfrage

Nach der Leseanfrage beginnt beim roten Punkt das Clockstretching. Für ca. 11,6 ms hält der SHT30 die CLK-Leitung auf 0.

Abbildung 7: Daten senden nach Auszeit

Abbildung 7: Daten senden nach Auszeit

Danach kann der ESP8266 die Taktleitung wieder übernehmen und die sechs Datenbytes einlesen.

Ist Clockstretching nicht enabled, beantwortet der SHT30 eine Leseanfrage mit einem Not Acknowledge-Bit (NACK). Diesen Umstand muss unser Programm handeln. Am besten man wartet mit dem Senden der Leseanfrage so lange, bis der SHT30 laut Datenblatt fertig sein müsste.

Die Routine muss nun aus den Vorgaben durch die Parameter stretching und rep das Kommandowort zusammenbauen, versenden, warten, falls stretching disabled ist und dann die Daten einlesen.

Die übergebenen Argumente werden auf Einhaltung des Wertebereichs geprüft. Dann verwenden wir sie als Indices im Bytes-Objekt SHT_ONESHOT und in der Liste mit den LOW-Bytes, die die Wiederholgenauigkeit festlegen. Die herausgepickten Werte senden wir als Bytearray zum SHT30.

Wenn das Stretching deaktiviert ist, müssen wir selber eine Pause einhalten, deren Dauer vom Repeatability-Wert abhängt und aus der Liste mtime mit rep als Index geholt werden kann. Ist Stretching aktiviert, kümmert sich der ESP8266 selbst im Verborgenen um die korrekte Abwicklung.

Aber wieso holen wir dann sechs Bytes vom SHT30 ab, Temperatur und Feuchte sind doch nur 16-Bit-Werte? Nun, nach den beiden Bytes für den Messwert wird jeweils ein Byte für eine Prüfsumme drangehängt, um die Korrektheit der Werte prüfen zu können.

Diesen Cyclic Redundancy Check oder kurz CRC übernimmt die Routine crcTest(), der wir jeweils die beiden Datenbytes und die Prüfsumme in einem Slice des empfangenen Bytes-Objekts übergeben und zu der wir gleich im Anschluss kommen. Sie meldet True zurück, wenn kein Fehler festgestellt wurde, sonst False. In diesem Fall werfen wir die entsprechende Exception.

Die Rohwerte werden in Instanz-Attribute verfrachtet und als Liste zurückgegeben.

Für den CRC brauchen wir drei Dinge: die Daten, die Prüfsumme und ein sogenanntes Polynom. Beim SHT30 lautet es 0x131. Der im Handbuch angegebene Wert von 0x31 ist falsch, wie man an dem daneben angegebenen Polynom ersehen kann! Jeder vorkommenden Potenz von x entspricht nämlich eine 1 an der Bitposition, die der Exponent angibt. Eine Beschreibung des Prüfvorgangs finden Sie hier, zusammen mit einem Beispiel.

SHTPOLY = const(0x131) # x^8 + x^5 + x^4 + 1 = 0b100110001

Durch Slicing und Indexing trennen wir das Bytes-Objekt in die beiden Datenbytes und das Prüfsummenbyte auf. blobb[:-1] liefert Byte 0 und Byte 1 und blobb[-1] liefert die Prüfsumme. Programm starten – F5.

Für die kontinuierliche Erfassung von Messwerten sind das Anstoßen der Messreihe und das Einlesen der Werte in getrennten Routinen realisiert. Es gibt dabei kein Clockstretching, dafür kann man aber verschiedene Messintervalle einstellen. Die Wartezeiten sind in dem Tupel QueryDelay untergebracht, auf die ein Hauptprogramm zugreifen kann.

Wie beim Single Shot wird das Befehlswort gemäß unseren Wünschen aus zwei Bytes zusammengesetzt. mps gibt die Anzahl Messungen pro Sekunde an.

Abbildung 8: Das sind die Dauerläufer

Abbildung 8: Das sind die Dauerläufer

startPeriodic() entspricht dem ersten Teil von getOneshot(). mps und rep sind Indices in die jeweiligen Listen.

Das Einlesen von Werten übernimmt readPeriodic(), das ähnlich wie der zweite Teil von getOneshot() aufgebaut ist. Wenn die Serienmessung getriggert ist, braucht man nur noch readPeriodic() auzurufen.

Wir starten das Programm erneut - F5

Alle jetzt noch fehlenden Kommandos haben feste Bytes-Objekte, die nicht zusammengesetzt werden müssen und daher weisen sie auch weitgehend dieselbe einfache Struktur auf.

Scanvorgänge lassen sich mit sendBrake() abbrechen.

sendReset() setzt den Sensor zurück und bewirkt das neue Laden von Kalibrierungsdaten.

Der Chip enthält eine Wärmequelle, mit deren Hilfe man die Funktion überprüfen kann. Ohne Argument aufgerufen, liefert heater() den Status, der wird durch Bit13 des Statusregisters angegeben. Wir isolieren das Bit durch Undieren und schieben es an die Position 0. Mit den Argumentwerten 0 oder 1 schalten wir den Heater aus oder ein.

readStatus() folgt in der Struktur dem Anfordern und Einlesen von Messwerten. Auch hier wird eine Prüfsumme mitgeliefert.

Eine ganze Reihe von Statusbits steht zur Verfügung. Durch den Decorator @property sparen wir uns die Eingabe von Klammern.

Programmstart – F5

Statusregister löschen:

Die Methoden getOneshot() und readPeriodic() liefern nur die Rohwerte für Temperatur und relative Luftfeuchte. calcValues() berechnet daraus die richtigen Messwerte. Die Formeln dafür verrät uns das Datenblatt. Zur Berechnung wird auf die bereits eingelesenen Rohwerte in den Attributen rawTemp und rawHum zurückgegriffen.

Die Werte werden in Instanzattributen gespeichert und auch direkt in Form einer Liste zurückgegeben. temp, hum und values ermöglichen das nachträgliche Auslesen der berechneten Werte.

Programmstart - F5

Manchmal will man den ganzzahligen und den Bruchanteil der Messwerte getrennt haben. Das erledigt die Methode readValuesDecimal(). Sie holt sich die Werte aus den Instanzattributen und produziert je eine Liste für Temperatur und Feuchte.

Programmstart – F5

Für den Test des Moduls müssen wir die Datei als sht30.py abspeichern und zum ESP8266 hochladen.

Testprogramm

Das Programm sht30_test.py enthält vier Routinen, die die Funktion des Moduls im Programmkontext demonstrieren. Die Routinen fassen zusammen, was wir bereits händisch auf REPL ausprobiert haben.

Eine fünfte Funktion bezieht die Helligkeitsmessung mit dem Modul BH1750 mit ein. Die Datei bh1750.py muss dazu in den Flash des ESP8266 hochgeladen sein. Wir lassen das Programm im Editorfenster von Thonny ausführen und können dann jede der Funktionen einzeln aufrufen.

In der nächsten Folge schließen wir die Untersuchung des AZ-Oneboards mit einem Modul für das SGP30-Board zunächst ab. Auch da gibt es wieder interessante Dinge zu erfahren.

Also, bleiben Sie dran!

DisplaysEsp-8266Projekte für anfängerSensoren

2 commentaires

Andreas Wolter

Andreas Wolter

@UKTechman: Yes it is. As workaround you could save the english version of the website as PDF in your webbrowser. That’s why we normally don’t make PDFs. The customers could do that in this easy way.

Best regards,
Andreas Wolter
AZ-Delivery Blog

UKTechman

UKTechman

The pdf seems to be in German only

Laisser un commentaire

Tous les commentaires sont modérés avant d'être publiés

Articles de blog recommandés

  1. ESP32 jetzt über den Boardverwalter installieren - AZ-Delivery
  2. Internet-Radio mit dem ESP32 - UPDATE - AZ-Delivery
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1 - AZ-Delivery
  4. ESP32 - das Multitalent - AZ-Delivery