Raspberry Pi Pico: Entwicklungsumgebung Thonny für MicroPython nutzen

Nachdem ich im ersten Artikel über den Raspberry Pi Pico die Hardware, die technischen Daten und das Pinout des Pico vorgestellt und mit der STM32 Bluepill, dem Arduino Nano und dem ESP8266 verglichen haben, blieb die Frage im Raum stehen, wie einfach sich der Pico programmieren lässt und ob er ein ernstzunehmender Konkurrent zu den etablierten Mikrocontrollern ist.

Im zweiten Artikel ging es dann um die Installation des UF2-Files für MicroPython und die erste Programmierung darin über Putty, was sich als wenig komfortabel herausgestellt hatte.

Darum wollen wir heute die Entwicklungsumgebung Thonny auf Windows 7 zur Programmierung des Raspberry Pi Pico in MicroPython installieren und ausprobieren.

Thonny downloaden und installieren

Zu finden ist Thonny unter thonny.org, der Download der Windows-Version findet sich unter https://github.com/thonny/thonny/releases/ Danach starten wir die heruntergeladene "thonny-3.3.13.exe" (oder ähnlich, je nach Version). Sollte Das Setup meckern, dass die Windows-Version nicht unterstützt wird, stellen wir unter den Eigenschaften der Exe die Kompatibilität auf "Windows 7":



Spätestens damit sollte die Installation einwandfrei durchlaufen. Nach dem Start von Thonny müssen wir dann noch in den Einstellungen angeben, dass wir mit dem MicroPython auf unserem Pi Pico arbeiten wollen. Außerdem geben wir die COM-Schnittstelle unseres Picos an:



Ab dann können wir mit Thonny auf unserem Pico arbeiten. Wir erhalten eine übersichtliche und funktionale Oberfläche:



Im oberen Teil können wir unseren Code eingeben und mit den Disketten-Symbolen speicher und wieder laden. Als Dateiendung empfiehlt sich *.py, um klar zu machen, dass es sich um ein Python-Programm handelt.

Der untere Teil ist die Konsole oder Kommandozeile. Das ist im Prinzip genau das Gleiche wie das, was wir im letzten Teil mit Putty hatten. Hier können wir die Ausgaben lesen und Befehle eingeben.

Allerdings jetzt mit ein bisschen mehr Komfort. Zum einen bleibt unser Programm oben im Editor erhalten. Zum Anderen haben wir den grünen Play-Button, der das aktuelle Programm aus dem Editor zum Pico überträgt und dort dann startet. So sparen wir uns das ewige Copy and Paste des Codes. Danach kann der rote Stop-Button benutzt werden, um das Programm wieder zu stoppen und Änderungen vorzunehmen. Danach kann das Programm wieder gestartet werden.

Man muss allerdings dabei bleiben, die Buttons zu benutzen. Drückt man zwischendrin STRG+C in der Konsole zum Abbruch des Programmes, kommt Thonny durcheinander. Dann hilft nur, den Pico neu zu verbinden und in harten Fällen auch Thonny neu zu starten.

Blink-Programm mit Thonny eingeben und starten

Probieren wir das doch einmal aus. Nehmen wir wieder unser kleines Blink-Progrämmchen: from machine import Pin from time import sleep led = Pin(25, Pin.OUT) while True: led.toggle() sleep(0.5) und geben es oben im Code-Fenster ein und speichern es dann als "blink.py". Danach klicken wie auf den grünen Play-Button - et voila - die LED blinkt. Nach diesem Test klicken wir auf den roten Stop-Button und Thonny sendet ein STRG+D für einen Soft-Reset und der Pico ist bereit für den nächsten Lauf mit vielleicht veränderten Programmversion.

Sollte Thonny Fehlermeldungen anzeigen, dann haben wir uns entweder verippt, oder aber vergessen, den Pi Pico in den Einstellungen einzustellen. Bei Kommunikationsfehlern hilft es eigentlich immer, Thonny zu beenden, den Pico zu trennen und neu einzustecken, kurz zu warten, und dann Thonny neu zu starten. Da Thonny klein und schlank ist, geht das zum Glück recht zügig.

