Lampeggio led con funzione "millis"

ciao a tutti, ho cercato di leggere diversi tutorial e post per capire meglio la funzione "millis", ma ho ancora dei dubbi.
Ho provato a fare un programma base per far lampeggiare due led, ma resta sempre solo acces quello sul pin 3 :thinking:

qui di seguito il codice:

unsigned long prevMillis = 0;
const long interval = 500;

void setup() {
  for (int ledPin = 2; ledPin<4; ledPin++) {
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  }
}

void loop() {
  if (millis() - prevMillis >= interval) {
    prevMillis = millis();
      digitalWrite(2, HIGH);
      digitalWrite(3, LOW);
      }
  else {
    digitalWrite(2, LOW);
    digitalWrite(3, HIGH);
  }
}

dove sto sbagliando??

l'obbiettivo finale e´ far lampeggiare 8 led in sequenza attivati dalla pressione di un pulsante e poi fermarli tramite la pressione dello stesso pulsante.
Ho fatto diverse prove, ma sono ancora in alto mare...

Forse ho capito l’errore base: con il codice scritto in quel modo, la condizione vera dell’if viene verificata solo nel momento in cui passa il mezzo secondo, poi riazzera il conteggio ed essendo veloce non vedo mai acceso il primo led.
Dovrei forse mettere un contatore (tipo una variabile ”prevMillis2”) anche per la condizione ”else”?

E per impostarlo su 8 led qual’é il codice più semplice da usare?
Grazie per l’aiuto.

1 Like

La clausola else non ci deve proprio essere, o meglio non va messa li, cioè:

void loop() {
  if (millis() - prevMillis >= interval) {
      prevMillis = millis();
      If (digitalRead(2) == LOW) {
          digitalWrite(2, HIGH);
          digitalWrite(3, LOW);
      } else {
          digitalWrite(2, LOW);
          digitalWrite(3, HIGH);
      }
  }
}

Per 8 led in sequenza cosa intendi?

Nella seconda parte ci sono due led lampeggianti

Ciao.

Ogni volta che scade il tempo controllato con millis incrementi un contatore. In base al valore del contatore comandi i led.

Grazie a tutti per le risposte.

Dopo averci dormito su, mi é venuta l’illuminazione del principiante :grin: ieri avevo fatto un test con 8 led ed un contatore, che però non funzionava; mi son accorto ora che verificavo il numero contenuto nella variabile del contatore con il simbolo ”=” anziché ”==” :face_with_peeking_eye: piú tardi faró delle prove e vedremo se funzionerà.

Il prossimo step sarà avviare e fermare la sequenza tramite pressione dello stesso pulsante (installato sul pin 10); anche li ho provato a ricreare una routine di controllo e conteggio, ma non funzionava…

Questo è il motivo per cui consigliano di effettuare i confronti di uguaglianza tra una costante e una variabile scrivendo prima la costante.

if (0 == C) ....

