Experimente

mit dem Neopixelring
am 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:

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

  • 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