piccolo problema con i cicli

ciao a tutti ragazzi, facendo questo programma che adesso linko ho riscontrato un problema nel ciclo while, cioè quando premo un altro pulsante non mi fa uscire dal ciclo e i miei led non si spengono più

#include <IRremote.h> 
int receiver = 11; 
IRrecv irrecv(receiver);
decode_results results;

void setup()
{
  Serial.begin(9600); 
  irrecv.enableIRIn(); 
  pinMode (5, OUTPUT);
  pinMode (6, OUTPUT);
  pinMode (9, OUTPUT);
  pinMode (10, OUTPUT);
}
void loop()
{
  if (irrecv.decode(&results))
  {
    Serial.println(results.value, HEX); 
    irrecv.resume();
  }
 
  if ( results.value == 0xFF38C7 ){ 
    digitalWrite(5, HIGH);   
    digitalWrite(6, HIGH);
    digitalWrite(9, HIGH);
    digitalWrite(10, HIGH);
   
   do {
       for(int fade=0; fade<255; fade+=5) 
   {
    analogWrite (5, fade);
    analogWrite (6, 255-fade);
    analogWrite (9, fade);
    analogWrite (10, 255-fade);
    delay (60);
   }  
   
      for(int fade=255; fade>0; fade-=5) 
   {
    analogWrite (5, fade);
    analogWrite (6, 255-fade);
    analogWrite (9, fade);
    analogWrite (10, 255-fade);
    delay (60);
   }
 } while ( results.value == 0xFF38C7 ); 

} 
   
  if ( results.value == 0xFF6897 ){ 
       digitalWrite(5, LOW);  
       digitalWrite(6, LOW);
       digitalWrite(9, LOW);
       digitalWrite(10, LOW);
  }
  
}

qualcuno può aiutarmi a risolvere il problema ?
grazie in anticipo :slight_smile:

Fa esattamente quello che gli hai chiesto, riassumendo:

if ( results.value == 0xFF38C7 )
{ ...
 do
 { ... due cicli for ...
 } while ( results.value == 0xFF38C7 ); 
}

Ovvero entri in quella parte se è quel tasto e cicli FINCHE' results.value è quel tasto.
Quindi giustamente rimane dentro al do-while
Quel ciclo do-while non ha nessun senso. La loop è già un ciclo infinito

ho provato già a non mettere il ciclo do while ; ma quando accendo i led i due for vengono letti una sola volta, io vorrei invece che i due for continuassero finché non spengo i led, mi sa allora che devo reimpostarlo diversamente ?

niente l'unica soluzione più vicina al mio scopo è questa; perché almeno i led si spengono ma vanno in dissolvenza solo una volta (i due cicli for), non so proprio come impostarlo diversamente

#include <IRremote.h> 
int receiver = 11; 
IRrecv irrecv(receiver); 
decode_results results;

void setup()
{
  Serial.begin(9600); 
  irrecv.enableIRIn(); 
  pinMode (5, OUTPUT);
  pinMode (6, OUTPUT);
  pinMode (9, OUTPUT);
  pinMode (10, OUTPUT);
}
void loop()
{
  if (irrecv.decode(&results))         //riceve segnale in esadecimale
  {
    Serial.println(results.value, HEX); 
    irrecv.resume();
  }
 
  if ( results.value == 0xFF38C7 ){  //accende i led
    digitalWrite(5, HIGH);   
    digitalWrite(6, HIGH);
    digitalWrite(9, HIGH);
    digitalWrite(10, HIGH);
   
       for(int fade=0; fade<255; fade+=5)  //dissolvenza led
   {
    analogWrite (5, fade);
    analogWrite (6, 255-fade);
    analogWrite (9, fade);
    analogWrite (10, 255-fade);
    delay (60);
   }  
   
      for(int fade=255; fade>0; fade-=5) 
   {
    analogWrite (5, fade);
    analogWrite (6, 255-fade);
    analogWrite (9, fade);
    analogWrite (10, 255-fade);
    delay (60);
   }


} 
   
  if ( results.value == 0xFF6897 ){  //spegni led
       digitalWrite(5, LOW);   
       digitalWrite(6, LOW);
       digitalWrite(9, LOW);
       digitalWrite(10, LOW);
  }
  
}

Ad ogni giro di loop la variabile results.value viene "azzerata"

Devi crearti una variabile di stato. Parti con LED_OFF (valore 0)
Quando premi tasto 0xFF38C7 allora metti questa variabile a LED_ON (valore 1)
Quando premi un altro tasto questa variabile o torna a LED_OFF oppure gli dai un altro valore per fare altro.

Quindi il programma deve fare le azioni in base al valore di questo stato

#include <IRremote.h> 

#define PINLED0 5
#define PINLED1 6
#define PINLED2 9
#define PINLED3 10
#define PINRECEIVER 11 

// stati possibili
#define LED_OFF 0
#define LED_ON_FADE 1
#define LED_ON_ALTRO 2
byte stato=LED_OFF;