Dal momento che un singolo = è un'assegnazione e a una costante non si può assegnare niente, l'errore viene rilevato al momento della compilazione e non diventa un subdolo errore di semantica (credere che un operatore o una funzione facciano una certa cosa mentre in realtà ne fanno un'altra).

Bravo

Indenti in maniera decente (ovvero meglio del 99% dei frequentatori)
E sai pensare ai problemi
Cosa anche piĂą rara
Prosegui così e riuscirai

Sia chiaro:
Hai ricevuto i miei complimenti (meritati)
La cosa è altrettanto rara

1 Like

Grazie, troppo gentile!
Ho finalmente risolto il codice che fa lampeggiare i led in sequenza se tengo un pulsante premuto, li spegne quando lo lascio:

int pulsante = 0;
int conteggio = 0;
unsigned long prevMillis = 0;
unsigned long currMillis = 0;
const long interval = 500;

void setup() {
  for (int ledPin = 2; ledPin<10; ledPin++) { // i led vanno dal pin 2 al 9
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  pinMode(10, INPUT);
  }
}

void loop() {
  currMillis = millis();
  pulsante=digitalRead(10);
      if (pulsante == HIGH) {
        if (currMillis - prevMillis >= interval) {
          prevMillis = currMillis;
          if (conteggio == 0) {
          digitalWrite(2, HIGH);
          digitalWrite(3, LOW);
          digitalWrite(4, LOW);
          digitalWrite(5, LOW);
          digitalWrite(6, LOW);
          digitalWrite(7, LOW);
          digitalWrite(8, LOW);
          digitalWrite(9, LOW);
          conteggio = 1;
          }
            else if (conteggio == 1) {
            digitalWrite(2, LOW);
            digitalWrite(3, HIGH);
            digitalWrite(4, LOW);
            digitalWrite(5, LOW);
            digitalWrite(6, LOW);
            digitalWrite(7, LOW);
            digitalWrite(8, LOW);
            digitalWrite(9, LOW);
            conteggio = 2;
            }
            else if (conteggio == 2) {
            digitalWrite(2, LOW);
            digitalWrite(3, LOW);
            digitalWrite(4, HIGH);
            digitalWrite(5, LOW);
            digitalWrite(6, LOW);
            digitalWrite(7, LOW);
            digitalWrite(8, LOW);
            digitalWrite(9, LOW);
            conteggio = 3;
            }
            else if (conteggio == 3) {
            digitalWrite(2, LOW);
            digitalWrite(3, LOW);
            digitalWrite(4, LOW);
            digitalWrite(5, HIGH);
            digitalWrite(6, LOW);
            digitalWrite(7, LOW);
            digitalWrite(8, LOW);
            digitalWrite(9, LOW);
            conteggio = 4;
            }
            else if (conteggio == 4) {
            digitalWrite(2, LOW);
            digitalWrite(3, LOW);
            digitalWrite(4, LOW);
            digitalWrite(5, LOW);
            digitalWrite(6, HIGH);
            digitalWrite(7, LOW);
            digitalWrite(8, LOW);
            digitalWrite(9, LOW);
            conteggio = 5;
            }
            else if (conteggio == 5) {
            digitalWrite(2, LOW);
            digitalWrite(3, LOW);
            digitalWrite(4, LOW);
            digitalWrite(5, LOW);
            digitalWrite(6, LOW);
            digitalWrite(7, HIGH);
            digitalWrite(8, LOW);
            digitalWrite(9, LOW);
            conteggio = 6;
            }
            else if (conteggio == 6) {
            digitalWrite(2, LOW);
            digitalWrite(3, LOW);
            digitalWrite(4, LOW);
            digitalWrite(5, LOW);
            digitalWrite(6, LOW);
            digitalWrite(7, LOW);
            digitalWrite(8, HIGH);
            digitalWrite(9, LOW);
            conteggio = 7;
            }
            else if (conteggio == 7) {
            digitalWrite(2, LOW);
            digitalWrite(3, LOW);
            digitalWrite(4, LOW);
            digitalWrite(5, LOW);
            digitalWrite(6, LOW);
            digitalWrite(7, LOW);
            digitalWrite(8, LOW);
            digitalWrite(9, HIGH);
            conteggio = 0;
            } 
          }
      }
      else {
          digitalWrite(2, LOW);
          digitalWrite(3, LOW);
          digitalWrite(4, LOW);
          digitalWrite(5, LOW);
          digitalWrite(6, LOW);
          digitalWrite(7, LOW);
          digitalWrite(8, LOW);
          digitalWrite(9, LOW);
          conteggio = 0;
      }
    }

il prossimo passo e far attivare la sequenza e spegnerla tramite pressione delle stesso pulsante!
Ho trovato diversi esempi in rete, ma non riesco a farli funzionare e piu´ che altro non li comprendo :thinking: di base cerco sempre di capire un codice prima di passare ad un altro tentativo!

ce l'ho fatta :smiley: son finalmente riuscito ad inserire la routine per la lettura del pulsante!
Ho usato l'esempio del progetto 10 dello starter kit; avevo provato anche ieri, ma sbagliavo ad inserire le parentesi } di chiusura al posto giusto in alcune condizioni e il loop non funzionava...
Il tasto di verifica del codice controlla solo che la sintassi sia corretta, quindi devo andare per tentativi e non avendo ancora l'occhio allenato alla lettura degli sketch, ci metto un po´ a trovare gli errori :sweat_smile:

comunque ora funziona, questo e´ il codice finale:

int pulsanteStato = 0; // variabile contente lo stato del pulsante
int prevPulsanteStato = 0;
int attivaSequenza = 0; // variabile per attivare/disattivare la sequenza di lampeggio
int conteggio = 0; // variabile per conteggiare la sequenza dei led da accendere
unsigned long prevMillis = 0;
unsigned long currMillis = 0;
const long interval = 500; // mezzo secondo di intervallo per il lampeggio tra i led

void setup() {
  for (int ledPin = 2; ledPin<10; ledPin++) { // i led vanno dal pin 2 al 9
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  pinMode(10, INPUT); // il pin 10 e´ collegato al pulsante
  }
}

void loop() {
  currMillis = millis();
  pulsanteStato=digitalRead(10);
  delay(1);
  if (pulsanteStato != prevPulsanteStato) {
    if (pulsanteStato == HIGH) {
      attivaSequenza = !attivaSequenza;
    }
  }
  if (attivaSequenza == 1) {
    if (currMillis - prevMillis >= interval) {
      prevMillis = currMillis;
      if (conteggio == 0) {
      digitalWrite(2, HIGH);
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(8, LOW);
      digitalWrite(9, LOW);
      conteggio = 1;
      }
      else if (conteggio == 1) {
      digitalWrite(2, LOW);
      digitalWrite(3, HIGH);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(8, LOW);
      digitalWrite(9, LOW);
      conteggio = 2;
      }
      else if (conteggio == 2) {
      digitalWrite(2, LOW);
      digitalWrite(3, LOW);
      digitalWrite(4, HIGH);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(8, LOW);
      digitalWrite(9, LOW);
      conteggio = 3;
      }
      else if (conteggio == 3) {
      digitalWrite(2, LOW);
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
      digitalWrite(5, HIGH);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(8, LOW);
      digitalWrite(9, LOW);
      conteggio = 4;
      }
      else if (conteggio == 4) {
      digitalWrite(2, LOW);
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, HIGH);
      digitalWrite(7, LOW);
      digitalWrite(8, LOW);
      digitalWrite(9, LOW);
      conteggio = 5;
      }
      else if (conteggio == 5) {
      digitalWrite(2, LOW);
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, HIGH);
      digitalWrite(8, LOW);
      digitalWrite(9, LOW);
      conteggio = 6;
      }
      else if (conteggio == 6) {
      digitalWrite(2, LOW);
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(8, HIGH);
      digitalWrite(9, LOW);
      conteggio = 7;
      }
      else if (conteggio == 7) {
      digitalWrite(2, LOW);
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(8, LOW);
      digitalWrite(9, HIGH);
      conteggio = 0;
      } 
    }
  } else {
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
    digitalWrite(7, LOW);
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
    conteggio = 0;
    }
  prevPulsanteStato = pulsanteStato;
}

