Arduino: controllo sequenziale uscite digitali

Durante la progettazione di un sistema di automazione accade frequentemente di avere la necessità di ripetere, sequenzialmente e in modo continuo, l’attivazione di apparati (ad es. motori) oppure la lettura continua dei dati provenienti da più sensori. Come attività di ripasso per i miei studenti ho deciso di riprendere alcuni argomenti affrontati nelle scorse settimane con specifiche esperienze di laboratorio:

  • automi a stati finiti;
  • utilizzo degli array;
  • input valori interi da serial monitor;
  • marcia, arresto, pausa di sequenze;
  • controllo uscite digitali mediante ingressi analogici;
  • realizzazione di commutatori con pulsanti con uno o più pulsanti;
  • utilizzo corretto dei tipi di dati per risparmiare memoria;
  • e molto altro

Di seguito 9 sketch in cui vengono ripresi gli argomenti sopra elencati e che potranno essere utilizzati nei prossimi mesi per sviluppare ulteriori sperimentazioni.
Come sempre all’interno degli sketch proposti trovate le spiegazioni di ogni parte del codice ed in alcuni casi trovate link di approfondimento che rimandano a questo sito.

Per ripercorrere gli argomenti svolti partirò dal classico sketch che permette di realizza l’accensione sequenziale di LED, come quello che potete trovare nelle mie slice: Alfabeto Arduino – Lezione 2 a pagina 66.
I LED nel circuito identificano gli apparati da attivare sequenzialmente, realizzando così il classico effetto “super car” (i diversamente giovani 🙂 sanno perché si chiama così).
Circuito e sketch verranno poi modificati per rispondere alle specifiche indicate ad inizio di ogni esempio.

Sketch 01

Sequenza di accensione e spegnimento da destra e sinistra e viceversa di 8 LED con tempo di accensione di 100 millisecondi.

 

/* Prof. Michele Maffucci
   30.12.2020
   Lezione di riferimento: https://wp.me/p4kwmk-4D3

   Versione 01
   Sequenza di accensione e spegnimento alternato
   da destra e sinistra e viceversa di 8 LED con
   tempo di accensione di 100 millisecondi.
   
   Questo codice è di dominio pubblico 
 */

// creazione di un array di 8 pin a cui vanno collegati i LED
// per ulteriori informazioni sull'uso degli array si consulti il seguente link:
// http://wp.me/p4kwmk-26e

byte ledPin[] = {3, 4, 5, 6, 7, 8, 9, 10};

// per approfondimenti sull'uso dei tipi di dati
// si consultino i link:
// https://wp.me/p4kwmk-4As
// https://wp.me/p4kwmk-1zF

// intervallo di accensione/spegnimento
byte ritardoLed = 100;

// indicatore di direzione di accensione
byte direzione = 1;

// indice dell'array per l'accensione del LED
byte ledCorrente = 0;

// variabile in cui memorizzare il tempo di accensione di Arduino
// per ulteriori informazioni sui tipi unsigned long si consulti il seguente link:
// http://wp.me/p4kwmk-1zF

unsigned long tempoTrascorso;

void setup() {                
  // impostiamo tutti i pin ad output
  for (byte x=0; x<8; x++) {
    pinMode(ledPin[x], OUTPUT);
  }
    
  // Memorizzazione del tempo trascorso
  // dal momento in cui avviamo Arduino
  // Per ulteriori informazioni sull'uso di millis() si consulti il seguente link:
  // http://wp.me/p4kwmk-1QG
  
  tempoTrascorso = millis();
}

void loop() {
  // Se sono passati "ritardoLed" millisecondi dall'ultimo cambiamento
  if ((millis() - tempoTrascorso) > ritardoLed) {
    cambiaStatoLed();
    tempoTrascorso = millis();
  }
}

// la funzione cambiaStatoLed() permette di controllare
// la sequenza di accensione dei LED

void cambiaStatoLed() {
  // spegne tutti i LED
  for (byte x=0; x<8; x++) {
    digitalWrite(ledPin[x], LOW);
  }
  // accende il LED corrente
  digitalWrite(ledPin[ledCorrente], HIGH);
  // incrementa la variabile direzione
  ledCorrente += direzione;
  // cambia la direzione se si arriva alla fine
  if (ledCorrente == 7) {
    direzione = -1;
  }
  if (ledCorrente == 0) {
    direzione = 1;
  }
}

Sketch 02

Sequenza di accensione e spegnimento da destra e sinistra e viceversa di 8 LED. Con un trimmer è possibile variare il tempo di accensione nell’intervallo da 50 millisecondi a 1000 millisecondi (1 secondo).

/* Prof. Michele Maffucci
   30.12.2020
   Lezione di riferimento: https://wp.me/p4kwmk-4D3

   Versione 02
   Sequenza di accensione e spegnimento alternato
   da destra e sinistra e viceversa di 8 LED controllato
   da un trimmer che permetterà di variare il tempo di accensione
   da 50 millisecondi a 1000 millisecondi (1 secondo).
   
   Questo codice è di dominio pubblico 
 */

