In questo nuovo articolo apprenderemo ad usare le funzioni dei LED WS2812 per gestire una palette di colori a nostra scelta tramite Arduino.
Abbiamo parlato di LED intelligenti WS2812B, di colore, di indirizzamento del singolo LED e della creazione di animazioni dinamiche del colore.
Oggi impareremo come creare una tavolozza di colori specifica per ogni stagione, o se preferite per ogni stato d’animo. Parte delle funzioni le abbiamo già viste negli articoli precedenti, quindi stavolta ci limiteremo a commentare i nostri file sorgente… e magari a provarli per conto nostro.
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
- LED WS2812 e Arduino – Altre animazioni sui colori
Cos’è mai una tavolozza?
Una tavolozza (palette, in inglese) non è altro che una tabella di lookup, che trasforma un numero di 8 bit (tra 0 e 255) in un colore RGB. Esistono principalmente due tipi di tavolozze, quelle a 16 colori e quelle a gradiente di 256 colori. Inutile dire che queste ultime sono quelle che offrono gli effetti più spettacolari.
Possiamo definire una palette attraverso il codice riportato di seguito. Dal momento che si tratta di una funzione di conversione, non dovremo occupare alcun byte della nostra preziosa memoria su Arduino per tener traccia dei colori: il valore del numero calcolerà automaticamente la sua posizione nella scala dei gradienti (o sfumature) definite dalla funzione.
1 2 3 4 5 6 |
DEFINE_GRADIENT_PALETTE ( heatmap_gp ) { 0, 0, 0, 0, // nero 128, 255, 0, 0, // rosso 200, 255, 255, 0, // giallo acceso 255, 255, 255, 255 // bianco } |
Nel listato precedente, osserviamo quattro righe di quattro valori ciascuna. Gli ultimi tre numeri corrispondono ai codici RGB del colore della palette, il primo di ciascuna riga rappresenta la posizione all’interno della tavolozza. il risultato di questa palette è il seguente:
La prima colonna corisponde alla posizione d ciascun triangolo, mentre i valori successivi rappresentano il colore relativo. La funzione creerà le sfumature necessarie per realizzare una transizione morbida.
Una volta definita la tavolozza possiamo passare alla scrittura del nostro codice sorgente. Utilizzeremo nel caso specifico un paio di nuovi comandi.
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 11 - Tavolozza #include <FastLED.h> #define NUM_LEDS 14 #define LED_PIN 6 CRGB leds[NUM_LEDS]; uint8_t paletteIndex = 0; DEFINE_GRADIENT_PALETTE ( heatmap_gp ) { 0, 0, 0, 0, // nero 128, 255, 0, 0, // rosso 200, 255, 255, 0, // giallo acceso 255, 255, 255, 255 // bianco }; CRGBPalette16 myPal = heatmap_gp; void setup() { FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS); FastLED.setBrightness(40); // up to 255 } void loop() { fill_palette(leds, NUM_LEDS, paletteIndex, 255 / NUM_LEDS, myPal, 255, LINEARBLEND); FastLED.show(); } |
La definizione a riga 10 indica il nostro indice iniziale all’interno della tavolozza (0, quindi nero).
A riga 19 istanziamo la nostra tavolozza secondo la definizione vista prima.
Il setup è identico ai precedenti, mentre all’interno del loop incontriamo di nuovo una funzione vista in precedenza; ora, però, disponiamo di tutte le informazioni per poterla utilizzare.
La funzione fill_palette() prende come parametri il nostro array leds[] composto da NUM_LEDS elementi, definisce l’inizio della palette (su zero) e determina la “sfumatura” dei colori, originariamente tra 0 e 255, lungo la striscia LED (255 / NUM_LEDS rappresenta la mappa del colore del LED i nella posizione definita all’interno della tavolozza).
Gli ultimi due parametri rappresentano la brllantezza del colore e il tipo di sfumatura richiesta (LINEARBLEND è lineare, mentre NOBLEND è “a quadrotti” di colore).
L’effetto finale è decisamente simile alla tavolozza che avevamo creato…
Blending and movement
Ora che abbiamo creato la nostra tavolozza preferita, mettiamo a frutto le idee apprese negli articoli precedenti, e facciamo “camminare” i colori: utilizziamo la macro EVERY_N_MILLISECONDS() posizionando il seguente codice a riga 28:
1 2 3 |
EVERY_N_MILLISECONDS(15) { paletteIndex++; } |
Il comando farà ciclare il punto di inizio della tavolozza (il nero) lungo l’intera striscia LED; creando un gradevole effetto. aumentando il valore del parametro in millisecondi, avremo un movimento che da frenetico diverrà via via veloce, classico, pensoso, imponente, uggioso…
Tavolozze predefinite
La libreria FastLED ci consente di definire una tavolozza anche utilizzando 16 valori fissi predeterminati: rappresenta l’ideale quando si desideri una tavolozza con valori di colore fissi.
Anzichè utilizzare la macro DEFINE_GRADIENT_PALETTE (), creeremo a nostra palette a mano. Commentiamo le righe dalla 12 alla 19 comprese, e aggiungiamo questo codice:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
CRGBPalette16 purplePalette = CRGBPalette16 ( CRGB::DarkViolet, CRGB::DarkViolet, CRGB::DarkViolet, CRGB::DarkViolet, CRGB::Magenta, CRGB::Magenta, CRGB::Linen, CRGB::Linen, CRGB::Magenta, CRGB::Magenta, CRGB::DarkViolet, CRGB::DarkViolet, CRGB::DarkViolet, CRGB::DarkViolet, CRGB::Linen, CRGB::Linen ); |
Abbiamo creato una tavolozza con 16 “punti fermi” pari ai colori predefiniti che ci offre la libreria. Lasceremo alla libreria l’eseguire lo “smoothing” dei colori. Questo sarà l’effetto finale.
…ovviamente animato.
Creiamo la nostra palette!
Creare una palette è più semplice di quanto si creda… basta conoscere i giusti riferimenti! Nel nostro caso, utilizzeremo due siti web utili ad indicare i valori ideali per le nostre palettes.
Il sito cpt-city dispoe di una quantità impressionante di tavolozze già pronte: dalle mappe di calore a quelle di altitudine-profondità del terreno. Quello che segue è solo uno delle migliaia di esempi presenti:
Una volta scelta la palette, possiamo estrarre i valori nel formato prescelto, acquisendo i valori di indice ed i valori RGB) o dirigerci sul sito di PaletteKnife.
E se proprio non vogliamo spremerci le meningi per tradurre quella sfilza di numeri, possiamo accedere al sito cssgradient.io,, dove sarà possibile crearci i nostri valori attraverso un sistema GUI user-friendly.
Nell’esempio riportato, ho creato una sorta di tavolozza che rappresenti il lato di un pianeta illuminato da destra dal sole, con il cielo nero sullo sfondo. Ho impostato i punti iniziale e finale sullo stesso valore (il nero) in modo che la tavolozza possa “ciclare”, più altri tre punti. Dal momento che in questo esempio i valori sono indicizzati da 0 a 100, dovremo calcolare le relative posizioni moltiplicandole per 2,55, come nel listato che segue.
1 2 3 4 5 6 7 |
DEFINE_GRADIENT_PALETTE ( heatmap_gp ) { 0, 0, 0, 0, // nero 127, 240, 157, 44, // arancio-marrone (127 = 50 * 2,55) 196, 224, 240, 44, // giallo acceso (196 = 77 * 2,55) 240, 254, 255, 243 // bianco (240 = 94 * 2,55) 255, 0, 0, 0 // nero iniziale (255 = 100 * 2,55) }; |
Riflessioni
Nella puntata di oggi abbiamo utilizzato le funzioni gradiente della libreria FastLED sulle striscie WS2812 con Arduino. Abbiamo visto come applicare i valori al nostro programma per creare esattamente l’effetto desiderato, ed abbiamo appreso come fare per “costruire” a mano o con una GUI le nostre funzioni di mapping.
Nella prossima puntata prenderemo in esame una serie di funzioni che simulano l’interferenza delle onde elettromagnetiche per creare giochi di luce ancor più divertenti.
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)
- Alimentatore 5V 1.5A
Parte dell’articolo si basa sulle lezioni online di Scott Marley.