Help con strano comportamento fade rgb anodico

Buonasera a tutti,

Mi chiamo Francesco e sono un autodidatta di Arduino (di mestiere sono un chimico), mi diletto ogni tanto con i miei arduino a realizzare piccoli progetti semplici. In questi mesi ho lavorato ad un sistema di led con telecomando IR per illuminare un diorama Lego. Dopo mesi di errori e sbattimenti sono riuscito a completare il codice ma ho incontrato un problema al di là delle mie conoscenze.

Nello scenario sono collegati numerosi led e ad ogni gruppo di led legato ad una funzione specifica (es: lampadari soffitto) ho assegnato un tasto del telecomando IR e fin qui tutto bene

E' presente anche una striscia RGB (anodica perchè il 4o pin va alimentato non va a massa???) che viene accesa di rosso con un pulsante, di blu con un altro e invece fa effetto fade con il terzo pulsante.

Il problema è questo, funziona tutto a meraviglia finchè non premo il pulsante dell'effetto fade: l'effetto fade si verifica ma manda in blocco tutto il resto, gli altri led che sono accesi non rispondono più al comando accensione/spegnimento e la stessa striscia rimane bloccata sul un colore.

Allego il codice ed un piccolo video per chiarezza.

Più che risolvere il problema sarei interessato a capire cosa si fa in questi casi? Come si riesce ad individuare il problema?

Grazie!!!

https://www.facebook.com/reel/658126203025868

#include <Adafruit_NeoPixel.h>
#include <IRremote.h>
#define timer 1000
#define num_pins 12
#define GREEN 10
#define BLUE 9
#define RED 8
#define delayTime 20


byte ledPinSX[] = {40, 41, 42, 43, 44, 45};
byte ledPinDX[] = {48, 49, 50, 51, 52, 53};
byte ledDelay = 1500;
byte direzioneSX = 1;
byte actualLedSX = 0;
byte direzioneDX = 1;
byte actualLedDX = 0;
byte lamp[] = {34, 35, 36};

unsigned long timeOccured;

IRrecv irrecv(22);
decode_results res;

void translateIR() { // describing Remote IR codes
  switch(res.value)  {
  case 0xFFA25D: Serial.println("POWER"); break;
  case 0xFFE21D: Serial.println("FUNC/STOP"); break;
  case 0xFF629D: Serial.println("VOL+"); break;
  case 0xFF22DD: Serial.println("FAST BACK");    break;
  case 0xFF02FD: Serial.println("PAUSE");    break;
  case 0xFFC23D: Serial.println("FAST FORWARD");   break;
  case 0xFFE01F: Serial.println("DOWN");    break;
  case 0xFFA857: Serial.println("VOL-");    break;
  case 0xFF906F: Serial.println("UP");    break;
  case 0xFF9867: Serial.println("EQ");    break;
  case 0xFFB04F: Serial.println("ST/REPT");    break;
  case 0xFF6897: Serial.println("0");    break;
  case 0xFF30CF: Serial.println("1");    break;
  case 0xFF18E7: Serial.println("2");    break;
  case 0xFF7A85: Serial.println("3");    break;
  case 0xFF10EF: Serial.println("4");    break;
  case 0xFF38C7: Serial.println("5");    break;
  case 0xFF5AA5: Serial.println("6");    break;
  case 0xFF42BD: Serial.println("7");    break;
  case 0xFF4AB5: Serial.println("8");    break;
  case 0xFF52AD: Serial.println("9");    break;
  case 0xFFFFFFFF: Serial.println(" REPEAT");break;  

  default: Serial.println(" other button   ");
  }// End Case

  delay(500); // Do not get immediate repeat
} //END translateIR

void setup() 
{
  Serial.begin(9600);
  Serial.println("IR Receiver Button Decode"); 
  irrecv.enableIRIn();
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);      
  pinMode(11, OUTPUT);
  pinMode(27, OUTPUT);
  pinMode(28, OUTPUT);
  pinMode(29, OUTPUT);    
  pinMode(36, OUTPUT); //lamps 1-2
  pinMode(37, OUTPUT); //lamps 3-4
  pinMode(38, OUTPUT); //lamps 4-6     
  pinMode(46, OUTPUT); //light repeater blaster  
  pinMode(47, OUTPUT); //high repeater blaster

for (byte x=0; x<3; x++){
    pinMode(lamp[x], OUTPUT);
  }

for (byte x=0; x<6; x++){
    pinMode(ledPinSX[x], OUTPUT);
    pinMode(ledPinDX[x], OUTPUT);
    timeOccured = millis();
  }
}