Suggerimenti per semplificare la lunga lista di istruzioni per fare lampeggiare i led??
Grazie del supporto!

Sfruttare il modello IPO

Tutto l'output raggruppato alla fine:

digitalWrite(2, attivaSequenza && 0==conteggio);
digitalWrite(3, attivaSequenza && 1==conteggio);
digitalWrite(4, attivaSequenza && 2==conteggio);
digitalWrite(5, attivaSequenza && 3==conteggio);
digitalWrite(6, attivaSequenza && 4==conteggio);
digitalWrite(7, attivaSequenza && 5==conteggio);
digitalWrite(8, attivaSequenza && 6==conteggio);
digitalWrite(9, attivaSequenza && 7==conteggio);
1 Like

Buona sera,
mi associo ai complimenti di @Standardoil, il tuo atteggiamento e' davvero encomiabile.
Detto questo, per quanto riguarda il prossimo "passo" l'hai praticamente gia' fatto.
Prova a pensare di non avere un software che accenda e spenga una sequenza di led, e di essere tu stesso a doverlo fare, accenderesti i led quando sono spenti e li spegneresti quando sono accesi....
Cio' che manca e' solamente sapere (quando viene premuto il pulsante) se la sequenza e' attiva oppure no. Timanca semplicemente una variabile che indichi lo stato dei led... Da qui fai cio' che vuoi