Wenn wir das UF2-File für den MicroPython wie im letzten Artikel noch nicht installiert haben, dann ist Thonny so intelligent, das zu erkennen und fordert uns auf, das zu tun:



Ein Klick auf "Installieren" lädt die neueste MicroPython-Version für den Pico herunter und schiebt sie auf das Pico-Laufwerk. Danach startet der Pico neu und steht über die neue serielle CDC-Verbindung zur Verfügung. Falls nicht: im letzten Artikel erkläre ich auch, wie man das Treiberproblem mit dem CDC-Treiber unter Windows 7 löst.

Programm permanent machen mit Thonny

Ein Problem haben wir allerdi?ngs immer noch: Trennen wir den Pico und schließen ihn zum Beispiel an eine Powerbank an, dann ist auch wieder das Programm weg.

Um dem entgegen zu wirken, müssen wir das Programm als "main.py" auf dem Pico speichern. Dazu kopieren wir zuerst unseren gesamten Source-Code mit STRG+C in die Zwischenablage. Dann klicken wir auf das grüne +, um eine neue Datei aufzumachen, in die wir unseren Source wieder hineinkopieren (STRG+V). Wir haben jetzt eine neue Datei namens "<untitled>". Dies erlaubt uns, auf das Speichern-Icon zu klicken:



Hier wählen wir nun als Speicherort die zweite Option, den Raspberry Pi Pico. Dort müssen wir zwingend als Dateinamen "main.py" eingeben. Das ist der vereinbarte Name und Zeichen für den Pico, dass dieses Python-Programm beim Start ausgeführt werden soll.

Sollte hier nach Klick auf OK ein Übertragungsfehler auftreten, dann muss noch einmal auf den roten Stop-Button geklickt werden und gegebenenfalls auch der Pico und Thonny neu gestartet werden. Die rechteckigen Klammern um den Dateinamen "[main.py]" zeigen an, dass dieses Script nicht lokal auf dem PC, sondern auf dem Pico selbst gespeichert ist. Man kann so auch andere Dateien auf dem Pico speichern, aber das macht wenig Sinn, denn es gibt "nur" 2 MB Flash-Speicher und der sollte nicht verschwendet werden mit Dateien, die man zur Ausführung auf dem Pico nicht benötigt.

Bei Speicher-/Übertraungsproblemen zum Pico einfach im Source am Ende ein Return einfügen und so die Datei ändert. So lässt sie sich erneut speichern.

Wenn der Pico ein Autostart-Script drauf hat, bockt er manchmal wenn er sich wieder mit Thonny verbinden soll. Da hilft dann abwechselndes auf Stop klicken und Pico an USB-Port neu einstecken. Irgendwann erscheint dann schon bei Klick auf Stop die MicroPython-Versionsmeldung wieder.

Erste Beurteilung

Das Arbeiten mit Thonny ist eher rudimentär. Thonny kennt nur einfaches Syntax-Highlighting, von Code-Vervollständigung oder Anzeige von Unterobjekten keine Spur. Trotzdem ist es eine Erleichterung gegenüber Notepad und Putty, da es die Dateien einfacher übertragen kann.

Trotzdem bleibt die Angelegenheit hakelig. Gerade die Verbindung zur serielle Schnittstelle ist häufig aus unerfindlichen Gründen getrennt. Da hilft zwar neu anstecken und Thonny neustarten, aber das ist natürlich sehr nervig. Einfacher wie mit der Arduino IDE ist das auch nicht.

Und dann kommt noch hinzu, das auf dem Pico ein MicroPython-Interpreter läuft. Da muss jede Code-Zeile einzeln interpretiert werden. Dass das nicht sonderlich performant ist, jetzt im Vergleich zu einem C-Programm, dürfte klar sein. Außerdem dürfte damit unnötig Energie verschwendet werden und eine gegebenenfalls als Stromlieferant angeschlossene Batterie schneller leer sein.

Wer allerdings gerne in Python programmiert und C scheut, für den mag das eine Lösung sein, solange er nichts super performantes braucht. So super sparsam muss man auf dem Pico mit Speicher ja auch nicht ungehen, er bringt ja einiges mit für einen Mikrocontroller.

Zweites Script: Temperaturmessung mit dem Pico

