Raspberry Pi Pico und Thonny mit MicroPython - Teil 2 - AZ-Delivery

Im ersten Teil hatten wir die Installation von Thonny, die Einrichtung des Raspberry Pi Pico, sowie erste Anwendungsprogramme zur Nutzung der Ein- und Ausgänge kennengelernt. Dieses Mal möchte ich Ihnen die Programmierung der bekannten Schnittstellen OneWire, UART und I2C, allesamt Zweitbelegungen der Pins, zeigen.

Zunächst noch einmal der Hinweis auf das offizielle Pinout-Diagramm.

Auch die MicroPython-Dokumentation, und insbesondere das Kapitel RP2 möchte ich als Quelle erneut angeben.

Verwendete Komponenten

 1 Raspberry Pi Pico RP2040 Mikrocontroller-Board
mehrere DS18B20 digitaler Edelstahl Temperatursensor Temperaturfühler
1 MB 102 Breadboard Kit
1 HD44780 1602 LCD Modul Display 2x16 Zeichen
1 I2C IIC Adapter serielle Schnittstelle für LCD Display
1 Drehpotentiometer 10KOhm
1 Pull-Up Widerstand 4,7KOhm
1 Raspberry Pi 400

Eindrahtbus (One Wire) am Beispiel des Temperatursensors DS18B20

Für den beliebten Temperatursensor DS18B20, ich selbst bevorzuge die wasserdichte Variante, gibt es zwei Module, die die Programmierung sehr einfach machen. Zunächst einmal benötigt man die OneWire-Bibliothek und dann die darauf aufbauende Bibliothek für den Temperatursensor. Die Schaltung ist sehr einfach: Der namensgebende „eine“ Draht geht bei meinem Projekt an Pin 12. Bitte vergessen Sie nicht den Pull-up-Widerstand (4,7 kOhm) zwischen Signalleitung und 3,3V. Wie jedes elektronische Gerät benötigt der Sensor auch eine Spannungsversorgung, also den roten Draht an 3,3V und den schwarzen an GND.

Ich versuche, mehrere Temperatursensoren DS18B20 parallel auf einen Eingang zu schalten.

Quellcode Download

Mit dem o.a. Programm werden die drei annähernd gleichen Temperaturen gemessen und in der Shell ausgegeben. Auch hier habe ich die Programmfragmente aus der Dokumentation kopiert und zu einem lauffähigen Programm ergänzt. Im oberen Teil werden onewire importiert und das Objekt ow instanziiert. Im unteren Programmteil wird zunächst das Modul ds18x20 importiert. Nach dem Instanziieren des Objekts ds werden der Eindrahtbus gescannt und die eindeutigen Kennungen der Sensoren in der Liste roms gespeichert. In der for-Schleife werden dann die Temperaturwerte für alle Elemente der Liste ermittelt und ausgegeben. Das war leicht, denn die verwendeten Module sind Teil des Programmpakets. Alle diese Module kann man sich anzeigen lassen. Haben Sie schon den Hinweis auf help() in der Zeile vor dem Prompt gesehen?

Hier finden Sie in der letzten Zeile den Hinweis auf help(‚modules‘). Dann werden alle sofort verfügbaren Python-Module angezeigt:

Für den RP Pico gibt es ein weiteres „eingebautes“ Modul mit Namen rp2. Nach dem Importieren kann man auch hierzu eine kleine Hilfe anschauen:

Mehr dazu im dritten Teil zu dieser Blog-Reihe. Andere Mikrocontroller haben übrigens auch spezifische Module mit Funktionen/Methoden, meist Erweiterungen für das Modul machine.

Für weitere Informationen verweise ich auf die offizielle Dokumentation.

DHT22

Als Nächstes möchte ich einen kombinierten Temperatur-/Luftfeuchte-Sensor verwenden, der außer der Spannungsversorgung ebenfalls nur einen Pin benötigt: den DHT22.

Pinbelegung des DHT22: 

  • Pin 1 = VCC
  • Pin 2 = Signal (an GP15 und über 10kOhm an VCC)
  • Pin 4 = GND

Für diesen Sensor gibt es kein eingebautes Modul, aber Hinweise auf ein Modul im Internet. Jetzt lernen wir, dass der interne Speicher des Pico doch ganz nützlich ist. Dort werden ab jetzt die „sonstigen“ Module abgespeichert. Aber ein Schritt nach dem anderen.

