Fade in e fade out

Salve a tutti!
Ho scritto questo codice, si avvia e il led rosso si accende. Premo il pulsante si spegne il led rosso e si accende il led verde. premo di nuovo si spegne il led verde e si accende il led giallo. premo di nuovo e il giallo lampeggio. premo ancora e ritorna sul rosso.
Fino qui tutto bene.
Vorrei aggiungere un fade out e fade ogni volta che premo il pulsante e cambio colore. Per esempio rosso sfuma (fade out) e si accende il verde piano piano (fade in), e poi uguale quando vado da verde a giallo, ecc.

Qualcuno potrebbe aiutarmi in modo che il codice non mi si blocchi?

Grazie

ecco il codice`

long unsigned prevTime_T = millis();
long interval_T = 600;
long t = 0;
long debounce_delay = 100;
int giallo_state = LOW;
int switchPin = 2;
int rosso = 4;
int giallo = 6;
int verde = 8;
int val;
int val2;
int buttonState;
int Mode = 0;

void setup() {

  pinMode(switchPin, INPUT);
  pinMode(rosso, OUTPUT);
  pinMode(giallo, OUTPUT);
  pinMode(verde, OUTPUT);
  buttonState = digitalRead(switchPin);
}
void loop() {
  long unsigned currentTime = millis();
  val = digitalRead(switchPin);
  delay(10);
  val2 = digitalRead(switchPin);
  if (val == val2) {
    if ((millis() - t) > debounce_delay) {
      t = millis();
      {
        if (val != buttonState) {
          if (val == LOW) {
            if (Mode == 0) {
              Mode = 1;
            } else {
              if (Mode == 1) {
                Mode = 2;
              } else {
                if (Mode == 2) {
                  Mode = 3;
                } else {
                  if (Mode == 3) {


                    Mode = 0;
                  }
                }
              }
            }
          }
        }

        buttonState = val;
      }
      if (Mode == 0) {  // all-off

        digitalWrite(rosso, HIGH);
        digitalWrite(giallo, LOW);
        digitalWrite(verde, LOW);
      }
      if (Mode == 1) {
        digitalWrite(rosso, LOW);
        digitalWrite(giallo, LOW);
        digitalWrite(verde, HIGH);
      }
      if (Mode == 2) {
        digitalWrite(rosso, LOW);
        digitalWrite(giallo, HIGH);
        digitalWrite(verde, LOW);
      }
      if (Mode == 3) {

        if (currentTime - prevTime_T > interval_T) {
          giallo_state = !giallo_state;
          digitalWrite(giallo, giallo_state);
          prevTime_T = currentTime;
          digitalWrite(rosso, LOW);
          digitalWrite(verde, LOW);
        }
      }
    }
  }
}

@dvdjk: ... fosse anche per una sola riga, come richiesto al punto 7 del REGOLAMENTO, il codice va racchiuso tra i tag CODE, per cui, cortesemente edita il tuo post qui sopra (quindi NON scrivendo un nuovo post, ma utilizzando il bottone a forma di piccola matita :pencil2: che si trova in basso del tuo post), seleziona la parte di codice e premi l'icona <code/> nella barra degli strumenti per contrassegnarla come codice. Inoltre, così com'è, non è molto leggibile ... assicurati di averlo correttamente indentato nell'IDE prima di inserirlo (questo lo si fa premendo ctrlT su un PC o cmd T su un Mac, sempre all'interno del IDE).

Grazie,

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà sistemato il codice come indicato, nel rispetto del regolamento nessuno ti risponderà (eventuali risposte o tuoi ulteriori post, verrebbero temporaneamente nascosti), quindi ti consiglio di farlo al più presto.

Grazie mille Guglielmo, scusami!

Se non indenti il codice premendo Ctrl+t non posso neanche copiarlo e postare la copia modificata. Con annidamento profondo come nel caso di:

if (val != buttonState) {

non si capisce qual'è la parentesi graffa di chiusura:

              }
            }
          }
        }
      }
   
        } // end if (val == val2) forse

Parte della sfilza di if può facilmente essere sostituita da:

      Mode = ++Mode % 4;

Credo si debba inserire come mostrato di seguito:

if (val != buttonState) {
      if (val == LOW) {
          Mode = ++Mode % 4;

Prova ad apportare la modifica suggerita e riposta il codice ma indentato e magari pure aggiungendo un commento dopo ogni graffa } come ho fatto prima.

Ciao.

You might try looking at the ledc functions, found at HERE

@sonofcy: Questa è la sezione Italiana del forum e l'unica lingua ammessa è l'Italiano. Se non siete in grado di scrivere in Italiano, cortesemente NON intervenite. Grazie.

Guglielmo

Quel programma è inadeguato per gestire il fade

Servirebbero talmente tante modifiche che fai prima a riscriverlo

Per cominciare se devi fare in SW sia il fade che il de-bounce sei già nei premi senza bisogno d'altro

Cerca e studia un po' di esempi di fade in out e prevedi il debounce Hw

I guess my browser is automatically translating, because I see English. Is there a way to turn off foreign language sections?

Evita la traduzione automatica fatta dal browser, e no, non c'è modo (che io conosca) per escludere le sezioni.


Avoid automatic translation done by the browser, and no, there is no way (that i know of) to exclude sections.

Guglielmo

I will try to keep an eye on the top of the page that shows the forum section I am in but being 82yo and autistic that is a challenge. I tried pasting the last response into google translate but when I did I still only see English. I just now turned off 'offer to translate' never saw the offer though.

Anche imparare ad usare lo switch() aiuta a rendere il codice più snello; esempio quella sfilza di if... (anche calcolo suggerito da Maurotec va bene)

            switch (Mode)
            { case 0: Mode = 1; break;
              case 1: Mode = 2; break;
              case 2: Mode = 3; break;
              case 3: Mode = 0; break;
            }

Grazie dell aiuto, l ho indentato ora

grazie mille

long unsigned prevTime_T = millis();
long interval_T = 600;
long t = 0;
long debounce_delay = 100;
int giallo_state = LOW;
int switchPin = 2;
int rosso = 4;
int giallo = 6;
int verde = 8;
int val;
int val2;
int buttonState;
int Mode = 0;

void setup() {

  pinMode(switchPin, INPUT);
  pinMode(rosso, OUTPUT);
  pinMode(giallo, OUTPUT);
  pinMode(verde, OUTPUT);
  buttonState = digitalRead(switchPin);
}

void loop() {
  long unsigned currentTime = millis();
  val = digitalRead(switchPin);
  delay(10);
  val2 = digitalRead(switchPin);
  if (val == val2) {
    if ((millis() - t) > debounce_delay) {
      t = millis();
      if (val != buttonState) {
        if (val == LOW) {
          if (Mode == 0) {
              Mode = 1;
          } else if (Mode == 1) {
              Mode = 2;
          } else if (Mode == 2) {
              Mode = 3;
          } else if (Mode == 3) {
              Mode = 0;
          }
        } // end if (val == LOW)
      } // end if (val != buttonState)
    }  // end if ((millis() - t) > debounce_delay)
  } // end if (val == val2)


  buttonState = val;
      
  if (Mode == 0) {  // all-off
      digitalWrite(rosso, HIGH);
      digitalWrite(giallo, LOW);
      digitalWrite(verde, LOW);
  } else if (Mode == 1) {
      digitalWrite(rosso, LOW);
      digitalWrite(giallo, LOW);
      digitalWrite(verde, HIGH);
  } else if (Mode == 2) {
      digitalWrite(rosso, LOW);
      digitalWrite(giallo, HIGH);
      digitalWrite(verde, LOW);
  } else if (Mode == 3) {

      if (currentTime - prevTime_T > interval_T) {
        giallo_state = !giallo_state;
        digitalWrite(giallo, giallo_state);
        prevTime_T = currentTime;
        digitalWrite(rosso, LOW);
        digitalWrite(verde, LOW);
      }
  }
} // end void loop()

Partendo dalla tua indentazione sono riuscito in pochi minuti ad aggiungere i commenti, scoprendo al tempo stesso che c'erano graffe ridondanti.
Nota:
if (cond) { } else if (cond) {} else if ecc
Non è questione di stile, ma di semantica. Se Mode vale 0 la cpu esegue il corpo della if e non valuta le altre if.

Adesso modifico il codice per rimuovere altre if:

void loop() {
  long unsigned currentTime = millis();
  val = digitalRead(switchPin);
  delay(10);
  val2 = digitalRead(switchPin);
  if (val == val2) {
    if ((millis() - t) > debounce_delay) {
      t = millis();
      if (val != buttonState) {
        if (val == LOW) {
             Mode = ++Mode % 4;
        } // end if (val == LOW)
      } // end if (val != buttonState)
    }  // end if ((millis() - t) > debounce_delay)
  } // end if (val == val2)

  buttonState = val;
      
  if (Mode == 0) {  // all-off
      digitalWrite(rosso, HIGH);
      digitalWrite(giallo, LOW);
      digitalWrite(verde, LOW);
  } else if (Mode == 1) {
      digitalWrite(rosso, LOW);
      digitalWrite(giallo, LOW);
      digitalWrite(verde, HIGH);
  } else if (Mode == 2) {
      digitalWrite(rosso, LOW);
      digitalWrite(giallo, HIGH);
      digitalWrite(verde, LOW);
  } else if (Mode == 3) {

      if (currentTime - prevTime_T > interval_T) {
        giallo_state = !giallo_state;
        digitalWrite(giallo, giallo_state);
        prevTime_T = currentTime;
        digitalWrite(rosso, LOW);
        digitalWrite(verde, LOW);
      }
  }
} // end void loop()

Prova questa mia modifica e verifica che si comporti semanticamente come la tua versione.

Dai una lettura a questi due articoli:

Impara a creare le funzioni di supporto che snelliscono il case e rendono più leggibile e comprensibile e ciò ci permette di ricavare la semantica con minore sforzo.

Ad esempio questa porzione di codice che fa lampeggiare il led può benissimo essere messa in una funzione di supporto.

     if (currentTime - prevTime_T > interval_T) {
          giallo_state = !giallo_state;
          digitalWrite(giallo, giallo_state);
          prevTime_T = currentTime;
          digitalWrite(rosso, LOW);
          digitalWrite(verde, LOW);
        }

In quei due articoli c'è appunto la funzione void flashingLight(bool tf) che fa lampeggiare due led quando serve.

Sei sulla buona strada, hai già scoperto il modo di introdurre a scelta una porzione di codice da eseguire in loop in base alla variabile di stato (Modo).

Stati, modi, fasi si somigliano

Ciao.

Aggiungo, se questo pezzo di codice lo "spezzi" e credi delle funzioni separate con un nome significativo, esempio:

} else if (Mode == 1) {  
   AccendiVerde();
} ...

... fuori da loop e setup:

void AccendiVerde()
{ 
  digitalWrite(rosso, HIGH);
  digitalWrite(giallo, LOW);
  digitalWrite(verde, LOW);
}

La modifica suggerita è ottima perché è funzionale, è semplice poiché le funzioni che devi creare non prendono argomenti e non restituiscono alcun valore al chiamante.

Quindi approvo al 100%. Un poco meno approvo lo stile per me orribile e per niente comodo se voglio copiare il codice all'interno della funzione devo evitare di selezionare la graffa iniziale:

{ digitalWrite(rosso, HIGH);

diversamente:

void AccendiVerde() {
    digitalWrite(rosso, HIGH);
    digitalWrite(giallo, LOW);
    digitalWrite(verde, LOW);

}

Posiziono il cursore ad inizio riga, premo shift+freccia giu (3 volte), ctrl+c, operazione che richiede poco tempo e soprattutto non richiede la mia concentrazione mentale per essere eseguita.

Ciao,

Grazie mille dell aiuto, gentilissimi.

Ora sto provando ad inserire il fade in e poi fade out quando cambio colore, ma (con il fadeamount) mi si blocca il loop, cioe mi si accende e spegne il rosso continuamente.
Forse la strada migliore e' usare ancora millis?
grazie a tutti

Ho modificato il codice , giusto per provare a fare il fade in per il rosso. La prima volta funziona il fade in per il rosso, poi quando raggiunge la massima luminoisita si blocca , e mi fa solo il rosso senza piu farmi il fade in.

l`long unsigned prevTime_T = millis();
long interval_T = 600;
long t = 0;
long debounce_delay = 100;
int giallo_state = LOW;
int switchPin = 2;
int rosso = 3;
int giallo = 6;
int verde = 8;
int val;
int val2;
int buttonState;
int Mode = 0;

unsigned long millisTimer = 0;
int PWMdelay = 50;
int condition = 0;
int i = 0;




void setup() {

  pinMode(switchPin, INPUT);
  pinMode(rosso, OUTPUT);
  pinMode(giallo, OUTPUT);
  pinMode(verde, OUTPUT);
  buttonState = digitalRead(switchPin);
}
void loop() {
  long unsigned currentTime = millis();
  val = digitalRead(switchPin);
  delay(10);
  val2 = digitalRead(switchPin);
  if (val == val2) {
    if ((millis() - t) > debounce_delay) {
      t = millis();
      {
        if (val != buttonState) {
          if (val == LOW) {
            if (Mode == 0) {
              Mode = 1;
            } else {
              if (Mode == 1) {
                Mode = 2;
              } else {
                if (Mode == 2) {
                  Mode = 3;
                } else {
                  if (Mode == 3) {


                    Mode = 0;
                  }
                }
              }
            }
          }
        }

        buttonState = val;
      }
      if (Mode == 0) {  // all-off

        if (condition == 0) {
          if ((millis() - millisTimer) > PWMdelay) {
            if (i < 255) {
              i++;
              millisTimer = millis();
            }
          }

          analogWrite(rosso, i);
        }


        digitalWrite(giallo, LOW);
        digitalWrite(verde, LOW);
      }
      if (Mode == 1) {
        digitalWrite(rosso, LOW);
        digitalWrite(giallo, LOW);
        digitalWrite(verde, HIGH);
      }
      if (Mode == 2) {
        digitalWrite(rosso, LOW);
        digitalWrite(giallo, HIGH);
        digitalWrite(verde, LOW);
      }
      if (Mode == 3) {

        if (currentTime - prevTime_T > interval_T) {
          giallo_state = !giallo_state;
          digitalWrite(giallo, giallo_state);
          prevTime_T = currentTime;
          digitalWrite(rosso, LOW);
          digitalWrite(verde, LOW);
        }
      }
    }
  }
}

`

Sarebbe più chiaro con uno switch/case, ma così è ancora più semplice:

if (!switchState) // E' più chiaro di un anonimo val.
  {
  Mode++;
  if (Mode==4) Mode=0;
  }

Per le letture di millis(), poi, mi trovo molto bene con variabili che iniziano con t_:

uint32_t t_prevTime=millis();
uint32_t t_Timer=0;

ma anche qui non è chiaro a che cosa servano! Sarebbe più chiaro:

uint32_t t_interm_giallo=millis();
uint32_t t_pwm_sfumo=0;

La prima volta la variabile i vale zero, la seconda volta i ha valore diverso da zero, il suo valore dipende da quando premi il pulsante. Se lo premi quando la luminosità del rosso è massima i vale 255.
Premendo passi a Mode 1 e dovresti ridurre i fino a zero e aumentare il pwm del giallo.

Non conosco altro modo per eseguire codice non "bloccante".

Ciao.