Beim Pico wird ja angepriesen, dass dieser eine RTC-Chip und einen Temperatursensor an Bord hat. Die RTC, also die Echtzeituhr, nützt nur leider nichts, wenn sie nicht batteriegepuffert ist. Denn auch, wenn sie genau ist, ist sie nicht mehr als ein Timer, denn die Uhr muss nach jeder Stromtrennung neu eingestellt werden. Eine RTC macht halt eben aus, dass sie die Uhrzeit behält, auch wenn der Strom weg ist. Das kann der Pico nicht. Auf der Seite mit den technischen Spezifikationen wird "Accurate on-chip clock" angepriesen, also "Genaue On-Chip-Uhr", was dazu verleiten könnte, anzunehmen, sie hätte eine echte Echtzeituhr wie die STM32-Bluepill on board. Das ist aber nicht der Fall. An den Pico müsste man ein externes RTC-Modul anschließen.

Außerdem wird auf der obigen Seite ein "Temperature sensor" angepriesen. Von welcher Qualität dieser ist, steht allerdings nicht dabei. Man wird annehmen, dass hier kein hochwertiger Bosch BMP280 verbaut ist. Man wird eher so etwas in Richtung DHT 11 erwarten.

Das Datasheet vom Pico verrät aber, dass hier eine gewöhnliche Diode zur Temperaturmessung zum Einsatz kommt:
4.3. Using the ADC

3. The ADC draws current (about 150µA if the temperature sense diode is disabled, but it varies from chip to chip) and therefore there will be...
Im anderen Datasheet zum RP2040 steht, was man benötigt, um die Temperatur mit dem vom virtuellen ADC-Port 4 gelieferten Wert auszurechnen: Bei 27° Celsius wird eine Spannung von 0.706 Volt geliefert; für jedes Grad mehr oder weniger beträgt der Spannungsunterschied 1.721 mV.

4.9.5. Temperature Sensor

The temperature sensor measures the Vbe voltage of a biased bipolar diode, connected to the fifth ADC channel (AINSEL=4). Typically, Vbe = 0.706V at 27 degrees C, with a slope of -1.721mV per degree. Therefore the temperature can be approximated as follows:

T = 27 - (ADC_voltage - 0.706)/0.001721

As the Vbe and the Vbe slope can vary over the temperature range, and from device to device, some user calibration may be required if accurate measurements are required.
Das lasse ich in folgendes Python-Programm einfließen: # (C) 2022 by Oliver Kuhlemann # Bei Verwendung freue ich mich um Namensnennung, # Quellenangabe und Verlinkung # Quelle: http://cool-web.de/raspberry/ import machine import utime from machine import Pin from time import sleep temp_sensor = machine.ADC(4) while True: temp_sensor_volt = temp_sensor.read_u16() * 3.3 / 65536 # read_u16 gibt Wert zwischen 0 und 65535 # zurück. Max-Wert 65535 bei 3.3V temperature = 27 - (temp_sensor_volt-0.706) / 0.001721 # 706 mV bei 27°C, jedes weitere °C # +/- 1.721 mV print(temperature) sleep(2) Der Code sollte sich dank der eingefügten Kommentare selbst erklären. Lassen wir ihn einmal laufen.

Bei realen 21.8 °C Zimmertemperatur liefert mein 1. Pico: 27.98696 27.51881 27.51881 27.51881 27.51881 Das es sich um einen Temperatursensor handelt und wo der sich befindet, finde ich heraus, indem ich meinen Finger auf den RP2040-Chip lege. Die Temperatur geht hoch. Und als ich meinen Finger wieder wegnehme, geht sie wieder runter. Die Diode für die Temperaturmessung befindet sich also im Chip oder direkt in dessen Umgebung.

Allerdings sind die Werte um mehr als 5 °C zu hoch. Also versuche ich meinen anderen Pi Pico. Aus der selben Bestellung, aus der selben Charge, geliefert als benachbarte Picos von der selben Rolle - die kommen ja in so kleinen schwarzen Plastikbehältnissen mit Klarsichtfolie drauf und Transportlöchern am Rand.

