Domanda:
Animazione LED RGB digitale
Rhys Edwards
2014-03-14 15:41:10 UTC
view on stackexchange narkive permalink

Ho cercato di far sfumare i colori l'uno nell'altro per un progetto su cui sto lavorando. L'ho ottenuto con l'effetto arcobaleno che alcuni dal codice di esempio di Adafruit, tuttavia voglio essere in grado di scegliere i colori ( es. blu scuro in azzurro).

Ho i colori che cambiano e sbiadiscono, tuttavia la dissolvenza spegne tutti i LED e inizia ad aumentare la luminosità del nuovo colore. Ho bisogno che i colori si sfumino piuttosto che sbiadiscano e aumentino la luminosità.

Qualcuno è in grado di indicarmi la giusta direzione?

  #include "LPD8806.h" #include "SPI.h" #define stripSize 64int nLEDs = 160; int dataPin = 2; int clockPin = 3; // Il primo parametro è il numero di LED nel filamento. Le strisce LED // sono 32 LED per metro ma puoi estendere o tagliare la striscia. I prossimi due // parametri sono i dati SPI e i pin di clock: LPD8806 strip = LPD8806 (64, dataPin, clockPin); // Puoi opzionalmente utilizzare l'SPI hardware per le scritture più veloci, tralasciare // i parametri dei pin di dati e clock. Ma questo limita l'uso a pin molto // specifici su Arduino. Per Arduino "classici" (Uno, Duemilanove, // ecc.), Data = pin 11, clock = pin 13. Per Arduino Mega, data = pin 51, // clock = pin 52. Per 32u4 Breakout Board + e Teensy, data = pin B2, // orologio = pin B1. Per Leonardo, questo può essere fatto SOLO sui pin ICSP.//LPD8806 strip = LPD8806 (nLEDs); void setup () {// Avvia la striscia LED strip.begin (); // Aggiorna la striscia, per iniziare sono tutte 'spente' strip.show ();} void loop () {//turnAllOn(strip.Color(30,30,30),4000); dissolvenza (0, 127, 0, 100); // rosso, verde, blu, ritardo - dissolve tutti i pixel di un colore //turnAllOn(strip.Color(30,100,30),4000); dissolvenza (50, 127, 02,100); // rosso, verde, blu, ritardo - dissolve tutti i pixel di un colore //turnAllOn(strip.Color(100,30,100),4000); dissolvenza (50, 127, 50, 100); // rosso, verde, blu, ritardo - dissolve tutti i pixel di un colore} void fade (uint32_t r, uint32_t g, uint32_t b, uint32_t wait) {int i, j; for (j = 0; j < 384; j ++) {
