Problema software con lampada RGB

Ciao a tutti, ho realizzato una lampada RGB, basata su Arduino 2009 standalone e LED Luxeon da 3 W, controllata solo tramite un telecomando (DTT):

La lampada, funziona perfettamente, ad esclusione della funzione fade():

/*

Nome Progetto: Arduino RGB Lamp
Versione:      0.5

Codici Telecomando DTT:

  Accensione = FFE817 = 16771095
  Muto       = FF40BF = 16728255
  Tasto 1    = FF32CD
  Tasto 2    = FF708F
  Tasto 3    = FFB24D
  Tasto 4    = FFF20D
  Tasto 5    = FF728D
  Tasto 6    = FFD02F
  Tasto 7    = FF52AD
  Tasto 8    = FF12ED
  Tasto 9    = FF50AF
  Tasto 0    = FFB04F
  Vol +      = FFA857 = 16754775
  Vol -      = FFE21D = 16769565
  PR +       = FF629D
  PR -       = FF6897
  TXT        = FF48B7
  OK         = FFAA55 = 16755285
  Menu       = FFA05F
  Exit       = FF18E7
  TV/Radio   = FFF00F
  <-PR       = FF30CF
  EPG        = FF22DD
  INFO       = FFD827
  Audio      = FFC837
  Subtitle   = FF827D
  FAV        = FF609F
  [][]       = FFE01F
  Pause      = FF906F
  Record     = FF5AA5
  Stop       = FF9867
  Rosso      = FF0AF5 = 16714485
  Verde      = FFCA35 = 16763445
  Giallo     = FF8A75 = 16747125
  Blu        = FF8877 = 16746615  
  
  Errore     = FFFFFFFF
*/

#include <IRremote.h>

#define MAX_R 190
#define MAX_GB 250
#define FADE_TIME 300    // Durata della sfumatura
#define COLOUR_TIME 1000 // Durata di ogni colore

// Dichiarazione dei pin
int PIN_2 = 2;
int PIN_3 = 3;
int PIN_4 = 4;
int PIN_5 = 5;
int RECV_PIN = 6;
int B_PIN = 11;
int G_PIN = 9;
int R_PIN = 10;

// Dichiarazione delle variabili
int mod_auto=0;

// Matrice dei colori (R,G,B)
int colours_matrix[9][4] = {
                            { MAX_R, MAX_GB, MAX_GB }, 
                            { MAX_R, MAX_GB, 0      }, 
                            { MAX_R, 0,      MAX_GB }, 
                            { MAX_R, 0,      0      },
                            { 0,     MAX_GB, MAX_GB },   
                            { 0,     MAX_GB, 0      },   
                            { 0,     0,      MAX_GB },   
                            { 0,     0,      0      }  
                          };
                            
int R=0, G=0, B=0, R_old=0;
int colore_attuale = 0, index = 0, i=0, j=0, count=0, uscita=0;

IRrecv irrecv(RECV_PIN);
decode_results results;

String tasto_premuto = "";
String tasto_power = String("16771095");
String tasto_rosso = String("16714485");
String tasto_verde = String("16763445");
String tasto_giallo= String("16747125");
String tasto_blu   = String("16746615");
String tasto_viola = String("16728255");
String tasto_ok    = String("16755285");
String tasto_volp  = String("16754775");
String tasto_volm  = String("16769565");

// Prototipi delle funzioni

void lamp_OFF(void);
int rnd(void);
void  wait_power_off(void);
void fade(void);

void setup()
{
  Serial.begin(9600);
  pinMode(PIN_2, OUTPUT);
  pinMode(PIN_3, OUTPUT);
  pinMode(PIN_4, OUTPUT);
  pinMode(PIN_5, OUTPUT);
  pinMode(RECV_PIN, INPUT);
  pinMode(R_PIN, OUTPUT);
  pinMode(G_PIN, OUTPUT);
  pinMode(B_PIN, OUTPUT);
  
  mod_auto=0;
  lamp_OFF();
  
  irrecv.enableIRIn(); // Start the receiver
}