// creazione di un array di 8 pin a cui vanno collegati i LED
// per ulteriori informazioni sull'uso degli array si consulti il seguente link:
// http://wp.me/p4kwmk-26e

byte ledPin[] = {3, 4, 5, 6, 7, 8, 9, 10};

// per approfondimenti sull'uso dei tipi di dati
// si consultino i link:
// https://wp.me/p4kwmk-4As
// https://wp.me/p4kwmk-1zF

// intervallo di accensione/spegnimento
int ritardoLed;

// variabile in cui memorizzare il valore restituito dall'analogRead
int val = 0;

// indicatore di direzione di accensione
byte direzione = 1;

// indice dell'array per l'accensione del LED
byte ledCorrente = 0;

// variabile in cui memorizzare il tempo di accensione di Arduino
// per ulteriori informazioni sui tipi unsigned long si consulti il seguente link:
// http://wp.me/p4kwmk-1zF

unsigned long tempoTrascorso;

void setup() {
  Serial.begin(9600);            
  // impostiamo tutti i pin ad output
  for (byte x=0; x<8; x++) {
    pinMode(ledPin[x], OUTPUT);
  }
    
  // Memorizzazione del tempo trascorso
  // dal momento in cui avviamo Arduino
  // Per ulteriori informazioni sull'uso di millis() si consulti il seguente link:
  // http://wp.me/p4kwmk-1QG
  
  tempoTrascorso = millis();
}

void loop() {

  // valore analogico letto su A0 inserito con il trimmer
  val = analogRead(A0);

// Togliere il commento per valutare
// valore massimo/minimo del valore restituito
// dall'analogRead in questo modo si potranno
// inserire nella map i valori massimi e minimi
// dell'intervallo di partenza

// Serial.println(val);
// delay(1000);

  // ValMax = 285, ValMin = 719
  // riconvertiti nell'intervallo 50, 1000
  
  ritardoLed = map(val, 285, 719, 50, 1000);
  
  // Se sono passati "ritardoLed" millisecondi dall'ultimo cambiamento
  if ((millis() - tempoTrascorso) > ritardoLed) {
    cambiaStatoLed();
    tempoTrascorso = millis();
  }
}

// la funzione cambiaStatoLed() permette di controllare
// la sequenza di accensione dei LED

void cambiaStatoLed() {
  // spegne tutti i LED
  for (byte x=0; x<8; x++) {
    digitalWrite(ledPin[x], LOW);
  }
  // accende il LED corrente
  digitalWrite(ledPin[ledCorrente], HIGH);
  // incrementa la variabile direzione
  ledCorrente += direzione;
  // cambia la direzione se si arriva alla fine
  if (ledCorrente == 7) {
    direzione = -1;
  }
  if (ledCorrente == 0) {
    direzione = 1;
  }
}

Sketch 03

Sequenza di accensione e spegnimento alternato da destra e sinistra e viceversa di 8 LED. L’accensione di ogni LED è fissato in partenza a 100 millisecondi. Con un messaggio sulle Serial Monitor viene richiesto di inserire un nuovo tempo di accensione e spegnimento di ogni LED (delay), tempo che può essere scelto a piacimento.

Lo schema di collegamento è analogo a quello utilizzato per lo sketch 01.

/* Prof. Michele Maffucci
   30.12.2020
   Lezione di riferimento: https://wp.me/p4kwmk-4D3

   Versione 03
   Sequenza di accensione e spegnimento alternato
   da destra e sinistra e viceversa di 8 LED.

   Partenza sequenza con 100 millisecondi e messaggio sulla
   Serial Monitor per modificare il tempo di
   accensione e spegnimento del singolo LED (delay)
   
   Questo codice è di dominio pubblico 
 */

// creazione di un array di 8 pin a cui vanno collegati i LED
// per ulteriori informazioni sull'uso degli array si consulti il seguente link:
// http://wp.me/p4kwmk-26e

byte ledPin[] = {3, 4, 5, 6, 7, 8, 9, 10};

// per approfondimenti sull'uso dei tipi di dati
// si consultino i link:
// https://wp.me/p4kwmk-4As
// https://wp.me/p4kwmk-1zF

// intervallo di accensione/spegnimento
int ritardoLed = 100;

// indicatore di direzione di accensione
byte direzione = 1;

// indice dell'array per l'accensione del LED
byte ledCorrente = 0;

// variabile in cui memorizzare il tempo di accensione di Arduino
// per ulteriori informazioni sui tipi unsigned long si consulti il seguente link:
// http://wp.me/p4kwmk-1zF

unsigned long tempoTrascorso;

// per stampare una sola volta il messaggio sulla Serial Monitor  
bool abilitaMessaggio = 0;

