Come utilizzare FadeCandy di Adafruit per il controllo dei LED
Panoramica
Immagine per gentile concessione di Adafruit
La collaborazione tra Adafruit e Micah di Scanlime ha portato all'introduzione di FadeCandy, una scheda driver con dithering integrato che può essere controllata tramite USB. FadeCandy comprende sia l'hardware che il software che rendono i progetti basati su LED indirizzabili WS2811/WS2812 più facili da realizzare e controllare, ottenendo così progetti migliori nell'aspetto e meno impegnativi per le risorse del microcontroller. FadeCandy aiuta i principianti a muovere i primi passi ed è allo stesso tempo uno strumento avanzato per i professionisti.
Il software FadeCandy Server è in grado di comunicare con una sola scheda FadeCandy ma anche con decine di schede. Funziona su Windows, Linux, Mac OS o su piattaforme embedded come Raspberry Pi. Il protocollo Open Pixel Control è un modo semplice per trasferire i dati pixel al server FadeCandy. Ogni controller supporta fino a 512 LED, su 8 stringhe di 64 LED ciascuna, ma non supporta i LED RGBW. Al momento della pubblicazione sono supportati solo i LED RGB. Più avanti in questo articolo verrà trattata la programmazione di base.
Il progetto in questione utilizza 52 NeoPixel Adafruit in ciascuna delle otto colonne destinate a intrattenere i giocatori in una macchina acchiappa-premi (la pesca di premi con la gru), ma servono anche come timer visivo per il conto alla rovescia. L'utilizzo di un alto numero di LED indirizzabili e delle librerie Arduino tradizionali con connessione diretta a GPIO rallenta il processore e provoca ritardi nella funzione di gioco così come problemi di tempistica di esecuzione. Poiché un Raspberry Pi 3 è già previsto per gli effetti sonori della macchina, la comunicazione luminosa con FadeCandy sarà aggiunta all'elenco delle attività Pi 3.
Determinare i requisiti di potenza
Quando si usano le stringhe di LED, il consumo energetico è un fattore da tenere in considerazione. Anche se ogni LED di colore richiede solo 20 milliampere di corrente, ogni NeoPixel di Adafruit con tre colori totalizza 60 milliampere quando tutti e tre i LED sono attivi. Moltiplicando questo valore per i 52 NeoPixel cablati in parallelo su ogni stringa, otteniamo una corrente massima per ciascuna superiore a 3 ampere. Questa corrente moltiplicata per 8 colonne risulta in 25 ampere, senza includere le varie stringhe più piccole disposte intorno al progetto. Ma perché un progetto dovrebbe avere tutti i LED di ogni NeoPixel accesi allo stesso tempo per lunghi periodi? In effetti non sarà così, di conseguenza la scelta di un alimentatore diventa un indovinello. Supponendo che il 75% dei NeoPixel siano accesi in qualsiasi momento e che ognuno mostri un solo colore, la corrente scende a circa 6 ampere. Programmare uno scenario di illuminazione e testare l'assorbimento di corrente con un amperometro è l'unico modo per avere certezze.
Una PCB di breakout può risolvere i problemi di progettazione e di cablaggio
Prima di iniziare la programmazione, si progetta una PCB personalizzata tramite KiCad in modo da suddividere le connessioni di FadeCandy in comode morsettiere che permetteranno una più facile organizzazione delle connessioni e delle uscite. Per la macchina acchiappa-premi, i LED rivolti indietro sono su un canale, così come quelli rivolti a destra, a sinistra e in avanti, per risparmiare canali. I LED dello scivolo superiori e inferiori sono separati, lasciando due canali per eventuali connessioni ausiliarie.
La PCB di breakout deve incorporare tracce in grado di gestire l'assorbimento di corrente potenziale del bus di alimentazione. Anche la scelta del rame per la scheda aiuta a gestire elevati valori di corrente. Un esempio di PCB creata con KiCad e lo strumento PCB Builder di DigiKey è illustrato nelle Figure 1 e 2.
Figura 1: PCB nuda così come acquistata.
Figura 2. Tracce del bus di alimentazione a corrente elevata.
Preparazione dello strumento PCB Builder
Una volta completamente sviluppata, una PCB personalizzata viene esportata con la funzione Plot del menu File dello strumento di progettazione di PCB in KiCad. Nella finestra di dialogo Plot, selezionare il pulsante Generate Drill File per salvare un file drill Gerber in una cartella preferita. Quindi, selezionare il pulsante Plot. KiCad creerà altri file Gerber e li metterà nella stessa cartella del file drill. Usando Esplora risorse di Windows, andare alla cartella che contiene i file Gerber. Selezionare tutti i file relativi alla PCB, poi fare clic destro sul blocco di file e selezionare Invia a... Cartella compressa. Nella cartella originale verrà creata una nuova cartella compressa (zip).
Lo strumento PCB Builder di DigiKey, basato sul Web, aiuta a ordinare PCB personalizzate, fornendo un'ampia gamma di opzioni e fornitori. Dopo aver aperto lo strumento PCB Builder, selezionare il pulsante Upload Gerber File, quindi cercare e selezionare la cartella compressa appena creata per caricare i file Gerber. Si apre una finestra PCB Tool Viewer che mostra un'immagine della scheda e una lista dei file/strati da includere nella costruzione (Figura 3).
Figura 3. PCB Builder Viewer: il primo passo per l'utilizzo dello strumento PCB Builder di DigiKey.
PCB Builder Viewer offre molti strumenti per esaminare la PCB proposta. Quando il mouse passa sull'immagine della PCB fa da lente di ingrandimento; il cursore a forma di mano permette di spostare la PCB in tutte le direzioni. Gli strati possono essere visualizzati selettivamente attivando l'icona a forma di occhio accanto a ciascuno in elenco.
Selezionare il pulsante Finish Upload per passare alla fase successiva dell'ordine. La finestra successiva mostra le statistiche per la PCB e un elenco di opzioni selezionabili, come i colori e lo spessore del rame (Figura 4). Le varie selezioni modificano i prezzi e la disponibilità dei fornitori che potrebbero anche non avere a disposizione le opzioni selezionate. Iniziare con una quantità pari a una scheda, quindi effettuare altre selezioni secondo le necessità.
Figura 4. Scelta delle specifiche, del fornitore e della quantità di PCB.
Ultimate tutte le selezioni e dopo aver scelto il fornitore, aumentare la quantità di schede di un'unità alla volta osservando il prezzo. Ripetere questo passaggio finché il prezzo non si stabilizza. Questo metodo permette di stabilire il numero massimo di schede che può essere prodotto al prezzo più basso. Quando si è pronti, selezionare il pulsante Aggiungi al carrello.
Assemblaggio della PCB di breakout personalizzata
La PCB completata è popolata con le morsettiere per stringhe di LED, le morsettiere di alimentazione e una basetta a 16 pin. La scheda FadeCandy di Adafruit è popolata con i pin della basetta e inserita nella basetta della PCB assieme a un distanziale stampato in 3D per supportare il terminale USB della scheda. Vedere la Figura 5.
Figura 5. Scheda di breakout completamente popolata.
Per implementare la scheda e iniziare la programmazione, viene utilizzato un banco di prova composto da 8 colonne di 26 NeoPixel di Adafruit per dimostrare il concetto. In seguito viene aggiornato a 52 NeoPixel nella macchina a chele reale.
Collegare le stringhe di LED alle morsettiere verdi facendo attenzione alle connessioni di alimentazione e di segnale appropriate. Una fonte di alimentazione a 5 V va collegata alle morsettiere nere facendo attenzione alle connessioni di alimentazione e di terra appropriate. La Figura 6 mostra il cablaggio dei NeoPixel prima di usare la scheda di breakout, mentre la Figura 7 mostra i miglioramenti nel cablaggio.
Figura 6. Cablaggio del banco di prova prima di usare una scheda di breakout.
Figura 7. Banco di prova organizzato con scheda di breakout.
Con l'hardware e il cablaggio a posto, collegare un Raspberry Pi 3 a FadeCandy usando l'apposito cavo USB, quindi collegare il Raspberry Pi a un monitor, una tastiera e un mouse. Accendere il sistema per iniziare la programmazione. FadeCandy è impostata come client che riceve dati via USB dal Pi che funge da server. In questa configurazione, il Pi comunica anche con un Arduino Mega tramite connessione seriale su USB. Il Mega gestisce tutti gli ingressi e le uscite della macchina e indica semplicemente al Pi se il gioco è in corso. Il Pi gestisce gli effetti di luci e suoni.
Sono disponibili numerose funzionalità e applicazioni per FadeCandy. Molti esempi dai più semplici a quelli più complessi sono reperibili online; molti altri vengono aggiunti frequentemente. Il codice seguente rappresenta alcune funzionalità multi-thread molto basilari per le necessità di illuminazione specifiche per questo progetto. Il Pi è programmato per attivare i NeoPixel con un colore di base e poi aggiungere lampi di luce casuali per evidenziare il campo di gioco. Durante il gioco, due delle stringhe vengono convertite in un orologio visivo per il conto alla rovescia. Vedere il video 1 come riferimento. Il codice usato per questo progetto è incluso di seguito (Listato 1).
Copy#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()
Listato 1. Codice usato per controllare i LED sul progetto della macchina acchiappa-premi.
Riepilogo
Usare LED indirizzabili è un lavoro che dà soddisfazioni, ma impegnativo. Spesso il codice necessario per un buon effetto visivo può interferire con altre operazioni del microcontroller. La scheda FadeCandy, così come altri tipi di driver LED dedicati, è utilizzata per alleggerire queste problematiche e per disporre di scenari luminosi praticamente infiniti. Insieme al giusto driver, le PCB personalizzate sono un ottimo modo per organizzare ingressi e uscite e distribuire l'alimentazione.

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.
Visit TechForum