Ausprobiert Teil 2
Rundes 1.28-Zoll-IPS-LCD-Display 240 x 240 Pixel
- RP2040, 6-Achsen-Sensor - Waveshare 22668
Ein wenig Mathematik muss sein:
- kleiner Exkurs in die Winkelfunktionen -
Bildbox 1 (klick hier)
Ausprobiert Teil 2
Rundes 1.28-Zoll-IPS-LCD-Display 240 x 240 Pixel- RP2040, 6-Achsen-Sensor - Waveshare 22668
Ein wenig Mathematik muss sein:
- kleiner Exkurs in die Winkelfunktionen -
Bildbox 1 (klick hier)
Hardware
- Rundes 1,28-Zoll-IPS-LCD-Display
- RP Pico 2040 (inclusive)
- USB-A zu USB-C Kabel
Unser Display ist rund. Deshalb kommt man z.B. bei der Darstellung von Punkten, Zeigern u.ä. nicht ohne die Winkelfunktionen Sinus und Cosinus
aus. Gehen wir kurz auf die Definitionen von Sinus und Cosinus ein.
sin(alpha) = Gegenkathete / Radius
Da die Gegenkathete hier der y-Koordinate im Koordinatensystem entspricht folgt daraus:
y = r * sin(alpha)
Analog gilt dann für den Cosinus:
cos(alpha) = Ankathete / Radius
Dabei entspricht die Ankathete der x-Koordinate, also:
x = r * cos(alpha)
Klicken Sie auf die Bildbox 1 (oben) und sehen sich die Abbildungen dazu an.
Auf den beiden unteren Fotos wird das für die 'Sekundenpunkte', 'Minutenpunkte', 'Stundenpunkte' bzw. die Position der Zeigerspitzen genuzt.
Los gehts mit einem Beispiel
Das Display hat 240 x 240 Pixel. Der Mittelpunkt liegt also bei P(120/120), so dass wir als Koordinaten nachfolgend immer
xpos = 120 und ypos = 120 nutzen.
Die jeweils neue x-Koordinate ergibt sich dann aus
xpos_neu = int(xpos + 100*math.cos((alpha)*math.pi/30)
und die y-Koordinate
ypos_neu = int(ypos + 100*math.sin((alpha)*math.pi/30).
Da 2*pi bekanntlich 360 Grad entsprechen, lassen sich mit pi/30 die 60 'Positionen' (360 / 180 * 30 = 60) darstellen.
Mit der 100 wird in unserem Fall der Radius festgelegt. Hier nun das Beispielprogramm:
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 import random
16 import math
17
18 # Release any resources currently in use for the displays
19 displayio.release_displays()
20
21 # Make the displayio SPI bus and the GC9A01 display
22 spi = busio.SPI(clock=board.LCD_CLK, MOSI=board.LCD_DIN)
23 display_bus = displayio.FourWire(spi, command=board.LCD_DC, chip_select=board.LCD_CS, reset=board.LCD_RST)
24 display = gc9a01.GC9A01(display_bus, width=240, height=240, rotation=90, backlight_pin=board.LCD_BL)
25
26 # Make the display context
27 group1 = displayio.Group()
28 display.show(group1)
29
30 width = 240
31 height = 240
32 xpos = 120
33 ypos = 120
34 radius = 120
35 i = 0
36
37# Make some circle:
38 circle = Circle(xpos, ypos, 120, fill=0xff0000, outline=0x000000)
39 group1.append(circle)
40 circle = Circle(xpos, ypos, 115, fill=0x000000, outline=0x000000)
41 group1.append(circle)
42 circle = Circle(xpos, ypos, 85, fill=0xffff00, outline=0xffff00)
43 group1.append(circle)
44 circle = Circle(xpos, ypos, 10, fill=0x0000ff, outline=0xffff00)
45 group1.append(circle)
46
47 while True:
48 for i in range (60):
49 xpos_neu = int(width/2 + 100*math.cos((i -15)*math.pi/30))
50 delta_x = xpos_neu - xpos
51 xpos = xpos_neu
52 ypos_neu = int(height/2 + 100*math.sin((i -15)*math.pi/30))
53 delta_y = ypos_neu - ypos
54 ypos = ypos_neu
55 circle.x = circle.x + delta_x
56 circle.y = circle.y + delta_y
57 time.sleep(0.05)
58 gc.collect()
59 #print(gc.mem_free())
Ein paar Erläuterungen. Die Programmzeilen 5 bis 28 entsprechen dem vorigen Beitrag zur Initialisierung des
Displays. Hinzu gekommen sind die Module 'from adafruit_display_shapes.circle import Circle' und
'import math', welche für die Kreisdarstellung und die mathematischen Berechnungen gebraucht
werden. In den Zeilen 37 bis 45 werden Kreise dargestellt, welche nacheinander das Display rot, dann mit kleinerem Durchmesser
schwarz und schließlich gelb einfärben. Zuletzt wird ein kleiner blauer Kreis als Punkt in dem schwarzen Ring
dargestellt. Sie sehen, dass die Syntax für den Kreis immer
circle = Circle(xpos, ypos, radius, fillcolor, outlinecolor)
ist. Es folgt die 'while' Schleife in Zeile 47. Dort wird in den Zeilen 56 und 57 eine Eigenschaft bei 'circle' genutzt, welche
mit 'circle.x' bzw. 'circle.y' die neue x und y Position des Mittelpunktes annehmen kann, ohne den Kreis neu definieren zu
müssen. Stattdessen wird in den Zeilen 49 bis 54 der neue geänderte Wert berechnet und als 'delta_x' und 'delta_y' zu
den Mittelpunktkoordinaten addiert. Dass hat den riesigen Vorteil, dass kein zusätzlicher Speicher belegt wird, denn dann
würde ganz schnell ein 'MemoryError' das Programm beenden.
Ich habe das Ganze in eine 'for i in range (60)' Schleife gepackt, deshalb steht in Zeile 49 und 52 beim Sinus bzw. Cosinus das 'i'.
Die subtrahierte 15 hat ihren Sinn, weil ich das Display bei der Initialisierung um 90 Grad gedreht habe (siehe Zeile 24) und die
Bewegung oben beginnen soll. Experimentieren Sie mit dem Beispiel und demnächst geht es weiter.
Zuvor gibt es aber noch eine kleine Zugabe. Probieren Sie das folgende Programm aus. Mit Hilfe der Zufallsfunktion 'random' wird
mit 'wert = random.randint(min,max)' ein ganzzahliger Zufallswert zwischen 'min' und 'max' erzeugt. Diesen verwende
ich für die x- und y-Koordinaten und lasse den Punkt innerhalb des schwarzen Kreises hin- und herspringen, bis er den weißen
Punkt trifft.
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 import random
16
17 # Release any resources currently in use for the displays
18 displayio.release_displays()
19
20 # Make the displayio SPI bus and the GC9A01 display
30 spi = busio.SPI(clock=board.LCD_CLK, MOSI=board.LCD_DIN)
31 display_bus = displayio.FourWire(spi, command=board.LCD_DC, chip_select=board.LCD_CS, reset=board.LCD_RST)
32 display = gc9a01.GC9A01(display_bus, width=240, height=240, rotation=90, backlight_pin=board.LCD_BL)
33
34 # Make the display context
35 group1 = displayio.Group()
36 display.show(group1)
37
38 width = 240
39 height = 240
40 xpos = 120
41 ypos = 120
42 radius = 120
43 xpos_neu = 0
44 ypos_neu = 0
45
46 # Make some circle:
47 circle = Circle(xpos, ypos, 120, fill=0xff0000, outline=0x000000)
group1.append(circle)
48 circle = Circle(xpos, ypos, 110, fill=0x000000, outline=0x000000)
49 group1.append(circle)
50 circle_m = Circle(xpos, ypos, 16, fill=0xffffff, outline=0x000000)
51 group1.append(circle_m)
52 circle_p = Circle(xpos, ypos, 10, fill=0x0000ff, outline=0xffff00)
53 group1.append(circle_p)
54
55 while True:
56 while not ((xpos_neu>=114 and xpos_neu<=126)and(ypos_neu>=114 and ypos_neu<=126) ):
57 x = random.randint(-75,75)
58 y = random.randint(-75,75)
59 xpos_neu = int(width/2 + x)
60 delta_x = xpos_neu - xpos
61 xpos = xpos_neu
62 ypos_neu = int(height/2 + y)
63 delta_y = ypos_neu - ypos
64 ypos = ypos_neu
65 circle_p.x = circle_p.x + delta_x
66 circle_p.y = circle_p.y + delta_y
67 time.sleep(0.2)
68 gc.collect()
69 circle_p.x = circle_p.x + 0
70 circle_p.y = circle_p.y + 0
71 #print(gc.mem_free())
Erinnert Sie das auch an ein Spiel aus der Kindheit, bei dem eine Kugel in einer kleinen Dose in ein Loch jongliert werden
mußte. In unserem Fall steckt die Idee dahinter, dass dies unter Nutzung des Beschleunigungssensors, über den unser
rundes Display verfügt, gemacht wird. Leider habe ich unter 'CircuitPython' das Modul QMI8658 noch
nicht fertig und so ist das hier vorläufig ein 'fake', aber ich bin mit Hochdruck dran. Sollte jemand das o.g. Modul für
'Circuitpython'(!!!) kennen und mir dabei weiterhelfen können, würde ich mich über entsprechende Hilfe sehr freuen.
Viel Spass und Erfolg beim Ausprobieren.
Die jeweils neue x-Koordinate ergibt sich dann aus
Da 2*pi bekanntlich 360 Grad entsprechen, lassen sich mit pi/30 die 60 'Positionen' (360 / 180 * 30 = 60) darstellen. Mit der 100 wird in unserem Fall der Radius festgelegt. Hier nun das Beispielprogramm:
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 import random 16 import math 17 18 # Release any resources currently in use for the displays 19 displayio.release_displays() 20 21 # Make the displayio SPI bus and the GC9A01 display 22 spi = busio.SPI(clock=board.LCD_CLK, MOSI=board.LCD_DIN) 23 display_bus = displayio.FourWire(spi, command=board.LCD_DC, chip_select=board.LCD_CS, reset=board.LCD_RST) 24 display = gc9a01.GC9A01(display_bus, width=240, height=240, rotation=90, backlight_pin=board.LCD_BL) 25 26 # Make the display context 27 group1 = displayio.Group() 28 display.show(group1) 29 30 width = 240 31 height = 240 32 xpos = 120 33 ypos = 120 34 radius = 120 35 i = 0 36 37# Make some circle: 38 circle = Circle(xpos, ypos, 120, fill=0xff0000, outline=0x000000) 39 group1.append(circle) 40 circle = Circle(xpos, ypos, 115, fill=0x000000, outline=0x000000) 41 group1.append(circle) 42 circle = Circle(xpos, ypos, 85, fill=0xffff00, outline=0xffff00) 43 group1.append(circle) 44 circle = Circle(xpos, ypos, 10, fill=0x0000ff, outline=0xffff00) 45 group1.append(circle) 46 47 while True: 48 for i in range (60): 49 xpos_neu = int(width/2 + 100*math.cos((i -15)*math.pi/30)) 50 delta_x = xpos_neu - xpos 51 xpos = xpos_neu 52 ypos_neu = int(height/2 + 100*math.sin((i -15)*math.pi/30)) 53 delta_y = ypos_neu - ypos 54 ypos = ypos_neu 55 circle.x = circle.x + delta_x 56 circle.y = circle.y + delta_y 57 time.sleep(0.05) 58 gc.collect() 59 #print(gc.mem_free())
ist. Es folgt die 'while' Schleife in Zeile 47. Dort wird in den Zeilen 56 und 57 eine Eigenschaft bei 'circle' genutzt, welche mit 'circle.x' bzw. 'circle.y' die neue x und y Position des Mittelpunktes annehmen kann, ohne den Kreis neu definieren zu müssen. Stattdessen wird in den Zeilen 49 bis 54 der neue geänderte Wert berechnet und als 'delta_x' und 'delta_y' zu den Mittelpunktkoordinaten addiert. Dass hat den riesigen Vorteil, dass kein zusätzlicher Speicher belegt wird, denn dann würde ganz schnell ein 'MemoryError' das Programm beenden.
Ich habe das Ganze in eine 'for i in range (60)' Schleife gepackt, deshalb steht in Zeile 49 und 52 beim Sinus bzw. Cosinus das 'i'. Die subtrahierte 15 hat ihren Sinn, weil ich das Display bei der Initialisierung um 90 Grad gedreht habe (siehe Zeile 24) und die Bewegung oben beginnen soll. Experimentieren Sie mit dem Beispiel und demnächst geht es weiter.
Zuvor gibt es aber noch eine kleine Zugabe. Probieren Sie das folgende Programm aus. Mit Hilfe der Zufallsfunktion 'random' wird mit 'wert = random.randint(min,max)' ein ganzzahliger Zufallswert zwischen 'min' und 'max' erzeugt. Diesen verwende ich für die x- und y-Koordinaten und lasse den Punkt innerhalb des schwarzen Kreises hin- und herspringen, bis er den weißen Punkt trifft.
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 import random 16 17 # Release any resources currently in use for the displays 18 displayio.release_displays() 19 20 # Make the displayio SPI bus and the GC9A01 display 30 spi = busio.SPI(clock=board.LCD_CLK, MOSI=board.LCD_DIN) 31 display_bus = displayio.FourWire(spi, command=board.LCD_DC, chip_select=board.LCD_CS, reset=board.LCD_RST) 32 display = gc9a01.GC9A01(display_bus, width=240, height=240, rotation=90, backlight_pin=board.LCD_BL) 33 34 # Make the display context 35 group1 = displayio.Group() 36 display.show(group1) 37 38 width = 240 39 height = 240 40 xpos = 120 41 ypos = 120 42 radius = 120 43 xpos_neu = 0 44 ypos_neu = 0 45 46 # Make some circle: 47 circle = Circle(xpos, ypos, 120, fill=0xff0000, outline=0x000000) group1.append(circle) 48 circle = Circle(xpos, ypos, 110, fill=0x000000, outline=0x000000) 49 group1.append(circle) 50 circle_m = Circle(xpos, ypos, 16, fill=0xffffff, outline=0x000000) 51 group1.append(circle_m) 52 circle_p = Circle(xpos, ypos, 10, fill=0x0000ff, outline=0xffff00) 53 group1.append(circle_p) 54 55 while True: 56 while not ((xpos_neu>=114 and xpos_neu<=126)and(ypos_neu>=114 and ypos_neu<=126) ): 57 x = random.randint(-75,75) 58 y = random.randint(-75,75) 59 xpos_neu = int(width/2 + x) 60 delta_x = xpos_neu - xpos 61 xpos = xpos_neu 62 ypos_neu = int(height/2 + y) 63 delta_y = ypos_neu - ypos 64 ypos = ypos_neu 65 circle_p.x = circle_p.x + delta_x 66 circle_p.y = circle_p.y + delta_y 67 time.sleep(0.2) 68 gc.collect() 69 circle_p.x = circle_p.x + 0 70 circle_p.y = circle_p.y + 0 71 #print(gc.mem_free())
Viel Spass und Erfolg beim Ausprobieren.