void setup() {
  // inizializzazione della serial monitor
  Serial.begin(9600);
               
  // impostiamo tutti i pin ad output
  for (byte x=0; x<8; x++) {
    pinMode(ledPin[x], OUTPUT);
  }

  // Memorizzazione del tempo trascorso
  // dal momento in cui avviamo Arduino
  // Per ulteriori informazioni sull'uso di millis() si consulti il seguente link:
  // http://wp.me/p4kwmk-1QG
  tempoTrascorso = millis();
}

void loop() {
  // consente di visualizzare sulla Serial Monitor
  // una sola stampa delle stringa
  if (abilitaMessaggio == 0) {
    // ritardo che evita la doppia stampa del messaggio 
    delay(200);
    Serial.print("Inserisci il ritardo in millisecondi: ");
    abilitaMessaggio = 1;
  }

  // Controlla se è disponibile almeno un carattere sulla seriale
  // La Serial.available() restituisce
  // 1 se presente un cattere,
  // 0 se non è presente un carattere

  // per maggior informazioni sull'uso di parseInt() consultare il link:
  // https://wp.me/p4kwmk-4Ah

  if (Serial.available())
  {
    // in r viene memorizzato il valore inserito
    // attraverso la Serial Monitor
    int r = Serial.parseInt();
    if (r != 0) {
      ritardoLed = r;
      Serial.println(ritardoLed);

      // abilita alla stampa di una nuova stringa:
      // "Inserisci il ritardo in millisecondi: "
      abilitaMessaggio = 0;
    }
  }
  
  // funzione che fa lampeggiare il LED su Arduino
  lampeggio();
}

void lampeggio() {
  // Se sono passati "ritardoLed" millisecondi dall'ultimo cambiamento
  if ((millis() - tempoTrascorso) > ritardoLed) {
    cambiaStatoLed();
    tempoTrascorso = millis();
  }
}

// la funzione cambiaStatoLed() permette di controllare
// la sequenza di accensione dei LED

void cambiaStatoLed() {
  // spegne tutti i LED
  for (byte x = 0; x < 8; x++) {
    digitalWrite(ledPin[x], LOW);
  }
  // accende il LED corrente
  digitalWrite(ledPin[ledCorrente], HIGH);
  // incrementa la variabile direzione
  ledCorrente += direzione;
  // cambia la direzione se si arriva alla fine
  if (ledCorrente == 7) {
    direzione = -1;
  }
  if (ledCorrente == 0) {
    direzione = 1;
  }
}

Sketch 04

Sequenza di accensione e spegnimento alternato da destra e sinistra e viceversa di 8 LED.
All’avvio tutti i LED sono spenti. Inserimento da Serial Monitor del tempo di accensione e spegnimento del singolo LED (delay) all’avvio. E’ possibile modificare il delay inserendo sulla Serial Monitor un nuovo valore.

Lo schema di collegamento è analogo a quello utilizzato per lo sketch 01.

/* Prof. Michele Maffucci
   30.12.2020
   Lezione di riferimento: https://wp.me/p4kwmk-4D3

   Versione 04
   Sequenza di accensione e spegnimento alternato
   da destra e sinistra e viceversa di 8 LED.

   All'avvio tutti i LED sono spenti.
   
   Inserimento da Serial Monitor del tempo di
   accensione del singolo LED (delay) all'avvio e
   nei momenti successivi
   
   Questo codice è di dominio pubblico 
 */

// creazione di un array di 8 pin a cui vanno collegati i LED
// per ulteriori informazioni sull'uso degli array si consulti il seguente link:
// http://wp.me/p4kwmk-26e

byte ledPin[] = {3, 4, 5, 6, 7, 8, 9, 10};

// per approfondimenti sull'uso dei tipi di dati
// si consultino i link:
// https://wp.me/p4kwmk-4As
// https://wp.me/p4kwmk-1zF

// intervallo di accensione/spegnimento
int ritardoLed;

// indicatore di direzione di accensione
byte direzione = 1;

// indice dell'array per l'accensione del LED
byte ledCorrente = 0;

// variabile in cui memorizzare il tempo di accensione di Arduino
// per ulteriori informazioni sui tipi unsigned long si consulti il seguente link:
// http://wp.me/p4kwmk-1zF
unsigned long tempoTrascorso;

// per stampare una sola volta il messaggio sulla Serial Monitor 
bool abilitaMessaggio = 0;

// per abilitare l'avvio della sequenza di accensione dopo
// l'inserimento del delay da Serial Monitor 
bool abilitaBlink = 0;

void setup() {
  // inizializzazione della serial monitor
  Serial.begin(9600);

  // impostiamo tutti i pin ad output
  for (byte x = 0; x < 8; x++) {
    pinMode(ledPin[x], OUTPUT);
  }

  // Memorizzazione del tempo trascorso
  // dal momento in cui avviamo Arduino
  // Per ulteriori informazioni sull'uso di millis() si consulti il seguente link:
  // http://wp.me/p4kwmk-1QG
  tempoTrascorso = millis();
}

