Go Down

Topic: [RISOLTO] millis su fade led rgb (Read 1 time) previous topic - next topic

LeoTer01

#15
Nov 20, 2018, 04:41 pm Last Edit: Nov 20, 2018, 04:52 pm by LeoTer01
effettivamente hai ragione però utilizzando il delay ero costretto a mettere valori del genere altrimenti andava lentissima :D
Però mettendo valori che vanno da 200 a 500 non cambia nulla: sempre acceso su rosso.

Leo

Claudio_FF

Però mettendo valori che vanno da 200 a 500 non cambia nulla: sempre acceso su rosso
Nel loop ci sono tre if eseguiti uno dopo l'altro che alla fine lasciano i valori invariati... in un if vengono incrementati e in un if successivo decrementati, risultato finale valore uguale all'inizio.
* * * *    'if' e 'case' non sono cicli   * * * *
* * * Una domanda ben posta è già mezza risposta. * * *
* La corrente si misura in 'mA', la quantità di carica in 'mAh' *

LeoTer01

Eh, probabilmente è per quello che non funziona ma non so proprio come risolvere il problema....ho provato di tutto ma non sono ancora riuscito a farlo funzionare. :smiley-cry:
Qualcuno mi potrebbe dare qualche linea guida, qualche aiuto su come fare?

P.S. Spero abbiate capito cosa voglio fare, in caso contrario cercherò di spiegarmi meglio!

Grazie
Leo

Datman

Prova facendo diversamente:
prendi un valore che varia ciclicamente, ad esempio il resto di millis() diviso 2000, e ne ricavi i valori per R, G e B sfasandoli tra loro: G=R+667; B=G+667. Naturalmente devi mettere degli if che azzerino al superamento del massimo: if(G>2000) G-=2000.

Tempo fa feci qualcosa del genere con un led RGB, ma usai dei delay perché non c'era altro nel programma. Mi resi conto, però, che per fare sfumi uniformi era necessaria una tabella con valori trovati sperimentalmente e, comunque, i 255 valori del pwm producevano visibili salti ai livelli di luminosità più bassi.
Hi,I'm Gianluca from Roma.I play&work with electronics since I was16(1984).
After 25yrs of maintenance on cameras&video mixers,since 2013myJob is HDTVstudios design.
Since Jan2015 IPlayWith Arduino:bit.ly/2F3LPWP
Thanks 4 a Karma if U like my answer

torn24

#19
Nov 21, 2018, 08:04 am Last Edit: Nov 21, 2018, 08:30 am by torn24
LeoTer01, il tuo codice iniziale con i cicli for() aveva il problema che usava i delay(), che tu non vuoi usare!

La tua alternativa con millis() non è una naturale evoluzione del codice con for().

Nel codice con for(), eseguo prima il primo for, poi il secondo for, poi il terzo for.

Per farlo con millis() a mio avviso dovresti usare una macchina a stati finiti, una variabile che assume tre valori, e tre if(), se stato=1 eseguo il primo decremento, poi stato passa a 2 ed eseguo il secondo decremento.


Esempio:

Code: [Select]



int R = 5;
int G = 6;
int B = 3;
int fadeR = 255;
int fadeG = 0;
int fadeB = 0;
unsigned long zero = 0;
unsigned long tempo=200;
byte stato=0; // A seconda del valore di stato esegue una cosa o un altra


void setup(){
pinMode(R, OUTPUT);
  pinMode(G, OUTPUT);
  pinMode(B, OUTPUT);
}
void loop(){
    analogRead(A5);
    pR = map(analogRead(A5), 0, 1023, 1, 20);
    tempo = pR;
    if(millis() - zero > tempo){

      if(stato==0){
    
        fadeR--;
        fadeG++;
        analogWrite(R, fadeR);
        analogWrite(G, fadeG);
        if(fadeR==0)
            stato=1; // Quando il colore rosso è zero passa allo stato successivo
        
      }else if(stato==1){
  
      
        fadeG--;
        fadeB++;
        analogWrite(G, fadeG);
        analogWrite(B, fadeB);
        if(fadeG==0)
            stato=2; // Quando il colore verde è zero passo allo stato successivo 2
        
      }else if(stato==2){
      
        fadeB--;
        fadeR++;
        analogWrite(B, fadeB);
        analogWrite(R, fadeR);
        if(fadeB==0)
             stato=0; // Quando l'ultimo stato è stato eseguito rincomincia tornando allo stato zero
        
      }
      zero = millis(); // Questo deve avvenire ogni step di tempo
    }
delay(10);
}










PER capire meglio leggi cosa sia una macchina a stati finiti in maniera da capire meglio, di imparare cose che ti possono tornare utili in altre occasioni :)

LeoTer01

