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.
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:
intpinPulsanti[] = {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
intpinLed[] = {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
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è:
intstato = 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:
constintINDICE_PIN = 4; // definisce una costante per il numero di pin
9
10
intpinPulsanti[INDICE_PIN] = {2,3,4,5}; // create un array of pin per gli input
11
// costituiti dai pulsanti
12
13
intpinLed[INDICE_PIN] = {10,11,12,13}; // crea un array di pin di output per il LED
14
15
voidsetup()
16
{
17
for(intindice = 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
28
voidloop(){
29
for(intindice = 0; indice < INDICE_PIN; indice++)
30
{
31
intstato = 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
intpinPulsanti[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.
Alla pressione del pulsante far lampeggiare con periodo 100 millisecondi il LED corrispondente.
5
*/
6
7
constintINDICE_PIN = 4; // definisce una costante per il numero di pin
8
9
intpinPulsanti[INDICE_PIN] = {2,3,4,5}; // create un array of pin per gli input
10
// costituiti dai pulsanti
11
12
intpinLed[INDICE_PIN] = {10,11,12,13}; // crea un array di pin di output per il LED
13
14
voidsetup()
15
{
16
for(intindice = 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
voidloop(){
28
for(intindice = 0; indice < INDICE_PIN; indice++)
29
{
30
intstato = 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.
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:
intval = 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:
intval = digitalRead(pinPulsanti[indice]); // legge il valore di input
32
if(val == LOW) // controlla se il pulsante è premuto
33
{
34
switch(indice)
35
{
36
case0:
37
blink1(pinLed[indice]);
38
break;
39
case1:
40
blink2(pinLed[indice]);
41
break;
42
case2:
43
blink3(pinLed[indice]);
44
break;
45
case3:
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
59
voidblink1(intpin)
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
67
voidblink2(intpin)
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
75
voidblink3(intpin)
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
83
voidblink4(intpin)
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.
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”
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?
Passavo di qui per caso ;).
Complimenti per la chiarezza espositiva e la modalitá passo passò di spiegazione. (Vedi la funzione stato spiegata passo passo).
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 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.
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.
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.
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!
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?
Ciao Gaetano.
Si diminuisce fino all’azzermaneto del contatore, però non ogni 20ms ma ogni 10ms.
Saluti.
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.
Grazie Giovanni,
sei gentilissimo
Saluti.
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
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.
Grazie per la risposta
Intendevo però dire che nella lezione 2:
https://www.maffucci.it/2010/11/17/arduino-lezione-02-facciamo-lampeggiare-un-led/
il led viene messo direttamente sulla scheda arduino senza alcuna resistenza nè prima nè dopo, almeno da quello che vedo nella seconda foto.
Grazie ancora
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.
complimenti! bel lavoro e preciso.
Apprezzo l’idea di imparare subito a strutturare con chiamate di funzioni esterne.
Bravissimo ,ben commentato , ho imparato cose nuove molto utili , grazie
…….
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.
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!
erano due ore che giravo su google per cercare di capire le funzioni… grazie davvero!
complimenti molto chiaro , adesso ho capito come funziona Arduino.
Grazie
complimenti per la spiegazione molto chiara. Adesso ho capito come funziona Arduino.