Die rpi_ws281xx library ist auf dem Pi erfolgreich installiert und das Testprogramm läuft. Nein???
Kein Problem! Lese dir meinen letzten Beitrag: Adressierung von LED Strips mit dem Raspberry Pi durch und installier die library.
Und es funktioniert?
Perfekt, in dem Post möchte ich dir coole Animationen zeigen, die du damit programmieren kannst.
Die Codes kannst du aus den Code Containern kopieren oder du lädst dir das fertige Programm aus dem Anhang herunter!
Vielleicht kannst du die Effekte noch verschönern? Die Programme habe ich in Anlehung an das GitHub Repository rpi_ws281xx_library und aus den Arduino Codebeispielen von der Seite Tweaking4All erstellt.
import time, math from rpi_ws281x import PixelStrip, Color import argparse # LED strip configuration: LED_COUNT = 70 # Number of LED pixels. LED_PIN = 13 # GPIO pin connected to the pixels (18 uses PWM!). # LED_PIN = 10 # GPIO pin connected to the pixels (10 uses SPI /dev/spidev0.0). LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) LED_DMA = 10 # DMA channel to use for generating signal (try 10) LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest LED_INVERT = False # True to invert the signal (when using NPN transistor level shift) LED_CHANNEL = 1 # set to '1' for GPIOs 13, 19, 41, 45 or 53
Als erstes legen wir die Parameter der library fest und importieren die nötigen librarys.
if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('-c', '--clear', action='store_true', help='clear the display on exit') args = parser.parse_args() strip = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL) strip.begin() print('Press Ctrl-C to quit.') if not args.clear: print('Use "-c" argument to clear LEDs on exit') try: while True: #Entkommentieren um Programm auszuwählen #colorWipe(strip, color) #theaterChase(strip) theaterChaseRainbow(strip) #pulsing_light(strip) #snow_sparkle(strip) #strobe(strip) #bouncing_balls() except KeyboardInterrupt: if args.clear: colorWipe(strip, Color(0, 0, 0), 10)
Erklärung: Die Effekte werden in der while Schleife abgespielt. Wird dem Programm das Argument "-c" übergeben, wird bei einem Keyboard Interrupt mit STRG+ C alle LEDs ausgeschalten.
"Die Animation "color_wipe" wischt die Farben rot, grün und blau über den LED Streifen. Zum Testen ob alles funktioniert."
def colorWipe(strip, color, wait_ms=50): """Wipe color across display a pixel at a time.""" for i in range(strip.numPixels()): strip.setPixelColor(i, color) #Funktion rpi_ws281x.color wandelt DEC in BIN um strip.show() time.sleep(wait_ms / 1000.0)
Erklärung:
Über die Main Routine wird die Funktion "color_wipe" aufgerufen. Als Funktionsargument wird der Wert Color(r,g,b) übergeben. Durch den import der Datei ws281xx findet man zu der Funktion color den Code. Dort werden die RGB Werte in binäre Werte umgewandelt.
Der Befehl strip.setPixelColor(i, color) benötigt binäre Werte!
"In der Animation "theaterChase" wird vorest jede dritte Pixel mit einer definierten Farbe gesetzt(LED=ON). Im Verlauf wird die Pixelnummeriung chronologisch um 1 erhöht. Der Effekt baut Spannung auf."
def theaterChase(strip, color, wait_ms=50, iterations=10): """Movie theater light style chaser animation.""" for j in range(iterations): for q in range(3): for i in range(0, strip.numPixels(), 3): strip.setPixelColor(i + q, color) strip.show() time.sleep(wait_ms / 1000.0) for i in range(0, strip.numPixels(), 3): strip.setPixelColor(i + q, 0)
Erklärung:
Der Wert "iterations=10" gibt der Funktion die Anzahl der Wiederholungen, die die Anzahl der Iterationen der for loop bestimmen. In der zweiten for loop wird die Pixelnummerierung jeweils um 1 erhöht. In der dritten for loop werden die LEDs nach dem 3er Intervall System auf die ganze Länge des LED Strips erweitert. In der vierten for loop, die in der dritten eingebettet ist, werden die gesetzten LEDs wieder ausgeschalten.
"Bei der Animation "theaterChaseRainbow" wird jedes dritte Pixel auf einen Wert im Farbspektrum(Regenbogen) gesetzt. Dadurch entsteht ein farbenprächtiges Spektakel."
def theaterChaseRainbow(strip, wait_ms=50): """Rainbow movie theater light style chaser animation.""" for j in range(256): for q in range(3): for i in range(0, strip.numPixels(), 3): strip.setPixelColor(i + q, wheel((i + j) % 255)) strip.show() time.sleep(wait_ms / 1000.0) for i in range(0, strip.numPixels(), 3): strip.setPixelColor(i + q, 0)
Erklärung:
Der Wert für j gibt die Position im Farbrad(Funktion wheel) an. .
Funktion wheel:
♦Zwischen 0-85 wird Rot auf 255 erhöht und Grün sinkt auf 0. Blau bleibt unverändert.
♦Zwischen 85-170 sinkt Rot auf 0 und erhöht und blau steight auf 255. Grün bleibt unverändert.
♦Zwischen 170-255 steigt Grün auf 255 und blau sinkt auf 0. Rot bleibt unverändert.
Sobald die Iteration über das Farbrad den Wert 255 erreicht hat ist der Farbfade vorbei und die Animation zu Ende. Die zweite for loop setzt wie bei dem Programm theaterChase schaltet jeweils eine LED weiter. Die dritte erweitert dieses Muster auf die ganze LED Strip.
"Das Programm erstellt das Farbspektrum im Abstand zwischen zwei vollen Farben.Ein Rgenbogen ohne Regen. Sowas gibts nur auf LED Strips"
def rainbow(strip, wait_ms=20, iterations=1): """Draw rainbow that fades across all pixels at once.""" for j in range(256 * iterations): for i in range(strip.numPixels()): strip.setPixelColor(i, wheel((i + j) & 255)) strip.show() time.sleep(wait_ms / 1000.0)
Erklärung:
Der Regenbogen wird über das Farbrad (Funktion wheel erzeugt). Da der Regenbogen jedoch 10 mal angezeigt werden soll würden die Werte wheel(i+j) den Wert 255 überschreiten. Aus diesem Grund wird der Wert 255 mit einem logisch & verglichen. Dieser Vergleich setzt die binären Ziffern nur bei Übereinstimmung auf 1. Die Folge davon ist, das die Zahl 256 eine binäre 00000000 darstellt. So wiederholt sich das Farbrad wieder von vorne.
"Wie der Name sagt, pulsieren die LEDs auf dem Streifen. Pulsieren deshalb, da die Helligkeitswerte in jedem Pixel nach dem System einer Sinusfunktion sich verändern. Erstaunlich was?"
def pulsing_light(strip, wait_ms=50, iterations=10): """Helle LIchteffekte in Kette""" position = 0 for i in range(strip.numPixels() * 2): position = position+1 for j in range(strip.numPixels()): strip.setPixelColor(j,Color(round(((math.sin(j+position) * 127 + 128)/255)*255),round(((math.sin(j+position) * 127 + 128) /255)*100), round(((math.sin(j+position) * 127 + 128) /255)*100))) strip.show() time.sleep(wait_ms/1000.0)
Erklärung:
Die Farbwerte werden in der Sinus-Funktion generiert. Funktion: math.sin(j+position) * 127 + 128/255) *255
Der Wert der Sinuskurve liegt zwischen 0 und 1. Umso länger die LED Kette, desto höher wird der Wert (j+position) in der Klammer.
Gefolgt von der Sinusfunktion werden die Werte mit *127+128/255 multipliziert und addiert und zusätzlich durch 255 geteilt. Dese Zahlen verschieben einmal die Sinus-Funktion um +128 Punkte auf der y-Achse und stellen den Sinuswert in Korellation mit dem RGB Wert. (sprich: Welche Werteveränderung der Sinusfunktion , ändern den RGB Wert um 1 Punkt. Durch die Muliplikation von 255 wird der maximale RGB Wert (i.d.Fall 255)
(sprich: Der Hochpunkt der Sinusfunktion hat den RGB Wert 255)
"Schnelle helle Blitze wie aus einem Stroboskop. Das flasht richtig!"
def strobe(strip, wait_ms=400, strobe_count=7, pulse_count=12): from random import randrange """LED als springender Ball""" for strobe in range(strobe_count): for pulse in range(pulse_count): for i in range(strip.numPixels()): strip.setPixelColorRGB(i, 255,255,255) strip.show() time.sleep(randrange(0,45,1)/1000.0) for i in range(strip.numPixels()): strip.setPixelColorRGB(i, 0,0,0) strip.show() time.sleep(wait_ms/1000.0)
Erklärung:
In strobe_count wird die Häufigkeit der Blitze eingestellt. Die Variable pulse_count stellt die Wiederholung der Blitze ein. Die Zeit zwischen den Pulsen ist eine Zufallszahl zwischen 0 und 45 ms time.sleep(randrange(0,45,1).
"Aufleuchtender Schneesplitter auch mit Sonnenbrille sehbar. Ja der ist hell!"
def snow_sparkle(strip,sparkle_delay=20): from random import randint pixel= randint(0,strip.numPixels()) speed_delay=randint(100,1000) for i in range(strip.numPixels()): strip.setPixelColor(i, Color(0x10,0x10,0x10)) strip.show() time.sleep(speed_delay/1000.0) strip.setPixelColorRGB(pixel, 255,255,255) strip.show() time.sleep(sparkle_delay/1000.0)
Erklärung:
Eine Zufallspixel, sowie eine Zufallszeit zwischen 100ms und 1 s werden "ausgewürfelt". Die Ganze LED Strip leuchten leicht weiss mit den Werten(0x10,0x10,0x10) in RGB(16,16,16). Der Zufallspixel leuchtet in der Zufallszeit kurz auf und verschwindet wieder.
"Schleudernde LED Pixel nach physikalischen Gesetzen. Wie im Film!"
def bouncing_balls(strip,ball_count=4, wait_ms=200): start_time = time.time() ClockTimeSinceLastBounce = [0 for i in range(ball_count)] StartHeight=1 for i in range(ball_count): ClockTimeSinceLastBounce[i] = time.time() Height = [0 for i in range(ball_count)] Position = [0 for i in range(ball_count)] ImpactVelocity = [0 for i in range(ball_count)] ImpactVelocityStart= math.sqrt(-2 * -9.81 * 1) Dampening = [0 for i in range(ball_count)] TimeSinceLastBounce = [0 for i in range(ball_count)] for i in range(0,ball_count,1): last_ClockTimeSinceLastBounce = ClockTimeSinceLastBounce[i] ClockTimeSinceLastBounce[i] = time.time() - last_ClockTimeSinceLastBounce Height[i] = StartHeight Position[i] = 0 ImpactVelocity[i] = math.sqrt(-2 * -9.81 * 1) TimeSinceLastBounce[i] = 0 Dampening[i] = 0.90 - (float(i)/(ball_count**2)) while True: for i in range(ball_count): TimeSinceLastBounce[i] = time.time() - ClockTimeSinceLastBounce[i] Height[i] = 0.5 * (-9.81) * (TimeSinceLastBounce[i]**2) + ImpactVelocity[i] * TimeSinceLastBounce[i] if (Height[i] < 0): Height[i] = 0 ImpactVelocity[i] = Dampening[i] * ImpactVelocity[i] ClockTimeSinceLastBounce[i] = time.time() if (ImpactVelocity[i] < 0.01): ImpactVelocity[i] = ImpactVelocityStart Position[i] = round(Height[i] * (strip.numPixels()-1)/StartHeight) #Hier wird die relative Höhe auf die absolute Höhe mit der LED Anzahl umgewandelt. for i in range(ball_count): strip.setPixelColorRGB(Position[i], 0, 0,255) strip.show() for i in range(strip.numPixels()): strip.setPixelColorRGB(i, 0,0,0) def snow_sparkle(strip,sparkle_delay=20): from random import randint pixel= randint(0,strip.numPixels()) speed_delay=randint(100,1000) for i in range(strip.numPixels()): strip.setPixelColor(i, Color(0x10,0x10,0x10)) strip.show() time.sleep(speed_delay/1000.0) strip.setPixelColorRGB(pixel, 255,255,255) strip.show() time.sleep(sparkle_delay/1000.0)
Erklärung:
Es werden Listen erstellt, in denen die Werte(Height, ClockTimeSinceLastBounce, Position...) gespeichert sind. In der Endlosschleife werden die Pixel anhand den Werten die zu setzenden Pixel gerechnet...