Dieser liefert die folgenden Werte: 15.34724 15.34724 15.34724 15.34724 15.34724 Selber Code, selbe Umgebungstemperatur, jetzt aber mehr als 5 Grad zuwenig. Die beiden Picos haben einen Messunterschied von mehr als 12 °C zueinander. Das ist unterirdisch schlecht und schlicht nicht benutzbar. Auch diese angepriesene Detail "Temperatursensor" stellt sich in der Realität als unbrauchbar und als kein Mehrwert heraus.

Wer ist nur auf die Idee gekommen, diese Diodenart als "Temperatursensor" zu verkaufen? Genauso gut könnte ich Standard-LEDs als Photovoltaik-Elemente anpreisen. Klar kann man auch mit LEDs Strom durch Lichteinfall erzeugen, als das ist dermassen ineffizient, dass hier keiner auf die Idee kommen würde, das ernsthaft zu versuchen.

"Temperatursensor" und "Echtzeituhr" kann man also vergessen. Ärgern wir uns nicht lange und tun wir einfach so, als wären sie nicht da.

Libraries für Komponenten in Thonny installieren

Unter der Arduino IDE und auch unter Visual Studio Code / Platform IO gibt es für den Arduino unzählige Libraries, also Bibliotheken, die man einbinden kann, um auf alle möglichen Sensoren zuzugreifen oder Ausgabegeräte anzusprechen. Das komplizierte Ansprechen der Geräte hat dann schon jemand anderes für uns erledigt und liefert uns eine API, die uns die Verwendung der Geräte so einfach wie möglich macht.

Der Arduino ist eben gerade deswegen auch so beliebt, weil es eben eine so große Gemeinde gibt, die Libraries samt Beispielprogramme entwickelt und man eigentlich immer was findet, was einem die Arbeit erleichtert. Und kommt ein neues Bauteil heraus, dauert es nicht lange, bis es auch unterstützt wird.

Nur wie funktioniert das mit den Libraries unter Thonny? Gibt es da auch so viele Libraries? Und finde ich wenigstens eine für ein gebräuchliches OLED-Display? Machen wir die Probe auf Exempel: wir wollen unsere "Temperatur" auf einem OLED anzeigen. Dazu nehme ich das beliebte und gebräuchliche OLED mit 128x64 Pixeln und einem SSD1306-Controller her.

Für Arduino und ESP8266/ESP32 findet man da leicht eine Library. Wie sieht es hier aus?

Unter "Extras / verwaltete Pakete" findet man im Menü von Thonny den entsprechenden Dialog. Dort gebe ich einfach "OLED" als Suchbegriff ein und schaue mir die Ergebnisliste an:



Der erste Eintrag "micropvthon-oled / Micropython scripts for use OLED displays." hört sich doch vielversprechend an. Also ausgewählt und angezeigt.



Zu dem Paket kann ich noch weitere Informationen abrufen, die meine Entscheidung erleichertern sollen, ob es das richtige ist. Viel steht da ja nicht zusätzlich, also einfach mal ausprobieren und installieren anklicken.

Dazu muss ich sagen, dass ich auch unter Arduino und Co. hin und wieder rumprobieren musste, bevor ich die für mich best passende Bibliothek gefunden habe. Da hilft oft auch nur: Installieren und Beispielcode ausprobieren, ob es mit der Hardware läuft.



Apropos Beispiele: Die Beispielprogramme, die mit installiert werden, habe ich umsonst auf meine lokalen Festplatte gesucht. Weder im Thonny-Ordner, noch im User-Ordner waren die zu finden. Nirgends auf der Platte. Bis ich dann auf die Idee gekommen bin, auf den Pico zu schauen. Okay, auf den Pico gehören die Libs ansich, damit er diese ausführen kann, aber die Beispielprogramme gehören auf die PC-Festplatte, da wo die Entwicklung stattfindet und nicht auf den Pico, wo sie nur Platz wegnehmen. Auch wenn man 2 MB Flash hat muss man nicht wie ein Neureicher damit um sich werfen.



Wie gesagt, auf dem Pico konnte ich dann die Beispielprogramme unter "examples" finden. Etwas anders als bei der Arduino IDE, aber wenn man es einmal weiß, kein Problem (naja, außer der Platzverschwendung).

