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 6

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:

/*Autore: Michele Maffucci
data: 10.01.13
Utilizzo degli array - ver.1
*/

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

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

void setup()
{
  for(int indice = 0; indice < 4; indice++)
  {
    pinMode(pinLed[indice], OUTPUT);            // dichiara il LED come output
    pinMode(pinPulsanti[indice], INPUT);        // dichiara il pulsante come input
    digitalWrite(pinPulsanti[indice],HIGH);     // abilita la resistenza di pull-up

    // l'abilitazione della resistenza di pull-up mi permette di non utilizzare
    // una resistenza esterna in serie al pulsante
  }
}

void loop(){
  for(int indice = 0; indice < 4; indice++)
  {
    int stato = digitalRead(pinPulsanti[indice]);  // legge il valore di input
    if (stato == LOW)                              // controlla se il pulsante è premuto
    {
      digitalWrite(pinLed[indice], HIGH);        // accende il LED il pulsante è premuto
    }
    else
    {
      digitalWrite(pinLed[indice], LOW);          // spegne il LED
    }
  }
}

Questo il risultato:

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

int pinPulsanti[] = {2,3,4,5};    // crea un array di pin per gli input
                                  // 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:

int 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:

...
  for(int indice = 0; indice < 4; indice++)
  {
    pinMode(pinLed[indice], OUTPUT);            // dichiara il LED come output
    pinMode(pinPulsanti[indice], INPUT);        // dichiara il pulsante come input
    digitalWrite(pinPulsanti[indice],HIGH);     // abilita la resistenza di pull-up

    // l'abilitazione della resistenza di pull-up mi permette di non utilizzare
    // una resistenza esterna in serie al pulsante

  }
...

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:

...
void loop(){
  for(int indice = 0; indice < 4; indice++)
  {
    int stato = digitalRead(pinPulsanti[indice]);  // legge il valore di input
    if (stato == LOW)                              // controlla se il pulsante è premuto
    {
      digitalWrite(pinLed[indice], HIGH);        // accende il LED il pulsante è premuto
    }
    else
    {
      digitalWrite(pinLed[indice], LOW);          // spegne il LED
    }
  }
}

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:

/*
Autore: Michele Maffucci
data: 10.01.13
Utilizzo degli array - ver.2
Uso del comando const per definire delle costanti
*/

const int INDICE_PIN = 4; // definisce una costante per il numero di pin

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

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

void setup()
{
  for(int indice = 0; indice < INDICE_PIN; indice++)
  {
    pinMode(pinLed[indice], OUTPUT);            // dichiara il LED come output
    pinMode(pinPulsanti[indice], INPUT);        // dichiara il pulsante come input
    digitalWrite(pinPulsanti[indice],HIGH);     // abilita la resistenza di pull-up

    // l'abilitazione della resistenza di pull-up mi permette di non utilizzare
    // una resistenza esterna in serie al pulsante
  }
}

void loop(){
  for(int indice = 0; indice < INDICE_PIN; indice++)
  {
    int stato = digitalRead(pinPulsanti[indice]);  // legge il valore di input
    if (stato == LOW)                              // controlla se il pulsante è premuto
    {
      digitalWrite(pinLed[indice], HIGH);        // accende il LED il pulsante è premuto
    }
    else
    {
      digitalWrite(pinLed[indice], LOW);         // spegne il LED
    }
  }
}

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

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

definisce un array di interi di dimensione 4

...

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

definisce un array di interi di dimensione 4

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

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:

/*
Autore: Michele Maffucci
data: 10.01.13
Alla pressione del pulsante far lampeggiare con periodo 100 millisecondi il LED corrispondente.
*/

const int INDICE_PIN = 4; // definisce una costante per il numero di pin

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

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

void setup()
{
  for(int indice = 0; indice < INDICE_PIN; indice++)
  {
    pinMode(pinLed[indice], OUTPUT);            // dichiara il LED come output
    pinMode(pinPulsanti[indice], INPUT);        // dichiara il pulsante come input
    digitalWrite(pinPulsanti[indice],HIGH);     // abilita la resistenza di pull-up

    // l'abilitazione della resistenza di pull-up mi permette di non utilizzare
    // una resistenza esterna in serie al pulsante
  }
}

void loop(){
  for(int indice = 0; indice < INDICE_PIN; indice++)
  {
    int stato = digitalRead(pinPulsanti[indice]);  // legge il valore di input
    if (stato == LOW)                              // controlla se il pulsante è premuto
    {
      digitalWrite(pinLed[indice], HIGH);        // accende il LED
      delay(100);                                // attende 100 millisecondi
      digitalWrite(pinLed[indice], LOW);         // spegne il LED
      delay(100);                                // attende 100 millisecondi
  }
    else
    {
      digitalWrite(pinLed[indice], LOW);          // spegne il LED
    }
  }
}

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 utilizzaimo 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.

/*
Autore: Michele Maffucci
data: 10.01.13
Uso delle funzioni esterne
*/

