Ausprobiert:

Raspberry Pi Pico W mit
Pico-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:

  • USB-Mouse-Jiggler mit Pico-LCD-1.14 Display
  • Pico Diashow mit LCD-1.14 Display
  • Pico W Netzwerkscanner mit LCD-1.14 Display
  • Pico W als Uhr mit Neopixelring

  • 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