void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value);
    tasto_premuto = String(results.value);
    if( !tasto_premuto.compareTo(tasto_rosso) ){
      analogWrite(R_PIN, MAX_R);
      digitalWrite(G_PIN, LOW);
      digitalWrite(B_PIN, LOW);
      colore_attuale = 3;
    }
    if( !tasto_premuto.compareTo(tasto_verde) ){
      digitalWrite(R_PIN, LOW);
      digitalWrite(G_PIN, MAX_GB);
      digitalWrite(B_PIN, LOW);
      colore_attuale = 5;
    }
    if( !tasto_premuto.compareTo(tasto_blu) ){
      digitalWrite(R_PIN, LOW);
      digitalWrite(G_PIN, LOW);
      digitalWrite(B_PIN, MAX_GB);
      colore_attuale = 6;
    }
    if( !tasto_premuto.compareTo(tasto_viola) ){
      analogWrite(R_PIN, MAX_R);
      digitalWrite(G_PIN, LOW);
      digitalWrite(B_PIN, MAX_GB);
      colore_attuale = 2;
    }
    if( !tasto_premuto.compareTo(tasto_giallo) ){
      analogWrite(R_PIN, MAX_R);
      digitalWrite(G_PIN, MAX_GB);
      digitalWrite(B_PIN, LOW);
      colore_attuale = 1;
    }
    if( !tasto_premuto.compareTo(tasto_volp) ){
      index = (colore_attuale + 1);
      if(index>7)
        index = 0;
      
      analogWrite(R_PIN, colours_matrix[index][0]);
      digitalWrite(G_PIN, colours_matrix[index][1]);
      digitalWrite(B_PIN, colours_matrix[index][2]);
      colore_attuale = index;
    }
    if( !tasto_premuto.compareTo(tasto_volm) ){
      index = (colore_attuale - 1);
      if(index<0)
        index = 7;
      
      analogWrite(R_PIN, colours_matrix[index][0]);
      digitalWrite(G_PIN, colours_matrix[index][1]);
      digitalWrite(B_PIN, colours_matrix[index][2]);
      colore_attuale = index;
    }
    if( !tasto_premuto.compareTo(tasto_power) ){
      lamp_OFF();
      mod_auto=0;
      colore_attuale = 7;
    }
    if( !tasto_premuto.compareTo(tasto_ok) )
      mod_auto=1;
    
    irrecv.resume(); // Receive the next value
  }
  if(mod_auto==1)
    fade();
}

// Funzioni

void lamp_OFF(void){
  digitalWrite(R_PIN, LOW);
  digitalWrite(G_PIN, LOW);
  digitalWrite(B_PIN, LOW);
  return;
}

int rnd(){
  int rand = random(0,7);
  return rand;
}

void  wait_power_off(void){
  for(int k=0;k<5;k++){
    if (irrecv.decode(&results)) {
      tasto_premuto = String(results.value);
      if( !tasto_premuto.compareTo(tasto_power) ){
        lamp_OFF();
        irrecv.resume(); // Receive the next value
        uscita=1;
        return;
      }      
    }
    delay(10);
  }
  return;  
}

void fade(void){
  uscita=0;
  mod_auto=0;
  count=0;
  while(1){ // Modalità loop, si esce solo con power_off
    j = rnd();
    R = colours_matrix[j][0];
    G = colours_matrix[j][1];
    B = colours_matrix[j][2];
    
    if(count){
      if(R_old > R){
        for(i=R_old; i>50; i=i-20){
          analogWrite(R_PIN, i);
          digitalWrite(G_PIN, G);
          digitalWrite(B_PIN, B);
          wait_power_off();
          if(uscita)
            return;
          delay(FADE_TIME);
          R_old = R;
        }
      }
      else if(R_old < R){
         for(i=80; i<R; i= i+20){
          analogWrite(R_PIN, i);
          digitalWrite(G_PIN, G);
          digitalWrite(B_PIN, B);
          wait_power_off();
          if(uscita)
            return;
          delay(FADE_TIME);
          R_old = R;
        }
      }
     else if(R_old==R){
       analogWrite(R_PIN, R);
       digitalWrite(G_PIN, G);
       digitalWrite(B_PIN, B);
       R_old = R;
     } 
    }
    else{    
      analogWrite(R_PIN, R);
      digitalWrite(G_PIN, G);
      digitalWrite(B_PIN, B);
      count = 1;
      R_old = R;
    }
    
    colore_attuale = j;

    for(i=0; i<(COLOUR_TIME/100); i++){
      wait_power_off();
      if(uscita)
        return;
      delay( COLOUR_TIME / (COLOUR_TIME/100) );
    }
  }
}

In pratica, nella maggior parte dei tentativi, non riesco ad uscire dal loop della stessa funzione fade(), nonostante prema numerose volte il tasto power (che funziona perfettamente al di fuori di questa funzione).

A nulla è servito, "spargere" controlli sulla ricezione del tasto power prima di ogni delay()... :0

