Arduino – lezione 07: lavorare con gruppi di valori e funzioni esterne

Questa settima lezione nasce dalla richiesta di alcuni miei studenti che hanno chiesto chiarimenti in merito all’uso degli array, della chiamata di funzioni esterne al loop e del controllo di flusso.

Per la realizzazione della lezione verrà usato un semplice circuito costituito da pulsanti, resistenze e led.

Fate attenzione che sui pulsanti non utilizzano una resistenza esterna di pull-up, perché abiliteremo la resistenza di pull-up interna di Arduino.

Nel montaggio noterete che ho impiegato un supporto costituito da due breadboard che ho costruito per rendere più agevole la realizzazione di esperienze con Arduino. Ovviamente potrete realizzare il tutto con una singola breadboard.

Lista componenti

  • Scheda Arduino (nel mio caso Arduino UNO Rev3);
  • 4 LED;
  • 4 resistenza da 220 Ohm;
  • 4 pulsanti normalmente aperti.

Schema topografico

Risultato del montaggio



Per completezza ripeto quanto detto in “Appunti di programmazione su Arduino: tipi di dati” che trovate su questo sito, chiarendo con un disegno:

Un array è un insieme di valori a cui si accede con un indice.
Un valore nell’array può essere richiamato con il nome dell’array e l’indice numerico che corrisponde al numero d’ordine del valore nell’array.
Gli array vengono indicizzati partendo dal numero zero e quindi il primo valore dell’array avrà indice 0.
Un array deve essere dichiarato ed opzionalmente si possono assegnare i valori prima di utilizzarlo.

Quindi l’array è una collezione organizzata di oggetti dello stesso tipo (campo di esistenza).
Il numero degli elementi contenuti nell’array viene detto dimensione dell’array.

Dire che la collezione di oggetti è organizzata vuol dire che si potrà identificare in modo univoco gli elementi dell’array.

L’identificazione di un elemento dell’array viene fatta mediante un indice.
In un array di dimensione N il valore dell’indice andrà da 0 a N-1.

Citando ancora quanto già spiegato:

int myArray[] = { value0, value1, value2...}

Allo stesso modo è possibile dichiarare un array dichiarandone il tipo e la dimensione e poi assegnare i valori:

int myArray[5];
// dichiara un array di interi avente una dimensione di 5

myArray[3] = 10;
// assegna in quarta posizione il valore 10

Per recuperare un valore all’interno di un array, bisogna dichiarare una variabile a cui poi viene assegnato il valore assunto allo specifivo indice:

x = myArray[3]; // ora x ha il valore 10

Prendiamo ora in considerazione il seguente sketch:

1/*Autore: Michele Maffucci
2data: 10.01.13
3Utilizzo degli array - ver.1
4*/
5 
6int pinPulsanti[] = {2,3,4,5};    // crea un array di pin per gli input
7                                  // costituiti dai pulsanti
8 
9int pinLed[] = {10,11,12,13};     // crea un array di pin di output per il LED
10 
11void setup()
12{
13  for(int indice = 0; indice < 4; indice++)
14  {
15    pinMode(pinLed[indice], OUTPUT);            // dichiara il LED come output
16    pinMode(pinPulsanti[indice], INPUT);        // dichiara il pulsante come input
17    digitalWrite(pinPulsanti[indice],HIGH);     // abilita la resistenza di pull-up
18 
19    // l'abilitazione della resistenza di pull-up mi permette di non utilizzare
20    // una resistenza esterna in serie al pulsante
21  }
22}
23 
24void loop(){
25  for(int indice = 0; indice < 4; indice++)
26  {
27    int stato = digitalRead(pinPulsanti[indice]);  // legge il valore di input
28    if (stato == LOW)                              // controlla se il pulsante è premuto
29    {
30      digitalWrite(pinLed[indice], HIGH);        // accende il LED il pulsante è premuto
31    }
32    else
33    {
34      digitalWrite(pinLed[indice], LOW);          // spegne il LED
35    }
36  }
37}

Questo il risultato:

Analizziamo il codice facendo riferimento allo schema che trovate di seguito:

1int pinPulsanti[] = {2,3,4,5};    // crea un array di pin per gli input
2                                  // costituiti dai pulsanti

