Experimente
mit dem Neopixelring
am Pi Pico
Bildbox 1 (klick hier)
Experimente
mit dem Neopixelringam Pi Pico
Bildbox 1 (klick hier)
Hardware / Software
- Raspberry Pi Pico W
- Neopixelring 12 LED
- Micro USB Kabel
- Firmware CircuitPython
- Thonny IDE
Auch in diesem Projekt verwende ich auf einem Pico W CircuitPython von Adafruit als Firmware. Es werden zunächst ein paar Effekte mit dem Neopixelring allgemein gezeigt, um dessen Funktionsweise zu verstehen.
Danach soll in Ergänzung des Projektes 'Pico W mit LCD-1.14 als RTC Uhr' eine Uhr mit dem Neopixelring realisiert werden. Diese soll die
Sekunden, Minuten und Stunden in verschiedenen Farben anzeigen. Die Uhrzeit wird aus dem Internet bezogen, um das kleine Gadget unabhängig
vom PC laufen lassen zu können.
Zunächst laden Sie sich bei Adafruit die neuste Firmware 'CircuitPython' herunter und übertragen diese, wie z.B. in
diesem Projekt
beschrieben, auf den Pico W. Ich lösche dann immer zuerst die Datei 'code.py' im Explorer, um jeglichen Autostart zu unterbinden. Danach downloaden
Sie sich diese
Zip-Datei
und entpacken sie. Es handelt sich um zwei Bibliotheken, welche später gebraucht werden. Den gesamten Inhalt kopieren
Sie in den 'lib'-Ordner des Pico W.
Bevor Sie loslegen können, müssen drei Kabel auf der Rückseite des Neopixelrings, wie im Foto zu sehen, angelötet werden.
* rot + 5 V : wird verbunden mit Pin 40 VBUS am Pico
* braun GND: wird verbunden mit Pin 38 GND am Pico
* blau DI : wird verbunden mit Pin 2 (GPIO 1) am Pico
Ich verwende dafür die 'Dupont Kabel Female-Female' oder 'Dupont Kabel Male-Female' und schneide zum Anlöten auf einer Seite
den Stecker (im zweiten Fall 'Male'!) ab. So lassen sich die Stecker ('Female') auf der anderen Seite in der Testphase direkt auf die
entsprechenden Anschlüsse des Pico oder ein Expanderboard stecken. Eine Vorlage für ein kleines Gehäuse aus dem 3D-Drucker
finden Sie
hier .
Los gehts
Schauen wir uns einen ersten Effekt mit dem Neopixelring an. Nachdem Sie den Neopixelring, wie oben dargestellt, angeschlossen haben, starten
Sie das untere Programm. Dabei leuchten alle LED's rot, dann grün und schließlich blau und es
schließt sich ein "Regenbogeneffekt" an.
1 import time
2 import board
3 import neopixel
4
5 # Anzahl der Neopixels
6 num_pixels = 12
7
8 # Pin where NeoPixels are connected
9 pixel_pin1 = board.GP1
10
11 # The order of the pixel colors - RGB or GRB. Some NeoPixels have red and green reversed!
12 # For RGBW NeoPixels, simply change the ORDER to RGBW or GRBW.
13 ORDER = neopixel.GRB
14
15 pixels1 = neopixel.NeoPixel(
16 pixel_pin1, num_pixels, brightness=0.2, auto_write=False, pixel_order=ORDER)
17
18 def wheel(pos):
19 # Input a value 0 to 255 to get a color value.
20 # The colours are a transition r - g - b - back to r.
21 if pos < 0 or pos > 255:
22 r = g = b = 0
23 elif pos < 85:
24 r = int(pos * 3)
25 g = int(255 - pos * 3)
26 b = 0
27 elif pos < 170:
28 pos -= 85
29 r = int(255 - pos * 3)
30 g = 0
31 b = int(pos * 3)
32 else:
33 pos -= 170
34 r = 0
35 g = int(pos * 3)
36 b = int(255 - pos * 3)
37 return (r, g, b) if ORDER in (neopixel.RGB, neopixel.GRB) else (r, g, b, 0)
38
39 def rainbow_cycle(wait):
40 for j in range(255):
41 for i in range(num_pixels):
42 pixel_index = (i * 256 // num_pixels) + j
43 pixels1[i] = wheel(pixel_index & 255)
44 pixels1.show()
45 time.sleep(wait)
46
47 while True:
48 # Pixelring red
49 pixels1.fill((255, 0, 0))
50 pixels1.show()
51 time.sleep(1)
52 # Pixelring green
53 pixels1.fill((0, 255, 0))
54 pixels1.show()
55 time.sleep(1)
56 # Pixelring blue
57 pixels1.fill((0, 0, 255))
58 time.sleep(1)
59 for k in range(5):
60 # rainbow cycle with 1ms delay per step
61 rainbow_cycle(0.001)
In den Zeilen 1 bis 16 werden die Bibliotheken importiert, die Anzahl der LED festgelegt, der GPIO 1 als Signaleingang am Pico
und die Variable 'pixels1' definiert. Das wird in dieser Form auch bei den weiteren Experimenten so sein. In den Zeilen 18 bis
37 wird eine Funktion 'wheel()' definiert, welche den Dreheffekt erzeugt. Die Funktion 'rainbow_cycle()' sorgt für den Farbwechsel im
RGB-Bereich und die 'while'-Schleife wiederholt das Ganze, bis zum Programmabbruch.
Der zweite Effekt ist ebenfalls sehr interessant. Die leuchtenden LED's rotieren im Kreis und ändern über den gesamten RGB-Bereich
die Farbe. Dabei wird durch Verkürzung der Warteschleife das Tempo immer weiter erhöht. Als Abschluss folgt wieder der
Regenbogen. So sehen z.B. die Effekte bei den Jahrmarktbuden aus.
1 import time
2 import board
3 import neopixel
4
5 # Number of NeoPixels
6 numpix = 12
7
8 # Pin where NeoPixels are connected
9 pixpin1 = board.GP1
10
11 strip1 = neopixel.NeoPixel(pixpin1, numpix, brightness=0.15)
12
13 sine1 = [ # These are the pixels in order of animation - 12 pixels in total:
14 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
15
16 COLORS = (
17 (155, 0, 0),
18 ( 0, 155, 0),
19 ( 0, 0, 155),
20 (155, 155, 0),
21 (155, 0, 155),
22 ( 0, 155, 155),
23 )
24
25 def colorwheel(pos):
26 if pos < 0 or pos > 255:
27 return (0, 0, 0, 0)
28 if pos < 85:
29 return (255 - pos * 3, pos * 3, 0, 0)
30 if pos < 170:
31 pos -= 85
32 return (0, 255 - pos * 3, pos * 3, 0)
33 pos -= 170
34 return (pos * 3, 0, 255 - pos * 3, 0)
35
36 def rainbow_cycle(wait):
37 for j in range(255):
38 for i in range(numpix):
39 rc_index = (i * 256 // numpix) + j
40 strip1[i] = colorwheel(rc_index & 255)
41 strip1.show()
42
43 while True: # Loop forever...
44 for wait in range(10, 1, -2):
45 for color in COLORS:
46 for i in range(len(sine1)):
47 # Set 'head' pixel to color:
48 strip1[sine1[i]] = color
49 # Erase 'tail,' 8 pixels back:
50 strip1[sine1[(i + len(sine1) - 1) % len(sine1)]] = [0, 0, 0]
51 strip1.write() # Refresh LED states
52 time.sleep(wait/300) # xx millisecond delay
53 # rainbow cycle
54 rainbow_cycle(0)
Die Neopixel-Uhr
Jetzt soll der Neopixelring die Uhrzeit anzeigen. Diese holen wir, von einer meiner Seiten (Zeile 45) aus dem Internet. Wird die Seite angefordert, so wird ein
Zeitstempel erzeugt, welcher die Anzahl der Sekunden seit dem 1.1.1970 enthält. Daraus werden die Stunden, Minuten und Sekunden von diesem Zeitpunkt
an errechnet und in 'localtime' gespeichert. Auf dem Neopixelring werden die Stunden rot , die Minuten grün
und die Sekunden blau dargestellt. Der "Stundenzeiger" steht auf einer der 12 LED und springt auf die nächste
Position, sobald die neue Stunde beginnt. Ebenso wandert auch der "Minutenzeiger" immer nur alle 5 Minuten um eine Position weiter. Die Zeit
läßt sich also eigentlich nur in 5-Minuten Schritten ablesen. Damit man dennoch sehen kann, dass ständig etwas "passiert",
leuchtet die LED der aktuellen Sekunde bei jedem Schritt etwas "schwächer" und an der nächsten Position schon etwas "heller". Wirkliche
Ableseprobleme gibt es nur, wenn sich jede Stunde einmal "Minutenzeiger" und "Stundenzeiger" für 5 Minuten überdecken. Schauen Sie
sich das Programm erst einmal an, kopieren es in Ihr Thonny und probieren es aus:
1 import os
2 import time, gc
3 import board
4 import ssl
5 import rtc
6 import wifi, ssl, socketpool
7 import socketpool
8 import microcontroller
9 import adafruit_requests
10 import displayio
11 import digitalio
12 import terminalio
13 import neopixel
14 from rainbowio import colorwheel
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 num_pixels = 12
24 pixel_pin = board.GP1
25 pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.05, auto_write=False)
26
27 def rainbow(speed):
28 for k in range (2):
29 for j in range(255):
30 for i in range(12):
31 pixel_index = (i * 256 // 12) + j
32 pixels[i] = colorwheel(pixel_index & 255)
33 pixels.show()
34 time.sleep(speed)
35 hour = 0
36 minute = 0
37 second = 0
38 start = 0
39
40 while True:
41 if start == 0 or (minute == 0 and second == 0) or (minute == 30 and second == 0):
42 start = 1
43 #UTC Zeit aus Internet holen:
44 requests = adafruit_requests.Session(pool, ssl.create_default_context())
45 response = requests.get("https://www.dgebhardt.de/timestamp.php")
46 r = rtc.RTC()
47 r.datetime = time.localtime(int(response.text))
48 dt = time.struct_time(r.datetime)
49 response.close()
50 gc.collect()
51 hour = (dt[3] + 1) % 12
52 minute = dt[4]
53 second = dt[5]
54 if second == 0 :
55 rainbow(0)
56 pixels.fill(( 0, 0, 0))
57 second += 1
58 if second == 60:
59 second = 0
60 minute += 1
61 if minute == 60:
62 second = 0
63 minute = 0
64 hour += 1
65 if hour == 12:
66 second = 0
67 minute = 0
68 hour = 0
69 hour_pixel = hour - 6
70 minute_pixel = int(minute / 5) - 6
71 second_pixel = int(second / 5) - 6
72 pixels[second_pixel] = (0, 0, 255)
73 # Sekunden-LED wird heller
74 if second % 5 == 1:
75 pixels[second_pixel + 1] = (0, 0, 25)
76 if second % 5 == 2:
77 pixels[second_pixel + 1] = (0, 0, 50)
78 if second % 5 == 3:
79 pixels[second_pixel + 1] = (0, 0, 75)
80 if second % 5 == 4:
81 pixels[second_pixel + 1] = (0, 0, 120)
82 if second % 5 == 5:
83 pixels[second_pixel + 1] = (0, 0, 255)
84 # Sekunden-LED wird schwaecher
85 if second % 5 == 1:
86 pixels[second_pixel] = (0, 0, 120)
87 if second % 5 == 2:
88 pixels[second_pixel] = (0, 0, 75)
89 if second % 5 == 3:
90 if second % 5 == 4:
91 pixels[second_pixel] = (0, 0, 25)
92 if second % 5 == 5:
93 pixels[second_pixel] = (0, 0, 0)
94 pixels[second_pixel -1] = (0, 0, 0)
95 if pixels[second_pixel] == pixels[minute_pixel]:
96 pixels[second_pixel] = (100, 100, 100)
97 if pixels[second_pixel] == pixels[hour_pixel]:
98 pixels[second_pixel] = (100, 0, 100)
99 if pixels[minute_pixel] == pixels[hour_pixel]:
100 pixels[minute_pixel] = (255, 100, 0)
101 pixels[hour_pixel] = (255, 0, 0)
102 pixels.show()
103 time.sleep(1)
Zur Funktionsweise des Programms:
In den Zeilen 16 und 17 wird die Onboard-LED ausgeschaltet, da sie hier nicht genutzt wird.
Die Zeilen 1 bis 21 unterscheiden sich von den Vorversuchen durch den Aufbau einer WLAN-Verbindung (Zeile 20,21). Im dargestellten Fall werden die
SSID und das Password nicht im Klartext eingetragen, sondern aus der Datei 'settings.toml' vom Pico W geholt. Den Inhalt dieser Datei zeige ich hier
noch einmal. Angelegt wird die leere Datei, wenn Sie Circuitpython auf dem Pico W installieren.
1 # Comments are supported
2 CIRCUITPY_WIFI_SSID="Ihre SSID eintragen"
3 CIRCUITPY_WIFI_PASSWORD="Ihr Passwort eintragen"
4 CIRCUITPY_WEB_API_PORT=80
5 CIRCUITPY_WEB_API_PASSWORD="passw0rd"
6 test_variable="Testvariable"
7 thumbs_up="\U0001f44d"
Sicher haben Sie auch bemerkt, dass keine Funktion 'wheels()' mehr vorkommt. Die wird jetzt direkt in der Funktion 'rainbow()' aufgerufen, nachdem sie über
'from rainbowio import colorwheel' in Zeile 14 importiert wurde. Dadurch läuft die Abarbeitung der Schleife wesentlich schneller, so dass der 'time.sleep(1), also
1 Sekunde Verzögerung in Zeile 103, gut funktioniert. Da die Zeit zu jeder vollen bzw. halben Stunde neu im Internet syncronisiert wird (Zeilen
43 bis 53), spielt ein geringes "Nachgehen" praktisch keine Rolle. Ansonsten verändern Sie den Wert in Zeile 103.
Beim Ablesen muss Ihnen bewußt sein, dass die Anzeige der Uhrzeit wie bei einem Digitaldisplay erfolgt.
Beispiel 1: Es ist '15:35 Uhr' - Die rote LED leuchtet bei der 3, die grüne LED leuchtet bei der 7.
Beispiel 2: Es ist '18:57 Uhr' - Die rote LED leuchtet bei der 6, die grüne LED leuchtet bei der 11.
Weitere verwandte Projekte:
1 import time 2 import board 3 import neopixel 4 5 # Anzahl der Neopixels 6 num_pixels = 12 7 8 # Pin where NeoPixels are connected 9 pixel_pin1 = board.GP1 10 11 # The order of the pixel colors - RGB or GRB. Some NeoPixels have red and green reversed! 12 # For RGBW NeoPixels, simply change the ORDER to RGBW or GRBW. 13 ORDER = neopixel.GRB 14 15 pixels1 = neopixel.NeoPixel( 16 pixel_pin1, num_pixels, brightness=0.2, auto_write=False, pixel_order=ORDER) 17 18 def wheel(pos): 19 # Input a value 0 to 255 to get a color value. 20 # The colours are a transition r - g - b - back to r. 21 if pos < 0 or pos > 255: 22 r = g = b = 0 23 elif pos < 85: 24 r = int(pos * 3) 25 g = int(255 - pos * 3) 26 b = 0 27 elif pos < 170: 28 pos -= 85 29 r = int(255 - pos * 3) 30 g = 0 31 b = int(pos * 3) 32 else: 33 pos -= 170 34 r = 0 35 g = int(pos * 3) 36 b = int(255 - pos * 3) 37 return (r, g, b) if ORDER in (neopixel.RGB, neopixel.GRB) else (r, g, b, 0) 38 39 def rainbow_cycle(wait): 40 for j in range(255): 41 for i in range(num_pixels): 42 pixel_index = (i * 256 // num_pixels) + j 43 pixels1[i] = wheel(pixel_index & 255) 44 pixels1.show() 45 time.sleep(wait) 46 47 while True: 48 # Pixelring red 49 pixels1.fill((255, 0, 0)) 50 pixels1.show() 51 time.sleep(1) 52 # Pixelring green 53 pixels1.fill((0, 255, 0)) 54 pixels1.show() 55 time.sleep(1) 56 # Pixelring blue 57 pixels1.fill((0, 0, 255)) 58 time.sleep(1) 59 for k in range(5): 60 # rainbow cycle with 1ms delay per step 61 rainbow_cycle(0.001)
Der zweite Effekt ist ebenfalls sehr interessant. Die leuchtenden LED's rotieren im Kreis und ändern über den gesamten RGB-Bereich die Farbe. Dabei wird durch Verkürzung der Warteschleife das Tempo immer weiter erhöht. Als Abschluss folgt wieder der Regenbogen. So sehen z.B. die Effekte bei den Jahrmarktbuden aus.
1 import time 2 import board 3 import neopixel 4 5 # Number of NeoPixels 6 numpix = 12 7 8 # Pin where NeoPixels are connected 9 pixpin1 = board.GP1 10 11 strip1 = neopixel.NeoPixel(pixpin1, numpix, brightness=0.15) 12 13 sine1 = [ # These are the pixels in order of animation - 12 pixels in total: 14 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 15 16 COLORS = ( 17 (155, 0, 0), 18 ( 0, 155, 0), 19 ( 0, 0, 155), 20 (155, 155, 0), 21 (155, 0, 155), 22 ( 0, 155, 155), 23 ) 24 25 def colorwheel(pos): 26 if pos < 0 or pos > 255: 27 return (0, 0, 0, 0) 28 if pos < 85: 29 return (255 - pos * 3, pos * 3, 0, 0) 30 if pos < 170: 31 pos -= 85 32 return (0, 255 - pos * 3, pos * 3, 0) 33 pos -= 170 34 return (pos * 3, 0, 255 - pos * 3, 0) 35 36 def rainbow_cycle(wait): 37 for j in range(255): 38 for i in range(numpix): 39 rc_index = (i * 256 // numpix) + j 40 strip1[i] = colorwheel(rc_index & 255) 41 strip1.show() 42 43 while True: # Loop forever... 44 for wait in range(10, 1, -2): 45 for color in COLORS: 46 for i in range(len(sine1)): 47 # Set 'head' pixel to color: 48 strip1[sine1[i]] = color 49 # Erase 'tail,' 8 pixels back: 50 strip1[sine1[(i + len(sine1) - 1) % len(sine1)]] = [0, 0, 0] 51 strip1.write() # Refresh LED states 52 time.sleep(wait/300) # xx millisecond delay 53 # rainbow cycle 54 rainbow_cycle(0)
Die Neopixel-Uhr
1 import os 2 import time, gc 3 import board 4 import ssl 5 import rtc 6 import wifi, ssl, socketpool 7 import socketpool 8 import microcontroller 9 import adafruit_requests 10 import displayio 11 import digitalio 12 import terminalio 13 import neopixel 14 from rainbowio import colorwheel 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 num_pixels = 12 24 pixel_pin = board.GP1 25 pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.05, auto_write=False) 26 27 def rainbow(speed): 28 for k in range (2): 29 for j in range(255): 30 for i in range(12): 31 pixel_index = (i * 256 // 12) + j 32 pixels[i] = colorwheel(pixel_index & 255) 33 pixels.show() 34 time.sleep(speed) 35 hour = 0 36 minute = 0 37 second = 0 38 start = 0 39 40 while True: 41 if start == 0 or (minute == 0 and second == 0) or (minute == 30 and second == 0): 42 start = 1 43 #UTC Zeit aus Internet holen: 44 requests = adafruit_requests.Session(pool, ssl.create_default_context()) 45 response = requests.get("https://www.dgebhardt.de/timestamp.php") 46 r = rtc.RTC() 47 r.datetime = time.localtime(int(response.text)) 48 dt = time.struct_time(r.datetime) 49 response.close() 50 gc.collect() 51 hour = (dt[3] + 1) % 12 52 minute = dt[4] 53 second = dt[5] 54 if second == 0 : 55 rainbow(0) 56 pixels.fill(( 0, 0, 0)) 57 second += 1 58 if second == 60: 59 second = 0 60 minute += 1 61 if minute == 60: 62 second = 0 63 minute = 0 64 hour += 1 65 if hour == 12: 66 second = 0 67 minute = 0 68 hour = 0 69 hour_pixel = hour - 6 70 minute_pixel = int(minute / 5) - 6 71 second_pixel = int(second / 5) - 6 72 pixels[second_pixel] = (0, 0, 255) 73 # Sekunden-LED wird heller 74 if second % 5 == 1: 75 pixels[second_pixel + 1] = (0, 0, 25) 76 if second % 5 == 2: 77 pixels[second_pixel + 1] = (0, 0, 50) 78 if second % 5 == 3: 79 pixels[second_pixel + 1] = (0, 0, 75) 80 if second % 5 == 4: 81 pixels[second_pixel + 1] = (0, 0, 120) 82 if second % 5 == 5: 83 pixels[second_pixel + 1] = (0, 0, 255) 84 # Sekunden-LED wird schwaecher 85 if second % 5 == 1: 86 pixels[second_pixel] = (0, 0, 120) 87 if second % 5 == 2: 88 pixels[second_pixel] = (0, 0, 75) 89 if second % 5 == 3: 90 if second % 5 == 4: 91 pixels[second_pixel] = (0, 0, 25) 92 if second % 5 == 5: 93 pixels[second_pixel] = (0, 0, 0) 94 pixels[second_pixel -1] = (0, 0, 0) 95 if pixels[second_pixel] == pixels[minute_pixel]: 96 pixels[second_pixel] = (100, 100, 100) 97 if pixels[second_pixel] == pixels[hour_pixel]: 98 pixels[second_pixel] = (100, 0, 100) 99 if pixels[minute_pixel] == pixels[hour_pixel]: 100 pixels[minute_pixel] = (255, 100, 0) 101 pixels[hour_pixel] = (255, 0, 0) 102 pixels.show() 103 time.sleep(1)
In den Zeilen 16 und 17 wird die Onboard-LED ausgeschaltet, da sie hier nicht genutzt wird.
Die Zeilen 1 bis 21 unterscheiden sich von den Vorversuchen durch den Aufbau einer WLAN-Verbindung (Zeile 20,21). Im dargestellten Fall werden die SSID und das Password nicht im Klartext eingetragen, sondern aus der Datei 'settings.toml' vom Pico W geholt. Den Inhalt dieser Datei zeige ich hier noch einmal. Angelegt wird die leere Datei, wenn Sie Circuitpython auf dem Pico W installieren.
1 # Comments are supported 2 CIRCUITPY_WIFI_SSID="Ihre SSID eintragen" 3 CIRCUITPY_WIFI_PASSWORD="Ihr Passwort eintragen" 4 CIRCUITPY_WEB_API_PORT=80 5 CIRCUITPY_WEB_API_PASSWORD="passw0rd" 6 test_variable="Testvariable" 7 thumbs_up="\U0001f44d"
Beim Ablesen muss Ihnen bewußt sein, dass die Anzeige der Uhrzeit wie bei einem Digitaldisplay erfolgt.
Beispiel 1: Es ist '15:35 Uhr' - Die rote LED leuchtet bei der 3, die grüne LED leuchtet bei der 7.
Beispiel 2: Es ist '18:57 Uhr' - Die rote LED leuchtet bei der 6, die grüne LED leuchtet bei der 11.
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