Ausprobiert Teil 3
Rundes 1.28-Zoll-IPS-LCD-Display 240 x 240 Pixel
- RP2040, 6-Achsen-Sensor - Waveshare 22668
Anleitung für die Firmware CircuitPython
Hardware
- Rundes 1,28-Zoll-IPS-LCD-Display
- RP Pico 2040 (inclusive)
- USB-A zu USB-C Kabel
Ausprobiert Teil 3
Rundes 1.28-Zoll-IPS-LCD-Display 240 x 240 Pixel- RP2040, 6-Achsen-Sensor - Waveshare 22668
Anleitung für die Firmware CircuitPython
- RP Pico 2040 (inclusive)
- USB-A zu USB-C Kabel
Nachdem wir den mathematischen Teil hinter uns haben, realisieren wir in dieser Folge eine erste (einfache) Uhrfunktion auf dem runden Display. Dabei nutzen wir aus der zweiten Folge die
Darstellung von Kreisen für die Hintergrundgestaltung und drei sich im Kreis bewegende Punkte für die Darstellung der Sekunden, Minuten und
Stunden. In der Mitte werden die Stunden und Minuten digital angezeigt.
Los gehts
Kopieren Sie den Code aus dem unteren Kasten ins Thonny und schauen sich die hinzugekommenen Teile an. Zunächst wird in Zeile 15 das Modul zum Zeichnen von Linien importiert. (Bei Ihnen ist evtl. ganz oben eine Leerzeile, die Sie löschen). Damit stellen wir kurze Striche zur Veranschaulichung der Minuten und Stunden dar. Dies geschieht in den Zeilen 43 bis 58. Dazwischen ordnen wir gelbe Ringe an. Wenn Sie das Programm starten, können Sie den Displayaufbau gut beobachten. Die Ausgabe des freien Speichers im Terminal zeigt, dass gar nicht mehr viel übrig ist. In Zeile 76 steht jetzt 'time.sleep(1)'. Damit wird vorläufig der Sekundentakt erzeugt, während der kleine weisse Punkt im äußeren Ring läuft.
1 # SPDX-FileCopyrightText: 2023 Detlef Gebhardt, written for CircuitPython 2 # SPDX-FileCopyrightText: Copyright (c) 2023 Detlef Gebhardt 3 # 4 # SPDX-License-Identifier: GEBMEDIA 5 import time 6 import gc 7 import board 8 import busio 9 from busio import I2C 10 import displayio 11 import terminalio 12 import gc9a01 13 from adafruit_display_text import label 14 from adafruit_display_shapes.circle import Circle 15 from adafruit_display_shapes.line import Line 16 import random 17 import math 18 19 # Release any resources currently in use for the displays 20 displayio.release_displays() 21 22 # Make the displayio SPI bus and the GC9A01 display 23 spi = busio.SPI(clock=board.LCD_CLK, MOSI=board.LCD_DIN) 24 display_bus = displayio.FourWire(spi, command=board.LCD_DC, chip_select=board.LCD_CS, reset=board.LCD_RST) 25 display = gc9a01.GC9A01(display_bus, width=240, height=240, rotation=90, backlight_pin=board.LCD_BL) 26 27 # Make the display context 28 group1 = displayio.Group() 29 display.show(group1) 30 31 width = 240 32 height = 240 33 xpos = 120 34 ypos = 120 35 radius = 120 36 i = 0 37 38 # Make some circles and lines: 39 circle = Circle(xpos, ypos, 120, fill=0xff0000, outline=0x000000) 40 group1.append(circle) 41 circle = Circle(xpos, ypos, 115, fill=0x000000, outline=0x000000) 42 group1.append(circle) 43 # Sekundenstriche 44 for i in range(60): 45 line = Line(xpos+int(105*math.cos(i*math.pi/30)),ypos-int(105*math.sin(i*math.pi/30)), 46 xpos+int(110*math.cos(i*math.pi/30)), ypos-int(110*math.sin(i*math.pi/30)),0xffffff) 47 group1.append(line) 48 display.show(group1) 49 circle = Circle(xpos, ypos, 100, fill=0xffff00, outline=0xffff00) 50 group1.append(circle) 51 circle = Circle(xpos, ypos, 95, fill=0x000000, outline=0x000000) 52 group1.append(circle) 53 # Stundenstriche 54 for i in range(12): 55 line = Line(xpos+int(95*math.cos(i*math.pi/6)),ypos-int(95*math.sin(i*math.pi/6)), 56 xpos+int(90*math.cos(i*math.pi/6)), ypos-int(90*math.sin(i*math.pi/6)),0xffffff) 57 group1.append(line) 58 display.show(group1) 59 circle = Circle(xpos, ypos, 80, fill=0xffff00, outline=0xffff00) 60 group1.append(circle) 61 circle = Circle(xpos, ypos, 75, fill=0x000000, outline=0x000000) 62 group1.append(circle) 63 64 circle = Circle(xpos, ypos, 5, fill=0xffffff, outline=0x000000) 65 group1.append(circle) 66 67 while True: 68 for i in range (60): 69 delta_x = xpos_neu - xpos 70 xpos = xpos_neu 71 ypos_neu = int(height/2 + 108*math.sin((i -15)*math.pi/30)) 72 delta_y = ypos_neu - ypos 73 ypos = ypos_neu 74 circle.x = circle.x + delta_x 75 circle.y = circle.y + delta_y 76 time.sleep(1) 77 print(gc.mem_free())
Im nächsten Schritt brauchen wir eine Uhrzeit. Dazu nutzen wir, solange die Uhr am PC angeschlossen ist time.localtime() und definieren hour, minute, second als Variable für die Stunden, Minuten und Sekunden. Diese Ergänzungen finden Sie im unteren Kasten ab Zeile 67. In den Zeilen 75 bis 80 werden noch die Minuten- und Stundenpunkte festgelegt. Die 'while'-Schleife beginnt jetzt in Zeile 82. Kopieren Sie den Code und dann sehen wir uns die Veränderungen in der Schleife an.
1 # SPDX-FileCopyrightText: 2023 Detlef Gebhardt, written for CircuitPython 2 # SPDX-FileCopyrightText: Copyright (c) 2023 Detlef Gebhardt 3 # 4 # SPDX-License-Identifier: GEBMEDIA 5 import time 6 import gc 7 import board 8 import busio 9 from busio import I2C 10 import displayio 11 import terminalio 12 import gc9a01 13 from adafruit_display_text import label 14 from adafruit_display_shapes.circle import Circle 15 from adafruit_display_shapes.line import Line 16 import random 17 import math 18 19 # Release any resources currently in use for the displays 20 displayio.release_displays() 21 22 # Make the displayio SPI bus and the GC9A01 display 23 spi = busio.SPI(clock=board.LCD_CLK, MOSI=board.LCD_DIN) 24 display_bus = displayio.FourWire(spi, command=board.LCD_DC, chip_select=board.LCD_CS, reset=board.LCD_RST) 25 display = gc9a01.GC9A01(display_bus, width=240, height=240, rotation=90, backlight_pin=board.LCD_BL) 26 27 # Make the display context 28 group1 = displayio.Group() 29 display.show(group1) 30 31 width = 240 32 height = 240 33 xpos = 120 34 ypos = 120 35 radius = 120 36 i = 0 37 38 # Make some circles and lines: 39 circle = Circle(xpos, ypos, 120, fill=0xff0000, outline=0x000000) 40 group1.append(circle) 41 circle = Circle(xpos, ypos, 115, fill=0x000000, outline=0x000000) 42 group1.append(circle) 43 # Minutenstriche 44 for i in range(60): 45 line = Line(xpos+int(105*math.cos(i*math.pi/30)),ypos-int(105*math.sin(i*math.pi/30)), 46 xpos+int(110*math.cos(i*math.pi/30)), ypos-int(110*math.sin(i*math.pi/30)),0xffffff) 47 group1.append(line) 48 display.show(group1) 49 circle = Circle(xpos, ypos, 100, fill=0xffff00, outline=0xffff00) 50 group1.append(circle) 51 circle = Circle(xpos, ypos, 95, fill=0x000000, outline=0x000000) 52 group1.append(circle) 53 # Stundenstriche 54 for i in range(12): 55 line = Line(xpos+int(95*math.cos(i*math.pi/6)),ypos-int(95*math.sin(i*math.pi/6)), 56 xpos+int(90*math.cos(i*math.pi/6)), ypos-int(90*math.sin(i*math.pi/6)),0xffffff) 57 group1.append(line) 58 display.show(group1) 59 circle = Circle(xpos, ypos, 80, fill=0xffff00, outline=0xffff00) 60 group1.append(circle) 61 circle = Circle(xpos, ypos, 75, fill=0x000000, outline=0x000000) 62 group1.append(circle) 63 64 circle = Circle(xpos, ypos, 5, fill=0xffffff, outline=0x000000) 65 group1.append(circle) 66 67 current_time = time.localtime() 68 hour = current_time[3] 69 minute = current_time[4] 70 second = current_time[5] 71 xpos_min = 120 72 ypos_min = 88 73 xpos_hour = 120 74 ypos_hour = 68 75 # Minutenpunkt in grün 76 circle_m = Circle(xpos_min,ypos_min, 5, fill=0x00ffff, outline=0x00ffff) 77 group1.append(circle_m) 78 # Stundenpunkt in rot 79 circle_h = Circle(xpos_hour, ypos_hour, 5, fill=0xff0000, outline=0xff0000) 80 group1.append(circle_h) 81 82 while True: 83 # minute setzen 84 xpos_min_neu = int(width/2 + 88*math.cos((minute-15)*math.pi/30)) 85 delta_min_x = xpos_min_neu - xpos_min 86 xpos_min = xpos_min_neu 87 ypos_min_neu = int(height/2 + 88*math.sin((minute-15)*math.pi/30)) 88 delta_min_y = ypos_min_neu - ypos_min 89 ypos_min = ypos_min_neu 90 circle_m.x = circle_m.x + delta_min_x 91 circle_m.y = circle_m.y + delta_min_y 92 gc.collect() 93 # hour 94 xpos_hour_neu = int(width/2 + int(68*math.cos((hour)*math.pi/6 + minute/2*math.pi/180 - math.pi/2))) 95 delta_hour_x = xpos_hour_neu - xpos_hour 96 xpos_hour = xpos_hour_neu 97 ypos_hour_neu = int(height/2 + int(68*math.sin((hour)*math.pi/6 + minute/2*math.pi/180 - math.pi/2))) 98 delta_hour_y = ypos_hour_neu - ypos_hour 99 ypos_hour = ypos_hour_neu 100 circle_h.x = circle_h.x + delta_hour_x 101 circle_h.y = circle_h.y + delta_hour_y 102 for i in range (60): 103 second *= 1 104 xpos_neu = int(width/2 + 108*math.cos((i -15)*math.pi/30)) 145 delta_x = xpos_neu - xpos 106 xpos = xpos_neu 107 ypos_neu = int(height/2 + 108*math.sin((i -15)*math.pi/30)) 108 delta_y = ypos_neu - ypos 109 ypos = ypos_neu 110 circle.x = circle.x + delta_x 111 circle.y = circle.y + delta_y 112 time.sleep(1) 113 gc.collect() 114 print(gc.mem_free()) 115 minute += 1 116 second = 0 117 if minute == 60: 118 minute = 0 119 hour += 1 120 if hour == 24: 121 hour = 0
Mathematisch kommt es jetzt auf die exakte Berechnung der Positionen der Minuten- und Stundenpunkte an.
Minuten: Da eine Stunde 60 Minuten hat und der Zeiger dabei 360 Grad zurücklegt, entspricht
1 Minute 360 / 60 = 6 Grad (also pi / 30). Für die Berechnung ergibt sich daraus:
xpos_min_neu = int(width/2 + 88*math.cos((minute-15)*math.pi/30))
Die 88 steht für den Radius und die -15 wegen der Displaydrehung um 90 Grad (also 15 Minuten). Analog gilt das für
die y-Position.
ypos_min_neu = int(height/2 + 88*math.sin((minute-15)*math.pi/30))
Aus diesen neuen Positionen und den alten Positionen wird die Differenz 'delta' bestimmt und in den Zeilen 90, 91 an den
Kreis übergeben. So wird der Minutenpunkt in den Zeilen 83 bis 91 aktualisiert.
Stunden: Für den Stundenpunkt ist das Ganze noch etwas aufwendiger, da sich der Stundenzeiger während
einer Stunde kontinuierlich mitbewegt. Grundsätzlich gilt: 12 Stunden sind 360 Grad. Also 360 / 12 = 30 Grad (also pi / 6).
Für die Berechnung ergibt sich daraus:
xpos_hour_neu = int(width/2 + int(68*math.cos((hour)*math.pi/6 + minute/2*math.pi/180 - math.pi/2)))
und
ypos_hour_neu = int(height/2 + int(68*math.sin((hour)*math.pi/6 + minute/2*math.pi/180 - math.pi/2)))
Die 68 steht für den Radius und die -pi/2 für die Displaydrehung. Der übrige Teil des Ausdrucks sorgt dafür, dass sich
der Stundenzeiger in Abhängikeit von den Minuten mitbewegt. So wird der Stundenpunkt von Zeile 93 bis 101 aktualisiert.
In den Zeilen 102 bis 114 wird der Sekundenpunkt wie gehabt gesetzt. Die Zeilen 115 bis 121 sorgen für das weiterzählen der
Minuten und Stunden, solange keine andere Methode dafür gewählt wird. Auf die Ganggenauigkeit kommt es im Augenblick
noch gar nicht an.
Mit ein paar Ergänzungen fügen wir dem Programm noch eine digitale Anzeige, wie auf dem Bild ganz oben, hinzu. Dazu wird ein
Rechteck mit abgerundeten Ecken 'roundrect' und ein 'label', welches die Zeit als String ausgibt, angelegt. Jetzt neu in den Zeilen
84 bis 96. Auch in der 'while'-Schleife sind die Zeilen 99 bis 107 jetzt neu. Die nachfolgenden Zeilen verschieben sich dadurch nach hinten.
Zur besseren Übersicht gebe ich den geänderten Code noch einmal komplett zum kopieren an.
1 # SPDX-FileCopyrightText: 2023 Detlef Gebhardt, written for CircuitPython 2 # SPDX-FileCopyrightText: Copyright (c) 2023 Detlef Gebhardt 3 # 4 # SPDX-License-Identifier: GEBMEDIA 5 import time 6 import gc 7 import board 8 import busio 9 from busio import I2C 10 import displayio 11 import terminalio 12 import gc9a01 13 from adafruit_display_text import label 14 from adafruit_display_shapes.circle import Circle 15 from adafruit_display_shapes.line import Line 16 from adafruit_display_shapes.roundrect import RoundRect 17 import random 18 import math 19 20 # Release any resources currently in use for the displays 21 displayio.release_displays() 22 23 # Make the displayio SPI bus and the GC9A01 display 24 spi = busio.SPI(clock=board.LCD_CLK, MOSI=board.LCD_DIN) 25 display_bus = displayio.FourWire(spi, command=board.LCD_DC, chip_select=board.LCD_CS, reset=board.LCD_RST) 26 display = gc9a01.GC9A01(display_bus, width=240, height=240, rotation=90, backlight_pin=board.LCD_BL) 27 28 # Make the display context 29 group1 = displayio.Group() 30 display.show(group1) 31 32 width = 240 33 height = 240 34 xpos = 120 35 ypos = 120 36 radius = 120 37 i = 0 38 39 # Make some circles and lines: 40 circle = Circle(xpos, ypos, 120, fill=0xff0000, outline=0x000000) 41 group1.append(circle) 42 circle = Circle(xpos, ypos, 115, fill=0x000000, outline=0x000000) 43 group1.append(circle) 44 # Minutenstriche 45 for i in range(60): 46 line = Line(xpos+int(105*math.cos(i*math.pi/30)),ypos-int(105*math.sin(i*math.pi/30)), 47 xpos+int(110*math.cos(i*math.pi/30)), ypos-int(110*math.sin(i*math.pi/30)),0xffffff) 48 group1.append(line) 49 display.show(group1) 50 circle = Circle(xpos, ypos, 100, fill=0xffff00, outline=0xffff00) 51 group1.append(circle) 52 circle = Circle(xpos, ypos, 95, fill=0x000000, outline=0x000000) 53 group1.append(circle) 54 # Stundenstriche 55 for i in range(12): 56 line = Line(xpos+int(95*math.cos(i*math.pi/6)),ypos-int(95*math.sin(i*math.pi/6)), 57 xpos+int(90*math.cos(i*math.pi/6)), ypos-int(90*math.sin(i*math.pi/6)),0xffffff) 58 group1.append(line) 59 display.show(group1) 60 circle = Circle(xpos, ypos, 80, fill=0xffff00, outline=0xffff00) 61 group1.append(circle) 62 circle = Circle(xpos, ypos, 75, fill=0x000000, outline=0x000000) 63 group1.append(circle) 64 65 circle = Circle(xpos, ypos, 5, fill=0xffffff, outline=0x000000) 66 group1.append(circle) 67 68 current_time = time.localtime() 69 hour = current_time[3] 70 minute = current_time[4] 71 second = current_time[5] 72 xpos_min = 120 73 ypos_min = 88 74 xpos_hour = 120 75 ypos_hour = 68 76 zeit = "00:00" 77 # Minutenpunkt in grün 78 circle_m = Circle(xpos_min,ypos_min, 5, fill=0x00ffff, outline=0x00ffff) 79 group1.append(circle_m) 80 # Stundenpunkt in rot 81 circle_h = Circle(xpos_hour, ypos_hour, 5, fill=0xff0000, outline=0xff0000) 82 group1.append(circle_h) 83 84 # Rechteck mit abgerundeten Ecken 85 roundrect1 = RoundRect(65, 100, 110, 45, 10, fill=0x0, outline=0xffffff, stroke=3) 86 group1.append(roundrect1) 87 88 # create the time-label 89 updating_label1 = label.Label( 90 font=terminalio.FONT, text=zeit, scale=2, color=0xffffff, 91 line_spacing=1) 92 # set label position on the display and add label 93 updating_label1.anchor_point = (0, 0) 94 updating_label1.anchored_position = (92, 110) 95 group1.append(updating_label1) 96 display.show(group1) 97 98 while True: 99 zeit = str(hour) + ":" + str(minute) 100 if second < 10: 101 zeit = str(hour) + ":" + str(minute) 102 if minute < 10: 103 zeit = str(hour) + ":" + "0" + str(minute) 104 if second < 10 and minute < 10: 105 zeit = str(hour) + ":" + "0" + str(minute) 106 # updating zeit 107 updating_label1.text = zeit 108 # minute setzen 109 xpos_min_neu = int(width/2 + 88*math.cos((minute-15)*math.pi/30)) 110 delta_min_x = xpos_min_neu - xpos_min 111 xpos_min = xpos_min_neu 112 ypos_min_neu = int(height/2 + 88*math.sin((minute-15)*math.pi/30)) 113 delta_min_y = ypos_min_neu - ypos_min 114 ypos_min = ypos_min_neu 115 circle_m.x = circle_m.x + delta_min_x 116 circle_m.y = circle_m.y + delta_min_y 117 gc.collect() 118 # hour 119 xpos_hour_neu = int(width/2 + int(68*math.cos((hour)*math.pi/6 + minute/2*math.pi/180 - math.pi/2))) 120 delta_hour_x = xpos_hour_neu - xpos_hour 121 xpos_hour = xpos_hour_neu 122 ypos_hour_neu = int(height/2 + int(68*math.sin((hour)*math.pi/6 + minute/2*math.pi/180 - math.pi/2))) 123 delta_hour_y = ypos_hour_neu - ypos_hour 124 ypos_hour = ypos_hour_neu 125 circle_h.x = circle_h.x + delta_hour_x 126 circle_h.y = circle_h.y + delta_hour_y 127 for i in range (60): 128 second *= 1 129 xpos_neu = int(width/2 + 108*math.cos((i -15)*math.pi/30)) 130 delta_x = xpos_neu - xpos 131 xpos = xpos_neu 132 ypos_neu = int(height/2 + 108*math.sin((i -15)*math.pi/30)) 133 delta_y = ypos_neu - ypos 134 ypos = ypos_neu 135 circle.x = circle.x + delta_x 136 circle.y = circle.y + delta_y 137 time.sleep(1) 138 gc.collect() 139 print(gc.mem_free()) 140 minute += 1 141 second = 0 142 if minute == 60: 143 minute = 0 144 hour += 1 145 if hour == 24: 146 hour = 0
Viel Spass und Erfolg beim Ausprobieren.
Viel Spass und Erfolg beim Ausprobieren.