Problema con cicli For...Then

Ciao a tutti.
Ho realizzato una illuminazione per la mia scala interna di casa, con l'idea di accendere in sequenza ogni gradino a seconda della direzione, per poi farli spegnere dopo un certo tempo nella stessa direzione.
Come led ho utilizzato dei WS2812, e come interruttori 2 IRSwitch (1 sul primo gradino e 1 sull'ultimo).
Poi ho fatto una semplice programmazione di test (Test01), utilizzando un ciclo For per l'accensione in una direzione, e un altro ciclo analogo per lo spegnimento.
In salita tutto ha funzionato a meraviglia: ogni scalino (gruppi di 3 led a gradino) si accende in sequenza non appena metto il piede sul primo gradino.
Allora ho implementato il codice (stessa filosofia) per la discesa. Ma stavolta non ne vuole sapere di funzionare.
A parte che funziona solo in discesa (ma questo penso sia un problema legato alla taratura dell'IR switch che regola la discesa), comunque ho provato a collegare il solo IR della salita (che è già tarato a dovere) utilizzandollo come se fosse quello della discesa ma il risultato non è cambiato.
In pratica i led si accendono in modo giusto in sequenza; ma si spengono in un colpo solo tutti insieme.
Ho provato a cambiare il colore dello spegnimento da nero a rosso. Con il rosso funziona: da bianchi si "spengono" in rosso in sequenza giusta. Come rimetto il colore nero, di nuovo ricominciano a spegnersi tutti contemporaneante.
Inoltre, utilizzando i 2 IRswitch, oltre al "non funzionamento" di cui sopra, il sensore della salita viene completamente ignorato. in pratica ho regolato al minimo il sensore della discesa (per attivarlo praticamente devo toccarlo) così da non mandare segnali, ma passando davanti a quello della salita, non viene più rilevato.

Penso che tutto sia un problema riconducibile alla programmazione, ma non so più dove mettere le mani...

Vi posto entrambe i codici (quello relativo alla sola salita - che funziona a dovere - e quello con salita e discesa - che è quello che non ne vuole sapere di funzionare)

Mi ci date uno sguardo? magari trovate l'errore, o se avete qualche altra soluzione....

Grazie

Andrea

/*
File di test in salita
Accende 16 scalini da 3 led (totale 48 led) ws2812 in sequenza in una direzione
Usa un IRSwitch per comandare l'accensione
Attende, poi li spegne nella stessa sequenza
*/


#include <FastLED.h> //Carico la libreria FastLed

#define NumLed 48 //Creo la costante NumLed pari a 48 leds

#define DataPin 7 //Creo la costante DataPin che assegna il pin 7 di controllo dei led

#define timer1 200 //definisco la costante timer1 pari a 200 ms
#define timer2 15000 //definisco la costante timer2 pari a 15000 ms (15 secondi)

CRGB leds[NumLed]; 

const unsigned int IR1=8;   //definisco la costante IR1 e la assegno al pin 8 - switch 1 rampa sala>notte

int IR1State = HIGH;    //definisco la variabile IR1State e le setto a HIGH - stato dello switch 1


void setup() {
  
  FastLED.addLeds<NEOPIXEL, DataPin>(leds, NumLed);
  
  pinMode (IR1, INPUT);  //stabilisco che il pin di IR1 è in input
}

void loop()  {
  IR1State = digitalRead (IR1);  //leggo lo stato di IR1
  
   if (IR1State == LOW) {  //accende in salita la scala sala>notte
    Rampa01A();
  }
  
}

void Rampa01A()  {
  for (int m = 0; m < NumLed; m=m+1){  //questo ciclo accende in sequenza gruppi di 3 led
  leds[m] = CRGB::White;
  leds[m=m+1] = CRGB::White;
  leds[m=m+1] = CRGB::White;
  FastLED.show();
  delay(timer1);
  }
  delay (timer2);
  for (int m = 0; m < NumLed; m=m+1){  //questo ciclo spegne in sequenza gruppi di 3 led
  leds[m] = CRGB::Black;
  leds[m=m+1] = CRGB::Black;
  leds[m=m+1] = CRGB::Black;
  FastLED.show();
  delay(timer1);
  }

e questo è quello per salita e discesa

/*
File di test per salita e discesa
Accende 16 scalini da 3 led (totale 48 led) ws2812 in sequenza in 2 direzioni
Usa 2 IRSwitch per comandare l'accensione
Attende, poi li spegne nella stessa sequenza
*/


#include <FastLED.h> //Carico la libreria FastLed

#define NumLed 48 //Creo la costante NumLed pari a 48 leds

#define DataPin 7 //Creo la costante DataPin che assegna il pin 7 di controllo dei led

#define timer1 200 //definisco la costante timer1 pari a 200 ms
#define timer2 15000 //definisco la costante timer2 pari a 15000 ms (15 secondi)

CRGB leds[NumLed]; 

const unsigned int IR1=8;   //definisco la costante IR1 e la assegno al pin 8 - switch 1 rampa sala>notte
const unsigned int IR2=9;   //definisco la costante IR1 e la assegno al pin 9 - switch 1 rampa notte>sala

int IR1State = HIGH;    //definisco la variabile IR1State e la setto a HIGH - stato dello switch 1
int IR2State = HIGH;    //definisco la variabile IR2State e la setto a HIGH - stato dello switch 2

void setup() {
  
  FastLED.addLeds<NEOPIXEL, DataPin>(leds, NumLed);
  
  pinMode (IR1, INPUT);  //stabilisco che il pin di IR1 è in input
  pinMode (IR2, INPUT);  //stabilisco che il pin di IR2 è in input
}

void loop()  {
  IR1State = digitalRead (IR1);  //leggo lo stato di IR1
  IR2State = digitalRead (IR2);  //leggo lo stato di IR2
  
  if (IR1State == LOW) {  //accende in salita la scala sala>notte
    Rampa01A();
  }
  
  if (IR2State == LOW) {  //accende in salita la scala notte>sala
    Rampa01B();
  }
  
}

void Rampa01A()  {
  for (int m = 0; m < NumLed; m=m+1){  //questo ciclo accende in sequenza gruppi di 3 led in salita
  leds[m] = CRGB::White;
  leds[m=m+1] = CRGB::White;
  leds[m=m+1] = CRGB::White;
  FastLED.show();
  delay(timer1);
  }
  delay (timer2);
  for (int m = 0; m < NumLed; m=m+1){  //questo ciclo spegne in sequenza gruppi di 3 led in salita
  leds[m] = CRGB::Black;
  leds[m=m+1] = CRGB::Black;
  leds[m=m+1] = CRGB::Black;
  FastLED.show();
  delay(timer1);
  }
}

void Rampa01B()  {
  for (int m=NumLed; m>=0; m=m-1) {  //questo ciclo accende in sequenza gruppi di 3 led in discesa
  leds[m] = CRGB::White;
  leds[m=m-1] = CRGB::White;
  leds[m=m-1] = CRGB::White;
  FastLED.show();
  delay(timer1);
  }
  delay(timer2);
  for (int m=NumLed; m>=0; m=m-1) {  //questo ciclo spegne in sequenza gruppi di 3 led in discesa
  leds[m] = CRGB::Black;
  leds[m=m-1] = CRGB::Black;
  leds[m=m-1] = CRGB::Black;
  FastLED.show();
  delay(timer1);
  }
}

L'errore è presente nei cicli for all'istruzione leds[m = m + 1]: non puoi assegnare un valore alla variabile m all'interno di un elemento di array.

Fai così:

void Rampa01A()  {
  for (int m = 0; m < NumLed; m = m + 3)
    leds[m] = CRGB::White;
    leds[m + 1] = CRGB::White;
    leds[m + 2] = CRGB::White;
    FastLED.show();
    delay(timer1);
  }
  delay (timer2);
  for (int m = 0; m < NumLed; m = m + 3)
    leds[m] = CRGB::Black;
    leds[m + 1] = CRGB::Black;
    leds[m + 2] = CRGB::Black;
    FastLED.show();
    delay(timer1);
  }
}

void Rampa01B()  {
  for (int m = NumLed; m < 0; m = m - 3) {  //questo ciclo accende in sequenza gruppi di 3 led in discesa
    leds[m] = CRGB::White;
    leds[m - 1] = CRGB::White;
    leds[m - 2] = CRGB::White;
    FastLED.show();
    delay(timer1);
  }
  delay(timer2);
  for (int m = NumLed; m < 0; m = m - 3) {  //questo ciclo spegne in sequenza gruppi di 3 led in discesa
    leds[m] = CRGB::Black;
    leds[m - 1] = CRGB::Black;
    leds[m - 2] = CRGB::Black;
    FastLED.show();
    delay(timer1);
  }

cyberhs:
L'errore è presente nei cicli for all'istruzione leds[m = m + 1]: non puoi assegnare un valore alla variabile m all'interno di un elemento di array.

ma puoi usare ++m e --m per aumentare o diminuire il valore prima del uso della variabile.
++mé uguale a m=m+1 prima del uso della variabile m. mentre m++ incrementa la variaboile dopo l' uso.

Controlla anche che l' indice non supera la grandezza del array.

Ciao Uwe

cyberhs:
L'errore è presente nei cicli for all'istruzione leds[m = m + 1]: non puoi assegnare un valore alla variabile m all'interno di un elemento di array.

No, è un modo lecito, prova questo semplice sketch per convicerti :slight_smile:

void setup() {
  // put your setup code here, to run once:
char  test[5] = {'1','2','3','4','5'};
Serial.begin(19200);
byte m = 0;

Serial.println(test[0]);
Serial.println(test[m+=1]);
Serial.println(test[m++]);
Serial.println(test[m = m+1]);
Serial.println(test[m+=1]);
}

void loop() {
  // put your main code here, to run repeatedly:

}

Astro lo so che è lecito, ma ad un novellino può confondere un po' le idee, non trovi?

Anche la soluzione di Uwe, per quanto perfetta, implica una conoscenza approfondita dell'incremento "locale" della variabile.

E' vero che prima o poi dovrà comprendere la differenza, ma penso sia un po' presto.

cyberhs:
Astro lo so che è lecito, ma ad un novellino può confondere un po' le idee, non trovi?

Tu hai detto questo:

L'errore è presente nei cicli for all'istruzione leds[m = m + 1]: non puoi assegnare un valore alla variabile m all'interno di un elemento di array.

Fino a prova contraria vuol dire che non si può fare e che lo ritieni un errore che causa problemi al suo sketch, però non è così :slight_smile:

ok, hai ragione tu: mi sono espresso male.

cyberhs:
L'errore è presente nei cicli for all'istruzione leds[m = m + 1]: non puoi assegnare un valore alla variabile m all'interno di un elemento di array.

Fai così:

Ho provato a sostituire per intero le 2 routines con le tue (copia / incolla).
In fase di compilazione, mi da una serie di errori ('m' was not declared in this scope, expected constructor, destructor, or type conversion before '(' token, 'm' does not name a type, 'leds' does not name a type, 'FastLED' does not name a type) ripetuti nell routine Rampa01A

Così ho provato a richiamare il mio programma originale e a variare a mano copiando le tue variazioni. Stavolta non ha dato errori di compilazione (????)

Stavolta ha funzionato ... peggio: gli scalini si accendevano in sequenza in salita alternandosi scalino-1led / scalino-2led / scalino-1led / scalino-2led, e così via, poi si spegnevano in sequenza. A scendere niente (eppure lo switch segnala il passaggio)

Allora mi sono messo di nuovo a guardare lo sketch che avevo fatto all'inizio. Ho rilevato un errore di sintassi (correggetemi se sbaglio) laddove nella sequenza inversa (numeri negativi) ho posto la variabile m=NumLed invece di m=NumLed-1.
Suppongo sia una stupidaggine in realtà, perchè non dovrebbe comportare altro se non uno sfalsamento dei led (se ho 10 led, in realtà nella logica del microprocessore non sono da 1 a 10 ma da 0 a 9, no?).
Eppure è l'unico cambiamento che ho fatto alla fine. MA adesso funziona tutto a perfezione....
Sinceramente non capisco......

Comunque vorrei chiedere a cybers se mi spiega la logica delle sue variazioni, nel senso: io quando faccio uno sketch cerco di immaginare come ragiona il processore e provo a tradurre l'idea in linguaggio. Ma leggendo le sue variazioni, io non comprendo il risultato, nel senso che non mi figuro di ottenere l'effetto che volevo, ma mi aspetto che i led si accendado molto sfalsati (cosa che succede in salita) o che non funzionino proprio (cosa che succede in discesa).
Non lo dico a scopo polemico, assolutamente, sono un totale "ignorante" in materia, ma se posso imparare nozioni (o trucchetti) nuovi ben vengano.

Andrea

E' una questione di leggibilità:

L'istruzione

leds[m = m + 1] prevede il calcolo del contenuto in parentesi quadra per determinare il valore dell'indice.

a questo io preferisco

m = m + 1;
leds[m];

Una cosa che non capisco è: perché incrementi/decrementi la variabile del for usato come indice degli array e non fai fare tutto al for stesso?

Ad esempio:

for (int m = 0; m < NumLed; m=m+1){  //questo ciclo accende in sequenza gruppi di 3 led
  leds[m] = CRGB::White;
  leds[m=m+1] = CRGB::White;
  leds[m=m+1] = CRGB::White;
  FastLED.show();
  delay(timer1);
}

Mi spieghi il motivo? Non lo capisco. Non è sbagliato, è solo illogico. Se vuoi andare di 3 in 3 fai una cosa così:

for (int m = 0; m < NumLed; m=m+3){  //questo ciclo accende in sequenza gruppi di 3 led
  leds[m] = CRGB::White;
  leds[m+1] = CRGB::White;
  leds[m+2] = CRGB::White;
  FastLED.show();
  delay(timer1);
}

leo72:
Una cosa che non capisco è: perché incrementi/decrementi la variabile del for usato come indice degli array e non fai fare tutto al for stesso?

Mi spieghi il motivo? Non lo capisco. Non è sbagliato, è solo illogico. Se vuoi andare di 3 in 3 fai una cosa così:

Infatti questa è la stessa variazione che mi aveva suggerito cyberhs.
Solo che così facendo i led mi si accendevano in modo errato: scalino 1=2 led, scalino2:1 led, scalino 3=2 led, scalino 4=1 led, e così via. (ogni scalino sono 3 led)

Quanto al perchè ho usato quel metodo, considerando che sono una zappa in programmazione, sono andato per (il)logica e tentativi, ed ho visto che ottenevo il risultato che volevo.

Andrea