Auf GitHub findet man eine Seite zum DHT22 von Daniel Perron.  Bei Analyse des Programms dht22test.py stelle ich fest, dass ein Programm-Modul mit Namen DHT22 verwendet wird, das ebenfalls auf der Seite heruntergeladen werden kann. Kurzerhand lade ich das gesamte Paket als zip-Datei herunter.

Darüber hinaus enthält das Testprogramm Code für die Anzeige auf einem LCD. Das möchte ich später zeigen, deshalb hier zunächst nur mein schlankes Programm dht22easyTest.py mit Anzeige von Temperatur und Luftfeuchtigkeit (engl. humidity) in Thonny. Nachdem ich die Zeile mit der Instanziierung von dht noch einmal angeschaut und den Parameter Pin.PULL_UP entdeckt habe, wollte ich wissen, ob man auf den externen Pull-up-Widerstand verzichten kann. Man kann.

Quellcode Download

Das Bild von Thonny hat sich ein wenig verändert. Unter dem Menüpunkt „Ansicht“ habe ich durch Anklicken von „Dateien“ ein Häkchen gesetzt und bringe so die Verzeichnisse auf dem PC (links oben) sowie dem RP Pico (links unten) zur Anzeige. Dort finden Sie DHT22.py und weitere Module, die wir später verwenden werden. Und übrigens: Wenn man sein Programm hier unter dem Namen main.py (bitte nicht boot.py verwenden) abspeichert, erhält man eine Autostart-Funktion für den autonomen Pico.

LCD

Als nächstes habe ich mir die von Daniel Perron empfohlenen Module für die LCDs angesehen. Deren Autor heißt Dave Hylands, sein GitHub - Name ist dhylands. Auch hier lade ich das gesamte Repository python_lcd als zip-Datei herunter.

Aus der Vielzahl der Dateien für verschiedene Mikrocontroller und die beiden Anschlussmöglichkeiten der LCDs – GPIOs oder I2C – speichere ich die Dateien lcd_api.py und machine_i2c_lcd.py im internen Speicher des Pico.

Nachtrag: Die Datei lcd_api.py wird für beide Versionen gebraucht. Für die I2C-Version dann zusätzlich machine_i2c_lcd.py benutzen. Für die GPIO-Version bitte die Datei nodemcu_gpio_lcd.py unter folgendem Link
https://github.com/dhylands/python_lcd/blob/master/lcd/nodemcu_gpio_lcd.py
laden und unter dem Namen gpio_lcd.py auf dem Pico abspeichern.

Für eine einfache Real Time Clock (RTC) möchte ich zunächst ein LCD1602 mit den GPIOs des Pico verbinden.

Die Spannungsversorgung des LCD sollte lieber mit 5V erfolgen, bei 3,3V ist das Bild sehr schwach.

Öffnen Sie bitte nun mein Beispielprogramm mit dem Namen Pico_GPIO-LCD1602_RTC.py

Mit Hilfe des Moduls gpio_lcd wird das Objekt lcd mit der Pinbelegung und der Displaygröße im Programm in der folgenden Zeile instanziiert:

 lcd = GpioLcd(rs_pin=Pin(0),
               enable_pin=Pin(1),
               d4_pin=Pin(2),
               d5_pin=Pin(3),
               d6_pin=Pin(4),
               d7_pin=Pin(5),
               num_lines=2, num_columns=16)

Selbstverständlich können Sie von dieser Belegung abweichen. Bitte beachten Sie ggf. die abweichende Pinbelegung im Original DHT22-Testprogramm von Daniel Perron, wenn Sie das nachmachen wollen.

Nachdem die auszugebenden Werte je Zeile einem String zugeordnet wurden, erfolgt die Ausgabe mit

 lcd.putstr(zeile_oben + "\n" + zeile_unten)

Um die Real Time Clock zu nutzen, muss die Klasse RTC aus dem Modul machine importiert werden. Durch Entkommentieren der Zeile 34 kann man Datum und Uhrzeit als Tupel mit den Werten (year,month,day,weekday,hour,minute,second,microsecond) setzen. Mit rtc.datetime() ohne Argument werden Datum und Uhrzeit abgefragt und können dann über den Index – wie üblich bei 0 beginnend – ausgewertet werden.

Zu meiner großen Überraschung hat die RTC im stromlosen Pico über Nacht weitergearbeitet, so dass nach dem Neustart des Programms am nächsten Morgen die exakte Zeit angezeigt wurde. Wie lange die interne RTC ohne Stromversorgung weiterarbeitet, kann ich allerdings nicht sagen.

