Archivi categoria: arduino

Arduino – Uso di LED RGB – approfondimento

Scrivo questa lezione come approfondimento della guida realizzata tempo fa: Arduino – lezione 09: uso di LED RGB in cui mostravo come funzionano e come si gestiscono i LED RGB con Arduino. Negli esercizi proposti utilizzavo un LED ad ANODO comune. In questa nuova lezione utilizzerò un diodo a CATODO comune e mostrerò tre esempi, nel primo ripropongo in una modalità diversa l’esercizio della prima lezione in cui faccio alcuni approfondimenti sull’uso della direttiva #define, mentre nel secondo e terzo esercizio viene mostrato come impostare il colore emesso dal LED RGB mediante input da tastiera su Serial Monitor richiamando con questi esempi l’uso del qualificatore const per una variabile e l’utilizzo della funzione parseInt(). Come sempre nei commenti, all’interno del codice, trovate la spiegazione del funzionamento di ogni parte dello sketch.

Esempio 01

Variazione colore continuo di un LED RGB secondo lo schema:

ROSSO > VERDE, VERDE > BLU, BLU > ROSSO

Scema di collegamento

/*  Prof. Maffucci Michele
    06.01.2021

    Esempio 01
    Variazione colore continuo
    di un LED RGB secondo lo schema:

    ROSSO > VERDE, VERDE > BLU, BLU > ROSSO

*/

/* Utilizzo della direttiva #define per definire una costante
   La direttiva viene utilizzata per definire una MACRO ovvero
   un simbolo.

   La sintassi per la definizione di una macro è:
   #define nome-MACRO  valore_MACRO

   Per convenzione il nome della macro viene scritta in maiuscolo.

   Il preprocessore legge la definizione di ogni MACRO e ogni volta che
   ne incontra il nome all'interno del programma (file sorgente) sostituisce
   al simbolo il valore corrispondente, senza che venga effettuata la verifica
   della correttezza sintattica dell'espressione risultante.
*/

#define VERDE 9
#define BLU 10
#define ROSSO 11

// tempo di dissolvenza tra i colori
#define tempoRitardo 10

void setup()
{
  // impostazione ad OUTPUT dei pin
  pinMode(ROSSO, OUTPUT);
  pinMode(VERDE, OUTPUT);
  pinMode(BLU, OUTPUT);

  // all'avvio viene emesso il colorore ROSSO
  digitalWrite(BLU, LOW);
  digitalWrite(VERDE, LOW);
  digitalWrite(ROSSO, HIGH);
}

// definizione di variabili
int valoreRosso;
int valoreVerde;
int valoreBlu;

void loop()
{
  // Impostazioni variabili per avere partire con LED:
  // ROSSO accesso, VERDE spento, BLU spento.
  valoreRosso = 255;
  valoreVerde = 0;
  valoreBlu = 0;

  // partendo dal ROSSO si sfuma al VERDE pieno quando i = 255
  for (int i = 0; i < 255; i += 1)
  {
    valoreRosso -= 1;
    valoreVerde += 1;

    // L'intensità del ROSSO viene diminuita ad ogni ciclo, mentre
    // l'intensità del VERDE viene aumentata ad ogni ciclo
    analogWrite(ROSSO, valoreRosso);
    analogWrite(VERDE, valoreVerde);
    delay(tempoRitardo);
  }

  // Impostazioni variabili per avere partire con LED:
  // ROSSO spento, VERDE acceso, BLU spento.
  valoreRosso = 0;
  valoreVerde = 255;
  valoreBlu = 0;

  // partendo dal VERDE si sfuma al BLU pieno quando i = 255
  for (int i = 0; i < 255; i += 1)
  {
    valoreVerde -= 1;
    valoreBlu += 1;

    // L'intensità del VERDE viene diminuita ad ogni ciclo, mentre
    // l'intensità del BLU viene aumentata ad ogni ciclo
    analogWrite(VERDE, valoreVerde);
    analogWrite(BLU, valoreBlu);
    delay(tempoRitardo);
  }

  // Impostazioni variabili per avere partire con LED:
  // ROSSO spento, VERDE spento, BLU acceso.
  valoreRosso = 0;
  valoreVerde = 0;
  valoreBlu = 255;

  // partendo dal BLU si sfuma al ROSSO pieno quando i = 255
  for (int i = 0; i < 255; i += 1)
  {
    valoreBlu -= 1;
    valoreRosso += 1;

    // L'intensità del BLU viene diminuita ad ogni ciclo, mentre
    // l'intensità del ROSSO viene aumentata ad ogni ciclo
    analogWrite(BLU, valoreBlu);
    analogWrite(ROSSO, valoreRosso);
    delay(tempoRitardo);
  }
}