const int INDICE_PIN = 4; // definisce una costante per il numero di pin

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

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

void setup()
{
  for(int indice = 0; indice < INDICE_PIN; indice++)
  {
    pinMode(pinLed[indice], OUTPUT);            // dichiara il LED come output
    pinMode(pinPulsanti[indice], INPUT);        // dichiara il pulsante come input
    digitalWrite(pinPulsanti[indice],HIGH);     // abilita la resistenza di pull-up

    // l'abilitazione della resistenza di pull-up mi permette di non utilizzare
    // una resistenza esterna in serie al pulsante

  }
}

void loop(){
  for(int indice = 0; indice < INDICE_PIN; indice++)
  {
    int stato = digitalRead(pinPulsanti[indice]);  // legge il valore di input
    if (stato == LOW)                              // controlla se il pulsante è premuto
    {
      blink1(pinLed[indice]);
    }
    else
    {
      digitalWrite(pinLed[indice], LOW);          // spegne il LED
    }
  }
}

void blink1(int pin)
{
  digitalWrite(pin, HIGH);       // accende il LED
  delay(50);                     // attende 50 millisecondi
  digitalWrite(pin, LOW);        // spegne il LED
  delay(50);                     // attende 50 millisecondi
}

Questo il risultato:

Analizziamo il codice:

...
void blink1(int pin)
{
  digitalWrite(pin, HIGH);       // accende il LED
  delay(50);                     // attende 50 millisecondi
  digitalWrite(pin, LOW);        // spegne il LED
  delay(50);                     // attende 50 millisecondi
}

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

void 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:

...
blink1(pinLed[indice]);
...

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è:

...
void blink1(10)
{
  digitalWrite(10, HIGH);       // accende il LED 10
  delay(50);                    // attende 50 millisecondi
  digitalWrite(10, LOW);        // spegne il LED 10
  delay(50);                    // attende 50 millisecondi
}

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.

/*
Autore: Michele Maffucci
data: 12.01.13
Uso di più funzioni esterne.
Usare l'istruzione if per discrimina il pulsante premuto.
*/

const int INDICE_PIN = 4; // definisce una costante per il numero di pin

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

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

void setup()
{
  for(int indice = 0; indice < INDICE_PIN; indice++)
  {
    pinMode(pinLed[indice], OUTPUT);            // dichiara il LED come output
    pinMode(pinPulsanti[indice], INPUT);        // dichiara il pulsante come input
    digitalWrite(pinPulsanti[indice],HIGH);     // abilita la resistenza di pull-up
    
    // l'abilitazione della resistenza di pull-up mi permette di non utilizzare
    // una resistenza esterna in serie al pulsante
  }
}

void loop(){
  for(int indice = 0; indice < INDICE_PIN; indice++)
  {
    int val = digitalRead(pinPulsanti[indice]);  // legge il valore di input
    if (val == LOW)                              // controlla se il pulsante è premuto
    {
      if (indice == 0)
      {
        blink1(pinLed[indice]);
      }
      if (indice == 1)
      {
        blink2(pinLed[indice]);
      }
      if (indice == 2)
      {
        blink3(pinLed[indice]);
      }
      if (indice == 3)
      {
        blink4(pinLed[indice]);
      }
    }
    else
    {
      digitalWrite(pinLed[indice], LOW);          // spegne il LED
    }
  }
}

void blink1(int pin)
{
  digitalWrite(pin, HIGH);       // accende il LED
  delay(50);                     // attende 50 millisecondi
  digitalWrite(pin, LOW);        // spegne il LED
  delay(50);                     // attende 50 millisecondi
}

void blink2(int pin)
{
  digitalWrite(pin, HIGH);       // accende il LED
  delay(100);                    // attende 100 millisecondi
  digitalWrite(pin, LOW);        // spegne il LED
  delay(100);                    // attende 100 millisecondi
}

void blink3(int pin)
{
  digitalWrite(pin, HIGH);       // accende il LED
  delay(150);                    // attende 150 millisecondi
  digitalWrite(pin, LOW);        // spegne il LED
  delay(150);                    // attende 150 millisecondi
}

void blink4(int pin)
{
  digitalWrite(pin, HIGH);       // accende il LED
  delay(200);                    // attende 200 millisecondi
  digitalWrite(pin, LOW);        // spegne il LED
  delay(200);                    // attende 200 millisecondi
}

Questo il risultato:

La parte fondamentale dello sketch è:

