sketch per controllo RGB, ciclo millis e input ignorato

Ciao a tutti, sono nuovo alla programmazione e al forum quindi mi scuso se chiederò ovvietà.
Ho scritto il mio primo sketch, l'obiettivo è costruire una centralina per illuminazione RGB.

2 pulsanti: il primo attiva dei colori RGB fissi predefiniti in un array (static cycle), ogni pressione del tasto cambia colore con un piccolo fade. L'ultimo valore della sequenza spegne tutti i led.
Il secondo pulsante fa partire una sequenza automatica di colori, definiti in un secondo array, che continua ininterrottamente fino a che, con il primo pulsante si reimposta un colore fisso o si spegne.

Con questo codice ottengo il funzionamento voluto, ma durante la sequenza automatica bisogna premere decine di volte il primo pulsante per fermarla. Sembra che il controllore sia "troppo impegnato" e ignori il comando.

Ho ovviamente usato dei cicli basati su millis ma non mi spiego il comportamento. Credo che il mio problema sia "strutturale", vi prego di consigliarmi eventualmente su come riorganizzare il progetto per evitare questo problema.

Grazie e saluti a tutti

//hardware configuration
int SW1 = 2;
int SW2 = 4;
int R = 9; 
int G = 10; 
int B = 11; 

//var RGB
int brightnessR = 0;    
int brightnessG = 0;
int brightnessB = 0;

//timer vars
unsigned long LastRun = 0;
unsigned long CurrentTime;

//control vars
int fadeAmount = 1;
int SwitchStatic = 0;
int SwitchSequence = 0;
int Sequence = 0;
int St = 0;

//static cycle
int Static[6][3]= {{255, 0, 0} , {0, 255, 0} , {0, 0, 255} , {255, 255, 0} , {255, 255, 255} , {255, 0, 255}};

//sequence 1 parameters
int Sequence1[5][3]= {{255, 0, 0} , {0, 255, 0} , {0, 0, 255} , {255, 255, 0} , {255, 255, 255}};
int Rest1 = 15000;
int Fade1 = 30;
 


void setup() {
  pinMode(R, OUTPUT);
  pinMode(G, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(SW1, INPUT); 
  pinMode(SW2, INPUT);
}

// main loop routine 
void loop() {

  // switch read
  SwitchStatic = digitalRead (SW1);
  SwitchSequence = digitalRead (SW2);
  
  
  //static cycle activation and control
    if (SwitchStatic == HIGH){
      Sequence = 0;   //used to break loops
      digitalWrite(LED_BUILTIN, HIGH) ;
      if (St < 6) {      
        LedSet(Static[St][0],Static[St][1],Static[St][2], 1);
        St = St + 1 ;
      }
      else {
        LedSet(0, 0, 0, 1);
        St = 0 ;   
      }
    }
  
  
  //sequence loop activation
    if (SwitchSequence == HIGH) {
      Sequence = 255;   
      digitalWrite(LED_BUILTIN, LOW);
      StartSequence();
      }
  }
  
//main loop function for automated sequence 
  void StartSequence() {
     while (Sequence != 0) {
       if (Sequence == 0) {   //breaks while if the var sequence is reset
         break;
       }  
       for (int i=0; i < 5; i++){
        if (Sequence == 0) {
          break;
        }
        LedCrossFade(Sequence1[i][0],Sequence1[i][1],Sequence1[i][2], Rest1, Fade1);
        }  
      }
    }

//function to set single color with fade (no rest time) 
  void LedSet(int Red, int Green, int Blue, int Fade) {
    while ((brightnessR != Red) or (brightnessG != Green) or (brightnessB != Blue)) {
      CurrentTime = millis();
      if (CurrentTime >= (LastRun + Fade)) {
        if (brightnessR < Red)  {
          brightnessR = brightnessR + fadeAmount;
        }
        else if (brightnessR > Red)  {
          brightnessR = brightnessR - fadeAmount;
        }
  
        if (brightnessG < Green)  {
          brightnessG = brightnessG + fadeAmount;
        }
        else if (brightnessG > Green)  {
          brightnessG = brightnessG - fadeAmount;
        }
    
        if (brightnessB < Blue)  {
          brightnessB = brightnessB + fadeAmount;
        }
        else if (brightnessB > Blue)  {
          brightnessB = brightnessB - fadeAmount;
        }
        
        analogWrite(R, brightnessR);
        analogWrite(G, brightnessG);
        analogWrite(B, brightnessB);
        LastRun = CurrentTime; 
      }
    }
  } 


//function to set color sequence with fade and rest time
void LedCrossFade(int Red, int Green, int Blue, int Rest, int Fade) {
    while ((brightnessR != Red) or (brightnessG != Green) or (brightnessB != Blue)) {
      if (Sequence == 0){   //breaks while if the var sequence is reset
        break;
      }
      CurrentTime = millis();
      if (CurrentTime >= (LastRun + Fade)) {
        if (brightnessR < Red)  {
          brightnessR = brightnessR + fadeAmount;
        }
        else if (brightnessR > Red)  {
          brightnessR = brightnessR - fadeAmount;
        }
    
        if (brightnessG < Green)  {
          brightnessG = brightnessG + fadeAmount;
        }
        else if (brightnessG > Green)  {
          brightnessG = brightnessG - fadeAmount;
        }
         
        if (brightnessB < Blue)  {
          brightnessB = brightnessB + fadeAmount;
        }
        else if (brightnessB > Blue)  {
          brightnessB = brightnessB - fadeAmount;
        }
        analogWrite(R, brightnessR);
        analogWrite(G, brightnessG);
        analogWrite(B, brightnessB);
        LastRun = CurrentTime; 
      }
    }
  CurrentTime = millis();   //rest loop
  LastRun = CurrentTime;
    while (CurrentTime <= (LastRun + Rest)) { 
      if (Sequence == 0){   //breaks while if the var sequence is reset
        break;
      }    
      CurrentTime = millis();
    }
  }

Buonasera,
essendo il tuo primo post, nel rispetto del regolamento, ti chiedo cortesemente di presentarti QUI (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con attenzione il su citato REGOLAMENTO ... Grazie.

Guglielmo

Ciao mioal,

non vorrei sbagliarmi ma nell'if:

  //sequence loop activation
    if (SwitchSequence == HIGH) {
      Sequence = 255;   
      digitalWrite(LED_BUILTIN, LOW);
      StartSequence();
      }

non c'è scritto che con "Sequence == 0" non lo deve fare...anzi tu lo metti a 255...

poi non capisco questa (ma sicuramente è una mia mancanza):

  CurrentTime = millis();   //rest loop
  LastRun = CurrentTime;
    while (CurrentTime <= (LastRun + Rest)) {
      if (Sequence == 0){   //breaks while if the var sequence is reset
        break;
      }   
      CurrentTime = millis();
    }

cioè CurrentTime è, per esempio, 1000 (valore di ritorno da millis()); LastRun = CurrentTime ed entri nel while dicendo "fintanto che 1000<=1000+15000 (valore di Rest)..."
secondo me ha più senso, ma posso sbagliare, fare così:

LastRun = millis();
    while (millis() <= (LastRun + Rest)) {
      if (Sequence == 0){   //breaks while if the var sequence is reset
        break;
      }

per il ciclo while...mi accorgo adesso che aggiorni CurrentTime alla fine...come si dice dalle mie parti..."con la diligenza (la carrozza) ma ci arrivo"... :smiley: :smiley:
e comunque, se non sbaglio, da qui non esci per 15 secondi.