Esempio 02

Inserimento da Serial Monitor dei valori di intensità del colore. La stringa di richiesta inserimento dei valori RGB viene ripetuta una sola volta e ad ogni nuovo inserimento non viene stampato sulla serial monitor il valore inserito.

Lo schema di collegamento è il medesimo dell’esempio 01.

/*  Prof. Maffucci Michele
    06.01.2021

    Esempio 02
    Inserimento da Serial Monitor dei valori
    di intensità del colore.
    La stringa di richiesta inserimento viene ripetuta una sola volta.
    Ad ogni nuovo inserimento non viene stampato sulla serial monitor
    il valore inserito.

    L'inserimento dei tre valori potrà essere effettuato
    in una delle due modalità:
    1. separando i tre numeri con spazio
    2. separando i tre numeri con la virgola
*/

/*
   Una variabile const indica al compilatore che il valore della
   variabile non può essere modificato durante l'esecuzione del programma.
   Una variabile const viene inizializzata nel momento della dichiarazione,
   se ciò viene fatto in un momento successivo il compilatore rileverà un
   errore che segnalerà anche errore in ogni operazione che comportano la
   modifica del valore dell avariabile definita come const
*/

const byte pinRosso = 11;
const byte pinBlu = 10;
const byte pinVerde = 9;

void setup() {
  // Inizializzazione della comunicazione seriale
  Serial.begin(9600);

  // Impostazione dei pin come OUTPUT
  pinMode(pinRosso, OUTPUT);
  pinMode(pinBlu, OUTPUT);
  pinMode(pinVerde, OUTPUT);

  // Messaggio sulla serial monitor
  Serial.println("Inserisci i valori R G B (es. 125, 50, 255)");
  Serial.println("-------------------------------------------");
  delay(1000);
}

void loop() {

  // 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()) {
    // memorizzazione dei colori nelle variabili
    int rosso = Serial.parseInt();
    int verde = Serial.parseInt();
    int blu = Serial.parseInt();

    // impostazione del PWM
    analogWrite(pinRosso, rosso);
    analogWrite(pinVerde, verde);
    analogWrite(pinBlu, blu);
  }
}

Esempio 3

Inserimento da Serial Monitor dei valori di intensità del colore.
Il valore inserito verrà stampato sulla Serial Monitor e ad ogni invio verrà richiesto di inserire un nuovo valore.

Lo schema di collegamento è il medesimo dell’esempio 01.

/*  Prof. Maffucci Michele
    06.01.2021

    Esempio 03
    Inserimento da Serial Monitor dei valori
    di intensità del colore.
    Il valore inserito verrà stampato sulla Serial Monitor e ad ogni
    invio verrà richiesto di inserire un nuovo valore.

    L'inserimento dei tre valori potrà essere effettuato
    in una delle due modalità:
    1. separando i tre numeri con spazio
    2. separando i tre numeri con la virgola
*/

/*
   Una variabile const indica al compilatore che il valore della
   variabile non può essere modificato durante l'esecuzione del programma.
   Una variabile const viene inizializzata nel momento della dichiarazione,
   se ciò viene fatto in un momento successivo il compilatore rileverà un
   errore che segnalerà anche errore in ogni operazione che comportano la
   modifica del valore dell avariabile definita come const
*/

const byte pinRosso = 11;
const byte pinBlu = 10;
const byte pinVerde = 9;

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