void loop()
{
  if (irrecv.decode(&res)) // have we received an IR signal?
  {
    translateIR();
    Serial.println(res.value, HEX); // display it on serial monitor in hexadecimal
    irrecv.resume();// receive the next value
    delay(500);
  }

if (res.value == 0xFF30CF){ //button 1 lamp led ON
for (byte x=0; x<3; x++) {
      digitalWrite(lamp[x], HIGH);
    } 
  }

if (res.value == 0xFF7A85){ //button 3 airstrip ON
for (byte x=0; x<6; x++) {
      digitalWrite(ledPinSX[x], HIGH);
      digitalWrite(ledPinDX[x], HIGH);      
    } 
  }

if (res.value == 0xFF10EF){ //button 4 machine guns
digitalWrite(46, HIGH);
digitalWrite(47, HIGH);
}

if (res.value == 0xFF38C7){ //button 5 blue MF engine
  digitalWrite(11, HIGH);
  digitalWrite(8, 255); //red
  digitalWrite(9, 0); //green
  digitalWrite(10, 0); //blue
}

if (res.value == 0xFF5AA5){ //button 6 red MF engine
  digitalWrite(11, HIGH);
  digitalWrite(8, 0); //red
  digitalWrite(9, 255); //green
  digitalWrite(10, 255); //blue
}

if (res.value == 0xFF4AB5){ //button 8 MF leds
  digitalWrite(28, HIGH);
  digitalWrite(29, HIGH);
}

if (res.value == 0xFF52AD){ //button 9 kiber cage
  digitalWrite(27, HIGH);
}

if (res.value == 0xFF42BD){ //button 7 fade MF engine
  digitalWrite(11, HIGH);
  int redVal = 255;
  int blueVal = 0;
  int greenVal = 0;
  for( int i = 0 ; i < 255 ; i += 1 ){
    greenVal += 1;
    redVal -= 1;
    analogWrite( GREEN, 255 - greenVal );
    analogWrite( RED, 255 - redVal );

    delay( delayTime );
  }

  redVal = 0;
  blueVal = 0;
  greenVal = 255;
  for( int i = 0 ; i < 255 ; i += 1 ){
    blueVal += 1;
    greenVal -= 1;
    analogWrite( BLUE, 255 - blueVal );
    analogWrite( GREEN, 255 - greenVal );

    delay( delayTime );
  }

  redVal = 0;
  blueVal = 255;
  greenVal = 0;
  for( int i = 0 ; i < 255 ; i += 1 ){
    redVal += 1;
    blueVal -= 1;
    analogWrite( RED, 255 - redVal );
    analogWrite( BLUE, 255 - blueVal );

    delay( delayTime );
  
}
}
if (res.value == 0xFF6897){ //button 0 all leds OFF
 
 digitalWrite(27, LOW);
 digitalWrite(28, LOW);
 digitalWrite(29, LOW);   
 digitalWrite(46, LOW);
 digitalWrite(47, LOW);
 digitalWrite(11, LOW);
 

 for (byte x=0; x<3; x++) {
      digitalWrite(lamp[x], LOW);
}
      
for (byte x=0; x<6; x++) {
      digitalWrite(ledPinSX[x], LOW);
      digitalWrite(ledPinDX[x], LOW);
}
} //end button 0

if (res.value == 0xFF18E7 && (millis() - timeOccured) > ledDelay){ //button 2 fade airstrip
    cambiaStatoLed();
      timeOccured = millis();
  }
}
void cambiaStatoLed(){
  for (byte x=0; x<6; x++) {
      digitalWrite(ledPinSX[x], LOW);
      digitalWrite(ledPinDX[x], LOW);
}
digitalWrite(ledPinSX[actualLedSX], HIGH);
    actualLedSX += direzioneSX;
    if (actualLedSX == 5) {
      direzioneSX = -1;
    }
    if (actualLedSX == 0) {
      direzioneSX = 1;
    }
    digitalWrite(ledPinDX[actualLedDX], HIGH);
    actualLedDX += direzioneDX;
    if (actualLedDX == 5) {
      direzioneDX = -1;
    }
    if (actualLedDX == 0) {
      direzioneDX = 1;
    }

}


Buonasera e benvenuto nella sezione Italiana del forum,

cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO di detta sezione, (... e, per evitare future possibili discussioni/incomprensioni, prestando molta attenzione al punto 15), dopo di che, come da suddetto regolamento (punto 16.7), fai la tua presentazione NELL'APPOSITA DISCUSSIONE spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.

Grazie,

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione, nel rispetto del succitato regolamento nessuno ti risponderà (eventuali risposte o tuoi ulteriori post, verrebbero temporaneamente nascosti), quindi ti consiglio di farla al più presto. :wink:

perdonami ma dopo la presentazione devo rifare lo stesso post?

No, no, va bene così :wink:

Guglielmo

Beh, considera che quando esegui questo pezzo di codice:

... tu blocchi qualsiasi altra cosa fino alla fine dato che, durante il periodo del "fade" sei chiuso in dei cicli FOR che usano anche dei delay() per ritardare i vari cicli e quindi null'altro può essere fatto sino a quando l'effetto non è completato.

