Doppio ciclo ma ne esegue solo uno

Buongiorno,
dovrei fare lampeggiare 2 led in modo alternato(2 lampeggi il sinistro, 2 lampeggi il destro), se abbozzo il codice con una sfilza di delay e molte righe ripetute funziona tutto.
Ho provato a scrivere con 2 cicli e lui mi esegue sempre il primo. dal monitor vedo che lo esegue fino alla fine e poi lo ripete come se tornasse all'inizio. Usa i tags code per formattare il codice per il forum.

ver con for

const int ledsx = 52;
const int leddx = 40;
int ledstate = LOW;
unsigned long before = 0;
unsigned long timer = 200;
int side = LOW;



void setup() {
  pinMode(ledsx, OUTPUT);
  pinMode(leddx, OUTPUT);
  digitalWrite(ledsx, LOW);
  digitalWrite(leddx, LOW);
}

void loop() {
  unsigned long time = millis();


  for (int x = 0; x < 4; x++) {
    if (time - before >= timer) {

      before = time;
      ledstate = !ledstate;
      digitalWrite(ledsx, ledstate);
    }
  }



  for (int x = 0; x < 4; x++) {

    if (time - before >= timer) {

      before = time;
      ledstate = !ledstate;
      digitalWrite(leddx, ledstate);
    }
  }
}

ver con while

const int ledsx = 52;
const int leddx = 40;
int ledstate = LOW;
unsigned long before = 0;
unsigned long timer = 200;



void setup() {
  pinMode(ledsx, OUTPUT);
  pinMode(leddx, OUTPUT);
  digitalWrite(ledsx, LOW);
  digitalWrite(leddx, LOW);
}

void loop() {
  unsigned long time = millis();
  int sx = 0;
  while (sx < 4) {
    if (time - before >= timer) {

      before = time;
      ledstate = !ledstate;
      digitalWrite(ledsx, ledstate);
    }
    sx++;
  }

  int dx = 0;
  while (dx < 4) {
    if (time - before >= timer) {

      before = time;
      ledstate = !ledstate;
      digitalWrite(ledsx, ledstate);
    }
    dx++;
  }
}

vedete qualcosa che non va?

Se usi millis(), quindi con eventi "a tempo", non devi usare alcun ciclo (while o for che sia) ma "lasciare andare" il codice di loop(), che di per sé è un ciclo (eseguito migliaia i volte al secondo). Poi va usata la logica delle "macchine a stati finiti", o FSM: nel tuo caso devi tenere traccia di quale LED sta lampeggiando, e quante volte ha lampeggiato.
Una cosa di questo tipo (codice scritto "al volo", da provare...):

// Pin dei LED
const byte P_LED[] = { 52, 40 };
// Millisecondi di accensione/spegnimento
#define LED_TIME 500
// Numero di blink da fare prima di cambiare
#define LED_BLINK 4

// Variabili globali:
// Indica il LED attivo (0=sx o 1=dx)
byte ledAttivo;
// Per il led attivo:
unsigned long tmrStart;
// Contatore di blink
byte ledBlink;

void setup() {
  Serial.begin(9600);
  
  for(int i=0; i<2; ++i) {
    pinMode(P_LED[i], OUTPUT);
    digitalWrite(P_LED[i], LOW);
  }
  
  // Inizio accendendo il primo LED
  ledAttivo = 0;
  digitalWrite(P_LED[ledAttivo], HIGH);
  tmrStart = millis();
}

void loop() {
  if (millis() - tmrStart >= LED_TIME) {
    tmrStart = millis();
    // Vedo se non ho finito i blink
    if (++ledBlink < LED_BLINK*2) {
      // Inverto lo stato
      digitalWrite(P_LED[ledAttivo], !digitalRead(P_LED[ledAttivo]));
    } else {
      // Ho finito, passo all'altro
      digitalWrite(P_LED[ledAttivo], LOW);
      ledAttivo = 1 - ledAttivo;
      digitalWrite(P_LED[ledAttivo], HIGH);
      ledBlink = 0;
    }
  }
}

Ovviamente chiedi per qualsiasi tuo dubbio su questo approccio.