for (i = 0; i < strip.numPixels (); i ++) {strip.setPixelColor (i, strip.Color ((r * j) / 1000, (g * j) / 1000, (b * j) / 1000 )); } strip.show (); } delay (wait);} void turnAllOn (uint32_t c, uint32_t wait) {int i; per (i = 0; i < strip.numPixels (); i ++) {strip.setPixelColor (i, c); // attiva tutti i pixel} strip.show (); // scrive il ritardo di uscita di tutti i pixel (aspetta); } uint32_t Wheel (uint16_t WheelPos) {byte r, g, b; switch (WheelPos / 128) {caso 0: r = 127 - WheelPos% 128; // Red down g = WheelPos% 128; // Green up b = 0; // pausa blu; caso 1: g = 127 - WheelPos% 128; // green down b = WheelPos% 128; // blu su r = 0; // rosso off break; caso 2: b = 127 - WheelPos% 128; // blue down r = WheelPos% 128; // rosso su g = 0; // pausa verde; } return (strip.Color (r, g, b));}  
Una risposta:
Peter Bloomfield
2014-03-14 16:36:48 UTC
view on stackexchange narkive permalink

Attualmente, la funzione di dissolvenza inizia da 0 e si interpola efficacemente fino al colore desiderato. Per sfumare tra i colori, avresti bisogno che lo schizzo ricordi il colore precedente che ha usato e inizi a sbiadire da quello invece che da 0.

L'approccio che userei è iniziare calcolando quanto ogni componente deve cambiare di volta in volta. Ad esempio, se si desidera sfumare da 100 a 200 su 50 passaggi, è necessario modificare di +2 a ogni passaggio. Se si desidera eseguire la stessa operazione al contrario (da 200 a 100), dovrebbe cambiare di -2.

Uno dei problemi è che ogni componente cambierà probabilmente di una quantità diversa (il rosso potrebbe va da 0 a 200, ma il blu può andare solo da 50 a 70). Se utilizzi sempre numeri interi, potrebbero verificarsi transizioni irregolari, quindi ti consiglio di utilizzare il punto mobile. È tecnicamente più lento (meno efficiente), ma probabilmente non abbastanza di cui preoccuparsi.

Probabilmente lo scriverei così:

  void fade (uint8_t oldR, uint8_t oldG, uint8_t oldB, uint8_t newR, uint8_t newG, uint8_t newB, uint32_t numSteps, uint32_t waitPerStep) {// Guardati dalla divisione per zero if (numSteps == 0) numSteps = 1; // Calcola quanto ogni colore deve cambiare in ogni passaggio const float stepR = (newR - oldR) / (float) numSteps, stepG = (newG - oldG) / (float) numSteps, stepB = (newB - oldB) / (float) numSteps; // Questi valori memorizzeranno i nostri colori lungo il percorso float r = oldR, g = oldG, b = oldB; uint8_t byteR = vecchioR, byteG = vecchioG, byteB = vecchioB; // Passa attraverso ogni passo di dissolvenza const uint16_t numPixels = strip.numPixels (); for (uint32_t step = 0; step < numSteps; ++ step) {// Sposta un passaggio verso il colore target r + = stepR; g + = stepG; b + = stepB; // Arrotonda i colori ai numeri interi qui così non dobbiamo farlo ripetutamente nel ciclo sotto byteR = (uint8_t) (r + 0.5f);
byteG = (uint8_t) (g + 0,5f); byteB = (uint8_t) (b + 0,5f); // Applica il colore a ogni pixel per (uint16_t pixel = 0; pixel < numPixels; ++ pixel) {strip.setPixelColor (pixel, byteR, byteG, byteB); } strip.show (); ritardo (waitPerStep); }}  

Come puoi vedere, gli passi il vecchio colore (che stai sbiadendo da ) e il nuovo colore (che stai sbiadendo a ). Come accennato in precedenza, questo significa che il tuo schizzo deve ricordare quale colore è stato utilizzato in precedenza, poiché non credo che la libreria fornisca un modo per leggere il colore corrente.

Ho incluso alcune ottimizzazioni in lì per farlo funzionare più velocemente. C'è di più che potresti fare per ottimizzarlo ulteriormente, se necessario.

Per usarlo, dovresti fare qualcosa del genere:

  // Dissolvenza dal nero al rosso e pausa brevemente dissolvenza (0, 0, 0, 255, 0, 0, 100, 10); ritardo (500); // dissolvenza dal rosso al viola e pausa breve dissolvenza (255, 0, 0, 255, 0, 255, 100 , 10); delay (500); // Dissolvenza dal viola al verde e pausa brevemente dissolvenza (255, 0, 255, 0, 255, 0, 100, 10); delay (500);  

Ho apportato un paio di altre modifiche rispetto alla tua funzione di dissolvenza. Prima di tutto, ho fatto in modo che tu possa impostare il numero di passaggi per la dissolvenza. Questo può essere molto utile perché cambi di colore più grandi richiederanno più passaggi per avere un aspetto uniforme.

Ho anche modificato il parametro wait . Nel tuo codice, inserisci il ritardo dopo che l'intera dissolvenza è stata completata, il che sembra un approccio strano. Ha più senso consentire un piccolo ritardo tra ogni fase della dissolvenza, in modo da poter controllare la velocità con cui va.

Nel mio esempio sopra, puoi vedere i parametri 100, 10 alla fine di ogni chiamata a fade () . Ciò significa che dividerà il cambio di colore in 100 passaggi, con un ritardo di 10 ms tra ogni passaggio. Il risultato è che ogni dissolvenza richiederà circa 1 secondo (senza contare il tempo impiegato per aggiornare effettivamente la striscia LED).

Ha risposto molto bene. Complimenti per tutti i dettagli del codice, le ottimizzazioni e le spiegazioni. Forse un piccolo bug: il colore da non appare mai quando inizi il ciclo con il primo incremento di passaggio. Dovresti aggiungere un'altra iterazione e incrementare solo alla fine del ciclo.
Grazie @jfpoilpret. Perdere il primo passo è in realtà intenzionale. Sulla base della domanda, presumo che i LED mostrino già il "vecchio" colore prima che venga chiamato "fade ()". Hai assolutamente ragione però. In altre circostanze potresti davvero volere quel passaggio in più.
Questo è davvero fantastico. Grazie mille per la recensione dettagliata!


Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 3.0 con cui è distribuito.
Loading...