definisce un array di interi di dimensione 4 che contiene i valori: 2,3,4,5

I 4 elementi sono:

pinPulsanti[0] coincide con il valore intero 2
pinPulsanti[1] coincide con il valore intero 3
pinPulsanti[2] coincide con il valore intero 4
pinPulsanti[3] coincide con il valore intero 5

Analogamente possiamo dire che:

1int pinLed[] = {10,11,12,13};     // crea un array di pin di output per il LED

è un array di dimensione 4 è contiene i valori 10, 11, 12, 13

pinLed[0] coincide con il valore intero 10
pinLed[1] coincide con il valore intero 11
pinLed[2] coincide con il valore intero 12
pinLed[3] coincide con il valore intero 13

La parte di codice contenuta nel setup:

1...
2  for(int indice = 0; indice < 4; indice++)
3  {
4    pinMode(pinLed[indice], OUTPUT);            // dichiara il LED come output
5    pinMode(pinPulsanti[indice], INPUT);        // dichiara il pulsante come input
6    digitalWrite(pinPulsanti[indice],HIGH);     // abilita la resistenza di pull-up
7 
8    // l'abilitazione della resistenza di pull-up mi permette di non utilizzare
9    // una resistenza esterna in serie al pulsante
10 
11  }
12...

consente di inizializzare come OUTPUT i pin digitali: 10, 11, 12, 13 e come INPUT i pin digitali: 2, 3, 4, 5 inoltre sui pin: 2, 3, 4, 5 viene abilitata la resistenza di pull-up.

Il for ciclerà fino a quando “indice” è minore di 4, quindi per i valori di “indice” pari a: 0, 1, 2, 3 cioè:

indice = 0

pinMode(pinLed[0], OUTPUT);
pinMode(pinPulsanti[0], INPUT);
DigitalWrite(pinPulsanti[0],HIGH);

andando a sostituire i valori contenuti nell’array avremo:

pinMode(10, OUTPUT);
pinMode(2, INPUT);
digitalWrite(2,HIGH);

cioè:

pin digitale 10 dichiarato come OUTPUT
pin digitale 2 dichiarato come INPUT
abilitazione della resistenza di pull-up sul pin 2

indice = 1

pinMode(pinLed[1], OUTPUT);
pinMode(pinPulsanti[1], INPUT);
DigitalWrite(pinPulsanti[1],HIGH);

andando a sostituire i valori contenuti nell’array avremo:

pinMode(11, OUTPUT);
pinMode(3, INPUT);
digitalWrite(3,HIGH);

cioè:

pin digitale 11 dichiarato come OUTPUT
pin digitale 3 dichiarato come INPUT
abilitazione della resistenza di pull-up sul pin 3

indice = 2

pinMode(pinLed[2], OUTPUT);
pinMode(pinPulsanti[2], INPUT);
DigitalWrite(pinPulsanti[2],HIGH);

andando a sostituire i valori contenuti nell’array avremo:

pinMode(12, OUTPUT);
pinMode(4, INPUT);
digitalWrite(4,HIGH);

cioè:

pin digitale 12 dichiarato come OUTPUT
pin digitale 4 dichiarato come INPUT
abilitazione della resistenza di pull-up sul pin 4

indice = 3

pinMode(pinLed[3], OUTPUT);
pinMode(pinPulsanti[3], INPUT);
DigitalWrite(pinPulsanti[3],HIGH);

andando a sostituire i valori contenuti nell’array avremo:

pinMode(13, OUTPUT);
pinMode(5, INPUT);
digitalWrite(5,HIGH);

cioè:

pin digitale 13 dichiarato come OUTPUT
pin digitale 5 dichiarato come INPUT
abilitazione della resistenza di pull-up sul pin 5

Nella successiva parte di codice:

1...
2void loop(){
3  for(int indice = 0; indice < 4; indice++)
4  {
5    int stato = digitalRead(pinPulsanti[indice]);  // legge il valore di input
6    if (stato == LOW)                              // controlla se il pulsante è premuto
7    {
8      digitalWrite(pinLed[indice], HIGH);        // accende il LED il pulsante è premuto
9    }
10    else
11    {
12      digitalWrite(pinLed[indice], LOW);          // spegne il LED
13    }
14  }
15}