// Stampa del messaggio su Serial Monitor:
// "Inserisci il ritardo in millisecondi: "
void inserisciRitardo() {
  
  // consente di visualizzare sulla Serial Monitor
  // una sola stampa delle stringa
  if (abilitaMessaggio == 0) {
    // ritardo che evita la doppia stampa del messaggio 
    delay(200);
    Serial.print("Inserisci il ritardo in millisecondi: ");
    abilitaMessaggio = 1;
  }

  // Controlla se è disponibile almeno un carattere sulla seriale
  // La Serial.available() restituisce
  // 1 se presente un cattere,
  // 0 se non è presente un carattere

  // per maggior informazioni sull'uso di parseInt() consultare il link:
  // https://wp.me/p4kwmk-4Ah

  if (Serial.available()) {
    // in r viene memorizzato il valore inserito
    // attraverso la Serial Monitor    
    int r = Serial.parseInt();
    if (r != 0) {
      ritardoLed = r;
      Serial.println(ritardoLed);

      // abilita alla stampa di una nuova stringa:
      // "Inserisci il ritardo in millisecondi: "
      abilitaMessaggio = 0;

      // abilita l'avvio del Blink sequenziale dei LED
      abilitaBlink = 1;
    }
  }
}

void loop() {
  inserisciRitardo();
    // Se sono passati "ritardoLed" millisecondi dall'ultimo cambiamento e abilitaBlink == 1
    // allora si cambia stato (si accende il LED successivo). 
    
    // L'AND con "abilitaBlink == 1" permette di avviare la sequenza di accensione
    // solo dopo l'inserimento del valore di ritardoLed, se non si facesse questo controllo
    // al primo avvio tutti i LED sarebbero accessi perché la funzione cambiaStatoLed() verrebbe
    // richiamata continuamente in quanto la differenza è sempre > di "ritardoLed" che è 0 e non
    // si percepirebbe il cambiamento di stato.

    
  if (((millis() - tempoTrascorso) > ritardoLed) && (abilitaBlink == 1)) {
    cambiaStatoLed();
    tempoTrascorso = millis();
  }
}

// la funzione cambiaStatoLed() permette di controllare
// la sequenza di accensione dei LED

void cambiaStatoLed() {
  // spegne tutti i LED
  for (byte x = 0; x < 8; x++) {
    digitalWrite(ledPin[x], LOW);
  }
  // accende il LED corrente
  digitalWrite(ledPin[ledCorrente], HIGH);
  // incrementa la variabile direzione
  ledCorrente += direzione;
  // cambia la direzione se si arriva alla fine
  if (ledCorrente == 7) {
    direzione = -1;
  }
  if (ledCorrente == 0) {
    direzione = 1;
  }
}

Sketch 05

Sequenza di accensione e spegnimento alternato da destra e sinistra e viceversa di 8 LED.
All’avvio tutti i LED sono spenti. Inserimento da Serial Monitor del tempo di accensione e spegnimento del singolo LED (delay) all’avvio. Mediante la pressione continua di un pulsante viene messa in pausa la sequenza, rilasciando il pulsante si riavvia la sequenza.

/* Prof. Michele Maffucci
   30.12.2020
   Lezione di riferimento: https://wp.me/p4kwmk-4D3

   Versione 05
   Sequenza di accensione e spegnimento alternato
   da destra e sinistra e viceversa di 8 LED.

   All'avvio tutti i LED sono spenti.

   Inserimento da Serial Monitor del tempo di
   accensione e spegnimento del singolo LED (delay)
   all'avvio e in momenti successivi.

   Mediante la pressione continua di un pulsante viene messa in pausa
   la sequenza, rilasciando il pulsante si riavvia la sequenza.

   Questo codice è di dominio pubblico
*/

// creazione di un array di 8 pin a cui vanno collegati i LED
// per ulteriori informazioni sull'uso degli array si consulti il seguente link:
// http://wp.me/p4kwmk-26e

byte ledPin[] = {3, 4, 5, 6, 7, 8, 9, 10};

// per approfondimenti sull'uso dei tipi di dati
// si consultino i link:
// https://wp.me/p4kwmk-4As
// https://wp.me/p4kwmk-1zF

// intervallo di accensione/spegnimento
int ritardoLed;

// indicatore di direzione di accensione
byte direzione = 1;

// indice dell'array per l'accensione del LED
byte ledCorrente = 0;

// variabile in cui memorizzare il tempo di accensione di Arduino
// per ulteriori informazioni sui tipi unsigned long si consulti il seguente link:
// http://wp.me/p4kwmk-1zF
unsigned long tempoTrascorso;

// per stampare una sola volta il messaggio sulla Serial Monitor
bool abilitaMessaggio = 0;