Nun das Ganze noch einmal von vorn mit meinem LCD2004 mit I2C-Adapter. Die passende Bibliothek, das Modul machin_i2c_lcd.py, habe ich schon auf dem Pico gespeichert. Laden Sie dazu bitte das Beispielprogramm Pico_I2C-LCD2004_RTC.py

LCD mit I2C-Adapter

Raspberry Pi Pico GP

Raspberry Pi Pico Pin

GND

GND

3, 8, 13,18,23, 28, 33, 38

VCC

VBUS = 5V

40

SDA

I2C0 SDA = GP8

11

SCL

I2C0 SCL = GP9

12


Mit den Zeilen

 from time import sleep
 from machine import I2C, Pin
 from machine_i2c_lcd import I2cLcd
 from machine import RTC

werden die notwendigen Klassen aus den Modulen importiert.

Die Initialisierung von I2C und dem LCD über I2C erfolgt mit

 i2c = I2C(0)                              # sda=Pin(8), scl=Pin(9)
 lcd = I2cLcd(i2c, 0x27, 4, 20)   # I2C-Adresse 0x27, 4 Zeilen, 20 Zeichen je Zeile

Im Beispielprogramm werden weitere Funktionen/Methoden des Moduls gezeigt:

  • lcd.move_to(spalte, zeile) 
  • lcd.backlight_off() 
  • lcd.backlight_on()
  • lcd.display_off()
  • lcd.display_on()

Diese befinden sich teilweise in dem auskommentierten Teil.

Damit haben wir auch eine der I2C-Schnittstellen, nämlich I2C(0) an den Pins GP8 und GP9, erstmalig benutzt.

Anstelle eines weiteren Beispiels für I2C verweise ich noch einmal auf den Blogbeitrag von Jörn Weise vom 13.Nov.2021. Darin zeigt er die Temperaturanzeige auf einem 1,3“ OLED mit der I2C-Schnittstelle.

UART oder auch die serielle Schnittstelle, aka RS232

Um die serielle Schnittstelle zu testen, benötigen wir eine Gegenstelle für die Kommunikation. In früheren Blog-Beiträgen hatte ich bereits ein Python-Programm mit dem Modul Serial auf dem Raspberry Pi vorgestellt. Hier soll der Schwerpunkt aber auf dem Pico und MicroPython liegen, deshalb nutze ich auf dem Raspi das Linux-Programm minicom. Alternativ hätte ich meinen PC mit einem USB-Seriell-Adapter und dem Programm Putty oder dem seriellen Monitor in der Arduino IDE benutzen können.

Die Verbindung zwischen Raspberry Pi und RP Pico ist schnell hergestellt. Ich verbinde zunächst jeweils einen Ground-Pin, dann 

TX = Pin(4) am Pico mit RX (phys. Pin 10) am Raspi, 

RX = Pin(5) am Pico mit TX (phys. Pin 08) am Raspi.

Vorbereitung am Raspi:

 sudo apt update
 sudo apt install minicom
 sudo minicom -D /dev/ttyS0 -d 9600

Um ein lokales Echo in minicom zu erhalten, drücke ich im Terminal Strg+A und E.

Ein geeignetes Terminalprogramm in MicroPython habe ich nicht gefunden. Entweder gibt es Beispiele zum Senden oder Empfangen von Daten. Ich möchte beides kombinieren. Vielleicht habe ich nicht die eleganteste Lösung gefunden, aber es funktioniert. Bitte laden Sie von den Beispielprogrammen nun Pico_UART.py. Es folgen einige Erklärungen dazu:

Das Modul Serial kennt MicroPython nicht. Stattdessen gibt es im Modul machine die Klasse UART mit wenigen Funktionen/Methoden. Nach dem Importieren der Klasse instanziieren wir ein Objekt uart1 mit folgendem Befehl:

 uart1 = UART(1, baudrate = 9600, tx = Pin(4), rx = Pin(5))

Die Befehle zum Senden bzw. Empfangen von Daten habe ich jeweils in den selbst-definierten Funktionen send() und receive() deklariert, den Wechsel zwischen Senden und Empfangen in der Funktion main() vorgenommen. Nach vielen Versuchen, in denen ich das Programm nur durch Ziehen des USB-Steckers beenden konnte, habe ich nach der Hilfe des Blogger-Kollegen Jürgen Grzesina den Befehl sys.exit() eingefügt. Damit wird das Programm mit Strg+C beendet. Zuvor sprang es zurück in die Endlosschleife oder wartete auf Empfangsdaten.