Considera che andare da 0 a 255 con un ritardo di 20 msec significa impiegare più di 5 secondi, tu ripeti la cosa tre volte ... ecco che per 15 secondi NON puoi fare altro.

Guglielmo

quindi non riesco ad inviare nemmeno l'istruzione di spegnere tutto perchè rimango incastrato nel ciclo for?
Dovrei introdurre quindi nel pulsante che spegne tutto un istruzione del tipo break?
ma dovrebbe essere localizzata all'interno del for per funzionare no?

ho notato solo adesso dal monitor seriale che quando mando l'istruzione per il fade cambiano i codici del remoto...ecco perchè gli altri comandi non rispondo più...

ps. che casino mi sto eccitando come uno scolaretto risolverò il problema!!!

No. Devi fare in modo che il loop continui a scorrere: quando viene premuto un pulsante, il valore viene memorizzato in una variabile, per esempio stato. Finché stato ha quel valore, a ogni giro di loop viene verificato se è trascorso il delayTime e ogni volta che è trascorso viene eseguito un passo del for (togliendo il for). Se viene premuto un altro pulsante, stato cambia e viene eseguita un'altra cosa; altrimenti, finita la sequenza, stato viene azzerato.

penso che il problema stia nel fatto che al termine dei 15 secondi i codici inviati dal telecomando cambiano! ho provato ad inserire un || res.value (nuovo segnale IR) nell'istruzione che spegne tutto e la striscia si spegne, ma sono cambiati anche tutti gli altri codici quindi di conseguenza il resto non funziona più...

Siamo a 3 contro 1. Il problema è quello che ti ha fatto notare @gpb01.
Mentre @Datman ti ha dato un indizio su come risolvere.

Ci siamo passati tutti e non sei il primo e non sarai l'ultimo.
Risolvere non è facile ed intuitivo, ma lo è il modo che hai usato che purtroppo ha questo effetto lato.

Se ci pensi è come se al posto dei for in sequenza ci mettessi:

delay(15000);

Se cerchi sul forum, trovi molti utenti che si chiedono come eseguire dei compiti in parallelo, uno recente:

Ciao, e benvenuto.

Quello è un'altro problema, in funzione della codifica IR i codici inviati possono avere una determinata sequenza ... se il tuo telecomando cambia i codici ... dovrai prevedere anche quella cosa ... :roll_eyes:

Guglielmo

Che modelli di trasmettitore e ricevitore stai usando come telecomando ?
Hai un link al prodotto ?

il ricevitore e il telecomando IR li ho recuperati dal kit elegoo mega 2560, ho provato senza successo a cercare le sigle o qualche altra informazione ma non saprei bene da dove cominciare, allego link e foto

Immagine 2023-06-24 133743

Quindi non dovrebbero essere dei "rolling code", ma dei comuni telecomandi IR con portante sui 38KHz, strano che i codici trasmessi cambino durante l'uso.

Non e' che, come gia detto da altri, semplicemente i cicli for bloccano tutto, quindi anche la ricezione dei codici, mentre fanno il fade ?

Infatti io farei un programmino semplice semplice SOLO per la lettura dei codici del telecomando e dopo li applicherei ad un programma più complesso ... così si è sicuri di cosa arriva. :wink:

Guglielmo

potrebbe funzionare, fare una funzione solo per il fade, basata su millis, da richiamare ad ogni giro del loop ?

No, sul IR è difficile che li trovi, ma trovi invii differenti a seconda se è tasto premuto, tasto rilasciato, tasto tenuto premuto ...

Guglielmo

SI, infatti è così che si fa, si chiama in continuazione la funzione che effettua solo un singolo step del "fade" e poi ritorna, così si possono continuare a fare altre cose :wink:

Guglielmo

con il mio metodo "rozzo" di inserire i nuovi codici ho risolto il problema (non sembrano cambiare nuovamente rifacendo il for del fade) ma sinceramente non mi piace molto questa soluzione

cosa genera questa specie di conflitto che crea il cambio codice?

Uhm ... cosi ad occhio, mi verrebbe da fare una cosa del genere ... condiziono la chiamata alla funzione in base ad una flag (cosi la chiamo solo se deve fare il fade), definisco una int per il gradino fra i livelli del fade (diciamo 10) ed una unsigned int per il valore del led (diciamo che parte da 15, led su un pin PWM), poi nella funzione, se millis - tempo >= 10 (tanto per fare uno step ogni 10mS, puo essere un valore a scelta), rimetto tempo = millis, controllo, se valore maggiore di diciamo 240 metto il gradino a -10, "else if" se e' minore di diciamo 15 metto il gradino a 10, poi valore += gradino ed analogWrite(ledPin, valore) ... cosi a naso potrebbe andare, o ci vedi qualche ca...volata ? (non posso testare in pratica adesso)