Anche in questo caso utilizziamo un ciclo for, però questa volta per verificare quale dei quattro pulsanti è premuto.

indice = 0

“stato” (dichiarata come variabile intera) assumerà il valore HIGH o LOW a seconda che il pulsante a cui si fa riferimento nell’array con indice = 0, è premuto oppure no.

int stato = digitalRead(pinPulsanti[0]);

detto in altro modo:

int stato = digitalRead(2);

con digitalRead(2) leggiamo lo stato sul pin 2

Se stato == LOW
vuol dire che il pin corrispondente si trova a a GND cioè il pulsante è stato premuto, ma se il pulsante viene premuto il LED corrispondente dovrà accendersi infatti il corpo dell’if è:

digitalWrite(pinLed[indice], HIGH);

supponendo che sia stato premuto il primo pulsante avremo:

digitalWrite(pinLed[0], HIGH);

detto in altro modo:

digitalWrite(10, HIGH);

e quindi si accenderà il led connesso al pin digitale 10

Nel caso in cui il pulsante connesso al pin 2 non sia premuto, vuol dire che stato == HIGH (ricordate che i pin digitali 2, 3, 4, 5 sono stati impostati ad HIGH) e quindi viene eseguito l’else:

digitalWrite(pinLed[indice], LOW);

poiché indice = 0 avremo:

digitalWrite(pinLed[0], LOW);

che detta in altro modo sarà:

digitalWrite(10, LOW);

ovvero spegniamo il LED connesso al pin digitale 0.

Si procede in modo analogo per i valori successivi di indice.

Eseguiamo alcuni miglioramenti allo sketch precedente introducendo il comando const:

1/*
2Autore: Michele Maffucci
3data: 10.01.13
4Utilizzo degli array - ver.2
5Uso del comando const per definire delle costanti
6*/
7 
8const int INDICE_PIN = 4; // definisce una costante per il numero di pin
9 
10int pinPulsanti[INDICE_PIN] = {2,3,4,5};    // create un array of pin per gli input
11                                            // costituiti dai pulsanti
12 
13int pinLed[INDICE_PIN] = {10,11,12,13};     // crea un array di pin di output per il LED
14 
15void setup()
16{
17  for(int indice = 0; indice < INDICE_PIN; indice++)
18  {
19    pinMode(pinLed[indice], OUTPUT);            // dichiara il LED come output
20    pinMode(pinPulsanti[indice], INPUT);        // dichiara il pulsante come input
21    digitalWrite(pinPulsanti[indice],HIGH);     // abilita la resistenza di pull-up
22 
23    // l'abilitazione della resistenza di pull-up mi permette di non utilizzare
24    // una resistenza esterna in serie al pulsante
25  }
26}
27 
28void loop(){
29  for(int indice = 0; indice < INDICE_PIN; indice++)
30  {
31    int stato = digitalRead(pinPulsanti[indice]);  // legge il valore di input
32    if (stato == LOW)                              // controlla se il pulsante è premuto
33    {
34      digitalWrite(pinLed[indice], HIGH);        // accende il LED il pulsante è premuto
35    }
36    else
37    {
38      digitalWrite(pinLed[indice], LOW);         // spegne il LED
39    }
40  }
41}

Il comando const viene utilizzato per definire delle costanti, cioè dei nomi assegnati in modo fisso a dei valori.
Possono essere assimiliati a delle macro, con la differenza che non accettano funzioni come valore.

Un modo alternativo all’uso del const è l’uso della direttiva #define.

Nello sketch precedente la variabile indice assume valori che vanno da 0 a 3. Potrebbe accadere che per errore si tenti di accedere accidentalmente a valori che si trovano oltre la dimensione dell’array, in questo caso il copilatore non vi darà nessun errore, per evitare l’accesso a valori che vanno al di fuori dell’array si utilizza il comando const. Così facendo se per errore richiediamo la lettura di un elemento con indice maggiore alla dimensione massima dell’array, il compilatore restituirà errore.

Analizziamo il codice:

definisce una variabile intera di nome INDICE_PIN che assume il valore 4

1...
2const int INDICE_PIN = 4; // definisce una costante per il numero di pin
3...

definisce un array di interi di dimensione 4

1...
2 
3int pinPulsanti[INDICE_PIN] = {2,3,4,5};    // create un array of pin per gli input
4                                            // costituiti dai pulsanti...

definisce un array di interi di dimensione 4

1...
2int pinPulsanti[INDICE_PIN] = {2,3,4,5};    // create un array of pin per gli input
3                                            // costituiti dai pulsanti
4...

Chiamata ad una funzione esterna

Aggiungiamo una piccola funzionalità allo sketch precedente, alla pressione del pulsante 1 si vuole far lampeggiare il led 1, alla pressione del pulsante 2 si vuole far lampeggiare il led 2 e allo stesso modo per gli altri, per far ciò utilizzeremo una funzione esterna di nome blink1 che si occuperà di far lampeggiare il LED.

Le funzioni vengono utilizzate per suddividere in blocchi le azioni che il nostro sketch deve eseguire. Le funzioni raccolgono le azioni di input e output.
L’uso delle funzioni favorisce la strutturazione del programma per meglio comprendere il codice e favorire modifiche future.

Questo lo sketch:

1/*
2Autore: Michele Maffucci
3data: 10.01.13
4Alla pressione del pulsante far lampeggiare con periodo 100 millisecondi il LED corrispondente.
5*/
6 
7const int INDICE_PIN = 4; // definisce una costante per il numero di pin
8 
9int pinPulsanti[INDICE_PIN] = {2,3,4,5};    // create un array of pin per gli input
10                                            // costituiti dai pulsanti
11 
12int pinLed[INDICE_PIN] = {10,11,12,13};               // crea un array di pin di output per il LED
13 
14void setup()
15{
16  for(int indice = 0; indice < INDICE_PIN; indice++)
17  {
18    pinMode(pinLed[indice], OUTPUT);            // dichiara il LED come output
19    pinMode(pinPulsanti[indice], INPUT);        // dichiara il pulsante come input
20    digitalWrite(pinPulsanti[indice],HIGH);     // abilita la resistenza di pull-up
21 
22    // l'abilitazione della resistenza di pull-up mi permette di non utilizzare
23    // una resistenza esterna in serie al pulsante
24  }
25}
26 
27void loop(){
28  for(int indice = 0; indice < INDICE_PIN; indice++)
29  {
30    int stato = digitalRead(pinPulsanti[indice]);  // legge il valore di input
31    if (stato == LOW)                              // controlla se il pulsante è premuto
32    {
33      digitalWrite(pinLed[indice], HIGH);        // accende il LED
34      delay(100);                                // attende 100 millisecondi
35      digitalWrite(pinLed[indice], LOW);         // spegne il LED
36      delay(100);                                // attende 100 millisecondi
37  }
38    else
39    {
40      digitalWrite(pinLed[indice], LOW);          // spegne il LED
41    }
42  }
43}

Come potete constatare alla pressione del pulsante, cioè quando “stato” assume il valore LOW, viene eseguito il blink del led corrispondente.

Utilizziamo ora una funzione esterna per poter eseguire l’effetto blink.

Come già sapete negli sketch Arduino le due funzioni principali che devono sempre essere presenti sono setup e loop.

Per dichiarare una nuova funzione e sufficiente dichiarare il tipo di valore che deve restituire, il suo nome e tutti i parametri (opzionali) che deve ricevere quando viene chiamata.

Come esempio utilizziamo lo sketch precedente per richiamare una funzione blink a cui viene passato come valore un intero che identifica il pin a cui è collegato il led da far lampeggiare.