Eine weitere Kleinigkeit hat mich an den Rand des Wahnsinns getrieben: Nach dem Programmstart erfolgt in der Kommandozeile die Abfrage. ob gesendet oder empfangen werden soll. Zum Senden soll die „1“ eingegeben werden, zum Empfangen die „0“, es geht aber auch mit jedem anderen Zeichen als „1“. Aber der Cursor springt nicht automatisch in die Shell, sondern befindet sich weiterhin im Editor. Also: erstmal Mausklick im unteren Teil von Thonny, der Kommandozeile.

Hier nun die Bilder von der spannenden Korrespondenz zwischen Raspberry Pi 400 und RP Pico:

Es heißt: Der Appetit kommt beim Essen. Ich hoffe, ich konnte Sie mit meiner Begeisterung für den RP Pico und MicroPython anstecken und Sie probieren es auch aus. 

DisplaysProjekte für anfängerRaspberry piSensoren

4 commenti

Guenter Purin

Guenter Purin

Hallo
vielleicht kann mir hier jemand weiter helfen
Pi Pico
Thonny editor
MicroPyhton

eigene Klasse: DRV8871_HBridge.py
auf dem Pico habebich einen Ordener erstellt mit dem Namen: myLib und inn diesem Ordern ist die Datei DRV8871_HBridge.py

main.py
from machine import Timer
import time

from myLib import DRV8871_HBridge

Motor1 = DRV8871_HBridge(7, 8, 1000)

c = 0
while True:

time.sleep(0.2) Motor1.SetPwmCcw© #Motor1.SetPwmCcwProcent(100) c = c+1 if c > 65535: c = 0

leider funktioniert das Importieren nicht. Wenn die Klasse in Main.py ist, dann funktioniert alles super

Frage: was mache ich hier falsch?

Schon mal DANKE für die Hilfe

Schöne Grüße

Guenter

Jürgen

Jürgen

Warum behält die RTC des Raspi Pico die Uhrzeit?
Ganz einfach, weil er sich die Zeit bei jedem Neustart des Programms Pico_I2C-LCD2004_RTC.py die Zeit wohl automatisch vom PC her updatet. Das macht offenbar Thonny von sich aus, wenn das Programm von der IDE aus gestartet wird.
Wie stellt man das fest?
Wenn man das Programm als main.py auf dem Raspi abspeichert und danach die Verbindung zum PC abzwickt, um sie gleich danach wieder herzustellen (man kann auch kurz den Pin GP30 = RUN auf GND legen), dann startet das Programm mit der Anzeige: Freitag 1.1.2021; 0:00 (Epoche des Raspi). Das gleiche passiert, wenn man den Aufbau an einer externen Spannungsquelle anschließt, ohne USB. Durch den Reset wird eine etwaige Verbindung zum PC unterbrochen und Thonny kann keine Infos mehr mit dem Raspi austauschen.
Stellt man danach in Thonny durch Klick auf den STOP-Button die Verbindung zu REPL wieder her, und startet das Programm von dort, dann hat der Kleine wieder die Uhrzeit vom PC.

Im stromlosen Zustand kann keine RTC weiterlaufen, es ist ja schließlich kein Akku, Goldcap oder Ähnliches auf dem Pico.

Gruß Jürgen

Bernd Albrecht

Bernd Albrecht

Auf die github-Seite https://github.com/dhylands/python_lcd wurde bereits im Blog hingewiesen. Im Verzeichnis lcd findet man die benötigten Module. Die Datei lcd_api.py wird für beide Versionen gebraucht. Für die I2C-Version dann zusätzlich machine_i2c_lcd.py benutzen; und für die GPIO-Version bitte die Datei nodemcu_gpio_lcd.py unter folgendem Link
https://github.com/dhylands/python_lcd/blob/master/lcd/nodemcu_gpio_lcd.py
laden und unter dem Namen gpio_lcd.py auf dem Pico abspeichern.

Martin

Martin

Hallo,
ich habe für die Realtime Clock das ganze GitHub Verzeichnis in Thonny eingebunden, die beiden genannten Dateien auf dem Pico gespeichert und wenn ich das Script starte, heißt es immer:
ImportError: no module named ‘gpio_lcd’
In dem Verzeichnis gibt es nur eine Datei pyb_gpio_lcd.py, aber selbst wenn ich den import Befehl von:
from gpio_lcd import GpioLcd in:
from pyb_gpio_lcd import GpioLcd ändere, wird diese nicht gefunden.
Wo liegt mein Fehler?

Lascia un commento

Tutti i commenti vengono moderati prima della pubblicazione