Grazie mille torn24! A vederlo così sembra la soluzione migliore. Mi studierò la macchina a stati finiti che non ho mai usato poi proverò il programma e vi farò sapere.
Il consiglio di Datman mi sembra un po' macchinoso ma lo terrò comunque in considerazione.

Leo

Etemenanki

#21
Nov 21, 2018, 11:02 am Last Edit: Nov 21, 2018, 11:18 am by Etemenanki
Ho letto ora il post e mi sono venuti un paio di dubbi ... tu esattamente "come" vuoi fare il fading ? ... colori separati (cioe', prima uno da zero al massimo e poi di nuovo a zero, poi il secondo, poi il terzo), o mix dei 3 in proporzione di un terzo ? (cioe' come, ad esempio, l'incrocio delle sinusoidi in una trifase ?)

Anche perche' 256 non puo essere diviso esattamente per 3, nel secondo caso (la scala va da 0 a 255, quindi sono 256 valori), per cui per poter fare tre rampe regolari da mixare, o vai da 0 a 254, o da 1 a 255 (dato che 255, invece, puoi dividerlo per 3 senza decimali di resto)

Poi, se e' il secondo caso, non ti basta partire con i valori iniziali di un terzo, due terzi e full ... cioe', ad esempio, 80, 165 e 250 per R, G e B, o nell'ordine che vuoi, (basta che nessun valore iniziale sia 1 o 255, per non "falsare" il primo controllo negli if) e fare una semplice sequenza di 3 if/else consecutivi e 3 flag per sapere se devono sommare o sottrarre (alle flag cambi valore quando <=255 e quando <=1, dentro gli stessi if) ?

Cioe', una cosa tipo

Code: [Select]


int R = 5;
int G = 6;
int B = 3;
byte fadeR = 80;
byte fadeG = 165;
byte fadeB = 250;
byte flag1 = 1;
byte flag2 = 1;
byte flag3 = 1;
unsigned long ZERO;
unsigned long tempo;

void setup(){
  pinMode(R, OUTPUT);
  pinMode(G, OUTPUT);
  pinMode(B, OUTPUT);
  zero = millis();
}

void loop(){

  analogRead(A5);
  tempo = map(analogRead(A5), 0, 1023, 10, 210);
  if(millis() - zero > tempo){
    if(flag1 == 1){
      fadeR++;
      if(fadeR >= 255) flag1=0;
      analogWrite(R, fadeR);
    }
    else if(flag1 == 0){
      fadeR--;
      if(fadeR <= 1) flag1=0;
      analogWrite(R, fadeR);
    }

    if(flag2 == 1){
      fadeG++;
      if(fadeG >= 255) flag2=0;
      analogWrite(G, fadeG);
    }
    else if(flag2 == 0){
      fadeG--;
      if(fadeG <= 1) flag2=0;
      analogWrite(G, fadeG);
    }

    if(flag3 == 1){
      fadeB++;
      if(fadeB >= 255) flag3=0;
      analogWrite(B, fadeB);
    }
    else if(flag3 == 0){
      fadeB--;
      if(fadeB <= 1) flag3=0;
      analogWrite(B, fadeB);
    }
  zero = millis();
  }
}

 EDIT: completato, ma l'ho buttato giu al volo col notepad partendo dal tuo, devi controllarlo ...
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.

LeoTer01

Il mio intento è creare una dissolvenza che fa così:
R che va da acceso a spento e contemporaneamente G va da spento a acceso.
G che va da acceso a spento e contemporaneamente B va da spento a acceso.
B che va da acceso a spento e contemporaneamente R va da spento a acceso.
Poi riparte.

Leo

Claudio_FF

Quindi hai tre fasi ben distinte, chiamiamole 0, 1, 2 che possono essere identificate dal valore di una variabile (il famoso stato delle macchine a stati).

Basta un if/else if/else per determinare la fase attiva ed eseguire solo le istruzioni corrispondenti.

Tra queste istruzioni ci va anche un if per riconoscere la fine della fase impostando quella nuova. Ad esempio per la fase 0 la condizione di termine è R completamente spento e G acceso al massimo.
* * * *    'if' e 'case' non sono cicli   * * * *
* * * Una domanda ben posta è già mezza risposta. * * *
* La corrente si misura in 'mA', la quantità di carica in 'mAh' *

Datman

#24
Nov 21, 2018, 12:06 pm Last Edit: Nov 21, 2018, 12:13 pm by Datman
Basta un solo ciclo che, sequenzialmente, sfuma tra R e G, poi tra G e B e poi tra B e R. Basta porre
Code: [Select]
A[1]=pinR; A[2]=pinG; A[3]=pinB; e poi sfumare tra A[x] e A[y], dove x va da 1 a 3 e y=x+1; if(y>3)y-=3;
Hi,I'm Gianluca from Roma.I play&work with electronics since I was16(1984).
After 25yrs of maintenance on cameras&video mixers,since 2013myJob is HDTVstudios design.
Since Jan2015 IPlayWith Arduino:bit.ly/2F3LPWP
Thanks 4 a Karma if U like my answer

LeoTer01

Dopo essermi studiato il funzionamento della macchina a stati finiti (che mi è stata fondamentale per un altro gioco di luce :smiley-wink: ) ho provato con il programma consigliato da torn24 e FUNZIONA!!! :)
Però accade una cosa molto strana: nonostante la variabile tempo cambi (controllato da seriale) il tempo della dissolvenza rimane sempre lo stesso :-\
Non riesco proprio a capire il motivo....vi lascio il programma:
Code: [Select]
analogRead(A5);
  pR = map(analogRead(A5), 0, 1023, 1, 20);
  tempo = pR;
  if(millis() - zero > tempo){
    if(stato == 0){
      fadeR--;
      fadeG++;
      analogWrite(R, fadeR);
      analogWrite(G, fadeG);
      if(fadeR == 0){
        stato = 1;
      }
     }
     else if(stato == 1){
      fadeG--;
      fadeB++;
      analogWrite(G, fadeG);
      analogWrite(B, fadeB);
      if(fadeG == 0){
        stato = 2;
      }
     }
     else if(stato == 2){
      fadeB--;
      fadeR++;
      analogWrite(B, fadeB);
      analogWrite(R, fadeR);
      if(fadeB == 0){
        stato = 0;
      }
     }
     zero = millis();
  }
}


