zweite schritte
Rundes 1.28-Zoll-IPS-LCD-Display
Anleitung für CircuitPython
Bildbox 1 (klick hier)
zweite schritte
Rundes 1.28-Zoll-IPS-LCD-DisplayAnleitung für CircuitPython
Bildbox 1 (klick hier)
Hardware
- Rundes 1,28-Zoll-IPS-LCD-Display
- RP Pico 2040 (inclusive)
- USB-A zu USB-C Kabel
Nach dem ersten Schritt folgt der zweite Schritt. Den tun wir jetzt gemeinsam. Die Anleitung baut inhaltlich auf der vorhergehenden auf und
setzt die Einrichtung der Firmware und das Vorhandensein der Bibliotheken im 'lib-Ordner' voraus. Wer an dieser Stelle hinzugekommen ist, kann
sich die
zip-Datei hier
noch einmal herunterladen und einsteigen.
Los gehts
In diesem Teil zeige ich zuerst, wie man eine Bitmap-Datei auf dem Display lädt und anzeigt. Zunächst legt man einen Ordner
'images' im Laufwerk 'CIRCUITPY' an. Dort hin kopiert man die Bitmap-Datei. Ich habe ein Bild 'erde.bmp' vorbereitet, welches
Sie verwenden können. Dieses ist genau 240x240 Pixel groß. Achten Sie darauf, dass die Farbtiefe nicht 'True Color' (also nicht 24 Bit) sein
kann. Verwenden Sie max. 256 oder besser sogar nur 16 Farben. Das zahlt sich beim Speicherbedarf aus.
Im unteren Kasten sehen Sie den Anfang des Programms. Zunächst werden wieder die Module importiert, dann das Display (Zeilen 20 bis 28) und der Sensor
(Zeile 33) initialisiert. Auf die beiden Variable in Zeile 35 und 36 gehe ich später noch ein.
1 # SPDX-FileCopyrightText : 2023 Detlef Gebhardt, written for CircuitPython
2 # SPDX-FileCopyrightText : Copyright (c) 2023 Detlef Gebhardt
3 # SPDX-Filename : Earth-Clock
4 # SPDX-License-Identifier: GEBMEDIA
5 import time
6 import gc
7 import board
8 import busio
9 import displayio
10 import terminalio
11 from adafruit_display_text import label
12 from adafruit_display_shapes.roundrect import RoundRect
13 from adafruit_display_shapes.circle import Circle
14 import adafruit_imageload
15 from adafruit_ticks import ticks_ms
16 import math
17 import gc9a01
18 import my_qmi8658
19
20 # Alle verwendeten Ressourcen freigeben
21 displayio.release_displays()
22 # Display initialisieren
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, backlight_pin=board.LCD_BL)
26 group1 = displayio.Group()
27 display.rotation = 90
28 display.brightness = 1
29
30 display.show(group1)
31
32 # Sensor initialisieren
33 sensor=my_qmi8658.QMI8658()
34
35 zeit = " Uhrzeit"
36 start = 0
37
38 image1, palette = adafruit_imageload.load(
39 "/images/erde.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette)
40 tile_grid1 = displayio.TileGrid(image1, pixel_shader=palette)
41 group1.append(tile_grid1)
42
43 # Rechteck mit abgerundeten Ecken
44 roundrect1 = RoundRect(60, 132, 120, 40, 10, fill=0x0, outline=0xffffff, stroke=3)
45 group1.append(roundrect1)
46
47 ## create the label for time
48 updating_label1 = label.Label(
49 font=terminalio.FONT, text=zeit, scale=2, color=0xffffff,
50 line_spacing=1)
51 # set label position on the display and add label
52 updating_label1.anchor_point = (0, 0)
53 updating_label1.anchored_position = (70, 140)
54 group1.append(updating_label1)
Uns interessiert das Laden der Bitmap-Datei. In Zeile 38 wird diese als 'image1' geladen und ein s.g. 'tile_grid' definiert. Dieses wird dann
unter 'group1' im Speicher abgelegt (Zeile 41). In unserem Fall wird das Bild sofort angezeigt, da wir den Befehl 'display.show(group1)'
schon in Zeile 30 aufgerufen haben. Wenn man z.B. mehrere Bilder anzeigen will, die dann z. B. in 'group1', 'group2' und 'group3' abgelegt sind,
werden diese erst bei Aufruf von 'display.show(group1)', 'display.show(group2)' oder
'display.show(group3)' angezeigt.
In den Zeilen 43 bis 45 sehen Sie, wie ein Rechteck mit abgerundeten Ecken angelegt wird und in den Zeilen 47 bis 54 wird ein 'label' für eine
Textausgabe angelegt. Damit soll später die Uhrzeit angezeigt werden. Deshalb wurde auch in Zeile 35 die Variable 'zeit' als String definiert.
Bevor Sie die 'while'-Schleife ergänzen und damit experimentieren, ändern Sie in Zeile 28 den Wert display.brightness = 1
auf 0. Damit ist bei Programmstart das Display abgeschaltet.
56 while True:
57 #read QMI8658
58 reading=sensor.Read_XYZ()
59 # Display wird um die y-Achse gekippt
60 wert_y = (10)*reading[0]
61 wert_x = (10)*reading[1]
62 #print(wert_y,wert_x)
63
64 if wert_y < -6:
65 display.rotation = 0
66 display.brightness = 1
67 start = ticks_ms()
68 if wert_y >= -6 and wert_y <= 6 and wert_x < -6:
69 display.rotation = 90
70 display.brightness = 1
71 start = ticks_ms()
72 if wert_y >= -6 and wert_y <= 6 and wert_x > 6:
73 display.rotation = 270
74 display.brightness = 1
75 start = ticks_ms()
76 if wert_y > 6:
77 display.rotation = 180
78 display.brightness = 1
79 start = ticks_ms()
80 # Display nach 3 sec abschalten
81 if (ticks_ms() - start)/ 1000 > 3:
82 display.brightness = 0
83 start = 0
In der 'while'-Schleife wird jetzt wie in der vorigen Anleitung der Sensor ausgewertet. Je nachdem, wie das Display gehalten wird, wird die
Drehung angepasst. So ist das Bild immer aufrecht zu sehen. Hinzu kommt jetzt aber, dass erst beim Bewegen das Display eingeschaltet wird.
Legt man das Display ab, so schaltet es sich nach drei Sekunden wieder aus. Dazu wird 'ticks_ms()' in den Zeilen
81 bis 83 genutzt. 'ticks_ms()' zählt die Millisekunden des Prozessortaktes im Hintergrund und unterbricht nicht den Programmablauf wie
z.B. 'time.sleep(x)'. Mit der Variable 'start' wird der aktuelle Wert von 'ticks_ms()' gesetzt und mit
(ticks_ms() - start)/ 1000 die Anzahl der vergangenen Sekunden erfasst. So wird in unserem Fall, wenn mindestens 3 Sekunden vergangen sind,
das Display ausgeschaltet. Der Wert von 'start' muss dann wieder auf Null gesetzt werden.
Wenn wir das Beispiel jetzt zu einer einfachen Uhr erweitern, werden die Sekunden ohne Unterbrechnung fortwährend gezählt. Zur besseren
Übersicht gebe ich im nächsten Kasten den kompletten Programmcode an und werden ihn dann schrittweise erläutern.
1 # SPDX-FileCopyrightText : 2023 Detlef Gebhardt, written for CircuitPython
2 # SPDX-FileCopyrightText : Copyright (c) 2023 Detlef Gebhardt
3 # SPDX-Filename : Earth-Clock
4 # SPDX-License-Identifier: GEBMEDIA
5 import time
6 import gc
7 import board
8 import busio
9 import displayio
10 import terminalio
11 from adafruit_display_text import label
12 from adafruit_display_shapes.roundrect import RoundRect
13 from adafruit_display_shapes.circle import Circle
14 import adafruit_imageload
15 from adafruit_ticks import ticks_ms
16 import math
17 import gc9a01
18 import my_qmi8658
19
20 # Alle verwendeten Ressourcen freigeben
21 displayio.release_displays()
22 # Display initialisieren
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, backlight_pin=board.LCD_BL)
26 group1 = displayio.Group()
27 display.rotation = 90
28 display.brightness = 0
29
30 display.show(group1)
31
32 # Sensor initialisieren
33 sensor=my_qmi8658.QMI8658()
34
35 zeit = "00:00:00"
36 xpos = 120
37 ypos = 120
38 width = 240
39 height = 240
40 i = 0
41 j = -15
42 start = 0
43
44 image1, palette = adafruit_imageload.load(
45 "/images/erde.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette)
46 tile_grid1 = displayio.TileGrid(image1, pixel_shader=palette)
47 group1.append(tile_grid1)
48
49 # Rechteck mit abgerundeten Ecken
50 roundrect1 = RoundRect(60, 132, 120, 40, 10, fill=0x0, outline=0xffffff, stroke=3)
51 group1.append(roundrect1)
52
53 # Ziffernring
54 for i in range(1,13,1):
55 updating_label = label.Label(
56 font=terminalio.FONT, text=str(i), scale=2, color=0xffff00,
57 line_spacing=1)
58 #set label position on the display and add label
59 updating_label.anchor_point = (0, 0)
60 #updating_label.anchored_position = (xpos-10+int(90*math.cos(i*math.pi/6)),ypos-10-int(90*math.sin(i*math.pi/6)))
61 if i<10:
62 updating_label.anchored_position = (xpos-5+int(105*math.cos(-1*i*math.pi/6+ math.pi/2)),
63 ypos-12-int(105*math.sin(-1*i*math.pi/6+ math.pi/2)))
64 else:
65 updating_label.anchored_position = (xpos-10+int(105*math.cos(-1*i*math.pi/6+ math.pi/2)),
66 ypos-12-int(105*math.sin(-1*i*math.pi/6+ math.pi/2)))
67 group1.append(updating_label)
68 display.show(group1)
69
70 ## create the label for time
71 updating_label1 = label.Label(
72 font=terminalio.FONT, text=zeit, scale=2, color=0xffffff,
73 line_spacing=1)
74 # set label position on the display and add label
75 updating_label1.anchor_point = (0, 0)
76 updating_label1.anchored_position = (70, 140)
77 group1.append(updating_label1)
78
79 # Stundenpunkt
80 xpos_hour = int(width/2 + 105*math.cos(j*math.pi/30))
81 ypos_hour = int(height/2 + 105*math.sin(j*math.pi/30))
82 circle_hour = Circle(xpos_hour, ypos_hour, 8, fill=0xff0000, outline=0x000000)
83 group1.append(circle_hour)
84 # Minutenpunkt
85 xpos_min = int(width/2 + 105*math.cos(j*math.pi/30))
86 ypos_min = int(height/2 + 105*math.sin(j*math.pi/30))
87 circle_min = Circle(xpos_min, ypos_min, 8, fill=0x00ff00, outline=0x000000 )
88 group1.append(circle_min)
89
90 current_time = time.localtime()
91 hour = current_time.tm_hour
92 minute = current_time.tm_min
93 second = current_time.tm_sec
94
95 while True:
96 #read QMI8658
97 reading=sensor.Read_XYZ()
98 # Display wird um die y-Achse gekippt
99 wert_y = (10)*reading[0]
100 wert_x = (10)*reading[1]
101 #print(wert_y,wert_x)
102 if current_time.tm_min <= 1 and current_time.tm_hour == 0:
103 if wert_y < -6 and display.brightness == 1:
104 # display.rotation = 0
105 start = ticks_ms()
106 if minute < 59:
107 minute += 1
108 time.sleep(0.6)
109 else:
110 minute = 0
111 time.sleep(0.6)
112 if wert_y > 6 and display.brightness == 1:
113 # display.rotation = 180
114 start = ticks_ms()
115 if hour < 24:
116 hour += 1
117 time.sleep(0.6)
118 else:
119 hour = 0
120 time.sleep(0.6)
121 if wert_y >= -6 and wert_y <= 6 and wert_x < -6:
122 display.rotation = 90
123 display.brightness = 1
124 start = ticks_ms()
125 if wert_y >= -6 and wert_y <= 6 and wert_x > 6:
126 display.rotation = 270
127 display.brightness = 1
128 start = ticks_ms()
129 # Display nach 5 sec abschalten
130 if (ticks_ms() - start)/ 1000 > 5:
131 display.brightness = 0
132 start = 0
133
134 # Sekunden zaehlen
135 current_time = time.localtime()
136 second = current_time.tm_sec
137 if second == 59:
138 minute += 1
139 if minute == 60:
140 minute = 0
141 hour += 1
142 if hour == 24:
143 hour = 0
144 time.sleep(1)
145 #
146 # Zeitstring zur Anzeige aufbereiten
147 #
148 zeit = str(hour) + ":" + str(minute) + ":" + str(second)
149 if second < 10:
150 zeit = str(hour) + ":" + str(minute) + ":" + "0" + str(second)
151 if minute < 10:
152 zeit = str(hour) + ":" + "0" + str(minute) + ":" + str(second)
153 if second < 10 and minute < 10:
154 zeit = str(hour) + ":" + "0" + str(minute) + ":" + "0" + str(second)
155 updating_label1.text = zeit
156 # Minuten- und Stundenpunkt setzen
157 # Minuten
158 xpos_min_neu = int(width/2 + 105*math.cos((minute-15)*math.pi/30))
159 delta_min_x = xpos_min_neu - xpos_min
160 xpos_min = xpos_min_neu
161 ypos_min_neu = int(height/2 + 105*math.sin((minute-15)*math.pi/30))
162 delta_min_y = ypos_min_neu - ypos_min
163 ypos_min = ypos_min_neu
164 circle_min.x = circle_min.x + delta_min_x
165 circle_min.y = circle_min.y + delta_min_y
166 # Stunden
167 xpos_hour_neu = int(width/2 + int(105*math.cos((hour)*math.pi/6 + minute/2*math.pi/180 - math.pi/2)))
168 delta_hour_x = xpos_hour_neu - xpos_hour
169 xpos_hour = xpos_hour_neu
170 ypos_hour_neu = int(height/2 + int(105*math.sin((hour)*math.pi/6 + minute/2*math.pi/180 - math.pi/2)))
171 delta_hour_y = ypos_hour_neu - ypos_hour
172 ypos_hour = ypos_hour_neu
173 circle_hour.x = circle_hour.x + delta_hour_x
174 circle_hour.y = circle_hour.y + delta_hour_y
Bis zur Zeile 53 ist das Programm bis auf ein paar zusätzlich Variable unverändert.
Ab Zeile 53 bis 68 werden am Aussenring des Displays die Ziffern 1 bis 12 ,wie bei einer Uhr üblich, angezeigt. In den Zeilen
79 bis 88 werden anstelle von Uhrzeigern ein grüner Punkt für die Minuten und ein roter Punkt für die Stunden als
Kreis mit dem Radius 8 definiert. Da sich die Punkte auf dem Aussenring bewegen sollen, werden keine absoluten x- und y-Koordinaten
verwendet, sondern später in Abhängigkeit von der Zeit berechnet.
In den Zeilen 90 bis 93 werden die Sekunden, Minuten und Stunden aus 'time.localtime()' gewonnen, solange das Display am Rechner
angeschlossen ist.
In der 'while'-Schleife springen wir erst einmal bis zur Zeile 134. Ab hier werden die Sekunden gezählt und jeweils die Minuten
und Stunden erhöht. Die Pause in der Zeile 144 ist notwendig, da der MC schnell genug ist, innerhalb der 'Sekunde 59' mehrfach die
Schleife zu durchlaufen und so die Minute mehrfach erhöhen würde. Auf die Ganggenauigkeit wirkt sich die Pause nicht aus, da
ja durch second = current_time.tm_sec (Zeile 136) die Sekunde korrekt bleibt.
Die Zeilen 144 bis 155 dienen der Anzeige der aktuellen Zeit. Wobei 149 bis 154 nur dafür sorgen, dass die Werte immer zweistellig
sind. In 155 wird die Variable 'text', die in den Zeilen 70 bis 77 angelegt wurde, mit der Zeit belegt. Ab Zeile 155 werden der 'Minutenpunkt'
und der 'Stundenpunkt' an die entsprechende Position gesetzt. Die Berechnung selbiger habe ich
hier und
hier in diesen Anleitungen
erklärt.
Bleibt noch die Erläuterung der Zeilen 96 bis 132.
Wenn das Display am Rechner angeschlossen ist, startet es ja mit der aktuellen sekundengenauen Zeit. Wird das Programm als 'main.py' oder 'code.py'
gespeichert, startet das Display auch mit externer Stromversorgung (z.B. Powerbank), aber mit der Zeit 00:00:00. Deshalb braucht es eine
Möglichkeit, die Uhr zu stellen:
Dazu nutzen wir den ACC-Sensor. Kippen Sie innerhalb der ersten zwei Minute nach dem Start das Display leicht in Ihre Richtung, schaltet sich das
Display ein. Jetzt halten Sie das Display am USB-Anschluss und drehen es nach oben. In dieser Position laufen die Minuten aufsteigend. Achten Sie darauf,
das Display rechtzeitig wieder nach unten zu nehmen, wenn der gewünschte Minutenwert erreicht ist. In der entgegengesetzten Richtung - nach
unten - stellen Sie die Stunden ein. Das Ganze funktioniert nur in den ersten zwei Minuten, damit sich bei späterer Bewegung am Arm des Trägers
die Zeit nicht ungewollt ändert. Wird die Uhr hingegen am Rechner gestartet, wäre ein Verstellen der Uhrzeit beim Start nur um 00:00 Uhr
möglich (aber nicht erforderlich).
Ansonsten schaltet sich das Display immer für jeweils drei Sekunden ein, wenn der Träger es zu sich dreht, um die Zeit abzulesen. Das
funktioniert aufgrund der Displaydrehung um 90 bzw. 270 Grad am linken wie am rechten Arm. Probieren Sie es aus. Ursprünglich hatte ich eine Variante getestet, bei der
zwei winzige Taster ins Gehäuse integriert waren. Aufgrund der Fertigungsqualität der Taster (100 Stück 5 Euro plus Versand) hat sich das
aber nicht bewährt. Ausserdem war es nicht gerade einfach, die Kabel an den Anschlüssen der Header mit dem Rastermass 1.25 mm anzulöten.
Viel Spass und Erfolg beim Ausprobieren.
Im unteren Kasten sehen Sie den Anfang des Programms. Zunächst werden wieder die Module importiert, dann das Display (Zeilen 20 bis 28) und der Sensor (Zeile 33) initialisiert. Auf die beiden Variable in Zeile 35 und 36 gehe ich später noch ein.
1 # SPDX-FileCopyrightText : 2023 Detlef Gebhardt, written for CircuitPython 2 # SPDX-FileCopyrightText : Copyright (c) 2023 Detlef Gebhardt 3 # SPDX-Filename : Earth-Clock 4 # SPDX-License-Identifier: GEBMEDIA 5 import time 6 import gc 7 import board 8 import busio 9 import displayio 10 import terminalio 11 from adafruit_display_text import label 12 from adafruit_display_shapes.roundrect import RoundRect 13 from adafruit_display_shapes.circle import Circle 14 import adafruit_imageload 15 from adafruit_ticks import ticks_ms 16 import math 17 import gc9a01 18 import my_qmi8658 19 20 # Alle verwendeten Ressourcen freigeben 21 displayio.release_displays() 22 # Display initialisieren 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, backlight_pin=board.LCD_BL) 26 group1 = displayio.Group() 27 display.rotation = 90 28 display.brightness = 1 29 30 display.show(group1) 31 32 # Sensor initialisieren 33 sensor=my_qmi8658.QMI8658() 34 35 zeit = " Uhrzeit" 36 start = 0 37 38 image1, palette = adafruit_imageload.load( 39 "/images/erde.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette) 40 tile_grid1 = displayio.TileGrid(image1, pixel_shader=palette) 41 group1.append(tile_grid1) 42 43 # Rechteck mit abgerundeten Ecken 44 roundrect1 = RoundRect(60, 132, 120, 40, 10, fill=0x0, outline=0xffffff, stroke=3) 45 group1.append(roundrect1) 46 47 ## create the label for time 48 updating_label1 = label.Label( 49 font=terminalio.FONT, text=zeit, scale=2, color=0xffffff, 50 line_spacing=1) 51 # set label position on the display and add label 52 updating_label1.anchor_point = (0, 0) 53 updating_label1.anchored_position = (70, 140) 54 group1.append(updating_label1)
In den Zeilen 43 bis 45 sehen Sie, wie ein Rechteck mit abgerundeten Ecken angelegt wird und in den Zeilen 47 bis 54 wird ein 'label' für eine Textausgabe angelegt. Damit soll später die Uhrzeit angezeigt werden. Deshalb wurde auch in Zeile 35 die Variable 'zeit' als String definiert.
Bevor Sie die 'while'-Schleife ergänzen und damit experimentieren, ändern Sie in Zeile 28 den Wert display.brightness = 1 auf 0. Damit ist bei Programmstart das Display abgeschaltet.
56 while True: 57 #read QMI8658 58 reading=sensor.Read_XYZ() 59 # Display wird um die y-Achse gekippt 60 wert_y = (10)*reading[0] 61 wert_x = (10)*reading[1] 62 #print(wert_y,wert_x) 63 64 if wert_y < -6: 65 display.rotation = 0 66 display.brightness = 1 67 start = ticks_ms() 68 if wert_y >= -6 and wert_y <= 6 and wert_x < -6: 69 display.rotation = 90 70 display.brightness = 1 71 start = ticks_ms() 72 if wert_y >= -6 and wert_y <= 6 and wert_x > 6: 73 display.rotation = 270 74 display.brightness = 1 75 start = ticks_ms() 76 if wert_y > 6: 77 display.rotation = 180 78 display.brightness = 1 79 start = ticks_ms() 80 # Display nach 3 sec abschalten 81 if (ticks_ms() - start)/ 1000 > 3: 82 display.brightness = 0 83 start = 0
Wenn wir das Beispiel jetzt zu einer einfachen Uhr erweitern, werden die Sekunden ohne Unterbrechnung fortwährend gezählt. Zur besseren Übersicht gebe ich im nächsten Kasten den kompletten Programmcode an und werden ihn dann schrittweise erläutern.
1 # SPDX-FileCopyrightText : 2023 Detlef Gebhardt, written for CircuitPython 2 # SPDX-FileCopyrightText : Copyright (c) 2023 Detlef Gebhardt 3 # SPDX-Filename : Earth-Clock 4 # SPDX-License-Identifier: GEBMEDIA 5 import time 6 import gc 7 import board 8 import busio 9 import displayio 10 import terminalio 11 from adafruit_display_text import label 12 from adafruit_display_shapes.roundrect import RoundRect 13 from adafruit_display_shapes.circle import Circle 14 import adafruit_imageload 15 from adafruit_ticks import ticks_ms 16 import math 17 import gc9a01 18 import my_qmi8658 19 20 # Alle verwendeten Ressourcen freigeben 21 displayio.release_displays() 22 # Display initialisieren 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, backlight_pin=board.LCD_BL) 26 group1 = displayio.Group() 27 display.rotation = 90 28 display.brightness = 0 29 30 display.show(group1) 31 32 # Sensor initialisieren 33 sensor=my_qmi8658.QMI8658() 34 35 zeit = "00:00:00" 36 xpos = 120 37 ypos = 120 38 width = 240 39 height = 240 40 i = 0 41 j = -15 42 start = 0 43 44 image1, palette = adafruit_imageload.load( 45 "/images/erde.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette) 46 tile_grid1 = displayio.TileGrid(image1, pixel_shader=palette) 47 group1.append(tile_grid1) 48 49 # Rechteck mit abgerundeten Ecken 50 roundrect1 = RoundRect(60, 132, 120, 40, 10, fill=0x0, outline=0xffffff, stroke=3) 51 group1.append(roundrect1) 52 53 # Ziffernring 54 for i in range(1,13,1): 55 updating_label = label.Label( 56 font=terminalio.FONT, text=str(i), scale=2, color=0xffff00, 57 line_spacing=1) 58 #set label position on the display and add label 59 updating_label.anchor_point = (0, 0) 60 #updating_label.anchored_position = (xpos-10+int(90*math.cos(i*math.pi/6)),ypos-10-int(90*math.sin(i*math.pi/6))) 61 if i<10: 62 updating_label.anchored_position = (xpos-5+int(105*math.cos(-1*i*math.pi/6+ math.pi/2)), 63 ypos-12-int(105*math.sin(-1*i*math.pi/6+ math.pi/2))) 64 else: 65 updating_label.anchored_position = (xpos-10+int(105*math.cos(-1*i*math.pi/6+ math.pi/2)), 66 ypos-12-int(105*math.sin(-1*i*math.pi/6+ math.pi/2))) 67 group1.append(updating_label) 68 display.show(group1) 69 70 ## create the label for time 71 updating_label1 = label.Label( 72 font=terminalio.FONT, text=zeit, scale=2, color=0xffffff, 73 line_spacing=1) 74 # set label position on the display and add label 75 updating_label1.anchor_point = (0, 0) 76 updating_label1.anchored_position = (70, 140) 77 group1.append(updating_label1) 78 79 # Stundenpunkt 80 xpos_hour = int(width/2 + 105*math.cos(j*math.pi/30)) 81 ypos_hour = int(height/2 + 105*math.sin(j*math.pi/30)) 82 circle_hour = Circle(xpos_hour, ypos_hour, 8, fill=0xff0000, outline=0x000000) 83 group1.append(circle_hour) 84 # Minutenpunkt 85 xpos_min = int(width/2 + 105*math.cos(j*math.pi/30)) 86 ypos_min = int(height/2 + 105*math.sin(j*math.pi/30)) 87 circle_min = Circle(xpos_min, ypos_min, 8, fill=0x00ff00, outline=0x000000 ) 88 group1.append(circle_min) 89 90 current_time = time.localtime() 91 hour = current_time.tm_hour 92 minute = current_time.tm_min 93 second = current_time.tm_sec 94 95 while True: 96 #read QMI8658 97 reading=sensor.Read_XYZ() 98 # Display wird um die y-Achse gekippt 99 wert_y = (10)*reading[0] 100 wert_x = (10)*reading[1] 101 #print(wert_y,wert_x) 102 if current_time.tm_min <= 1 and current_time.tm_hour == 0: 103 if wert_y < -6 and display.brightness == 1: 104 # display.rotation = 0 105 start = ticks_ms() 106 if minute < 59: 107 minute += 1 108 time.sleep(0.6) 109 else: 110 minute = 0 111 time.sleep(0.6) 112 if wert_y > 6 and display.brightness == 1: 113 # display.rotation = 180 114 start = ticks_ms() 115 if hour < 24: 116 hour += 1 117 time.sleep(0.6) 118 else: 119 hour = 0 120 time.sleep(0.6) 121 if wert_y >= -6 and wert_y <= 6 and wert_x < -6: 122 display.rotation = 90 123 display.brightness = 1 124 start = ticks_ms() 125 if wert_y >= -6 and wert_y <= 6 and wert_x > 6: 126 display.rotation = 270 127 display.brightness = 1 128 start = ticks_ms() 129 # Display nach 5 sec abschalten 130 if (ticks_ms() - start)/ 1000 > 5: 131 display.brightness = 0 132 start = 0 133 134 # Sekunden zaehlen 135 current_time = time.localtime() 136 second = current_time.tm_sec 137 if second == 59: 138 minute += 1 139 if minute == 60: 140 minute = 0 141 hour += 1 142 if hour == 24: 143 hour = 0 144 time.sleep(1) 145 # 146 # Zeitstring zur Anzeige aufbereiten 147 # 148 zeit = str(hour) + ":" + str(minute) + ":" + str(second) 149 if second < 10: 150 zeit = str(hour) + ":" + str(minute) + ":" + "0" + str(second) 151 if minute < 10: 152 zeit = str(hour) + ":" + "0" + str(minute) + ":" + str(second) 153 if second < 10 and minute < 10: 154 zeit = str(hour) + ":" + "0" + str(minute) + ":" + "0" + str(second) 155 updating_label1.text = zeit 156 # Minuten- und Stundenpunkt setzen 157 # Minuten 158 xpos_min_neu = int(width/2 + 105*math.cos((minute-15)*math.pi/30)) 159 delta_min_x = xpos_min_neu - xpos_min 160 xpos_min = xpos_min_neu 161 ypos_min_neu = int(height/2 + 105*math.sin((minute-15)*math.pi/30)) 162 delta_min_y = ypos_min_neu - ypos_min 163 ypos_min = ypos_min_neu 164 circle_min.x = circle_min.x + delta_min_x 165 circle_min.y = circle_min.y + delta_min_y 166 # Stunden 167 xpos_hour_neu = int(width/2 + int(105*math.cos((hour)*math.pi/6 + minute/2*math.pi/180 - math.pi/2))) 168 delta_hour_x = xpos_hour_neu - xpos_hour 169 xpos_hour = xpos_hour_neu 170 ypos_hour_neu = int(height/2 + int(105*math.sin((hour)*math.pi/6 + minute/2*math.pi/180 - math.pi/2))) 171 delta_hour_y = ypos_hour_neu - ypos_hour 172 ypos_hour = ypos_hour_neu 173 circle_hour.x = circle_hour.x + delta_hour_x 174 circle_hour.y = circle_hour.y + delta_hour_y
Ab Zeile 53 bis 68 werden am Aussenring des Displays die Ziffern 1 bis 12 ,wie bei einer Uhr üblich, angezeigt. In den Zeilen 79 bis 88 werden anstelle von Uhrzeigern ein grüner Punkt für die Minuten und ein roter Punkt für die Stunden als Kreis mit dem Radius 8 definiert. Da sich die Punkte auf dem Aussenring bewegen sollen, werden keine absoluten x- und y-Koordinaten verwendet, sondern später in Abhängigkeit von der Zeit berechnet.
In den Zeilen 90 bis 93 werden die Sekunden, Minuten und Stunden aus 'time.localtime()' gewonnen, solange das Display am Rechner angeschlossen ist.
In der 'while'-Schleife springen wir erst einmal bis zur Zeile 134. Ab hier werden die Sekunden gezählt und jeweils die Minuten und Stunden erhöht. Die Pause in der Zeile 144 ist notwendig, da der MC schnell genug ist, innerhalb der 'Sekunde 59' mehrfach die Schleife zu durchlaufen und so die Minute mehrfach erhöhen würde. Auf die Ganggenauigkeit wirkt sich die Pause nicht aus, da ja durch second = current_time.tm_sec (Zeile 136) die Sekunde korrekt bleibt.
Die Zeilen 144 bis 155 dienen der Anzeige der aktuellen Zeit. Wobei 149 bis 154 nur dafür sorgen, dass die Werte immer zweistellig sind. In 155 wird die Variable 'text', die in den Zeilen 70 bis 77 angelegt wurde, mit der Zeit belegt. Ab Zeile 155 werden der 'Minutenpunkt' und der 'Stundenpunkt' an die entsprechende Position gesetzt. Die Berechnung selbiger habe ich hier und hier in diesen Anleitungen erklärt.
Bleibt noch die Erläuterung der Zeilen 96 bis 132.
Wenn das Display am Rechner angeschlossen ist, startet es ja mit der aktuellen sekundengenauen Zeit. Wird das Programm als 'main.py' oder 'code.py' gespeichert, startet das Display auch mit externer Stromversorgung (z.B. Powerbank), aber mit der Zeit 00:00:00. Deshalb braucht es eine Möglichkeit, die Uhr zu stellen:
Dazu nutzen wir den ACC-Sensor. Kippen Sie innerhalb der ersten zwei Minute nach dem Start das Display leicht in Ihre Richtung, schaltet sich das Display ein. Jetzt halten Sie das Display am USB-Anschluss und drehen es nach oben. In dieser Position laufen die Minuten aufsteigend. Achten Sie darauf, das Display rechtzeitig wieder nach unten zu nehmen, wenn der gewünschte Minutenwert erreicht ist. In der entgegengesetzten Richtung - nach unten - stellen Sie die Stunden ein. Das Ganze funktioniert nur in den ersten zwei Minuten, damit sich bei späterer Bewegung am Arm des Trägers die Zeit nicht ungewollt ändert. Wird die Uhr hingegen am Rechner gestartet, wäre ein Verstellen der Uhrzeit beim Start nur um 00:00 Uhr möglich (aber nicht erforderlich).
Ansonsten schaltet sich das Display immer für jeweils drei Sekunden ein, wenn der Träger es zu sich dreht, um die Zeit abzulesen. Das funktioniert aufgrund der Displaydrehung um 90 bzw. 270 Grad am linken wie am rechten Arm. Probieren Sie es aus. Ursprünglich hatte ich eine Variante getestet, bei der zwei winzige Taster ins Gehäuse integriert waren. Aufgrund der Fertigungsqualität der Taster (100 Stück 5 Euro plus Versand) hat sich das aber nicht bewährt. Ausserdem war es nicht gerade einfach, die Kabel an den Anschlüssen der Header mit dem Rastermass 1.25 mm anzulöten.
Viel Spass und Erfolg beim Ausprobieren.