void setup() {
  // Inizializzazione della comunicazione seriale
  Serial.begin(9600);

  // Impostazione dei pin come OUTPUT
  pinMode(pinRosso, OUTPUT);
  pinMode(pinBlu, OUTPUT);
  pinMode(pinVerde, OUTPUT);
}

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 i valori R G B (es. 125, 50, 255): ");
    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()) {
    // memorizzazione dei colori nelle variabili
    int rosso = Serial.parseInt();
    int verde = Serial.parseInt();
    int blu = Serial.parseInt();
    Serial.print(rosso);
    Serial.print(", ");
    Serial.print(verde);
    Serial.print(", ");
    Serial.println(blu);
    Serial.println("-------------------------------------------");

    // impostazione del PWM
    analogWrite(pinRosso, rosso);
    analogWrite(pinVerde, verde);
    analogWrite(pinBlu, blu);

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

Esercizi per i miei studenti

Esercizio 1

Utilizzare tre pulsanti che funzionino come interruttori che permettono di accendere e spegnere un solo LED alla volta:

  • pulsante 1: LED ROSSO
  • pulsante 2: LED VERDE
  • pulsante 3: LED BLU

Ogni cambiamento di stato deve essere segnalato sulla Serial Monitor.

Esercizio 2

Utilizzare due pulsanti in gredo di realizzare la seguente automazione:

  • pulsante 1: attivare/disattivare la modalità di variazione continua del colore, così come esposta nell’esempio 01
  • pulsante 2: attivare/disattivare la generazione casuale di un colore

Ogni cambiamento di stato deve essere segnalato sulla Serial Monitor.

Esercizio 3

Utilizzando la Serial Monitor come unico strumento per inviare comandi ad Arduino, realizzare un menù di selezione che permette di impostare le funzionalità dell’esercizio 01 e dell’esercizio 03.

Arduino: utilizzo di buzzer attivi e passivi – lezione 1

Nella progettazione di un sistema di automazione sono molto spesso previsti apparati di interazione e di allarme che potranno essere visivi o sonori. Per quanto riguarda gli apparati sonori spesso vengono utilizzati dei buzzer, chiamati anche cicalini. Con questo dispositivo potremo quindi segnalare lo stato di un sistema.

I buzzer possono essere di due tipi:

  • attivi
  • passivi

I buzzer possono essere di tipo magnetico o piezoelettrici la scelta del tipo dipende sostanzialmente da tre fattori:

  1. segnale di pilotaggio
  2. potenza di uscita richiesta
  3. spazio fisico disponibile

Buzzer attivo

Un buzzer attivo usa un oscillatore interno che permette di emettere un tono a frequenza fissa se viene alimentato con una tensione continua.

L’oscillatore interno è in grado di modificare il campo magnetico di una bobina a cui è connesso meccanicamente una membrana che oscillerà alla frequenza fissata dall’oscillatore.

Con Arduino si potrà realizzare un sistema di automazione in grado di comandare l’emissione del suono abilitando o disabilitando l’alimentazione del buzzer.

Caratteristiche tecniche di un buzzer attivo

  • Tensione nominale: 6V DC
  • Tensione di esercizio: 4-8V DC
  • Corrente nominale: < 30mA
  • Tipo di suono: segnale acustico continuo
  • Frequenza di risonanza: ~2300 Hz

Buzzer passivo

Un buzzer passivo non possiede un oscillatore interno e quindi è indispensabile un circuito esterno in grado di generare un’onda quadra che mettere in oscillazione la membrana interna del buzzer, questi attuatori potranno così emettere toni a diversa frequenza.

Con Arduino si potrà realizzare un sistema di automazione in grado di comandare l’emissione del suono per un certo tempo ad una determinata frequenza utilizzando il la modulazione digitale PWM.

Caratteristiche tecniche di un buzzer attivo

  • Tensione nominale: 5V DC
  • Tensione di esercizio: 4-8V DC
  • Corrente nominale massima: ≤ 32 mA
  • Min. Uscita audio a 10 cm: 85 dB
  • Temperatura di esercizio: da 20°C a 45°C

Pilotare un buzzer con Arduino

Per produrre un suono con Arduino si utilizza la funzione tone, il link vi rimanda al references di Arduino in cui troverete tutti i dettagli di utilizzo della funzione.

L’istruzione che verrà utilizzata è:

tone(pin, frequenza)
tone(pin,frequenza,durata)
  • pin: sarà il pin (PWM) su cui sarà presente il segnale modulato a cui verrà connesso il buzzer.
  • frequenza: frequenza del suono emesso. (unsigned int)
  • durata: la durata del tono espressa in millisecondi. (unsigned long)

Come indicato nel references:

Genera un’onda quadra alla frequenza specificata ( e duty cycle al 50% ) su un pin. Una durata puà essere specificata, altrimenti l’onda continua fino alla chiamata di noTone(). Il pin può essere connesso ad un buzzer piezoelettrico o altro speaker per riprodurre toni.

Solo un tono alla volta può essere generato. Se un tono è gia in riproduzione su un pin differente, la chiamata a tone() non avrà alcun effetto. Se il tono è in riproduzione sullo stesso pin, la chiamata ne imposterà la frequenza.

L’uso della funzione tone() interferirà con l’output PWM sui pin 3 e 11 (sulle schede diverse dalla Mega ).

Non è possibile generare toni inferioni a 31Hz. Per i dettagli tecnici, vedi le note di Brett Hagman.

NOTA: Se vuoi riprodurre toni differenti su pin multipli, hai bisogno di chiamare noTone() su un pin prima di chiamare tone() sul pin successivo.

La funzione noTone() interrompe la generazione dell’onda quadra causata da tone(). L’uso di noTone() non ha alcun effetto se non si sta generando alcun tono.

Sintassi:

noTone(pin);

Con Arduino è possibile riprodurre un solo tono alla volta in quanto l’utilizzo della funzione tone è legato ad un timer specifico del microcontrollore, il timer2 e se questo è richiesto da altre funzioni, come ad esempio un analogRead su pin PWM la funzione tone non potrà essere utilizzata. Per aggirare questo limite è possibile utilizzare la libreria Tone.h che vedremo nella prossime lezioni.

Il suono che può essere riprodotto mediante un altoparlante o un buzzer passivo collegato ad Arduino sarà un suono “metallico”, non sarà simile a quello di uno strumento musicale, e questo verrà ottenuto utilizzando un’onda quadra alla frequenza specificata.

Per riprodurre suoni simili a quelli di uno strumento musicale bisognerà utilizzare una scheda elettronica esterna che verrà controllata da Arduino, ma vedremo questa possibilità in una lezione successiva.

Per questa lezione utilizzerò prima un buzzer attivo e successivamente un buzzer passivo.

Esempio 1 – utilizzo buzzer attivo

 

/* Prof. Michele Maffucci
   data: 04.01.2021

   Esempio 01
   Utilizzo di un buzzer attivo
*/

// pin a cui è collegato il buzzer
byte buzzerPin = 2;
int buzzerRitardo = 1000;

void setup() {
  // inizializzazione pin a cui è collegto il buzzer
  pinMode(buzzerPin, OUTPUT);
}

void loop() {

  // buzzer ON
  digitalWrite(buzzerPin,HIGH);
  delay(buzzerRitardo);

  // buzzer OFF
  digitalWrite(buzzerPin,LOW);
  delay(buzzerRitardo);
}

Esempio 02 – utilizzo buzzer attivo

Per richiamare l’uso di valori interi dalla Serial Monitor di seguito uno sketch che permette di inserire da computer il valore del delay che regola l’ON e l’OFF del buzzer attivo.

Lo schema di collegamento è il medesimo dell’esempio precedente.

/* Prof. Michele Maffucci
   data: 04.01.2021

   Esempio 02
   Utilizzo di un buzzer attivo
   Inserimento delay da Serial Monitor
*/

// pin a cui è collegato il buzzer
byte buzzerPin = 2;
int  buzzerRitardo = 0;

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

void setup() {

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

  // inizializzazione pin a cui è collegto il buzzer
  pinMode(buzzerPin, OUTPUT);
}

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) {
      buzzerRitardo = r;
      Serial.println(buzzerRitardo);

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

  // funzione permette di fare suonare il Buzzer
  suona();
}