Leo

torn24

Code: [Select]
pR = map(analogRead(A5), 0, 1023, 1, 20);

Non so se usi proprio questa riga, ma in questo caso hai un intervallo di tempo da 1 millisecondi a 20 millisecondi. Un uomo non è in grado di percepire queste differenze. Potresti percepire la differenza tra
100 e 300 millisecondi, comunque maggiore è l'intervallo più percepisci la differenza.

Claudio_FF

#27
Nov 22, 2018, 10:45 am Last Edit: Nov 22, 2018, 10:52 am by Claudio_FF
Quote from: torn24
Un uomo non è in grado di percepire queste differenze
Però il fading avviene in 256 cicli da 1..20ms, quindi in un tempo compreso tra 0.256 e 5.12 secondi (in realtà anche un po' più lento perché tra l'aggiornamento zero=millis() e la condizione >tempo si ritarda di minimo un altro millisecondo a giro), quindi dovrebbe essere perfettamente visibile... a meno che non ci siano altri ritardi nell'esecuzione del loop che noi non vediamo.
* * * *    'if' e 'case' non sono cicli   * * * *
* * * Una domanda ben posta è già mezza risposta. * * *
* La corrente si misura in 'mA', la quantità di carica in 'mAh' *

gpb01

#28
Nov 22, 2018, 11:02 am Last Edit: Nov 22, 2018, 11:09 am by gpb01
Se ho letto bene i vari post (ma ovviamente potrei sbagliare), in quello che state facendo, se volte un buon fade, state dimenticando una cosa fondamentale che, chi fa illuminazione con led RGB, conosce bene ...

... l'occhio umano NON è affatto lineare e quindi, fare un fade lineare variando semplicemente il PWM dei vari colori, da sempre un pessimo risultato (crescita rapida della luminosità all'inizio, fino circa al 50%, e poi sembra quasi che non cresca più o cresca molto lentamente).  I fade fatti bene tengono conto del GAMMA e del HUE per i calcoli e, se ben ricordo, ci sono anche librerie apposta per Arduino che effettuano tali calcoli e permettono di ottenere fade come si deve.

Provate a fare una ricerca ... :)

Guglielmo

Edit: Credo che la libreria FastLED abbia tutta una serie di funzioni per operazione HSV 
Search is Your friend ... or I am Your enemy !

Claudio_FF

Per quanto riguarda la semplice luminosità di un LED monocromatico ho trovato ottima l'applicazione di un esponenziale cubico. Si eleva il valore PWM al cubo e si divide per 65025 ottenendo di nuovo un valore compreso trra 0 e 255, ma con andamento esponenziale, che per l'occhio è una bella variazione progressiva della luminosità.

Nel caso dei LED RGB non ho mai provato (provvederemo  :) ), ma le non linearità dovrebbero essere ancora peggiori perché i singoli colori base non si comportano tutti allo stesso modo (immagino servirebbe una diversa curva di attivazione per ciascuno).
* * * *    'if' e 'case' non sono cicli   * * * *
* * * Una domanda ben posta è già mezza risposta. * * *
* La corrente si misura in 'mA', la quantità di carica in 'mAh' *

Go Up