IRrecv irrecv(PINRECEIVER); 
decode_results results;

void setup()
{ Serial.begin(9600); 
  irrecv.enableIRIn(); 
  pinMode (PINLED0, OUTPUT);
  pinMode (PINLED1, OUTPUT);
  pinMode (PINLED2, OUTPUT);
  pinMode (PINLED3, OUTPUT);
}

void loop()
{ if (irrecv.decode(&results))         //riceve segnale in esadecimale
  { Serial.println(results.value, HEX); 
    irrecv.resume();
  }
  // analizza tasto e modifica stato di conseguenza
  switch( results.value )
  { case 0xFF6897: stato=LED_OFF;      break;  //spegni led
    case 0xFF38C7: stato=LED_ON_FADE;  break;
  //case 0xFF0000: stato=LED_ON_ALTRO; break;  // altro tasto FF0000 è inventato non reale!!!
  }
  // analizza lo stato e agisce di conseguenza
  switch(stato)
  { case LED_OFF: 
      ledSpegni(); 
      break;
    case LED_ON_FADE: 
      ledAccendi(); //accende i led
      ledDissolvenzaSu(60);  
      ledDissolvenzaGiu(60);
      break;
    case LED_ON_ALTRO:
      // altro effetto
      break; 
   }
} 

void ledSpegni()
{ digitalWrite(PINLED0, HIGH);   
  digitalWrite(PINLED1, HIGH);
  digitalWrite(PINLED2, HIGH);
  digitalWrite(PINLED3, HIGH);
}
void ledAccendi()
{ digitalWrite(PINLED0, LOW);   
  digitalWrite(PINLED1, LOW);
  digitalWrite(PINLED2, LOW);
  digitalWrite(PINLED3, LOW);
}
void ledDissolvenzaSu(int attesa)
{ for(int fade=0; fade<255; fade+=5)  //dissolvenza led
  { analogWrite (PINLED0, fade);
    analogWrite (PINLED1, 255-fade);
    analogWrite (PINLED2, fade);
    analogWrite (PINLED3, 255-fade);
    delay (attesa);
  }
}
void ledDissolvenzaGiu(int attesa)
{ for(int fade=255; fade>0; fade-=5) 
  { analogWrite (PINLED0, fade);
    analogWrite (PINLED1, 255-fade);
    analogWrite (PINLED2, fade);
    analogWrite (PINLED3, 255-fade);
    delay (attesa);
  }
}

Grazie mille per il tuo tempo :slight_smile: ci stavo provando già, ma hai fatto molto prima di me hahahahah grazie ancora :slight_smile:

scusami volevo chiederti una cosa, mettendo altri effetti ho notato che il salto avviene solo quando finisce il case, se io volessi mettere un controllo che quando premo un altro tasto cambia effetto o semplicemente si spegne, cosa dovrei usare ? ho già provato con degli if ma non va

Il problema grosso sono le dissolvenze, hai due for da 0 a 255/5 con attesa di 60 millesimi 50*60=> 3 secondi in cui Arduino è "bloccato" in quel lavoro.
Farlo non bloccante non è per nulla semplice. Nel caso di stato=LED_ON_FADE dovresti far fare al codice solo 1 passo alla volta ricordando con un'altra variabile in quale momento è e quale valore è del fade (quindi la variabile int fade deve diventare globale e non locale al for).

Devi fare in modo che la loop non abbia dei cicli for o while. Così il controllo del tasto iniziale viene eseguito di continuo. Quei cicli for per gli effetti devi farli memorizzando in variabile globale in quale momento sei (dissolvenzasu, dissolvenzagiu) e anche il valore di fade.

Quindi in poche parole bisogna fare un ciclo for a mano? Per fare in ciclo for a mano bisogna usare degli if?

Spiega cosa vuoi fare
Non sono riuscito a seguire il tuo programma

Ho capito solo che hai del led e a comando vuoi fare degli effetti di luce, ma se durante un effetto dai un altro comando deve cambiare subito, giusto?

Quali ingressi, quali uscite, quali effetti?

In pratica ho usato 4 uscite per i led, tutti e 4 pwm, in pratica il programma funziona nn ci sono problemi ma quando premo un altro pulsante per cambiare effetto, prima di cambiare arduino aspetta che finisca il ciclo del case scelto, (E nn sempre lo fa infatti devo premere più volte il pulsante) in pratica volevo mettere dei controlli in modo che quando premo un pulsante l'effetto subito cambia

I led stanno sui piedini 5,6,9,10 mentre infrarossi sull' 11

skitarrata:
Quindi in poche parole bisogna fare un ciclo for a mano? Per fare in ciclo for a mano bisogna usare degli if?