void suona() {
  // buzzer ON
  digitalWrite(buzzerPin,HIGH);
  delay(buzzerRitardo);

  // buzzer OFF
  digitalWrite(buzzerPin,LOW);
  delay(buzzerRitardo);
}

Esempio 03 – utilizzo buzzer attivo

Utilizziamo ora un trimmer per modificare il delay che varia tra 100 e 1000 millisecondi, per fare questa operazione utilizzeremo la funzione map che rimapperà i valori presenti su A0 nell’intervallo 100, 1000.

 

/* Prof. Michele Maffucci
   data: 01.01.2021

   Esempio 03
   Utilizzo di un buzzer attivo
   Inserimento delay da Trimmer per impostare
   un ritardo tra 100 e 1000 millisecondi
*/

// pin a cui è collegato il buzzer
byte buzzerPin = 2;
int  buzzerRitardo = 0;

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

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

void setup() {

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

  // inizializzazione pin a cui è collegto il buzzer
  pinMode(buzzerPin, OUTPUT);
}

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 100, 1000

  buzzerRitardo = map(val, 285, 719, 100, 1000);

  // funzione permette di fare suonare il Buzzer
  suona();
}

void suona() {
  // buzzer ON
  digitalWrite(buzzerPin,HIGH);
  delay(buzzerRitardo);

  // buzzer OFF
  digitalWrite(buzzerPin,LOW);
  delay(buzzerRitardo);
}

Esempio 4 – utilizzo buzzer passivo

Utilizziamo ora un buzzer passivo per riprodurre un tono in base alla frequenza impostata da un trimmer collegato al pin A0. Si faccia attenzione che ora il buzzer è collegato al pin 5 di tipo PWM

/* Prof. Michele Maffucci
   data: 04.01.2021

   Esempio 04
   Utilizzo di un buzzer passivo per riprodurre
   un tono in base alla frequenza impostata
   da un trimmer collegato al pin A0
*/

// pin (PWM) a cui è collegato il buzzer
byte buzzerPin = 5;

// variabile in cui memorizzare la frequenza del tono
int  intonazionePin = 0;

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

// frequenza del tono
unsigned int frequenza;

// durata del tono
unsigned long durata = 10;

void setup()
{
  // inizializzazione pin a cui è collegto il buzzer
  pinMode(buzzerPin, OUTPUT);
}

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 1000, 5000

  // frequenza assunerà un valore tra 1000 Hz e 5000 Hz
  frequenza = map(val, 285, 719, 1000, 5000);

  // emissione del tono
  tone(buzzerPin, frequenza, durata);

  // pausa di 1 millisecondo
  delay(1);
}

Nella prossime lezioni, utilizzando un buzzer passivo, realizzeremo dei brevi brani musicali e successivamente sostituiremo il buzzer con un altoparlante da 8 Ohm.

Buon Making a tutti 🙂

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;
  }
}

Continua a leggere

Arduino: cicli infiniti ed uscita da un ciclo infinito

Per rispondere ad un quesito che mi è stato posto questa mattina a lezione da alcuni allievi condivido questo breve approfondimento sulla gestione dei cicli infiniti.

Parliamo di un ciclo infinito quando il controllo entra nel corpo del ciclo e non esce mai da esso, ciò accade quando la condizione di test del loop non è mai false.

Possiamo realizzare un ciclo infinito in C in diversi modi:

for (int i = 0; i >= 0; )
{
    // corpo del ciclo in cui la variabile i non viene mai modificata
}

Nell’esempio la variabile i viene inizializzata a 0 e la condizione di controllo i>=0 all’inizio è vera. La variabile i non viene modificato in nessun punto del codice inoltre l’espressione di aggiornamento della variabile non è presente, ciò implica che i avrà sempre come valore 0 e la condizione di controllo i>=0 non è mai falsa e quindi il corpo del for viene eseguito ad ogni ciclo.

Un modo più sintetico per realizzare un ciclo infinito è quello di utilizzare una condizione sempre vera utilizzando l’istruzione while:

while (true)
{
    // corpo del while
}

Questo comportamento può essere realizzato anche scrivendo 1 per indicare “condizione sempre vera”.

while (1)
{
    // corpo del while ripetuto per sempre
}

o ancora utilizzando un’uguaglianza sempre vera:

while (3==3)
{
    // corpo del while ripetuto per sempre
}

che nella programmazione con Arduino può essere ottenuto anche con:

while (HIGH)
{
    // corpo del while ripetuto per sempre
}

E’ possibile realizzare un ciclo infinito anche con l’istruzione for omettendo la condizione di ripetizione del ciclo, cioè che bisognerebbe inserire tra i due punti e virgola.

for (;;)
{
    // corpo del for ripetuto per sempre
}

Terminare un ciclo infinito

Negli esempi visti precedentemente la condizione sempre vera causava la ripetizione infinita del corpo dell’istruzione, però esiste il modo per terminare un ciclo infinito utilizzando l’istruzione break usata appunto per uscire da un ciclo: for, while oppure do..while, ma anche per uscire da una istruzione switch case.

Poiché nelle nostre sperimentazioni utilizziamo Arduino vediamo come realizzare l’uscita da un loop infinito.

Lo scopo è quello di far lampeggiare ripetutamente un LED e bloccare il lampeggio con la pressione di un pulsante.

Realizzimo il seguente circuito:

Utilizzando l’istruzione while.

Esempio 1

/*
  Prof. Michele Maffucci
  Data: 16.11.2020
  Esempio1: Funzionamento dell'istruzione break
*/
const int pinPulsante = 8; // pin digitale 8

void setup()
{
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT); // abilita il pin a cui è connesso il LED come output
  pinMode(pinPulsante, INPUT);  // abilita il pin a cui è connesso il pulsante come input
}
void loop()
{
  while (true) // ciclo infinito
  {
    if (digitalRead(pinPulsante) == HIGH)
    {
      break; // esce dal ciclo se si preme il pulsante
    }
    lampeggio(); // chiama la funzione che accende e spegne il LED
  }
}
void lampeggio()
{
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);
}

Come si può notare viene utilizzata l’istruzione break per uscire dal ciclo. Fino a quando il pulsante non sarà premuto la condizione: digitalRead(pinPulsante) == HIGH sarà falsa, pertanto non verrà eseguito il corpo dell’if e quindi non potrà essere eseguito il break, in questa condizione ciò che segue l’if è la chiamata della funzione lampeggia().

Nel caso in cui il pulsante viene premuto, la condizione digitalRead(pinPulsante) == HIGH risulta vera, pertanto viene eseguito il corpo dell’if che contiene l’istruzione break che causerà l’uscita dal ciclo while.

Il codice sopra indicato funziona anche se nel while viene sostituito true con HIGH:

...
while (true) // ciclo infinito
  {
       // corpo del while
  }
...

con

...
while (HIGH) // ciclo infinito
  {
       // corpo del while
  }
...

Come spiegato ad inizio lezione, un ciclo infinito può essere ottenuto anche con un’istruzione for quindi si ottiene il medesimo risultato se si utilizza il codice che segue.

Esempio 2

/*
  Prof. Michele Maffucci
  Data: 16.11.2020
  Funzionamento dell'istruzione break
*/
const int pinPulsante = 8; // pin digitale 8

void setup()
{
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT); // abilita il pin a cui è connesso il LED come output
  pinMode(pinPulsante, INPUT);  // abilita il pin a cui è connesso il pulsante come input
}
void loop()
{
  for (;;) // ciclo infinito
  {
    if (digitalRead(pinPulsante) == HIGH)
    {
      break; // esce dal ciclo se si preme il pulsante
    }
    lampeggio(); // chiama la funzione che accende e spegne il LED
  }
}
void lampeggio()
{
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);
}

Differenze tra ciclo for e ciclo while

  • Il ciclo for ha necessità di una variabile al suo interno, mente il ciclo while può utilizzare qualsiasi variabile definita prima dell’istruzione while.
  • L’uso del ciclo do-while permette di realizzare sempre una volta il corpo delle istruzioni in esso contenuto (indipendentemente dall’espressione condizionale) e ciò non può essere fatto con un  ciclo for.

Esercizio per i miei studenti

Esercizio 1

Realizzare le stesse funzionalità dell’esempio precedente (usando un ciclo infinito nel loop()) aggiungendo la stampa sequenziale crescente di un numero n = n + 1 sulla Serial Monitor. Alla pressione del pulsante si interrompe il lampeggio del LED e si azzera il contatore.

Buon Coding a tutti 🙂

Arduino: strutturare il codice in blocchi funzionali

Molto spesso durante le prime fasi di realizzazione di uno sketch Arduino si tende a non strutturare il proprio programma in blocchi funzionali separati, tutto il codice viene inserito all’interno del loop(). Questo tipo di approccio, soprattutto se siamo in presenza di un codice molto lungo, rende difficoltosa la lettura del programma da parte di altre persone e non permette una facile comprensione del funzionamento o l’identificazione di possibili errori.

Ho parlato in passato come strutturare il codice in blocchi funzionali nel post:
Arduino – lezione 07: lavorare con gruppi di valori e funzioni esterne, ma in quella lezione utilizzavo istruzioni che in questa fase dell’anno scolastico non sono ancora conosciute da alcuni allievi soprattutto del 3′ anno, che iniziano ad utilizzare Arduino, pertanto la presente lezione dovrebbe chiarire in modo più semplice l’argomento.

Le funzioni vengono utilizzate per organizzare le azioni eseguite dal vostro programma. Ogni funzione può essere identificata da un’azione specifica richiamata dal programma principale loop(), oppure richiamate da altre funzioni sempre all’interno del nostro sketch.

Senza saperlo quando avete iniziato a programmare con Arduino avete utilizzato delle funzioni: loop() e setup() le due funzioni sempre presenti in ogni sketch.

Per creare una funzione bisogna:

  • definire il tipo di valore restituito dalla funzione;
  • assegnare un nome alla funzione;
  • e opzionalmente impostare una serie di parametri che la funzione riceverà quando viene chiamata (si dice anche invocata).

Creiamo una semplice funzione che permette di fare lampeggiare un LED, non possiede parametri e non restituisce nessun valore.
Assegnare alla funzione il tipo void vuol dire che non restituisce nulla e non inserire nulla tra le parentesi tonde indica che la funzione non accetta nessun parametro.

Esempio 1

// Prof. Michele Maffucci
// Es.01 - Usare le funzioni
// Data: 15.11.2020

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  lampeggia();
}

// blink LED una volta
void lampeggia()
{
  digitalWrite(LED_BUILTIN, HIGH); // accende il LED
  delay(1000); // pausa di 1 secondo
  digitalWrite(LED_BUILTIN, LOW); // spegne il LED
  delay(1000); // pausa di 1 secondo
}

Ogni volta che il loop() chiama (invoca) la funzione esterna lampeggia() viene effettuato il blink del LED sulla scheda.

Esempio 2

Realizziamo ora un secondo esempio in cui la funzione “lampeggia” accetta come parametro un valore intero che definisce il delay da impostare all’interno del funzione.

// Prof. Michele Maffucci
// Es.02 - Usare le funzioni
// Data: 15.11.2020

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  // chiamiamo la funzione lampeggia passando il valore
  // specificato all'interno delle parentesi tonde
  lampeggia(250);
}

// blink LED una volta
// per far si che la funzione accetti un parametro in input
// bisogna dichiarare il tipo del parametro in ingresso
// nella funzione lampeggia: int pausa

void lampeggia(int pausa)
{
  digitalWrite(LED_BUILTIN, HIGH); // accende il LED
  delay(pausa); // pausa: valore inserito nella variabile "pausa"
  digitalWrite(LED_BUILTIN, LOW); // spegne il LED
  delay(pausa); // pausa: valore inserito nella variabile "pausa"
}

Esempio 3

Realizziamo ora un terzo sketch in cui i parametri di ingresso per la funzione lampeggia() sono due, uno che definisce il tempo di accensione del LED ed uno che definisce il tempo di spegnimento del LED:

// Prof. Michele Maffucci
// Es.03 - Usare le funzioni
// Data: 15.11.2020

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  // chiamiamo la funzione lampeggia passando il valore
  // specificato all'interno delle parentesi tonde
  lampeggia(250, 1000);
}

// blink LED una volta
// per far si che la funzione accetti duen parametri in input
// bisogna dichiarare il tipo per ogni parametro in ingresso
// nella funzione lampeggia: int pausaOn e int pausaOff

void lampeggia(int pausaOn, int pausaOff)
{
  digitalWrite(LED_BUILTIN, HIGH); // accende il LED
  delay(pausaOn); // delay LED ON
  digitalWrite(LED_BUILTIN, LOW); // spegne il LED
  delay(pausaOff); // delay LED OFF
}

Esempio 4

Definiamo ora una funzione che ha 3 parametri di ingresso: il tempo in cui il LED rimane acceso, il tempo in cui il LED rimane spento e il numero di volte (cicli) che deve ripetersi il lampeggio, al termine del numero di cicli il LED non lampeggerà più. Come specificato nei commenti la variabile chiave verrà utilizzata per eseguire una volta sola la chiamata della funzione lampeggio:

// Prof. Michele Maffucci
// Es.04 - Usare le funzioni
// Data: 15.11.2020

// chiave e la variabile che consente l'esecuzione della
// chiamata della funzione lampegga una sola volta
int chiave = 0;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  // chiamiamo la funzione lampeggia passando il valore
  // specificato all'interno delle parentesi tonde
  if (chiave == 0) {
    chiave = 1;
    lampeggia(250, 1000, 5);
  }
}

// blink LED una volta
// per far si che la funzione accetti tre parametri in input
// bisogna dichiarare il tipo per ogni parametro in ingresso
// nella funzione lampeggia: int pausaOn, int pausaOff, int contatore
// la variabile contatore definisce il numero di cicli di lampeggio

void lampeggia(int pausaOn, int pausaOff, int contatore)
{
  for (int i = 0; i < contatore; i++) {
    digitalWrite(LED_BUILTIN, HIGH); // accende il LED
    delay(pausaOn); // delay LED ON
    digitalWrite(LED_BUILTIN, LOW); // spegne il LED
    delay(pausaOff); // delay LED OFF
  }
}

All’interno dello sketch precedente la funzione lampeggio utilizza un ciclo for per ripetere, per il numero di volte specificato dalla variabile contatore, il codice di accensione e spegnimento (corpo del for).

Esempio 5

Per completezza e per richiamare il modo con cui utilizzare l’istruzione while, di seguito trovate lo sketch che realizza la medesima funzionalità dello sketch precedente in cui il ciclo for viene sostituito da un while:

// Prof. Michele Maffucci
// Es.05 - Usare le funzioni
// Data: 15.11.2020

// chiave e la variabile che consente l'esecuzione della
// chiamata della funzione lampegga una sola volta
int chiave = 0;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  // chiamiamo la funzione lampeggia passando il valore
  // specificato all'interno delle parentesi tonde
  if (chiave == 0) {
    chiave = 1;
    lampeggia(250, 1000, 5);
  }
}

// blink LED una volta
// per far si che la funzione accetti tre parametri in input
// bisogna dichiarare il tipo per ogni parametro in ingresso
// nella funzione lampeggia: int pausaOn, int pausaOff, int contatore
// la variabile contatore definisce il numero di cicli di lampeggio

void lampeggia(int pausaOn, int pausaOff, int contatore)
{
  while (contatore > 0) {
     digitalWrite(LED_BUILTIN, HIGH); // accende il LED
    delay(pausaOn); // delay LED ON
    digitalWrite(LED_BUILTIN, LOW); // spegne il LED
    delay(pausaOff); // delay LED OFF
    contatore = contatore - 1; // decremento del contatore
  }
}

Esempio 6

Nello sketch che segue realizziamo una funzione che accetta un parametro e restituisce un valore. Il parametro che viene passato alla funzione definisce la durata dei tempi di accensione e spegnimento del LED (in millisecondi). La funzione continua a far lampeggiare un LED fino a quando non viene premuto un pulsante. Il valore restituito dalla funzione è il numero di lampeggi effettuati, questo valore verrà stampato sulla Serial Monitor:

// Prof. Michele Maffucci
// Es.06 - Usare le funzioni
// Data: 15.11.2020

const int pinPulsante = 8; // pin a cui colleghiamo il pulsante

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(pinPulsante, INPUT);
  Serial.begin(9600);
}

void loop() {
  Serial.println("Premere il pulsante per interrompere il lampeggio");
  int contatore = lampeggia(500); // lampeggio del LED: 500 ms ON e 500 ms OFF
  Serial.print("Il numero di volte in cui il LED ha lampeggiato è stato di: ");
  Serial.println(contatore);
  while (digitalRead(pinPulsante) == HIGH)
  {
    // non viene fatto nulla fino a quando non rilascio il pulsante
  }
}

// la funzione fa lampeggiare il LED per un periodo specificato (int periodo)
// e restituisce il numero di volte in cui il LED ha lampeggiato

int lampeggia(int periodo)
{
  int contatoreLampeggio = 0;

  while (digitalRead(pinPulsante) == LOW)
    // ripetere finché non viene premuto il pulsante
    // cicla fino a quando il pulsante non viene premuto
  {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(periodo);
    digitalWrite(LED_BUILTIN, LOW);
    delay(periodo);
    contatoreLampeggio = contatoreLampeggio + 1; // incrementa il contatore
  }
  // in questo punto vuol dire che pinPulsante è HIGH
  // ciò vuol dire che il pulsante è premuto

  // contatoreLampeggio è il valore che viene restituito alla funzione chiamante
  return contatoreLampeggio;
}

Il tipo di dato che precede in nome della funzione:

int lampeggia()

indica il tipo di dato restituito dalla funzione. Ricordarsi che nella funzione chiamante, nel nostro caso il loop(), quando chiamiamo la funzione questa deve terminare con un punto e virgola:

int contatore = lampeggia(500);

Errori comuni che vengono commessi nella chiamata di funzioni

Rimando a queste due brevi note che mostrano alcuni errori tipici:

Buon Making a tutti 🙂

Esercizi per i miei studenti

Esercizio 1

Realizzare un circuito costituito da 4 pulsanti e 4 led, connessi ad Arduino.

  • Alla pressione del pulsante P1 il LED1 effettua il blink con un tempo di 200 ms
  • Alla pressione del pulsante P2 il LED2 effettua il blink con un tempo di 400 ms
  • Alla pressione del pulsante P3 il LED3 effettua il blink con un tempo di 600 ms
  • Alla pressione del pulsante P4 il LED4 effettua il blink con un tempo di 800 ms

Fare in modo tale che ci sia una funzione esterna, chiamata dal loop(), che effettui il blink dei led.

Esercizio 2

Aggiungere all’esercizio 1 un pulsante che se premuto accende in sequenza ripetuta i 4 led. L’accensione in sequenza deve avvenire chiamando una funzione esterna al loop().