1/*
2Autore: Michele Maffucci
3data: 10.01.13
4Uso delle funzioni esterne
5*/
6 
7const int INDICE_PIN = 4; // definisce una costante per il numero di pin
8 
9int pinPulsanti[INDICE_PIN] = {2,3,4,5};    // create un array of pin per gli input
10                                            // costituiti dai pulsanti
11 
12int pinLed[INDICE_PIN] = {10,11,12,13};               // crea un array di pin di output per il LED
13 
14void setup()
15{
16  for(int indice = 0; indice < INDICE_PIN; indice++)
17  {
18    pinMode(pinLed[indice], OUTPUT);            // dichiara il LED come output
19    pinMode(pinPulsanti[indice], INPUT);        // dichiara il pulsante come input
20    digitalWrite(pinPulsanti[indice],HIGH);     // abilita la resistenza di pull-up
21 
22    // l'abilitazione della resistenza di pull-up mi permette di non utilizzare
23    // una resistenza esterna in serie al pulsante
24 
25  }
26}
27 
28void loop(){
29  for(int indice = 0; indice < INDICE_PIN; indice++)
30  {
31    int stato = digitalRead(pinPulsanti[indice]);  // legge il valore di input
32    if (stato == LOW)                              // controlla se il pulsante è premuto
33    {
34      blink1(pinLed[indice]);
35    }
36    else
37    {
38      digitalWrite(pinLed[indice], LOW);          // spegne il LED
39    }
40  }
41}
42 
43void blink1(int pin)
44{
45  digitalWrite(pin, HIGH);       // accende il LED
46  delay(50);                     // attende 50 millisecondi
47  digitalWrite(pin, LOW);        // spegne il LED
48  delay(50);                     // attende 50 millisecondi
49}

la parte inclusa tra parentesi graffe non è altro che il corpo del blink, ma cosa vuol dire:

1void blink1(int pin)

Stiamo dicendo che blink1 è una funzione che accetta come input una variabile intera a cui viene assegnato di nome pin, in questo modo, quando all’interno del loop viene invocata:

1...
2blink1(pinLed[indice]);
3...

verrà passata a blink1 l’intero corrispondente al valore dell’array con indice “indice”.

Supponendo che “indice” corrisponda al valore 0, allora:

pinLed[0] che coincide con il valore intero 10

e quindi a blink1 viene passato il valore 10:

blink1(10);

cioè:

1...
2void blink1(10)
3{
4  digitalWrite(10, HIGH);       // accende il LED 10
5  delay(50);                    // attende 50 millisecondi
6  digitalWrite(10, LOW);        // spegne il LED 10
7  delay(50);                    // attende 50 millisecondi
8}

si accenderà e si spegnerà il led connesso al pin digitale 10.

Facciamo un ulteriore passo ed aggiungiamo più funzioni richiamate all’interno del loop.
Realizziamo uno sketch che:

  • alla pressione del pulsante 1 il led 1 si accenda per 50 millisecondi e si spenga per 50 millisecondi;
  • alla pressione del pulsante 2 il led 2 si accenda per 100 millisecondi e si spenga per 100 millisecondi;
  • alla pressione del pulsante 3 il led 3 si accenda per 150 millisecondi e si spenga per 150 millisecondi;
  • alla pressione del pulsante 4 il led 4 si accenda per 200 millisecondi e si spenga per 200 millisecondi.

Si utilizzeranno una serie di if per capire quale pulsante è stato premuto.