No, il ciclo for è un blocco che sfrutta quella variabile fade. Ma la variabile nasce e muore con quel ciclo.
Invece quello che devi fare è avere una variabile fade globale (dichiarata all'inizio) e ad ogni ciclo di loop, se stato=LED_ON_FADE dovrai aumentare o diminuire fade di 5, ed eseguire quelle 4 digitalWrite, controllare fade se ha raggiunto il minimo o il massimo ed eventualmente azzerarla. Senza però un'altra variabile d'appoggio che sappia se tra un loop() e l'altro eri in fase di dissolvenzasu o dissolvenzagiu difficilmente ne esci.
Il ciclo continuo lo fa la loop, tu però devi controllare se la fade ha finito.

Ancora meglio sarebbe avere 2 stati LED_ON_FADESU e LED_ON_FADEGIU
Quando premi il tasto per il fade poni stato=LED_ON_FADESU, quello stato porta fade da 0 a 255, quando arriva a 255 allora stato=LED_ON_FADEGIU che invece porta fade da 255 a 0 e quando arriva a 0 rimette lo stato=LED_ON_FADESU
Si chiama macchina a stati finiti. Il passaggio da uno stato all'altro può dipendere dall'evento "premo tasto del telecomando" oppure dalla fine di un calcolo (nel nostro caso di fade)

#include <IRremote.h> 

#define PINLED0 5
#define PINLED1 6
#define PINLED2 9
#define PINLED3 10
#define PINRECEIVER 11 

// stati possibili
#define LED_OFF 0
#define LED_ON_FADESU 1
#define LED_ON_FADEGIU 2
byte stato=LED_OFF;
int fade=0;

IRrecv irrecv(PINRECEIVER); 
decode_results results;

void setup()
{ Serial.begin(9600); 
  irrecv.enableIRIn(); 
  pinMode (PINLED0, OUTPUT);
  pinMode (PINLED1, OUTPUT);
  pinMode (PINLED2, OUTPUT);
  pinMode (PINLED3, OUTPUT);
}

void loop()
{ if (irrecv.decode(&results))         //riceve segnale in esadecimale
  { Serial.println(results.value, HEX); 
    irrecv.resume();
  }
  // analizza tasto e modifica stato di conseguenza
  switch( results.value )
  { case 0xFF6897: stato=LED_OFF; break;  //spegni led
    case 0xFF38C7: stato=LED_ON_FADESU; fade=0; break;
  }
  // analizza lo stato e agisce di conseguenza
  switch(stato)
  { case LED_OFF: 
      ledSpegni(); 
      break;
    case LED_ON_FADESU: 
      ledDissolvenza(60);
      fade+=5; 
      if(fade>=255) stato=LED_ON_FADEGIU;
      break;
    case LED_ON_FADEGIU:
      ledDissolvenza(60);
      fade-=5; 
      if(fade<=0) stato=LED_ON_FADESU;
      break; 
   }
} 

void ledSpegni()
{ digitalWrite(PINLED0, HIGH);   
  digitalWrite(PINLED1, HIGH);
  digitalWrite(PINLED2, HIGH);
  digitalWrite(PINLED3, HIGH);
}
void ledAccendi()
{ digitalWrite(PINLED0, LOW);   
  digitalWrite(PINLED1, LOW);
  digitalWrite(PINLED2, LOW);
  digitalWrite(PINLED3, LOW);
}
void ledDissolvenza(int attesa)
{ analogWrite (PINLED0, fade);
  analogWrite (PINLED1, 255-fade);
  analogWrite (PINLED2, fade);
  analogWrite (PINLED3, 255-fade);
  delay (attesa);
}

nid ti ammiro molto, non solo per la tua disponibilità ma anche sul fatto che appena pensi le cose cosi subito le fai, e il bello che ti vengono pure bene, invece io devo farmi sempre prima lo schema logico su carte e poi vedere se in linguaggio mi va bene oppure no hahaha, spero un giorno di diventare come te, grazie ancora :slight_smile:

Di nulla. Nessuno nasce imparato.
Considera che sono un programmatore di professione, da 30 anni. :slight_smile:
Se invece mi fai domande di elettronica 9 volte su 10 vado in tilt :confused:

sul concetto di FSM (finite state machine, macchina a stati finiti) può essere utile leggere questo, uno dei pochi tutorial in italiano che ho trovato in rete, molto si trova ma in inglese:
http://www.lucadentella.it/2013/04/30/macchina-a-stati-finiti-e-arduino/

Io le macchine a stati finiti li ho fatti in calcolatori elettronici, nn so se sia la stessa cosa perche comunque non abbiamo mai usati arduino, ma gli darò un occhiata lo stesso :slight_smile:

si effettivamente come teoria e la stessa, ma non avevo mai pensato che si poteva fare pure con arduino, ciò che non capisco è perché l'università non tratta proprio arduino o altre schede, microcontrollori, macchine sequenziali ecc.. più odierne, è pur vero che sto ancora all'inizio, e spero che cambierà qualcosa nel corso degli anni, comunque grazie per il link :wink: