Go Down

Topic: Pausa alla funzione loop finchè non cambia una condizione. Come fare? (Read 133 times) previous topic - next topic

Sara_kon

Buona sera a tutti!
Premetto di aver appena iniziato con Arduino, per cui ho ancora moltissimo da imparare.

Oggi ho giocato un po' con il led RGB e ho scritto un codice che mette in relazione un sensore di temperatura e il led stesso.

Quando il sensore è sotto una certa temperatura, il led "pulsa" in verde e blu, quando questa viene superata, avviene una transizione di colore: verde, giallo e infine rosso (if...else).
Essendo questa funzione nella sezione loop, quando il led diventa rosso il loop ricomincia e torna ad essere verde giallo rosso e così via fino a che la temperatura scende sotto il limite dato e la luce torna ad essere verde/blu.
Io vorrei che nel momento il cui il led è rosso, il lop si "blocchi" sul colore rosso, fino a che la temperatura non si abbassa.
Come posso fare?

Code: [Select]
void loop() {
    if (temperature >= baselineTemp && temperature < baselineTemp +10) {
   for(int i = 0; i < 256; i++){
    rgb(0,255-i,i); //da verde a blu
    delay(10);
    }
    for(int i = 0; i < 256; i++){
    rgb(0,i,255-i); //da blu a verde
    delay(10);
    }
  }

  else if (temperature >= baselineTemp +10) {
    for(int i=0; i < 256; i++){
    rgb(0+i,255,0);  // da verde a giallo   
    delay(10);
    }
    for(int i=0; i < 256; i++){
    rgb(255,255-i,0);  // da giallo a rosso   
    delay(10);
    }
  }
}

gpb01

Buonasera,
essendo il tuo primo post, nel rispetto del regolamento della sezione Italiana del forum (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con molta attenzione tutto il su citato REGOLAMENTO ... Grazie. :)

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell'apposito thread, nessuno ti potrà rispondere, quindi ti consiglio di farla al più presto. ;)
Search is Your friend ... or I am Your enemy !


Claudio_FF

Io vorrei che nel momento il cui il led è rosso, il lop si "blocchi" sul colore rosso, fino a che la temperatura non si abbassa. Come posso fare?
Con una apposita variabile flag / bandierina / indicatore che imposti a 1 per indicare il raggiungimento di una certa situazione. Questa variabile potrebbe chiamarsi uhmm... 'blocco' :D

Quindi nei vari 'if' testi anche questa variabile per sapere se eseguire qualcosa oppure no.

E quando si verifica la situazione di "sblocco" la reimposti a 0.


Tecnicamente l'uso di variabili flag (variabili di stato) permette di tenere conto delle situazioni in cui ci si viene a trovare man mano che l'elaborazione prosegue, in modo che ogni esecuzione del loop non sia puramente reattiva (come se avvenisse per la prima volta), ma si possa tenere conto anche della "storia passata".
********* IF e SWITCH non sono cicli ! *********
**** Una domanda ben posta è già mezza risposta ****
*** La corrente si misura in mA, la quantità di carica in mAh ***

AndreAndre

Ciao :)
il loop non puoi "bloccarlo", per farti capire corrisponde ad un while(1){}, per fare quello che vuoi dovresti usare delle variabili di stato come ha detto Claudio_FF
Per farti un esempio sul tuo codice potresti fare
Code: [Select]

void loop(){
  static byte variable_state;
  if(temperature >= baselineTemp && temperature < baselineTemp +10) variable_state = 0;
  if(temperature >= baselineTemp +10) variable_state = 1;

  if(variable_state == 0){
    for(int i = 0; i < 256; i++){
      rgb(0,255-i,i); //da verde a blu
      delay(10);
    }
    for(int i = 0; i < 256; i++){
      rgb(0,i,255-i); //da blu a verde
      delay(10);
    }
  }
 
  if(variable_state == 1){
    for(int i=0; i < 256; i++){
      rgb(0+i,255,0);  // da verde a giallo   
      delay(10);
    }
    for(int i=0; i < 256; i++){
      rgb(255,255-i,0);  // da giallo a rosso   
      delay(10);
    }
    variable_state = 2;
  }

  if(variable_state == 2){
    rgb(255,0,0); //rosso
  }
}


oppure potresti utilizzare lo switch case
Code: [Select]