Anzi puoi usare attivaSequenza, quindi lo stato e' definito da questa variabile.

Quindi quando viene premuto il pulsante

Se attivaSequenza ==1 attivaSequenza = 0
altrimenti attivaSequenza = 0
quindi la variabile che indica lo stato del pulsante non serve piu'

Massimo

1 Like

Grazie a tutti per le risposte ed i suggerimenti!

Il mio team di lavoro é composto da me e mio figlio di 10 anni :grin: lui lancia le idee e si occupa di costruire i circuiti, io penso al SW (ci andrà ancora un attimo perché si diverta con quello :wink: ).

Di tempo ne abbiamo, le idee non finiscono mai e speriamo che con il giusto metodo si riesca a fare delle belle cose!
Per ora ci divertiamo :smiling_face_with_sunglasses:

Farete cose bellissime ....fidati

1 Like

Hai fatto una FSM (Finite State Machine) dove la variabile di stato è conteggio.

Purtroppo io per lampeggio intendo un'altra cosa, questa è una sequenza binaria: 0000 0000, 0000 0001, 0000 0010, 0000 0100 ecc.

Molto simile all'effetto SuperCar del telefilm, solo che poi quello torna anche indietro e ricomincia all'infinito.

Con una lista di pin (array o vettore) basterebbe contare da 0 a 7, ad ogni incremento del contatore spegni il pin[0] e accendi il pin[1] ecc.

Ciao.

Hai ragione, Ă© una sequenza piĂş che un lampeggio.
Perdonatemi se spesso useró una terminologia inappropriata :grin: uso troppo il metodo ”training on the job” piú che imparare la teoria :face_with_peeking_eye:

Hai un esempio del codice che suggerisci?
Grazie

Quindi dovrei mantenere nei vari if/else del millis solo l’incremento della variabile “conteggio” e poi aggiungere questo tuo codice alla fine?

Perdona l’ignoranza, ma come fa quell’istruzione a settare il led a zero se le due condizioni AND non sono vere?
Inoltre non dovrei anche scrivere “attivaSequenza == 1”?

L'idea è quella. Dopo di che (in questo specifico caso) puoi semplificare l'intera struttura if/else in un semplice incremento del contatore.

Sul pin viene scritto il risultato dell'espressione booleana, zero o uno (corrispondente a false/true o LOW/HIGH che sono solo alias di 0 e 1).

Gli operatori booleani && || e ! considerano la verità dei loro operandi (falso se uguale a 0, vero diverso da 0). Aggiungere il confronto esplicito in questo caso non fa nessuna differenza (anche se può rendere più chiaro e leggibile il codice).

In generale basta tenere conto del tipo di operandi atteso dagli operatori, e del risultato prodotto dalle operazioni:

Operatori Operandi Risultato
Aritmetici: + - * / % Numeri Numero
Logici bitwise: & | ^ ~ << >> sequenza bit sequenza bit
Confronto: < > <= >= == != Numeri 0/1
Logici booleani: && || ! vero/falso 0/1

E delle precedenze di calcolo. Nel caso in questione prima viene calcolato il confronto n==conteggio e poi si calcola l'and booleano && tra la "veritĂ " di attivaSequenza e la "veritĂ " del risultato del confronto.

Grazie Claudio_FF dei chiarimenti.

Queste basi teoriche legate ad esempi pratici e specifici (senza dover imparare di botto tutta la teoria, in fondo non punto a diventate programmatore professionista :wink:) sono davvero utili e di rapida comprensione :+1:

Sai che questa cosa è bellissima? Dovevo dirtelo...
Complimenti a te soprattutto, e sono anche io sicuro che se il figlio si appassiona vorrĂ  iniziare a scrivere anche lui il software (a 10 anni ormai ce la possono fare benissimo)!

1 Like

(breve OT)
e' bellissima davvero, ieri sera quando l'ho letto mi sono commosso... E' cio' che ho sempre sognato, ma purtroppo non ho avuto figli

Massimo

1 Like