Verwendung des FadeCandy von Adafruit für die LED-Steuerung

Übersicht

Bildquelle: Adafruit

Die Zusammenarbeit zwischen Adafruit und Micah von Scanlime führte zur Einführung von Fadecandy, einer Treiberkarte mit eingebautem Dithering, die über USB gesteuert werden kann. Fadecandy besteht sowohl aus Hardware als auch aus Software, die den Aufbau und die Steuerung von adressierbaren LED-Kunstprojekten mit den Modulen WS2811/WS2812 vereinfachen und so besser aussehende Projekte ermöglichen, die die Ressourcen des Mikrocontrollers weniger belasten. FadeCandy ist ein einfacher Einstieg für Anfänger, der aber auch als fortgeschrittenes Werkzeug für Profis funktioniert.

Die Fadecandy-Serversoftware kommuniziert mit einem Fadecandy-Board oder auch mit Dutzenden. Sie läuft auf Windows, Linux, Mac OS oder auf eingebetteten Plattformen wie dem Raspberry Pi. Das Protokoll „Open Pixel Control“ ist ein einfacher Weg, um Pixeldaten auf den Fadecandy-Server zu übertragen. Jedes Controller-Board unterstützt bis zu 512 LEDs, die in 8 Streifen zu je 64 LEDs angeordnet sind, aber keine RGBW-LEDs. Zum Zeitpunkt der Veröffentlichung wurden nur RGB-LEDs unterstützt. Die grundlegende Programmierung wird später in diesem Artikel behandelt.

Das vorliegende Projekt verwendet 52 NeoPixel von Adafruit in jeder der acht Spalten, die die Spieler zu einem Klauenmaschinen-Spiel locken und gleichzeitig als visuelle Countdown-Timer dienen sollen. Die Verwendung einer großen Anzahl adressierbarer LEDs und herkömmlicher Arduino-Bibliotheken mit direkter Verbindung zum GPIO verlangsamt den Prozessor und führt zu Verzögerungen in der Spielfunktion sowie zu Problemen bei der Ausführungszeit. Da ein Raspberry Pi 3 bereits für die Soundeffekte der Klauenmaschine vorgesehen ist, wird die Lichtkommunikation mit dem FadeCandy auf die Aufgabenliste des Pi 3 gesetzt.

Bestimmung des Strombedarfs

Ein wichtiger Aspekt bei der Verwendung von LED-Leisten ist der Stromverbrauch. Obwohl jede Farb-LED nur 20 Milliampere Strom verbraucht, hat zum Beispiel jedes Adafruit-NeoPixel drei Farben, die zusammen 60 Milliampere verbrauchen, wenn alle drei LEDs aktiv sind. Multipliziert man dies mit den 52 parallel verdrahteten NeoPixeln auf jedem Streifen, so ergibt sich eine maximale Stromstärke von mehr als 3 Ampere in jedem Streifen. Multipliziert man diese Stromstärke mit den 8 Spalten, ergibt sich eine potenzielle Stromaufnahme von 25 Ampere, ohne die verschiedenen kleineren Leisten, die um das Projekt herum angeordnet sind. Aber warum sollten bei einem Projekt alle LEDs in jedem NeoPixel über längere Zeiträume gleichzeitig leuchten? Die Antwort ist, dass das nicht der Fall ist, so dass die Auswahl eines Netzteils zu einem Ratespiel wird. Wenn man davon ausgeht, dass 75 % der NeoPixel zu einem bestimmten Zeitpunkt eingeschaltet sind und jedes nur eine Farbe anzeigt, sinkt der Strom auf etwa 6 Ampere. Nur wenn Sie ein Beleuchtungsszenario programmieren und die Stromaufnahme mit einem Messgerät prüfen, können Sie sicher sein.

Erwägen Sie eine Breakoutplatine, um Design- und Verdrahtungsprobleme zu lösen

Bevor mit der Programmierung begonnen werden kann, wird eine kundenspezifische Leiterplatte mit KiCad entworfen, um die FadeCandy-Anschlüsse auf praktische Klemmenblöcke aufzuteilen, die den Anschluss und die Organisation der Ausgänge erleichtern. Bei der Klauenmaschine befinden sich die nach hinten gerichteten LEDs auf einem Kanal, ebenso wie die nach rechts, links und vorne gerichteten LEDs, um Kanäle einzusparen. Die LEDs für die obere und die untere Preisrutsche sind getrennt, so dass zwei Kanäle für zusätzliche Anschlüsse zur Verfügung stehen.