Uscendo dalla funzione Fade dovresti mettere mod_auto=0 altrimenti, al prossimo ciclo (ricorda che chiami fave dentro a loop(), quindi viene fatto all'infinito), ci rientri dentro.

if(mod_auto==1) {
    fade();
    mod_auto=0;
}

L'avevo già inserito all'inizio della funzione fade():

void fade(void){
  uscita=0;
  mod_auto=0;
...

Ah, è vero... non l'avevo visto :smiley:

Hai provato a fare un po' di debug, mettendo un po' di Serial.print in diversi punti della funzione Fade per vedere da quale ciclo non esce?

Ciao, si ho provato ma non cavo il ragno dal buco! :~

Ho modificato la funzione in versione debug così:

void fade(void){
  uscita=0;
  mod_auto=0;
  count=0;
  int nCicli=0;
  while(1){ // Modalità loop, si esce solo con power_off
    j = rnd();
    ++nCicli;
    Serial.print(nCicli, DEC);
    Serial.print(") j = ");
    Serial.println(j, DEC);
    R = colours_matrix[j][0];
    G = colours_matrix[j][1];
    B = colours_matrix[j][2];
    
    if(count){
      if(R_old > R){
        Serial.println("R_old>R");
        for(i=R_old; i>50; i=i-20){
          analogWrite(R_PIN, i);
          digitalWrite(G_PIN, G);
          digitalWrite(B_PIN, B);
          wait_power_off();
          if(uscita)
            return;
          delay(FADE_TIME);
          R_old = R;
        }
      }
      else if(R_old < R){
        Serial.println("R_old<R"); 
        for(i=80; i<R; i= i+20){
          analogWrite(R_PIN, i);
          digitalWrite(G_PIN, G);
          digitalWrite(B_PIN, B);
          wait_power_off();
          if(uscita)
            return;
          delay(FADE_TIME);
          R_old = R;
        }
      }
     else if(R_old==R){
       Serial.println("R_old=R");
       analogWrite(R_PIN, R);
       digitalWrite(G_PIN, G);
       digitalWrite(B_PIN, B);
       wait_power_off();
       if(uscita)
         return;
       R_old = R;
     } 
    }
    else{    
      analogWrite(R_PIN, R);
      digitalWrite(G_PIN, G);
      digitalWrite(B_PIN, B);
      count = 1;
      R_old = R;
    }
    
    colore_attuale = j;

    for(i=0; i<(COLOUR_TIME/100); i++){
      wait_power_off();
      if(uscita)
        return;
      delay( COLOUR_TIME / (COLOUR_TIME/100) );
    }
  }
}
void  wait_power_off(void){
  for(int k=0;k<5;k++){
    if (irrecv.decode(&results)) {
      tasto_premuto = String(results.value);
      if( !tasto_premuto.compareTo(tasto_power) ){
        lamp_OFF();
        irrecv.resume(); // Receive the next value
        uscita=1;
        Serial.println("Uscita dalla funzione fade()!");
        return;
      }      
    }
    delay(10);
  }
  return;  
}

Ottenendo il seguente output:

1) j = 1
2) j = 1
R_old=R
3) j = 5
R_old>R
4) j = 2
R_old<R
5) j = 4
R_old>R
6) j = 2
R_old<R
7) j = 0
R_old=R
8) j = 2
R_old=R
9) j = 5
R_old>R
10) j = 1
R_old<R
11) j = 0
R_old=R
12) j = 5
R_old>R
13) j = 0
R_old<R
14) j = 2
R_old=R
15) j = 3
R_old=R
16) j = 5
R_old>R
17) j = 1
R_old<R
18) j = 1
R_old=R
19) j = 4
R_old>R
20) j = 4
R_old=R
21) j = 3
R_old<R
22) j = 1
R_old=R
23) j = 3
R_old=R
24) j = 5
R_old>R
25) j = 4
R_old=R
26) j = 3
R_old<R
27) j = 3
R_old=R
28) j = 0
R_old=R
29) j = 2
R_old=R
30) j = 1
R_old=R
31) j = 1
R_old=R
32) j = 2
R_old=R
33) j = 2
R_old=R
34) j = 1
R_old=R
35) j = 2
R_old=R
36) j = 3
R_old=R
37) j = 1
R_old=R
38) j = 1
R_old=R

Non c'è verso di far terminare la funzione fade() !

EDIT: ho risolto, semplificando così la funzione d'uscita:

void  wait_power_off(void){
  if (irrecv.decode(&results)) {
        lamp_OFF();
        irrecv.resume(); // Receive the next value
        uscita=1;
        Serial.println("Uscita dalla funzione fade()!");
        return;
   }      
  return;  
}

vedi; Ti ha aiutato chiedercelo. :wink: :wink: :wink:

Spesso quando devi pensare come spiegare il problema agli altri per chiedere aiuto ti fa capire meglio il problema e spesso porta questo a una soluzione.

Comunque siamo quá per il prossimo Tuo problema.

Ciao Uwe

uwefed:
vedi; Ti ha aiutato chiedercelo. :wink: :wink: :wink:

In che modo? :slight_smile:
Chiaramente ringrazio comunque leo72 per i suoi interventi...

Non mancherò di aprire un topic anche per gli eventuali "problemi" futuri... :slight_smile: