Ausprobiert:
Raspberry Pi Pico W mit
Pico-LCD-1.14 Display als RTC-Uhr
Bildbox 1 (klick hier)
Ausprobiert:
Raspberry Pi Pico W mitPico-LCD-1.14 Display als RTC-Uhr
Bildbox 1 (klick hier)
Was Sie für die Umsetzung brauchen:
Hardware / Software
- Raspberry Pi Pico W
- Pico-LCD-1.14 Display
- Micro USB Kabel
- Firmware CircuitPython
- Thonny IDE
Bevor es richtig los geht, wie versprochen einige Bemerkungen, was bei der Nutzung des Pico W und CircuitPython wichtig ist.
Als erstes sollten Sie wissen, dass beim Pico W vom WLAN-Modul von Hause aus ein erheblicher Teil des Speichers (2 MB RAM) belegt wird.
Nach der Installation der Firmware stehen gerade mal rund 500 KB RAM zur Verfügung. Da heißt es, sparsam mit der Speicherverwaltung
umzugehen. An entsprechender Stelle werde ich explicit darauf eingehen.
Zunächst laden Sie sich bei Adafruit die neuste Firmware 'CircuitPython' herunter und übertragen diese, wie in den
anderen Projekten (z.B. hier)
mehrfach beschrieben auf den Pico W. Ich lösche dann immer zuerst die Datei 'code.py' im Explorer, um jeglichen Autostart zu unterbinden. Danach
rufen Sie im Thonny die mitgelieferte Datei 'settings.toml' auf und passen diese wie folgt an:
# Comments are supported CIRCUITPY_WIFI_SSID="hier Ihren SSID-Namen eintragen" CIRCUITPY_WIFI_PASSWORD="hier Ihr Passwort eintragen" CIRCUITPY_WEB_API_PORT=80 CIRCUITPY_WEB_API_PASSWORD="passw0rd" test_variable="Ein beliebiger Text" thumbs_up="\U0001f44d"
Dadurch müssen Sie später im Pythoncode die 'SSID' und das 'Passwort' nicht im Klartext eintragen, so dass sie für jeden Betrachter
sichtbar sind. Die Datei 'settings.tmol' ist übrigens nicht ohne weiteres mit dem Dateiexplorer auslesbar.
Probieren Sie zunächst die Herstellung der WLAN-Verbindung aus:
1 import os 2 import ipaddress 3 import wifi 4 import socketpool 5 6 print() 7 print("Connecting to ",os.getenv("test_variable")," . . .") 8 9 # connect to your SSID 10 wifi.radio.connect(os.getenv('CIRCUITPY_WIFI_SSID'), os.getenv('CIRCUITPY_WIFI_PASSWORD')) 11 12 print("Connected to your WiFi") 13 14 pool = socketpool.SocketPool(wifi.radio) 15 16 # prints MAC address to REPL 17 print("My MAC addr:", [hex(i) for i in wifi.radio.mac_address]) 18 19 # prints IP address to REPL 20 print("My IP address is", wifi.radio.ipv4_address) 21 22 # pings Google 23 ipv4 = ipaddress.ip_address("8.8.4.4") 24 print("Ping google.com: %f ms" % (wifi.radio.ping(ipv4)*1000))
Wenn Sie die neueste Firmware verwenden, brauchen keine Bibliotheken in den 'lib'-Ordner kopiert werden. Die Zeile 7 zeigt Ihnen nur an, dass
die 'test_variable' aus der 'settings.tmol' richtig gefunden wurde. Wenn Sie keine Fehlermeldung bekommen, ist der Pico W erfolgreich
mit dem WLAN verbunden und zeigt die MAC-Adresse, die IP-Adresse und die Zeit für ein Ping zu Google an. Im anderen Fall bleibt nur die
Überprüfung von 'SSID' und 'Passwort' oder von evtl. in der Fritzbox eingestellten Beschränkungen. (Dazu fragen Sie Ihren Arzt oder
Administrator.)
Im nächsten Schritt zeige ich das Herunterladen des 'struct_time' Tupels von der Adafruitseite. Vorher sollten Sie aber die Datei
'adafruit_request.mpy' in den 'lib'-Ordner speichern. Die finden Sie
hier als zip-Datei
zum Herunterladen. Nach dem Entpacken können Sie
gleich den gesamten Inhalt in den 'lib'-Ordner kopieren. Die anderen Bibliotheken werden später ebenfalls verwendet.
1 import os 2 import time, gc 3 import wifi, ssl, socketpool 4 import rtc 5 import socketpool 6 import adafruit_requests 7 8 # connect to your SSID 9 wifi.radio.connect(os.getenv('CIRCUITPY_WIFI_SSID'), os.getenv('CIRCUITPY_WIFI_PASSWORD')) 10 pool = socketpool.SocketPool(wifi.radio) 11 12 # Zeit aus dem Internet holen 13 requests = adafruit_requests.Session(pool, ssl.create_default_context()) 14 response = requests.get("https://io.adafruit.com/api/v2/time/seconds") 15 r = rtc.RTC() 16 r.datetime = time.localtime(int(response.text)) 17 dt = time.struct_time(r.datetime) 18 hour = dt[3] + 1 19 minute = dt[4] 20 second = dt[5] 21 response.close() 22 del response 23 response = None 24 gc.collect() 25 datum = str(dt[2]) + "." + str(dt[1]) + "." + str(dt[0]) 26 wday = dt[6] 27 if wday == 0: 28 tag = "Montag" 29 if wday == 1: 30 tag = "Dienstag" 31 if wday == 2: 32 tag = "Mittwoch" 33 if wday == 3: 34 tag = "Donnerstag" 35 if wday == 4: 36 tag = "Freitag" 37 if wday == 5: 38 tag = "Samstag" 39 if wday == 6: 40 tag = "Sonntag" 41 42 print(tag, "\n", datum, "\n", hour,":",minute,":",second)
Bis zur Zeile 11 werden die Bibliotheken importiert und die WLAN-Verbindung hergestellt. Zeile 14 stellt eine Anfrage an die Adafruitseite
"https://io.adafruit.com/api/v2/time/seconds" und bekommt als Antwort die Sekunden vom 1.1.1970, welche dann in den Zeilen 15 und
16 als date_time
verfügbar sind. Damit wird in Zeile 17 der Variable 'dt' die 'time_struct_time' zugewiesen. Diese hat die folgende Form:
time.struct_time(tm_year= xxxx, tm_mon=xx, tm_mday=xx, tm_hour=xx, tm_min=xx, tm_sec=xx, tm_wday=xx, tm_yday=xx, tm_isdst=-1)
Daraus kann jetzt in den Zeilen 18, 19 und 20 die Stunde, Minute und Sekunde belegt werden. Die Funktion der Zeilen 21 bis 24 erkläre ich
gleich noch. Vorher noch der Hinweis, dass in den Zeilen 25 bis 40 das Datum und die Wochentage jeweils als String definiert werden.
Zu den Zeilen 21 bis 24:
Ich hatte bereits darauf hingewiesen, dass der Pico W nach dem Aufspielen der Firmware über wenig freien Speicher im RAM verfügt.
Bei der Erweiterung des
Projektes kommen aber noch die Darstellung eines Hintergrundbildes auf dem Display und der Abruf von Wetterdaten hinzu. Dabei kam es
regelmäßig zum Absturz des Pico W wegen Speicherüberschreitung. Deshalb habe ich mich schon hier für
die Freigabe von nicht benötigtem Speicher entschieden. Konkret schließt Zeile 21 die Anfrage (d.h. beendet die Verbindung
zu der Internetseite), löscht die Antwort (Zeile 22) und setzt sie auf 'NONE' (Zeile 23). Der Aufruf 'gc.collect()' in Zeile 24 veranlasst
das Betriebssystem des Pico W alle nicht benötigten Bereiche freizugeben. Damit konnte ich sehr gute Erfahrungen sammeln.
Bleibt noch, mit einem Print-Befehl in Zeile 42 die Variablen in der Kommandozeile von Thonny auszugeben. Die beiden Beispiele ('wifi_test.py'
und 'get_time.py') können Sie in gepackter Form
hier downloaden.
Nach dem Entpacken, lassen sie sich entsprechend der obigen Ausführungen
im Thonny zum Ausprobieren starten.
Darstellung am Display
Jetzt sollen der Wochentag, das Datum und die Uhrzeit auf dem Display dargestellt werden. Dazu verbinden Sie im spannungslosen Zustand den
Pico W mit dem LCD-1.14 Display von Waveshare. Achten Sie darauf, dass die Markierung 'USB' auf dem Display mit dem USB-Anschluss am Pico W
übereinstimmt. Um das Display nutzen zu können, wird eine Class 'WavesharePicoLCD114' benutzt. Die packen wir in die Datei
'init_pico_lcd.py'. Sie kommt in das Hauptverzeichnis des Pico W und wird vom späteren Programm importiert.
1 import busio
2 import board
3 import displayio
4 from adafruit_st7789 import ST7789
5
6
7 class WavesharePicoLCD114:
8 def __init__(self, spi=None, cs=board.GP9, dc=board.GP8, reset=board.GP12):
9 displayio.release_displays()
10 if not spi:
11 self._spi = busio.SPI(board.GP10, board.GP11)
12
13 self._display_bus = displayio.FourWire(
14 self._spi, command=dc, chip_select=cs, reset=reset
15 )
16
17 self.display = ST7789(
18 self._display_bus,
19 rotation=90,
20 width=240,
21 height=135,
22 rowstart=40,
23 colstart=53,
24 )
25
Falls Ihnen aufgefallen ist, dass bei meinen Abbildungen der Minijoystick rechts ist und somit das Display quasi auf dem Kopf steht,
hier die Erklärung. Bei mir ist auf dem Schreibtisch die Stromversorgung für den USB-Anschluss rechts, deshalb habe ich
in der Datei 'init_pico_lcd.py' bei rotation=90 eingestellt. Im Original sollte hier rotation=270
stehen.
Weiter geht es mit dem Progamm 'uhr-display.py'. Hier zunächst der komplette Pythoncode, den Sie in die Zwischenablage kopieren und im
Thonny einsetzen und ausprobieren können.
1 import os
2 import time, gc
3 import board
4 import ssl
5 import wifi, ssl, socketpool
6 import rtc
7 import socketpool
8 import microcontroller
9 import adafruit_requests
10 import displayio
11 import digitalio
12 import terminalio
13 from adafruit_display_text import label
14 from init_pico_lcd import WavesharePicoLCD114
15
16 led = digitalio.DigitalInOut(board.LED)
17 led.direction = digitalio.Direction.OUTPUT
18
19 # connect to your SSID
20 wifi.radio.connect(os.getenv('CIRCUITPY_WIFI_SSID'), os.getenv('CIRCUITPY_WIFI_PASSWORD'))
21 pool = socketpool.SocketPool(wifi.radio)
22
23 # built-in display
24 lcd = WavesharePicoLCD114()
25 display = lcd.display
26
27 # Make the display context
28 main_group = displayio.Group()
29 display.show(main_group)
30
31 # make bitmap that spans entire display
32 background = displayio.Bitmap(display.width, display.height, 3)
33 mypal = displayio.Palette(1)
34 mypal[0] = 0x0000FF # set colors (black)
35 main_group.append(displayio.TileGrid(background, pixel_shader=mypal))
36 background.fill(0) # change background to blue (mypal[2])
37
38 # create the label
39 updating_label = label.Label(
40 font=terminalio.FONT, text="your city", scale=3, color=0xFFFFFF,
41 line_spacing=1.0
42 )
43 # set label position on the display
44 updating_label.anchor_point = (0, 0)
45 updating_label.anchored_position = (1, 10)
46 # add label to group that is showing on display
47 main_group.append(updating_label)
48
49 hour = 0
50 minute = 0
51 second = 0
52 tag = "heute"
53 datum = "1.1.1970"
54 start = 0
55
56 while True:
57 zeit = str(hour) + ":" + str(minute) + ":" + str(second)
58 # update text property to change the text showing on the display
59 updating_label.text = (" " + str(tag) +
60 "\n " + str(datum) +
61 "\n " + zeit
62 )
63 if (start == 0) or (minute == 0 and second == 0) or (minute == 30 and second == 0):
64 start = 1
65 # Zeit aus dem Internet holen
66 requests = adafruit_requests.Session(pool, ssl.create_default_context())
67 response = requests.get("https://io.adafruit.com/api/v2/time/seconds")
68 r = rtc.RTC()
69 r.datetime = time.localtime(int(response.text))
70 response.close()
71 dt = time.struct_time(r.datetime)
72 hour = dt[3] + 1
73 minute = dt[4]
74 second = dt[5]
75 response.close()
76 del response
77 response = None
78 gc.collect()
79 datum = str(dt[2]) + "." + str(dt[1]) + "." + str(dt[0])
80 wday = dt[6]
81 if wday == 0:
82 tag = "Montag"
83 if wday == 1:
84 tag = "Dienstag"
85 if wday == 2:
86 tag = "Mittwoch"
87 if wday == 3:
88 tag = "Donnerstag"
89 if wday == 4:
90 tag = "Freitag"
91 if wday == 5:
92 tag = "Samstag"
93 if wday == 6:
94 tag = "Sonntag"
95 second += 1
96 if second == 60:
97 second = 0
98 minute += 1
99 if minute == 60:
100 second = 0
101 minute = 0
102 hour += 1
103 if hour == 12:
104 second = 0
105 minute = 0
106 hour = 0
107 gc.collect()
108 time.sleep(0.7)
In den Zeilen 1 bis 54 sind jetzt neu die Zeilen 23 bis 25. Sie definieren die Variable 'lcd' und 'display'. Anschließend wird ein blauer
Hintergrund für das Display festgelegt (Zeilen 31 bis 36). Für die spätere Textausgabe sorgen die Zeilen 38 bis 47. Ausserdem
werden noch einige Variable definiert ( Zeilen 49 bis 54).
In der entscheidenten 'while' Schleife werden:
- die Variable 'zeit' aus den Variablen 'hour', 'minute' und 'second' als Zeichenkette definiert (Zeile 57);
- die Textausgabe mit Hilfe des 'updateting_label.text' Befehls bei jedem Durchlauf erneuert (Zeilen 58 bis 62);
- dann folgt eine Schleife, welche beim Programmstart (start = 0) und dann jede volle halbe Stunde die Zeit aus dem Internet, wie weiter
oben bereits beschrieben, aktualisiert (Zeilen 63 bis 94);
- danach wird die Zeit durch Erhöhen der Sekunden ganz einfach weitergezählt. Dadurch soll eine unnötig hohe Anzahl von
Zugriffen auf die Netzverbindung gering gehalten werden (Zeilen 95 bis 108);
Dafür braucht der Pico natürlich seine Zeit. Deshalb wurde bei 'time.sleep(0.7) in Zeile 108 auch keine volle Sekunde als
Verzögerung
gewählt. Die 0.7 Sekunden führten beim Versuch dazu, dass die Uhr pro halbe Stunde knapp 1,5 Minuten nachging, was ja aber durch die
Aktualisierung immer wieder ausgeglichen wird. Es bleibt jedem selbst überlassen, für das 'time.sleep()' noch bessere Werte für
die Ganggenauigkeit zu finden.
Weitere verwandte Projekte:
time.struct_time(tm_year= xxxx, tm_mon=xx, tm_mday=xx, tm_hour=xx, tm_min=xx, tm_sec=xx, tm_wday=xx, tm_yday=xx, tm_isdst=-1)
1 import busio 2 import board 3 import displayio 4 from adafruit_st7789 import ST7789 5 6 7 class WavesharePicoLCD114: 8 def __init__(self, spi=None, cs=board.GP9, dc=board.GP8, reset=board.GP12): 9 displayio.release_displays() 10 if not spi: 11 self._spi = busio.SPI(board.GP10, board.GP11) 12 13 self._display_bus = displayio.FourWire( 14 self._spi, command=dc, chip_select=cs, reset=reset 15 ) 16 17 self.display = ST7789( 18 self._display_bus, 19 rotation=90, 20 width=240, 21 height=135, 22 rowstart=40, 23 colstart=53, 24 ) 25
Weiter geht es mit dem Progamm 'uhr-display.py'. Hier zunächst der komplette Pythoncode, den Sie in die Zwischenablage kopieren und im Thonny einsetzen und ausprobieren können.
1 import os 2 import time, gc 3 import board 4 import ssl 5 import wifi, ssl, socketpool 6 import rtc 7 import socketpool 8 import microcontroller 9 import adafruit_requests 10 import displayio 11 import digitalio 12 import terminalio 13 from adafruit_display_text import label 14 from init_pico_lcd import WavesharePicoLCD114 15 16 led = digitalio.DigitalInOut(board.LED) 17 led.direction = digitalio.Direction.OUTPUT 18 19 # connect to your SSID 20 wifi.radio.connect(os.getenv('CIRCUITPY_WIFI_SSID'), os.getenv('CIRCUITPY_WIFI_PASSWORD')) 21 pool = socketpool.SocketPool(wifi.radio) 22 23 # built-in display 24 lcd = WavesharePicoLCD114() 25 display = lcd.display 26 27 # Make the display context 28 main_group = displayio.Group() 29 display.show(main_group) 30 31 # make bitmap that spans entire display 32 background = displayio.Bitmap(display.width, display.height, 3) 33 mypal = displayio.Palette(1) 34 mypal[0] = 0x0000FF # set colors (black) 35 main_group.append(displayio.TileGrid(background, pixel_shader=mypal)) 36 background.fill(0) # change background to blue (mypal[2]) 37 38 # create the label 39 updating_label = label.Label( 40 font=terminalio.FONT, text="your city", scale=3, color=0xFFFFFF, 41 line_spacing=1.0 42 ) 43 # set label position on the display 44 updating_label.anchor_point = (0, 0) 45 updating_label.anchored_position = (1, 10) 46 # add label to group that is showing on display 47 main_group.append(updating_label) 48 49 hour = 0 50 minute = 0 51 second = 0 52 tag = "heute" 53 datum = "1.1.1970" 54 start = 0 55 56 while True: 57 zeit = str(hour) + ":" + str(minute) + ":" + str(second) 58 # update text property to change the text showing on the display 59 updating_label.text = (" " + str(tag) + 60 "\n " + str(datum) + 61 "\n " + zeit 62 ) 63 if (start == 0) or (minute == 0 and second == 0) or (minute == 30 and second == 0): 64 start = 1 65 # Zeit aus dem Internet holen 66 requests = adafruit_requests.Session(pool, ssl.create_default_context()) 67 response = requests.get("https://io.adafruit.com/api/v2/time/seconds") 68 r = rtc.RTC() 69 r.datetime = time.localtime(int(response.text)) 70 response.close() 71 dt = time.struct_time(r.datetime) 72 hour = dt[3] + 1 73 minute = dt[4] 74 second = dt[5] 75 response.close() 76 del response 77 response = None 78 gc.collect() 79 datum = str(dt[2]) + "." + str(dt[1]) + "." + str(dt[0]) 80 wday = dt[6] 81 if wday == 0: 82 tag = "Montag" 83 if wday == 1: 84 tag = "Dienstag" 85 if wday == 2: 86 tag = "Mittwoch" 87 if wday == 3: 88 tag = "Donnerstag" 89 if wday == 4: 90 tag = "Freitag" 91 if wday == 5: 92 tag = "Samstag" 93 if wday == 6: 94 tag = "Sonntag" 95 second += 1 96 if second == 60: 97 second = 0 98 minute += 1 99 if minute == 60: 100 second = 0 101 minute = 0 102 hour += 1 103 if hour == 12: 104 second = 0 105 minute = 0 106 hour = 0 107 gc.collect() 108 time.sleep(0.7)
In der entscheidenten 'while' Schleife werden:
- die Variable 'zeit' aus den Variablen 'hour', 'minute' und 'second' als Zeichenkette definiert (Zeile 57);
- die Textausgabe mit Hilfe des 'updateting_label.text' Befehls bei jedem Durchlauf erneuert (Zeilen 58 bis 62);
- dann folgt eine Schleife, welche beim Programmstart (start = 0) und dann jede volle halbe Stunde die Zeit aus dem Internet, wie weiter oben bereits beschrieben, aktualisiert (Zeilen 63 bis 94);
- danach wird die Zeit durch Erhöhen der Sekunden ganz einfach weitergezählt. Dadurch soll eine unnötig hohe Anzahl von Zugriffen auf die Netzverbindung gering gehalten werden (Zeilen 95 bis 108);
Dafür braucht der Pico natürlich seine Zeit. Deshalb wurde bei 'time.sleep(0.7) in Zeile 108 auch keine volle Sekunde als Verzögerung gewählt. Die 0.7 Sekunden führten beim Versuch dazu, dass die Uhr pro halbe Stunde knapp 1,5 Minuten nachging, was ja aber durch die Aktualisierung immer wieder ausgeglichen wird. Es bleibt jedem selbst überlassen, für das 'time.sleep()' noch bessere Werte für die Ganggenauigkeit zu finden.
Weitere verwandte Projekte:
Damit ist das Programm vollständig. Viel Spass und Erfolg beim Ausprobieren. Wenn Ihnen diese Anleitung gefallen hat, tragen Sie hier bitte einen Kommentar ein.
Zurück