1/*
2Autore: Michele Maffucci
3data: 12.01.13
4Uso di più funzioni esterne.
5Usare l'istruzione if per discrimina il pulsante premuto.
6*/
7 
8const int INDICE_PIN = 4; // definisce una costante per il numero di pin
9 
10int pinPulsanti[INDICE_PIN] = {2,3,4,5};    // create un array of pin per gli input
11                                            // costituiti dai pulsanti
12 
13int pinLed[INDICE_PIN] = {10,11,12,13};     // crea un array di pin di output per il LED
14 
15void setup()
16{
17  for(int indice = 0; indice < INDICE_PIN; indice++)
18  {
19    pinMode(pinLed[indice], OUTPUT);            // dichiara il LED come output
20    pinMode(pinPulsanti[indice], INPUT);        // dichiara il pulsante come input
21    digitalWrite(pinPulsanti[indice],HIGH);     // abilita la resistenza di pull-up
22     
23    // l'abilitazione della resistenza di pull-up mi permette di non utilizzare
24    // una resistenza esterna in serie al pulsante
25  }
26}
27 
28void loop(){
29  for(int indice = 0; indice < INDICE_PIN; indice++)
30  {
31    int val = digitalRead(pinPulsanti[indice]);  // legge il valore di input
32    if (val == LOW)                              // controlla se il pulsante è premuto
33    {
34      if (indice == 0)
35      {
36        blink1(pinLed[indice]);
37      }
38      if (indice == 1)
39      {
40        blink2(pinLed[indice]);
41      }
42      if (indice == 2)
43      {
44        blink3(pinLed[indice]);
45      }
46      if (indice == 3)
47      {
48        blink4(pinLed[indice]);
49      }
50    }
51    else
52    {
53      digitalWrite(pinLed[indice], LOW);          // spegne il LED
54    }
55  }
56}
57 
58void blink1(int pin)
59{
60  digitalWrite(pin, HIGH);       // accende il LED
61  delay(50);                     // attende 50 millisecondi
62  digitalWrite(pin, LOW);        // spegne il LED
63  delay(50);                     // attende 50 millisecondi
64}
65 
66void blink2(int pin)
67{
68  digitalWrite(pin, HIGH);       // accende il LED
69  delay(100);                    // attende 100 millisecondi
70  digitalWrite(pin, LOW);        // spegne il LED
71  delay(100);                    // attende 100 millisecondi
72}
73 
74void blink3(int pin)
75{
76  digitalWrite(pin, HIGH);       // accende il LED
77  delay(150);                    // attende 150 millisecondi
78  digitalWrite(pin, LOW);        // spegne il LED
79  delay(150);                    // attende 150 millisecondi
80}
81 
82void blink4(int pin)
83{
84  digitalWrite(pin, HIGH);       // accende il LED
85  delay(200);                    // attende 200 millisecondi
86  digitalWrite(pin, LOW);        // spegne il LED
87  delay(200);                    // attende 200 millisecondi
88}

Questo il risultato:

La parte fondamentale dello sketch è:

1...
2  for(int indice = 0; indice &lt; INDICE_PIN; indice++)
3  {
4    int val = digitalRead(pinPulsanti[indice]);  // legge il valore di input
5    if (val == LOW)                              // controlla se il pulsante è premuto
6    {
7      if (indice == 0)
8      {
9        blink1(pinLed[indice]);
10      }
11      if (indice == 1)
12      {
13        blink2(pinLed[indice]);
14      }
15      if (indice == 2)
16      {
17        blink3(pinLed[indice]);
18      }
19      if (indice == 3)
20      {
21        blink4(pinLed[indice]);
22      }
23    }
24...

come precedentemente descritto il for scansiona lo stato dei pulsanti, ad ogni ciclo del for viene memorizzato in val lo stato del pulsante: LOW oppure HIGH. Se lo stato è LOW vuol dire che uno dei pulsanti è stato premuto, a questo punto bisognerà controllare quale dei pulsanti è stato premuto e ciò verrà fatto con la serie dei quattro if che seguono.

Per evitare di utilizzare una serie di if, possiamo usare l’istruzione switch che in maniera più sintetica ed elegante svolge la stessa funzione della serie di if inseriti nel precedente sketch:

1/*
2Autore: Michele Maffucci
3data: 12.01.13
4Uso di più funzioni esterne
5Usare l'istruzione case per sapere quale pulsante è stato premuto.
6*/
7 
8const int INDICE_PIN = 4; // definisce una costante per il numero di pin
9 
10int pinPulsanti[INDICE_PIN] = {2,3,4,5};    // create un array of pin per gli input
11                                            // costituiti dai pulsanti
12 
13int pinLed[INDICE_PIN] = {10,11,12,13};               // crea un array di pin di output per il LED
14 
15void setup()
16{
17  for(int indice = 0; indice < INDICE_PIN; indice++)
18  {
19    pinMode(pinLed[indice], OUTPUT);            // dichiara il LED come output
20    pinMode(pinPulsanti[indice], INPUT);        // dichiara il pulsante come input
21    digitalWrite(pinPulsanti[indice],HIGH);     // abilita la resistenza di pull-up
22     
23    // l'abilitazione della resistenza di pull-up mi permette di non utilizzare
24    // una resistenza esterna in serie al pulsante
25  }
26}
27 
28void loop(){
29  for(int indice = 0; indice &lt; INDICE_PIN; indice++)
30  {
31    int val = digitalRead(pinPulsanti[indice]);  // legge il valore di input
32    if (val == LOW)                              // controlla se il pulsante è premuto
33    {
34      switch(indice)
35      {
36        case 0:
37          blink1(pinLed[indice]);
38          break;
39        case 1:
40          blink2(pinLed[indice]);   
41          break;
42        case 2:
43          blink3(pinLed[indice]); 
44          break;
45        case 3:
46          blink4(pinLed[indice]);
47          break;
48        default:
49          break;
50      }
51    }
52    else
53    {
54      digitalWrite(pinLed[indice], LOW); // spegne il LED
55    }
56  }
57}
58 
59void blink1(int pin)
60{
61  digitalWrite(pin, HIGH);       // accende il LED
62  delay(50);                     // attende 50 millisecondi
63  digitalWrite(pin, LOW);        // spegne il LED
64  delay(50);                     // attende 50 millisecondi
65}
66 
67void blink2(int pin)
68{
69  digitalWrite(pin, HIGH);       // accende il LED
70  delay(100);                    // attende 100 millisecondi
71  digitalWrite(pin, LOW);        // spegne il LED
72  delay(100);                    // attende 100 millisecondi
73}
74 
75void blink3(int pin)
76{
77  digitalWrite(pin, HIGH);       // accende il LED
78  delay(150);                    // attende 150 millisecondi
79  digitalWrite(pin, LOW);        // spegne il LED
80  delay(150);                    // attende 150 millisecondi
81}
82 
83void blink4(int pin)
84{
85  digitalWrite(pin, HIGH);       // accende il LED
86  delay(200);                    // attende 200 millisecondi
87  digitalWrite(pin, LOW);        // spegne il LED
88  delay(200);                    // attende 200 millisecondi
89}

In tutti gli esempi sopra esposti abbiamo passato alle funzioni esterne solo un parametro, vediamo con questo ultimo sketch come passare due parametri, uno che indica quale LED far lampeggiare ed un secondo che passa un intero corrispondente al tempo iniziale di accensione e spegnimento del LED. Si vuole realizzare la funzionalità tale per cui se si mantiene premuto il pulsante la frequenza di accensione e spegnimento aumenta.

1/*
2  Autore: Michele Maffucci
3  data: 12.01.13
4  Uso delle funzioni esterne con due parametri
5*/
6 
7const int INDICE_PIN = 4; // definisce una costante per il numero di pin
8 
9int pinPulsanti[INDICE_PIN] = {2, 3, 4, 5}; // create un array of pin per gli input
10// costituiti dai pulsanti
11 
12int pinLed[INDICE_PIN] = {10, 11, 12, 13};  // crea un array di pin di output per il LED
13 
14void setup()
15{
16  for (int indice = 0; indice < INDICE_PIN; indice++)
17  {
18    pinMode(pinLed[indice], OUTPUT);            // dichiara il LED come output
19    pinMode(pinPulsanti[indice], INPUT);        // dichiara il pulsante come input
20    digitalWrite(pinPulsanti[indice], HIGH);    // abilita la resistenza di pull-up
21 
22    // l'abilitazione della resistenza di pull-up mi permette di non utilizzare
23    // una resistenza esterna in serie al pulsante
24  }
25}
26 
27void loop() {
28  for (int indice = 0; indice < INDICE_PIN; indice++)
29 
30  { int stato = digitalRead(pinPulsanti[indice]); // legge il valore di input
31    if (stato == LOW) // controlla se il pulsante è premuto
32    {
33      blink1(pinLed[indice], 100);
34    }
35    else
36    { digitalWrite(pinLed[indice], LOW); // spegne il LED
37    }
38  }
39}
40void blink1(int pin, int tempo) {
41  for (int contatore = tempo; contatore > 10 && contatore <= tempo; contatore = contatore - 10)
42  {
43    digitalWrite(pin, HIGH);       // accende il LED
44    delay(contatore);              // attende 100 millisecondi
45    digitalWrite(pin, LOW);        // spegne il LED
46    delay(contatore);              // attende 100 millisecondi
47  }
48}

Questo il risultato:

All’interno del loop() viene chiamata la funzione:

1blink1(pinLed[indice], 100);

Supponiamo che il pulsante premuto sia il primo, si avrà quindi:

indice = 0

stato = digitalRead(pinPulsanti[indice]);
stato = digitalRead(pinPulsanti[0]);
stato = digitalRead(5);
stato = LOW;

a questo punto

1...
2    if (stato == LOW)
3...

risulta vero e viene chiamata la funzione blink1:

1...
2        blink1(pinLed[indice], 100);
3...

andando a sostituire i valori:

blink1(pinLed[0], 100);
blink1(13, 100);

il ciclo for permetterà di aumentare la frequenza con cui lampeggia il LED:

dire:
contatore=tempo

vuol dire:
contatore=100

contatore>10 && contatore <= tempo si traduce in: contatore>10 && contatore <= 100 dove ‘&&’ è AND logico ovvero la funzione logica è vera se entrambe le condizioni: contatore>10
e
contatore <= 100

sono vere.

Con contatore=contatore-10 assegnamo ad ogni ciclo il valore che aveva al ciclo precedente decrementato di 10 unità.

16 pensieri su “Arduino – lezione 07: lavorare con gruppi di valori e funzioni esterne

  1. Gaetano

    Buongiorno Michele,
    sono un appassionato di elettronica, navigando mi sono imbattuto, direi fortunatamente, sul tuo blog; ho dato una rapida occhiata e lo trovo ben fatto, anche per queste sessioni di lezioni, anche se dovevo iniziare dalla prima e non da questa! 😀

    Con l’ultimo esempio, se ho capito e compreso bene dal codice, in poche parole, quando premo un qualsiasi pulsante il led corrispondente, inizialmente si accende e si spegne per il tempo iniziale impostato da noi e per i successivi “lampeggi” diminuiti ogni volta di 20ms fino all’azzeramento del contatore?

    Rispondi
  2. Giovanni

    Passavo di qui per caso ;).
    Complimenti per la chiarezza espositiva e la modalitá passo passò di spiegazione. (Vedi la funzione stato spiegata passo passo).

    Grazie per i consigli preziosi.

    Rispondi
  3. Fabius62

    Innanzitutto buongiorno e complimenti per le lezioni svolte.
    Una domanda.
    Ho notato che ora ai led mette una resistenza in serie, mentre nei primi esempi il led era collegato direttamente sui pin, ovvero ai 5 volt, facendomi venire il dubbio sul perchè il led non si danneggiava.

    Grazie e complimenti ancora

    Rispondi
    1. admin Autore articolo

      Ciao.

      Grazie a te per avermi scritto.
      Nel circuito serie, resistenza – LED non è importante chi venga prima collegato al pin di Arduino, l’importante però che vi sia la resistenza in serie al diodo LED, fai attenzione che la resistenza limita la corrente circolante nel LED sia che essa sia messa prima o dopo il LED.

      Saluti.

      Rispondi
        1. admin Autore articolo

          Scusami non avevo inteso.
          La tua precisazione è giusta, ciò è possibile farlo solo Arduino 2009.
          Se disponi di una versione diversa, più recente, devi inserire una resistenza in serie al LED per limitare la corrente che circola in esso.

          Saluti.

          Rispondi
  4. Francesco

    Salve,
    sto seguendo con grandissimo interesse ed attenzione le sue lezioni . Una sola cosa non riesco a capire bene, ovvero il discorso sull’attivazione delle resistenze di pull-up interne di arduino. Mi spiego meglio, non capisco se si tratta di resistenze reali che possiede arduino, oppure se si tratta di resistenze virtuali. Grazie mille e complimenti per il sito.

    Rispondi
  5. Daniele

    Ciao a tutti ragazzi, sono alle primissime armi con questo fantastico “giocattolino” .. Io dovevo tramite un pc industriale controllare arduino e attaccargli 2 batterie da 12 volt con 3 led rispettivamente verde, giallo e rosso che, nel caso scendano sotto i 10,8 volt, devono staccarsi automaticamente e accendersi il led rosso e quello giallo mentre quello verde appena si attaccano le batterie.
    Si può fare? E se sì, che cosa devo utilizzare e come fare?
    Grazie mille in anticipo!

    Rispondi

Lascia un commento

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

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.