// per abilitare l'avvio della sequenza di accensione dopo
// l'inserimento del delay da Serial Monitor
bool abilitaBlink = 0;

// abilitazione/disabilitazione pausa sequenza
byte pulsante = 11;

void setup() {
  // inizializzazione della serial monitor
  Serial.begin(9600);

  // impostiamo tutti i pin ad output
  for (byte x = 0; x < 8; x++) {
    pinMode(ledPin[x], OUTPUT);
    // per ulteriori informazioni sull'uso di millis() si consulti il seguente link:
    // http://wp.me/p4kwmk-1QG
  }

  // inizializzazione pin pulsante
  pinMode(pulsante, INPUT);

  // Memorizzazione del tempo trascorso
  // dal momento in cui avviamo Arduino
  // Per ulteriori informazioni sull'uso di millis() si consulti il seguente link:
  // http://wp.me/p4kwmk-1QG
  tempoTrascorso = millis();
}

// Stampa del messaggio su Serial Monitor:
// "Inserisci il ritardo in millisecondi: "
void inserisciRitardo() {

  // consente di visualizzare sulla Serial Monitor
  // una sola stampa delle stringa
  if (abilitaMessaggio == 0) {
    // ritardo che evita la doppia stampa del messaggio
    delay(200);
    Serial.print("Inserisci il ritardo in millisecondi: ");
    abilitaMessaggio = 1;
  }

  // Controlla se è disponibile almeno un carattere sulla seriale
  // La Serial.available() restituisce
  // 1 se presente un cattere,
  // 0 se non è presente un carattere

  // per maggior informazioni sull'uso di parseInt() consultare il link:
  // https://wp.me/p4kwmk-4Ah

  if (Serial.available()) {
    // in r viene memorizzato il valore inserito
    // attraverso la Serial Monitor
    int r = Serial.parseInt();
    if (r != 0) {
      ritardoLed = r;
      Serial.println(ritardoLed);

      // abilita alla stampa di una nuova stringa:
      // "Inserisci il ritardo in millisecondi: "
      abilitaMessaggio = 0;

      // abilita l'avvio del Blink sequenziale dei LED
      abilitaBlink = 1;
    }
  }
}

void loop() {
  inserisciRitardo();
  // Se sono passati "ritardoLed" millisecondi dall'ultimo cambiamento e abilitaBlink == 1
  // allora si cambia stato (si accende il LED successivo).

  // L'AND con "abilitaBlink == 1" permette di avviare la sequenza di accensione
  // solo dopo l'inserimento del valore di ritardoLed, se non si facesse questo controllo
  // al primo avvio tutti i LED sarebbero accessi perché la funzione cambiaStatoLed() verrebbe
  // richiamata continuamente in quanto la differenza è sempre > di "ritardoLed" che è 0 e non
  // si percepirebbe il cambiamento di stato.


  if (((millis() - tempoTrascorso) > ritardoLed) && (abilitaBlink == 1)) {
    controlloBlink();
    tempoTrascorso = millis();
  }
}

// la funzione controlloBlink() verifica se il pulsante
// di pausa è premuto. Fino a quando viene premuto viene mantenuta
// la pausa, quando rilascio la sequenza continua.

void controlloBlink() {
  while (true) {
    if (digitalRead(pulsante) == LOW) {
      break;
    }
  }
  cambiaStatoLed();
}

// la funzione cambiaStatoLed() permette di controllare
// la sequenza di accensione dei LED

void cambiaStatoLed() {
  // spegne tutti i LED
  for (byte x = 0; x < 8; x++) {
    digitalWrite(ledPin[x], LOW);
  }
  // accende il LED corrente
  digitalWrite(ledPin[ledCorrente], HIGH);
  // incrementa la variabile direzione
  ledCorrente += direzione;
  // cambia la direzione se si arriva alla fine
  if (ledCorrente == 7) {
    direzione = -1;
  }
  if (ledCorrente == 0) {
    direzione = 1;
  }
}

Sketch 06

Sequenza di accensione e spegnimento alternato da destra e sinistra e viceversa di 8 LED.
All’avvio tutti i LED sono spenti. Inserimento da Serial Monitor del tempo di accensione e spegnimento del singolo LED (delay) all’avvio.

Utilizzo del pulsante come interruttore:

  • prima pressione si avvia la sequenza.
  • seconda pressione stop sequenza.

Se durante lo stop si inserisce un nuovo valore del delay, alla successiva pressione del pulsante (avvio) la sequenza si riavvia con il nuovo delay inserito.

Lo schema di collegamento è analogo a quello utilizzato per lo sketch 05.