...
  for(int indice = 0; indice < INDICE_PIN; indice++)
  {
    int val = digitalRead(pinPulsanti[indice]);  // legge il valore di input
    if (val == LOW)                              // controlla se il pulsante è premuto
    {
      if (indice == 0)
      {
        blink1(pinLed[indice]);
      }
      if (indice == 1)
      {
        blink2(pinLed[indice]);
      }
      if (indice == 2)
      {
        blink3(pinLed[indice]);
      }
      if (indice == 3)
      {
        blink4(pinLed[indice]);
      }
    }
...

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:

/*
Autore: Michele Maffucci
data: 12.01.13
Uso di più funzioni esterne
Usare l'istruzione case per sapere quale pulsante è stato premuto.
*/

const int INDICE_PIN = 4; // definisce una costante per il numero di pin

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

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

void setup()
{
  for(int indice = 0; indice < INDICE_PIN; indice++)
  {
    pinMode(pinLed[indice], OUTPUT);            // dichiara il LED come output
    pinMode(pinPulsanti[indice], INPUT);        // dichiara il pulsante come input
    digitalWrite(pinPulsanti[indice],HIGH);     // abilita la resistenza di pull-up
    
    // l'abilitazione della resistenza di pull-up mi permette di non utilizzare
    // una resistenza esterna in serie al pulsante
  }
}

void loop(){
  for(int indice = 0; indice < INDICE_PIN; indice++)
  {
    int val = digitalRead(pinPulsanti[indice]);  // legge il valore di input
    if (val == LOW)                              // controlla se il pulsante è premuto
    {
      switch(indice)
      {
        case 0:
          blink1(pinLed[indice]);
          break;
        case 1:
          blink2(pinLed[indice]);    
          break;
        case 2:
          blink3(pinLed[indice]);  
          break;
        case 3:
          blink4(pinLed[indice]);
          break;
        default:
          break;
      }
    }
    else
    {
      digitalWrite(pinLed[indice], LOW); // spegne il LED
    }
  }
}

void blink1(int pin)
{
  digitalWrite(pin, HIGH);       // accende il LED
  delay(50);                     // attende 50 millisecondi
  digitalWrite(pin, LOW);        // spegne il LED
  delay(50);                     // attende 50 millisecondi
}

void blink2(int pin)
{
  digitalWrite(pin, HIGH);       // accende il LED
  delay(100);                    // attende 100 millisecondi
  digitalWrite(pin, LOW);        // spegne il LED
  delay(100);                    // attende 100 millisecondi
}

void blink3(int pin)
{
  digitalWrite(pin, HIGH);       // accende il LED
  delay(150);                    // attende 150 millisecondi
  digitalWrite(pin, LOW);        // spegne il LED
  delay(150);                    // attende 150 millisecondi
}

void blink4(int pin)
{
  digitalWrite(pin, HIGH);       // accende il LED
  delay(200);                    // attende 200 millisecondi
  digitalWrite(pin, LOW);        // spegne il LED
  delay(200);                    // attende 200 millisecondi
}

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.

/*
Autore: Michele Maffucci
data: 12.01.13
Uso delle funzioni esterne con due parametri
*/

const int INDICE_PIN = 4; // definisce una costante per il numero di pin

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

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

void setup()
{
  for(int indice = 0; indice < INDICE_PIN; indice++)
  {
    pinMode(pinLed[indice], OUTPUT);            // dichiara il LED come output
    pinMode(pinPulsanti[indice], INPUT);        // dichiara il pulsante come input
    digitalWrite(pinPulsanti[indice],HIGH);     // abilita la resistenza di pull-up
    
    // l'abilitazione della resistenza di pull-up mi permette di non utilizzare
    // una resistenza esterna in serie al pulsante
  }
}

void loop(){
  for(int indice = 0; indice < INDICE_PIN; indice++)
  {
    int stato = digitalRead(pinPulsanti[indice]);  // legge il valore di input
    if (stato == LOW)                              // controlla se il pulsante è premuto
    {
        blink1(pinLed[indice], 100);
    }
    else
    {
      digitalWrite(pinLed[indice], LOW);          // spegne il LED
    }
  }
}

void blink1(int pin, int tempo)
{
  for (int contatore=tempo; contatore>10 && contatore <= tempo; contatore=contatore-10)
  {
    digitalWrite(pin, HIGH);       // accende il LED
    delay(contatore);              // attende 100 millisecondi
    digitalWrite(pin, LOW);        // spegne il LED
    delay(contatore);              // attende 100 millisecondi
  }
}

Questo il risultato:

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

        blink1(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

...
    if (stato == LOW) 
...

risulta vero e viene chiamata la funzione blink1:

...
        blink1(pinLed[indice], 100);
...

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à.

Articoli simili:

Questa voce è stata pubblicata in arduino e contrassegnata con , , , , . Contrassegna il permalink.

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

  1. Gaetano scrive:

    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?

  2. Giovanni scrive:

    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.

  3. Fabius62 scrive:

    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

    • admin scrive:

      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.

  4. Gianni scrive:

    complimenti! bel lavoro e preciso.
    Apprezzo l’idea di imparare subito a strutturare con chiamate di funzioni esterne.

  5. nico scrive:

    Bravissimo ,ben commentato , ho imparato cose nuove molto utili , grazie
    …….

  6. Francesco scrive:

    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.

  7. Daniele scrive:

    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!

  8. Tony scrive:

    erano due ore che giravo su google per cercare di capire le funzioni… grazie davvero!

Lascia un commento

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