Questo nuovo articolo su Arduino e i LED intelligenti WS2812 si sofferma ancora sul colore, mentre inizieremo a creare semplici animazioni e pattern animati.
Articoli precedenti:
- LED WS2812 per Arduino – Cosa sono e come si usano
- LED WS2812 – Attività di configurazone con Arduino
- LED WS2812 e Arduino – Ora giochiamo con i colori
Abbiamo imparato a creare e gestire i colori utilizzndo le striscie LED WS2812, ma la tecnica rimane fredda e indigesta senza esempi ed un pizzico d’arte.
Per questa ragione nell’articolo di oggi partiremo dallo schema di configurazione classico per il nostro sistema di visualizzazione e presenteremo numerosi esempi di utilizzo, ciascuno corredato dal proprio originale codice sorgente. Come sempre in fondo all’articolo troverete il link per accedere alla raccolta di programmi che analizzeremo quest’oggi.
Iniziamo subito!
Come “muovere” il colore
Il programma #07 aggiunge la variabile hue (un intero senza segno a 8 bit) e la azzera. Nel loop assegna a ciascun LED della catena il valore iniziale (pari a zero), ma anziché lavorare in RGB lavorerà in HSV: ciascuno dei LED della striscia verrà inizializzato con un valore CHSV composto dai componenti di tinta, saturazione e valore (vedere l’articolo precedente per una trattazione dell’argomento). L’assegnazione del colore determina il valore contenuto nella variabile hue (inizialmente zero) con i valori massimi per saturazione e luminanza. Successivamente viene utilizzata la macro EVERY_N_MILLISECONDS(n) per eseguire il codice ogni n millisecondi utilizzando un timer non bloccante predefinito nella libreria FastLED. Il codice si limita a sommare 1 al valore di tinta (hue). Trattandosi di una variabile byte, giunta al valore 255 tornerà a zero, chiudendo il cerchio delle variazioni dei colori.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
// Programma 07 - hue_change #include <FastLED.h> #define NUM_LEDS 14 #define LED_PIN 6 #define MAX 255 CRGB leds[NUM_LEDS]; uint8_t hue = 0; void setup() { FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS); FastLED.setBrightness(40); // up to 255 } void loop() { for (int i = 0; i < NUM_LEDS; i++) { // Modificando il valore di MAX si modifica la saturazione e la luminosità del colore // (vedi puntata precedente) leds[i] = CHSV(hue, MAX, MAX); } // Nell'esempio, il valore della tinta viene cambiato ogni 40 millisecondi // Consente di gestire la velocità nella transizione del colore EVERY_N_MILLISECONDS(40) { // la variabile hue è di tipo unsigned integer 8 bit, // quindi quando supera il valore di 255 torna a zero hue++; } FastLED.show(); } |
Inseguendo l’arcobaleno
Abbiamo ora a disposizione tutte le nozioni necesssarie per creare una animazione di colore con un arcobaleno che si muove lungo la striscia LED. Partiamo dal programma precedente, modificando riga 22.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
// Programma 08 - hue_rainbow #include <FastLED.h> #define NUM_LEDS 14 #define LED_PIN 6 #define MAX 255 CRGB leds[NUM_LEDS]; uint8_t hue = 0; void setup() { FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS); FastLED.setBrightness(40); // up to 255 } void loop() { for (int i = 0; i < NUM_LEDS; i++) { // Modificando il valore di MAX si modifica la saturazione e la luminosità del colore // (vedi puntata precedente) leds[i] = CHSV(hue + (i * 10), MAX, MAX); } // Nell'esempio, il valore della tinta viene cambiato ogni 40 millisecondi // Consente di gestire la velocità nella transizione del colore EVERY_N_MILLISECONDS(40) { // la variabile hue è di tipo unsigned integer 8 bit, // quindi quando supera il valore di 255 torna a zero hue++; } FastLED.show(); } |
Ciascuno dei LED della nostra striscia mostrerà un valore di colore leggermente spostato rispetto al precedente, quindi avremo un colore che passerà attraverso le sfumature dell’arcobaleno sia sull’intera striscia che su ciascuno dei relatvi LED, simulandone così il movimento.
Tutte le sfumature del blu
Continuiamo i nostri esperimenti sulle variabili che gestiscono il colore.
Nel programma seguente definiamo una tinta predefinita (160, il blu), ma modifichiamo i valori di saturazione e luminanza in modo random.
La libreria FastLED dispone di funzioni random specifiche, da utilizzarsi in tutta sicurezza senza dover caricare e configurare generatori esterni. Nello specifico, poniamo la saturazione ad un valore compreso tra 0 e 255, e la luminanza ad un valore che varia tra 100 e 255. Non mettiamo l’ultimo elemento a zero per evitare di avere LED “spenti” nel nostro nuovo pattern.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// Programma 09 - hue_random_blue #include <FastLED.h> #define NUM_LEDS 14 #define LED_PIN 6 CRGB leds[NUM_LEDS]; uint8_t hue = 0; void setup() { FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS); FastLED.setBrightness(40); // up to 255 } void loop() { EVERY_N_MILLISECONDS(48) { // Creiamo un pixel per il led in posizione 0 leds[0] = CHSV(160, random8(), random8(100, 255)); // copiamo il led appena creato all'estremità opposta, // simulando un movimento sulla striscia for (int i = NUM_LEDS - 1; i > 0; i--) { leds[i] = leds[i - 1]; } } FastLED.show(); } |
Per il resto, impostiamo un intervallo di tempo (nello specifico 48 millisecondi), definiamo il colore del LED in posizione zero, e attraverso un ciclo for() impostiamo tutti gli altri allo stesso valore, ma a partire dall’ultimo. L’effetto finale sarà dato da una sorta di luce psico-stroboscopica, ma dalle variazioni tanto più addolcite quanto maggiore risulterà l’intervallo di tempo tra un cambio di parametri e l’altro.
Gestire la luminosità
Sinora abbiamo tenuto la luminosità specifica dell’intera striscia ad un valore prefissato attraverso il metodo setBrightness().
Ma possiamo gestire la luminosità della striscia in altri modi, ad esempio con un potenziometro (dimmer). Analizziamo assieme il circuito:
Aggiungiamo al nostro circuito un potenziometro da 10 kΩ, in cui i reofori esterni siano collegati al positivo ed alla massa, mentre il connettore centrale (in arancio nell’immagine) sarà collegato al pin A1 di Arduino. Come sappiamo, questo collegamento consente di inviare al pin analogico A1 un valore “quantizzato” in 1024 (210) passi. Ciascun valore rappresenta un milleventiquattresimo della tensione tra ground ed i 5V di alimentazione. In questo modo, ruotando il potenziometro forniremo ad Arduino un valore compreso tra 0 e 1023.
Definiamo la costante PIN_POT pari ad A1 nel nostro sketch e commentiamo la riga 15 del codice.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
// Programma 10 - Controllo luminosità #include <FastLED.h> #define NUM_LEDS 14 #define LED_PIN 6 #define PIN_POT A1 CRGB leds[NUM_LEDS]; uint8_t hue = 0; void setup() { FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS); // FastLED.setBrightness(40); // up to 255 } void loop() { uint16_t Pot_value = analogRead(PIN_POT); uint8_t luminosita = map(Pot_value, 0, 1023, 0, 200); FastLED.setBrightness(luminosita); EVERY_N_MILLISECONDS(48) { // Creiamo un pixel per il led in posizione 0 leds[0] = CHSV(160, random8(), random8(100, 255)); // copiamo il led appena creato all'estremità opposta, // simulando un movimento sulla striscia for (int i = NUM_LEDS - 1; i > 0; i--) { leds[i] = leds[i - 1]; } } FastLED.show(); } |
La riga 20 dichiara una variabile a 16 bit (Pot_value) che conterrà il valore analogico letto attraverso il potenziometro.
La riga 21 dichiara una variabile a 8 bit (luminosità) ottenuta traducendo (mappando) il valore del potenziometro da un campo di valori pari a [0, 1023] ad un campo pari a [0, 255] (la funzione map non fa altro che implementare una proporzione).
Alla riga 22, infine, inseriamo il valore di luminosità, così ottenuto ruotando il potenziometro, all’interno del metodo setBrightness().
Il resto del programma è identico al precedente: avremo i LED che variano in saturazione in modo random, ma potremo definire attraverso il potenziometro il livello luminoso generale della striscia.
I più attenti tra i lettori avranno intuito la possibilità di utilizzare un potenziometro software per variare le sfumature (hue) di colore di conseguenza, oltre alla luminosità… Ce ne occuperemo nella prossima puntata!
Riflessioni
Nella puntata di oggi abbiamo approfondito le funzioni avanzate della libreria FastLED con le striscie WS2812, relative ai colori. Abbiamo visto come per creare animazioni sulle striscie sia sufficiente “muovere” il colore dei pixel sulla striscia, e abbiamo imparato a gestire i parametri e la luminosità dei LED. Nella prossima puntata prenderemo in esame i pattern specifici di colore, e vedremo come presentare gruppi di colori assortiti creando un effetto di modifica automatica della tinta.
Troverete i file sorgente con gli esempi proposti su GitHub come al solito.
A risentirci tra sette giorni!
Link utili
- Arduino uno
- Arduino nano
- Elegoo starter kit
- Striscia LED WS2812 (5m 30 LED/m)
- Striscia LED WS2812 (1m 144 LED/m)