Die Breakoutplatine muss Leiterbahnen enthalten, die die potenzielle Stromaufnahme des Strombusses bewältigen können. Die Wahl von 2 oz Kupfer für die Platine hilft auch bei der Verarbeitung größerer Strommengen. Ein Beispiel für eine mit KiCad und dem Tool PCB Builder von DigiKey erstellte Leiterplatte ist in den Abbildungen 1 und 2 dargestellt.

Abbildung 1: Unbestückte Leiterplatte vom Anbieter.

Abbildung 2: Hochstrom-Stromschienen.

Vorbereitung mit dem PCB-Builder-Tool

Sobald die Entwicklung abgeschlossen ist, wird eine benutzerdefinierte Leiterplatte mithilfe der Plot-Funktion im Menü Datei des Platinenentwurfswerkzeugs KiCad exportiert. Wählen Sie in der Dialogbox Plot die Schaltfläche Generate Drill File , um eine Gerber-Bohrdatei in einem Ordner Ihrer Wahl zu speichern. Wählen Sie dann die Schaltfläche Plot. KiCad erstellt zusätzliche Gerber-Dateien und legt sie im selben Ordner wie die Bohrdatei ab. Navigieren Sie mit dem Windows-Dateimanager zu dem Ordner, der die Gerber-Dateien enthält. Wählen Sie alle Dateien aus, die mit der Leiterplatte zusammenhängen; klicken Sie dann mit der rechten Maustaste auf den Dateiblock und wählen Sie An komprimierten (gezippten) Ordner senden. Ein neuer, gezippter Ordner wird im ursprünglichen Ordner angezeigt.

Digi-Keys webbasiertes PCB Builder Tool hilft bei der Bestellung kundenspezifischer Leiterplatten und ermöglicht eine breite Palette von Optionen und Anbietern. Sobald das PCB Builder Tool gestartet ist, wählen Sie die Schaltfläche Upload Gerber File; navigieren Sie dann zu dem zuvor erstellten gezippten Ordner und wählen Sie ihn aus. Es öffnet sich ein Fenster, das ein Bild der Leiterplatte und eine Liste der Dateien/Schichten zeigt, die in die Produktion einbezogen werden sollen (siehe Abbildung 3).

Abbildung 3: Betrachter des PCB Builders; Der erste Schritt zur Verwendung des PCB-Builder-Tools von DigiKey.

Der Betrachter des PCB Builder bietet viele Werkzeuge, um die vorgeschlagene Leiterplatte zu untersuchen. Wenn Sie mit dem Mauszeiger über das Bild der Leiterplatte fahren, wird das Bild vergrößert und verkleinert, und mit dem Handcursor können Sie die Leiterplatte in alle Richtungen bewegen. Ebenen können selektiv angezeigt werden, indem das augenförmige Symbol neben jeder Ebene in der Ebenenliste umgeschaltet wird.

Wählen Sie die Schaltfläche Hochladen beenden, um zum nächsten Bestellschritt zu gelangen. Das nächste Fenster zeigt die Statistiken für die Leiterplatte und eine Liste von Optionen, die Sie auswählen können, z. B. Farben und Kupferstärke (siehe Abbildung 4). Beachten Sie, dass sich durch die Auswahl die Preise und die Verfügbarkeit von Anbietern ändern, die die ausgewählten Optionen möglicherweise nicht anbieten. Beginnen Sie mit der Anzahl der Platinen und wählen Sie dann je nach Bedarf weitere Optionen aus.

Abbildung 4: Auswahl der Platinenspezifikationen, des Lieferanten und der Menge.

Wenn alle Optionen gewählt sind und der bevorzugte Lieferant feststeht, erhöhen Sie die Platinenanzahl um 1 und beobachten Sie den Preis. Wiederholen Sie diesen Schritt, bis der Preis steigt. Mit dieser Methode wird die maximale Anzahl von Platinen ermittelt, die zum niedrigsten Preis produziert werden können. Wählen Sie die Schaltfläche In den Warenkorb, wenn Sie bestellen möchten.

Montieren Sie die Breakoutplatine

Die fertige Platine ist mit Klemmenblöcken für LED-Leisten, Klemmenblöcken für die Stromversorgung und einer 16-poligen Steckleiste bestückt. Das FadeCandy-Board von Adafruit wird mit Stiften bestückt und zusammen mit einem 3D-gedruckten Abstandshalter, der das USB-Ende der Platine unterstützt, in die Steckleiste auf der Platine eingesetzt. Siehe Abbildung 5.

Abbildung 5: Vollständig bestückte Breakoutplatine.

Um das Board zu implementieren und mit der Programmierung zu beginnen, wird ein Testfeld aus 8 Spalten mit 26 Adafruit-Neopixeln verwendet, um das Konzept zu demonstrieren, das später auf 52 Neopixeln in der eigentlichen Klauenmaschine erweitert wird.

Schließen Sie die LED-Leisten an die grünen Klemmenblöcke an und achten Sie dabei auf die richtigen Strom- und Signalanschlüsse. Eine 5V-Stromquelle wird an die schwarzen Klemmenblöcke angeschlossen, wobei die richtigen Strom- und Erdungsanschlüsse zu beachten sind. Abbildung 6 zeigt die NeoPixel-Verdrahtung vor der Verwendung der Breakoutplatine und Abbildung 7 zeigt die Verbesserungen bei der Verdrahtung.

Abbildung 6: Verdrahtung des Testfelds vor der Verwendung eines Breakout-Boards.

Abbildung 7: Testfeld mit Breakout-Organisation.

Wenn die Hardware und die Verkabelung an Ort und Stelle sind, schließen Sie einen Raspberry Pi 3 mit dem richtigen USB-Kabel an den FadeCandy an; verbinden Sie dann den Raspberry Pi mit einem Monitor, einer Tastatur und einer Maus. Schalten Sie das System ein, um mit der Programmierung zu beginnen. Der FadeCandy wird als Client eingerichtet, der Daten über USB vom Pi empfängt, der als Server fungiert. In dieser Konfiguration kommuniziert der Pi auch mit einem Arduino Mega über eine serielle Verbindung über USB. Der Mega verarbeitet alle Ein- und Ausgaben des Spielautomaten und teilt dem Pi lediglich mit, ob das Spiel läuft. Der Pi sorgt für die Ton- und Lichteffekte.

Es gibt eine breite Palette von Funktionen und Anwendungen für das FadeCandy. Viele einfache und komplexe Beispiele sind im Internet zu finden, und es kommen regelmäßig weitere hinzu. Der folgende Code stellt eine sehr grundlegende Multi-Thread-Funktionalität für die spezifischen Bedürfnisse der Beleuchtung für dieses Projekt dar. Der Pi ist so programmiert, dass er die Neopixels mit einer Grundfarbe flutet und dann zufällige Lichtblitze hinzufügt, um das Feld zu akzentuieren. Wenn das Spiel gespielt wird, werden zwei der Streifen in eine visuelle Countdown-Uhr umgewandelt. Siehe Video 1 als Referenz. Der für dieses Projekt verwendete Code ist unten aufgeführt (Listing 1).

Kopieren#Raspberry Pi Game Machine Script
import serial
import threading
import queue
import random
import opc, time
import pygame

#Initialize the sound mixer
pygame.mixer.init(44100, 16, 2)

#Create a game start sound effect object
Start_Sound = pygame.mixer.Sound("glass.wav")
Start_Sound.set_volume(1.0)
Start_Sound.play()

#Create a tick-tock sound object
Tick_Sound = pygame.mixer.Sound("ticktock.wav")
Tick_Sound.set_volume(1.0)
#Tick_Sound.play(maxtime=600)

#Create an end of game sound object
End_Sound = pygame.mixer.Sound("Buzzer-sound-16.wav")
End_Sound.set_volume(1.0)
#End_Sound.play()

#Build queue objects for transfer between threads
game_q = queue.Queue(1)
users_q = queue.Queue(1)
matrix_q = queue.Queue(1)

#State the NeoPixel array for the testbed
numLEDs = 8*26
pixels = [ (0,0,0) ] * numLEDs

#Set FadeCandy meter start pixel
meterStartPix = 130

#Create a serial communication object for the Mega
serMega = serial.Serial('/dev/ttyACM0', 115200)

#Create a client object for the Open Pixel server
client = opc.Client('localhost:7890')

#Define a function for the t1 thread that reads data from the Mega
def MegaData():
        while True:
                if serMega.inWaiting() > 0:
                        GameDuration = int(serMega.readline())
                        PlayFlag = int(serMega.readline())
                        game_q.put((GameDuration, PlayFlag))
                        TotalUsers = int(serMega.readline())
                        if not users_q.full():
                                users_q.put(TotalUsers)
                                
                time.sleep(0.001)
                        
#Define a function for the t2 thread which runs the time meter Neopixels                            
def RunMeter():

        while True:
                GameDuration, PlayFlag = game_q.get()
                matrix_q.put(PlayFlag)
                SleepNum = (float(GameDuration)/100/27)
              
                if PlayFlag == 1:
                        #Quickly fill the meter with green
                        meterPix = meterStartPix
                        Start_Sound.play()
                        for i in range(0, 26):
                                pixels[meterPix] = (0, 200, 0)
                                client.put_pixels(pixels)
                                time.sleep(.02)
                                meterPix = meterPix+1
                                
                        #Fill the meter with red based on game timer
                        meterPix = meterStartPix + 25       
                        for i in range(0, 26):
                                if not game_q.empty():
                                        GameDuration, PlayFlag = game_q.get()
                                if PlayFlag == 1:
                                        pixels[meterPix] = (200, 0, 0)
                                        Tick_Sound.play(maxtime=600)
                                        client.put_pixels(pixels)
                                        time.sleep(SleepNum)
                                        meterPix = meterPix-1
                                else:
                                        break
                                
                        #Wait a tad bit
                        time.sleep(.50)
                        End_Sound.play()
                        time.sleep(.50)
                        
                        #Quickly Clear the meter with soft white
                        meterPix  = meterStartPix
                        for i in range(0, 26):

                                pixels[meterPix] = (30, 30, 30)
                                client.put_pixels(pixels)
                                time.sleep(.01)
                                meterPix = meterPix+1
                                                                
                        time.sleep(2)
                else:
                        
                        #Quickly Clear the meter with soft white
                        meterPix = meterStartPix
                        
                        for i in range(0, 26):

                                pixels[meterPix] = (30, 30, 30)
                                client.put_pixels(pixels)
                                time.sleep(.01)
                                meterPix = meterPix+1
                                
                        time.sleep(2) 
                time.sleep(0.001)
                
#Define a function for the t3 thread that controls the non-meter Neopixels               
def RunMatrix():
       
        numLEDs = 6*26
      
        while True:
                if not matrix_q.empty():
                        play_flag = matrix_q.get()
                        if play_flag == 1:
                                numLEDs = 5*26
                        else:
                                numLEDs = 6*26   

                r = random.randint(25,85)
                g = random.randint(25,85)
                b = random.randint(25,85)
                Bright = 3 
                DotNum = 10 
                              
                for j in range(5):
                        for h in range(10):
                                pixels = [ (r, g, b) ] * numLEDs

                                for g in range(DotNum):
                                        p = random.randint(0,numLEDs-1)
                                        pixels[p] = (r*Bright, g*Bright, b*Bright)
                                
                                client.put_pixels(pixels)
                                
                                if not matrix_q.empty():
                                        play_flag = matrix_q.get()
                                        if play_flag == 1:
                                                numLEDs = 5*26
                                        else:
                                                numLEDs = 6*26 
                                time.sleep(.1)

#Create thread objects                                
t1 = threading.Thread(target = MegaData)
t2 = threading.Thread(target = RunMeter)
t3 = threading.Thread(target = RunMatrix)
t1.start()
t2.start()
t3.start()

Listing 1: Code für die Steuerung der LEDs des Klauenmaschinenprojekts.

Zusammenfassung

Die Arbeit mit adressierbaren LEDs ist eine befriedigende, aber anspruchsvolle Aufgabe. Oft kann der für den perfekten visuellen Effekt erforderliche Code andere Funktionen des Mikrocontrollers beeinträchtigen. Das FadeCandy-Board sowie andere Arten von dedizierten LED-Treibern werden verwendet, um solche Probleme zu lindern und die Tür zu einer endlosen Reihe von Beleuchtungsszenarien zu öffnen. Zusammen mit dem richtigen Treiber sind maßgefertigte Leiterplatten eine hervorragende Möglichkeit, Ein- und Ausgänge zu organisieren und die Stromversorgung zu verteilen.

Über den Autor

Image of Don Johanneck

Don Johanneck, Technical Content Developer bei DigiKey, arbeitet seit 2014 für das Unternehmen. Seit dem Wechsel in seine aktuelle Position ist er für das Verfassen von Beschreibungen zu Videos und Produkten verantwortlich. Er hat seinen Abschluss als Associate of Applied Science im Bereich Elektronik und automatisierte Systeme vom Northland Community & Technical College im Rahmen des DigiKey-Stipendienprogramms erworben. Er genießt die Modellierung von Funksteuerungen, die Restaurierung von alten Maschinen und das Basteln.

More posts by Don Johanneck
 TechForum

Have questions or comments? Continue the conversation on TechForum, Digi-Key's online community and technical resource.

Visit TechForum