void loop(){
  static byte variable_state;
  if(temperature >= baselineTemp && temperature < baselineTemp +10) variable_state = 0;
  if(temperature >= baselineTemp +10) variable_state = 1;

  switch(variable_state){
    case 0: for(int i = 0; i < 256; i++){
                 rgb(0,255-i,i); //da verde a blu
                 delay(10);
               }
               for(int i = 0; i < 256; i++){
                 rgb(0,i,255-i); //da blu a verde
                 delay(10);
               }
               break;
    case 1: for(int i=0; i < 256; i++){
                 rgb(0+i,255,0);  // da verde a giallo   
                 delay(10);
               }
               for(int i=0; i < 256; i++){
                 rgb(255,255-i,0);  // da giallo a rosso   
                 delay(10);
               }
               variable_state = 2;
               break;
    case 2: rgb(255,0,0); //rosso
               break;
  }
}

Sara_kon

Grazie a tutti ragazzi, non appena ci sarò riuscita (SE dovessi riuscire) posterò qui il risultato.
Ho provato tutte le soluzioni proposte ma l'esito, sebbene migliore, non mi soddisfa ancora.
Ora sto smanettando con la funzione switch case e ho fatto un piccolo diagramma che forse rende più chiaro quello che ho in mente

Maurotec

Se noti il case 1 dell'esempio di AndreAndre seleziona un nuovo case da eseguire al prossimo loop con l'istruzione:     variable_state = 2;

Può tornare utile avere uno storico degli stati precedente, cioè almeno il precedente a quello corrente e allora si usa una seconda variabile di stato es. vecchia_variabile_state a cui si deve assegnare il valore dello stato corrente.

Gli stati possono avere dei nomi simbolici, ROSSO, VERDE, ecc.
Supponiamo che:

vecchia_variabile_state = VERDE
variable_state = ROSSO

Da che colore ci si è arrivati al colore ROSSO, ci si è arrivati dal colore VERDE.

anziché usare i numeri nei case crea delle macro con #define, es.
Code: [Select]

#define VERDE_BLU 0
#define VERDE_GIALLO 1
#define ROSSO 2

switch(variable_state){
    case VERDE_BLU: for(int i = 0; i < 256; i++){
                 rgb(0,255-i,i); //da verde a blu
                 delay(10);
               }
               for(int i = 0; i < 256; i++){
                 rgb(0,i,255-i); //da blu a verde
                 delay(10);
               }
               break;
    case VERDE_GIALLO: for(int i=0; i < 256; i++){
                 rgb(0+i,255,0);  // da verde a giallo   
                 delay(10);
               }
               for(int i=0; i < 256; i++){
                 rgb(255,255-i,0);  // da giallo a rosso   
                 delay(10);
               }
               
               variable_state = 2;
               break;
    case ROSSO: rgb(255,0,0); //rosso
               break;
  }



Ciao.

paolo311

ho fatto un piccolo diagramma che forse rende più chiaro quello che ho in mente
Rendi tutte le condizioni in espressioni logiche, "girando" le espressioni sempre nello stesso verso, cioè utilizzando T come parametro di confronto:

(immaginando due variabili BT e T di tipo adeguato)

BT <= T < BT+4      -->   T >= BT && T< (BT+4)
BT+4 <= T              -->   T >= (BT+4)
BT+4 <= T < BT+7  -->   T >= (BT+4) && T< (BT+7)
BT+7 <= T              -->   T >= (BT+7)

Intanto si scopre che ci sono dei valori ricorrenti che si potrebbero buttare in variabili apposite:

BT+4 = lowerLimit
BT+7 = upperLimit

a questo punto il codice che controlla il led dovrebbe seguire la logica che hai espresso nel grafo:

Code: [Select]

if (T >= BT && T < lowerLimit)
{
     fadeBlueToGreen();
}
else if (T >= lowerLimit)
{
     fadeGreenToYellowAndRed();
     if (T >= lowerLimit && T < upperLimit)
     {
         fadeRedToYellowAndGreen();
         fadeGreenToYellowAndRed();
     }
     else if (T >= upperLevel)
     {
        red()
     }
}


Come ti hanno già fatto notare altri, non puoi mettere in pausa la funzione loop, un certo effetto continua a verificarsi solo se si mantiene la condizione che lo governa.

Ciao

Go Up