/* Prof. Michele Maffucci
   30.12.2020
   Lezione di riferimento: https://wp.me/p4kwmk-4D3

   Versione 06
   Sequenza di accensione e spegnimento alternato
   da destra e sinistra e viceversa di 8 LED.

   All'avvio tutti i LED sono spenti.

   Inserimento da Serial Monitor del tempo di
   accensione e spegnimento del singolo LED (delay)
   all'avvio e in momenti successivi.

   Utilizzo del pulsante come interruttore:
   - prima pressione si avvia la sequenza.
   - seconda pressione stop sequenza.

     Se durante lo stop si inserisce un nuovo valore del delay,
     alla successiva pressione del pulsante la sequenza si riavvia
     con il nuovo delay inserito.

   Questo codice è di dominio pubblico
*/

// creazione di un array di 8 pin a cui vanno collegati i LED
// per ulteriori informazioni sull'uso degli array si consulti il seguente link:
// http://wp.me/p4kwmk-26e

byte ledPin[] = {3, 4, 5, 6, 7, 8, 9, 10};

// per approfondimenti sull'uso dei tipi di dati
// si consultino i link:
// https://wp.me/p4kwmk-4As
// https://wp.me/p4kwmk-1zF

// intervallo di accensione/spegnimento
int ritardoLed;

// indicatore di direzione di accensione
byte direzione = 1;

// indice dell'array per l'accensione del LED
byte ledCorrente = 0;

// variabile in cui memorizzare il tempo di accensione di Arduino
// per ulteriori informazioni sui tipi unsigned long si consulti il seguente link:
// http://wp.me/p4kwmk-1zF
unsigned long tempoTrascorso;

// per stampare una sola volta il messaggio sulla Serial Monitor
bool abilitaMessaggio = 0;

// per abilitare l'avvio della sequenza di accensione dopo
// l'inserimento del delay da Serial Monitor
bool abilitaBlink = 0;

// abilitazione/disabilitazione pausa sequenza
byte pulsante = 11;

// stato del pulsante attuale
bool stato = 0;

// stato del pulsante al passo precedente
bool stato_precedente = 0;

// controllo attivazione sequenza mediante pulsante
bool attivaSequenza = 0;

void setup() {
  // inizializzazione della serial monitor
  Serial.begin(9600);

  // impostiamo tutti i pin ad output
  for (byte x = 0; x < 8; x++) {
    pinMode(ledPin[x], OUTPUT);
  }
  pinMode(pulsante, INPUT);

  // Memorizzazione del tempo trascorso
  // dal momento in cui avviamo Arduino
  // Per ulteriori informazioni sull'uso di millis() si consulti il seguente link:
  // http://wp.me/p4kwmk-1QG
  tempoTrascorso = millis();
}

void spegniLed() {
  for (byte x = 0; x < 8; x++) {
    digitalWrite(ledPin[x], LOW);
  }
}

// Stampa del messaggio su Serial Monitor:
// "Inserisci il ritardo in millisecondi: "
void inserisciRitardo() {

  // consente di visualizzare sulla Serial Monitor
  // una sola stampa delle stringa
  if (abilitaMessaggio == 0) {
    // ritardo che evita la doppia stampa del messaggio
    delay(200);
    Serial.print("Inserisci il ritardo in millisecondi: ");
    abilitaMessaggio = 1;
  }

  // Controlla se è disponibile almeno un carattere sulla seriale
  // La Serial.available() restituisce
  // 1 se presente un cattere,
  // 0 se non è presente un carattere

  // per maggior informazioni sull'uso di parseInt() consultare il link:
  // https://wp.me/p4kwmk-4Ah

  if (Serial.available()) {
    int r = Serial.parseInt(); // in r viene memorizzato il valore inserito in numero
    if (r != 0) {
      ritardoLed = r;
      Serial.println(ritardoLed);

      // abilita alla stampa di una nuova stringa:
      // "Inserisci il ritardo in millisecondi: "
      abilitaMessaggio = 0;

      // abilita l'avvio del Blink sequenziale dei LED
      abilitaBlink = 1;
    }
  }
}

void loop() {
  inserisciRitardo();
  // Se sono passati "ritardoLed" millisecondi dall'ultimo cambiamento e abilitaBlink == 1
  // allora si cambia stato (si accende il LED successivo).

  // L'AND con "abilitaBlink == 1" permette di avviare la sequenza di accensione
  // solo dopo l'inserimento del valore di ritardoLed, se non si facesse questo controllo
  // al primo avvio tutti i LED sarebbero accessi perché la funzione cambiaStatoLed() verrebbe
  // richiamata continuamente in quanto la differenza è sempre > di "ritardoLed" che è 0 e non
  // si percepirebbe il cambiamento di stato.


  if (((millis() - tempoTrascorso) > ritardoLed) && (abilitaBlink == 1)) {
    controlloPulsante();
    tempoTrascorso = millis();
  }
}

// la funzione controlloPulsante() verifica lo stato
// attuale e precedente del pulsante in modo in modo che
// ad ogni pressioni venga avviata o fermata la sequenza,
// in modo che il funzionamento sia come quello di un interruttore
// Una pressione avvia la sequenza, seconda pressione ferma la sequenza.

void controlloPulsante() {
  stato = digitalRead(pulsante);

  // controllo se il pulsante è stato premuto
  if ((stato == HIGH) && (stato_precedente == LOW)) {
    attivaSequenza = 1 - attivaSequenza;
    delay(15);
  }

  stato_precedente = stato;

  if (attivaSequenza == 1) {
    cambiaStatoLed();
  } else {
    spegniLed();
  }
}

// la funzione cambiaStatoLed() permette di controllare
// la sequenza di accensione dei LED

void cambiaStatoLed() {
  // spegne tutti i LED
  for (byte x = 0; x < 8; x++) {
    digitalWrite(ledPin[x], LOW);
  }
  // accende il LED corrente
  digitalWrite(ledPin[ledCorrente], HIGH);
  // incrementa la variabile direzione
  ledCorrente += direzione;
  // cambia la direzione se si arriva alla fine
  if (ledCorrente == 7) {
    direzione = -1;
  }
  if (ledCorrente == 0) {
    direzione = 1;
  }
}

Sketch 07

Attivazione ciclica. Comando accensione sequenziale di 8 LED con un pulsante. Ad ogni pressione si accende il LED successivo. All’avvio si accende il primo LED. Accesso l’ultimo LED, la pressione successiva del pulsante accende il primo LED della serie.

Lo schema di collegamento è analogo a quello utilizzato per lo sketch 05.

/* Prof. Michele Maffucci
   30.12.2020
   Lezione di riferimento: https://wp.me/p4kwmk-4D3

   Versione 07
   Attivazione ciclica.
   Comando accensione sequenziale di 8 LED con un pulsante.
   Ad ogni pressione si accende il LED successivo.

   All'avvio si accende il primo LED.
   Accesso l'ultimo LED, la pressione successiva
   del pulsante accende il primo LED.

   Questo codice è di dominio pubblico
*/

// abilitazione/disabilitazione pausa sequenza
byte pulsante = 11;

// creazione di un array di 8 pin a cui vanno collegati i LED
// per ulteriori informazioni sull'uso degli array si consulti il seguente link:
// http://wp.me/p4kwmk-26e

byte ledPin[] = {3, 4, 5, 6, 7, 8, 9, 10};

// per approfondimenti sull'uso dei tipi di dati
// si consultino i link:
// https://wp.me/p4kwmk-4As
// https://wp.me/p4kwmk-1zF

void setup() {
  // impostiamo tutti i pin ad output
  for (byte x = 0; x < 8; x++) {
    pinMode(ledPin[x], OUTPUT);
  }
  pinMode(pulsante, INPUT);
}

// inizializzazione della variabile utilizzata per memorizzare
// il pin del LED attivo in un determinato istante
byte pinAttivo = 3;

void loop() {

  // se il pulsante è stato premuto si incrementa la variabile pinAttivo
  // al raggiungimento del valore limite alla successiva pressione viene
  // attivato il primo LED, quello collegato al pin 3

  if (digitalRead(pulsante)) {
    pinAttivo++;
    if (pinAttivo >= 11) {
      pinAttivo = 3;
    }
    delay(250);
  }

  // ogni volta che viene incrementata la variabile pinAttivo
  // vengono spenti tutti i LED accendendo solo quello collegato
  // al pin corrispondente alla variabile pinAttivo

  for (byte i = 0; i < 8; i++) {
    digitalWrite(ledPin[i], LOW);
  }

  // Viene acceso il LED collegato al pinAttivo

  digitalWrite(pinAttivo, HIGH);
}

Sketch 08

Attivazione avanti/indietro. Comando accensione sequenziale di 8 LED con un pulsante. Ad ogni pressione si accende il LED successivo, raggiunto l’ultimo LED si controllerà l’attivazione dei LED in senso inverso.

Lo schema di collegamento è analogo a quello utilizzato per lo sketch 05.

/* Prof. Michele Maffucci
   30.12.2020
   Lezione di riferimento: https://wp.me/p4kwmk-4D3

   Versione 08
   Attivazione avanti/indietro.
   Comando accensione sequenziale di 8 LED con un pulsante.
   Ad ogni pressione si accende il LED successivo,
   raggiunto l'ultimo LED si controllerà l'attivazione dei
   LED in senso inverso.

   Questo codice è di dominio pubblico
*/

// controllo accensione LED
byte pulsante = 11;

// creazione di un array di 8 pin a cui vanno collegati i LED
// per ulteriori informazioni sull'uso degli array si consulti il seguente link:
// http://wp.me/p4kwmk-26e

byte ledPin[] = {3, 4, 5, 6, 7, 8, 9, 10};

// per approfondimenti sull'uso dei tipi di dati
// si consultino i link:
// https://wp.me/p4kwmk-4As
// https://wp.me/p4kwmk-1zF