Buongiorno 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 (... quello che vedi in blu è un link, fai click su di esso per raggiungere la 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:

Fatta

Questa riga

Viene eseguita una sola volta all'inizio della loop()

Quindi time non viene mai aggiornata

Usa invece della variabile time direttamente la millis()

Io si, ma la devi vedere anche tu.

while (sx < 4) {
    Serial.println(time); // aggiunta
    if (time - before >= timer) {
      before = time;
      ledstate = !ledstate;
      digitalWrite(ledsx, ledstate);
    }
    sx++;
  }

Osservando il ciclo while isolato si capisce subito che time ha sempre
lo stesso valore.

while (sx < 4) {
    time = millis();   // aggiorna la variabile time
    if (time - before >= timer) {
      before = time;
      ledstate = !ledstate;
      digitalWrite(ledsx, ledstate);
    }
    sx++;
  }

Oppure in alternativa:

while (sx < 4) {
    
    if (millis() - before >= timer) {
      before = millis();
      ledstate = !ledstate;
      digitalWrite(ledsx, ledstate);
    }
    sx++;
  }

Comunque, dopo che ti chiarisci questo problema, ti consiglio di provare a fare il tutto senza cicli while, for, do while.

Ciao e benveniuuuuto. :grinning_face:

Non avevo riflettuto sul fatto che la variabile non si aggiornasse, cmq che intendi senza usare i cicli? Volevo crearla in modo da usarla su più modelli con lappeggi differenti.

Leggi il mio post #2 (era stato temporaneamente osscurato in attesa che tu fecessi la presentazione), fammi sapere.

Tutto questo perchè non si segue la
"Regola prima del debug":

Seguire il programma riga a riga, con l'indice
Quello della mano destra

Non sapevo del discorso di non usare i cicli con gli eventi a tempo. Stasera mi studio l'esempio che mi avete dato con logica di tato. E vi aggiorno.

Mi scuso per non avere visto il post di @docdoc.

Non solo, il while cicla 4 volte e passa all'altro while che fa la stessa cosa, il loop termina e ricomincia dal primo while. Durante il ciclo while eseguito alla velocità di arduino, il valore restituito da millis() sarà sempre lo stesso 4 volte consecutive, per rendertene conto puoi usare la Serial.println(millis()) all'interno del while. In breve il comportamento dei cicli innestati (cioè uno dentro l'altro) deve essere compreso bene, per poi poterli usare quando serve. Ovviamente se non serve, come in questo caso (come ha mostrato @docdoc), non li si usa.

Nel codice di @docdoc viene usato l'operatore pre-incremento:

if (++ledBlink < LED_BLINK*2)

Prima di effetturare la verifica dell'espressione della if, la variabile ledBlink viene incrementata di una unità, cioè se il suo valore era 0, sarà 0+1 = 1, allora l'espressione sarà IF (1 < 8), la seconda volta sarà, IF (2 < 8) ecc.

Inoltre c'è l'uso di array e le macro del preprocessore (quelle direttive che iniziano con #).

Ciao.

utilizzando il codice di docdoc funziona perfettamente, mi sa che devo fare un passo indietro e studiare un po' di più per sviluppare del codice ad un buon livello. grazie per il grandissimo aiuto

Ok, bene, e comunque c'è sempre da imparare qualcosa, tranquillo che vale per tutti noi!!!

Comunque per quel codice che ti ho suggerito il concetto è relativamente semplice:

  1. cercare di evitare del tutto di usare delay() e cicli while() entro al loop: il loop deve poter "girare" più rapidamente possibile per poter eseguire più compiti (non contemporaneamente ma se il loop() viene eseguito un migliaio di volte al secondo, "sembrano" operazioni contemporanee)
  2. studiare bene millis() ed il suo utilizzo perché è la base di tutte le temporizzazioni, guarda ad esempio QUI anche QUI e QUI ..
  3. se il codice deve effettuare operazioni che dipendono da alcune condizioni, è utile definire una "macchina a stati finiti", per questo argomento probabilmente più che spiegartelo qui meglio un video come questo (spesso Aliverti fa buoni video introduttivi):
    https://www.youtube.com/watch?v=bj2cdgKhCDg&ab_channel=paoloaliverti

in realtà lo seguivo ma non avevo visto questi video. cmq sono anche riuscito ad implementare un tasto che accende e spegne il sistema, ora sto lavorando per l'implementazione della terza stroboscopica.

C'hai la ù che ti fa falso contatto. :grinning_face_with_smiling_eyes:

Ciao.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.