Nach einem kurzen Einlesen der Beispielprogramme; Copy, Paste und Anpassen von ein paar Zeilen konnte ich mein Programm zu anpassen, dass es die Temperatur auf dem OLED ausgibt: # (C) 2022 by Oliver Kuhlemann # Bei Verwendung freue ich mich um Namensnennung, # Quellenangabe und Verlinkung # Quelle: http://cool-web.de/raspberry/ import machine import utime import oled from machine import Pin, I2C from time import sleep from oled import SSD1306_I2C temp_sensor = machine.ADC(4) # für OLED scl = Pin(17) # OLED am rechten Ende angeschlossen sda = Pin(16) # GP 16 und 17, das ist I2C 0 i2c = I2C(0, scl=scl, sda=sda, freq=400000) # I2C-Bus initialisieren, 400 KHz oled = SSD1306_I2C(128, 64, i2c) # OLED am I2C-Bus initialisieren while True: temp_sensor_volt = temp_sensor.read_u16() * 3.3 / 65536 # read_u16 gibt Wert zwischen 0 und # 65535 zurück. max 65535 bei 3.3V temperature = 27 - (temp_sensor_volt-0.706) / 0.001721 # 706 mV bei 27°C, # jedes weitere °C +/- 1.721 mV print(temperature) # in Konsole über ser ausgeben oled.fill(0) # OLED löschen oled.text("Temperatur:", 0, 1) # auf OLED ausgeben oled.text("{:.2f}".format(temperature) + " Celsius", 1, 10 ) # zwei Nachkommastellen oled.show() sleep(2) Das Ergebnis sieht dann aus:



Die Library (oder Paket, wie es bei Thonny) heißt, hat auf Anhieb funktioniert. Die Lib hat mir gefallen, denn es sind wirklich nur ein paar Zeilen Code nötig und die API (Application Programming Interface, also die Funktionen, die man von außen, sprich in meinem Programm, anspricht) hat sprechende Namen.

Ob ich jetzt in C oder Python programmiere, ist mir erst einmal egal. Allerdings weiß ich auch, das C-Programme locker mal 100 mal so schnell sein können wie Python Programme, weniger Speicher brauchen und man mit Ihnen einfach so gut wie alles machen kann (nur in ganz speziellen und seltenen Fällen muss man mal zu Assembler greifen). Darum stört mich das Python nicht weiter.

Schön am Pico ist die Variabilität der GPIO-Pins. Beim Arduino bin ich zum Beispiel auf A4 und A5 festgelegt für den IC2-Bus. Beim Pico suche ich mir aus dem GPIO-Pinout quasi irgendwelche Pins aus, die mir gerade passen. Passend fand ich vom Breadboard-Aufbau die rechte obere Ecke des Pico-Boards, das hält die Kabel kurz und damit die Übersichtlichkeit auf dem Breadboard hoch.

Der I2C()-Funktion werden einfach die Nummer des I2C-Busses dort, die Pins und die Stadardfrequenz von 400 KHz übergeben. Fertig. Die Lib sorgt dann für eine genau so einfache Initialisierung des OLED-Displays.

Fazit zur Arbeit mit Thonny

Die Entwicklung mit Thonny ist auf jeden Fall sehr viel besser als quasi werkzeuglos mit Putty. Trotzdem bleibt das Hakelige mit der seriellen Schnittstelle, die nicht immer da ist und man dann genervt den Pico ab- und wieder anstecken muss.

Mit dem MicroPython-UF2-Autoinstaller und dem Paketverwalter gibt es gute Tools, die die Arbeit erleichern, auch wenn es ein wenig unsinnig ist, die Beispielprogramme auf dem Pico-Laufwerk zu speichern.

Für kleine Programme ist Thonny auf jeden Fall schon einmal brauchbar. Allerdings kann man damit nicht alles machen und auch der Editor-Komfort ist nicht sonderlich hoch. Keine Code-Vervollständigung, kein Auflisten von Unterobjekten, nur rudimentäres Syntax-Highlighting... Aber wie gesagt, für kleine Progrämmchen reicht das.

Im nächsten Artikel will ich einmal CircuitPython ausprobieren, das soll so ähnlich sein, nur besser, ohne Frickelei mit der serielle Schnittstellen und sogar die HID-Emulation (Tastatur, Maus) soll damit gehen.