void setup() {

  // impostiamo tutti i pin ad output
  for (byte x = 0; x < 8; x++) {
    pinMode(ledPin[x], OUTPUT);
  }
  pinMode(pulsante, INPUT);
}

// inizializzazione della variabile utilizzata per memorizzare
// il pin del LED attivo in un determinato istante
byte pinAttivo = 3;

// indicatore di direzione di accensione
byte direzione = 1;

// indice dell'array per l'accensione del LED
byte ledCorrente = 0;

void loop() {

  // se il pulsante viene premuto si incrementa la variabile ledCorrente
  // usata come indice dell'array di LED, che sarà incrementata di una
  // unità ad ogni pressione, al raggiungimento del valore massimo (7) viene
  // modificata la direzione di accensione e decrementando la variabile
  // ledCorrente, al raggiungimento del valore minimo (0) viene
  // modificata la direzione di accensione.

  if (digitalRead(pulsante)) {

    // spegne tutti i LED
    for (byte x = 0; x < 8; x++) {
      digitalWrite(ledPin[x], LOW);
    }

    // accende il LED corrente
    digitalWrite(ledPin[ledCorrente], HIGH);
    // incrementa la variabile direzione
    ledCorrente += direzione;
    // cambia la direzione se si arriva alla fine
    if (ledCorrente == 7) {
      direzione = -1;
    }
    if (ledCorrente == 0) {
      direzione = 1;
    }
  }
  delay(250);
}

Sketch 09

Sequenza di accensione e spegnimento di 8 LED mediante due pulsanti. All’avvio tutti i LED sono spenti. Alla pressione del pulsante di sinistra si comanda l’accensione e lo spegnimento da destra verso sinistra dei LED. Alla pressione del pulsante di destra si comanda l’accensione e lo spegnimento da sinistra verso destra dei LED.

/* Prof. Michele Maffucci
   30.12.2020
   Lezione di riferimento: https://wp.me/p4kwmk-4D3

   Versione 09
   Sequenza di accensione e spegnimento di 8 LED
   mediante due pulsanti

   All'avvio tutti i LED sono spenti.

   Alla pressione del pulsante di sinistra si comanda
   l'accensione e lo spegnimento da destra verso sinistra dei LED.
   Alla pressione del pulsante di destra si comanda
   l'accensione e lo spegnimento da sinistra verso destra dei LED.

   Questo codice è di dominio pubblico
*/

// controllo accensione LED da DX a SX
byte pulsanteSx = 11;

// controllo accensione LED da SX a DX
byte pulsanteDx = 12;

// creazione di un array di 8 pin a cui vanno collegati i LED
// per ulteriori informazioni sull'uso degli array si consulti il seguente link:
// http://wp.me/p4kwmk-26e

byte ledPin[] = {3, 4, 5, 6, 7, 8, 9, 10};

// per approfondimenti sull'uso dei tipi di dati
// si consultino i link:
// https://wp.me/p4kwmk-4As
// https://wp.me/p4kwmk-1zF

void setup() {

  // impostiamo tutti i pin ad output
  for (byte x = 0; x < 8; x++) {
    pinMode(ledPin[x], OUTPUT);
  }
  pinMode(pulsanteSx, INPUT);
  pinMode(pulsanteDx, INPUT);
}

// inizializzazione della variabile utilizzata per memorizzare
// il pin del LED attivo in un determinato istante
byte pinAttivo = 3;

// indicatore di direzione di accensione
byte direzione = 1;

// indice dell'array per l'accensione del LED
byte ledCorrente = 0;

void loop() {

  // se il pulsante SX viene premuto si incrementa la variabile pinAttivo
  // al raggiungimento del valore limite alla successiva pressione
  // viene spento l'ultimo LED e pressioni successive del pulsante di SX
  // non causerà nulla

  if (digitalRead(pulsanteSx)) {
    pinAttivo++;
    if (pinAttivo > 10) {
      pinAttivo = 10;
    }
    delay(250);
  }

  // se il pulsante DX viene premuto si decrementa la variabile pinAttivo
  // al raggiungimento del valore limite alla successiva pressione
  // viene spento l'ultimo LED e pressioni successive del pulsante di DX
  // non causerà nulla

  if (digitalRead(pulsanteDx)) {
    pinAttivo--;
    if (pinAttivo < 3) {
      pinAttivo = 3;
    }
    delay(250);
  }

  // ogni volta che viene incrementata la variabile pinAttivo
  // vengono spenti tutti i LED accendendo solo quello collegato
  // al pin corrispondente alla variabile pinAttivo

  for (byte i = 0; i < 8; i++) {
    digitalWrite(ledPin[i], LOW);
  }

  // Viene acceso il LED collegato al pinAttivo

  digitalWrite(pinAttivo, HIGH);
}

Buon making a tutti 🙂

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.