Il linguaggio di programmazione usato in Arduino è una versione semplificata del linguaggio C con in più delle funzioni per gestire in maniera semplice le interfacce di input/output della scheda. I programmi vengono scritti al PC utilizzando il software Arduino - un IDE o ambiente di sviluppo integrato - e trasmessi via USB alla scheda Arduino, dove vengono eseguiti.
Il codice sorgente di un programma per Arduino si chiama sketch.
Ogni sketch contiene sempre due funzioni:
La funzione setup()
viene eseguita una volta sola dopo aver acceso la scheda o caricato un nuovo programma, poi il controllo passa alla funzione loop()
che viene eseguita ciclicamente (cioè ripetuta all'infinito).
Tutti i linguaggi di programmazione prevedono delle regole di sintassi che devono essere seguite rigorosamente perché il programma funzioni. Le regole principali per il linguaggio Arduino sono:
//
permette di aggiungere un commento in una riga del codice; quello che scriviamo dopo questo simbolo viene ignorato dal programma ma può essere utile per spiegarne il funzionamento /*
e */
viene ignorato; in questo modo possiamo scrivere commenti che si estendono su più righe{
e }
delimitano l'inizio e la fine di un blocco di codice (inserite con la combinazione di tasti AltGr-Maiusc-è
e AltGr-Maiusc-+
);
Nei programmi abbiamo bisogno di memorizzare dei dati; per far questo usiamo:
Le variabili hanno un nome, un tipo e un valore e devono essere dichiarate, cioè elencate, prima di poter essere utilizzate. Una dichiarazione come questa:
int valoreSensore = 0;
dice che useremo una variabile chiamata valoreSensore
per memorizzare numeri interi a che il suo valore iniziale è 0
(il valore inziale è opzionale).
Nel corso del programma possiamo assegnare un nuovo valore alle variabili con l'operatore di assgnazione (simbolo =
):
valoreSensore = 100;
Ogni volta che compare il nome della variabile, verrà utilizzato il valore precedentemente assegnato.
Possiamo scegliere un nome a piacere per le variabili ma non può essere uguale a una delle parole chiave del linguaggio Arduino (quelle elencate nella pagina della guida di riferimento). Inoltre è bene:
ledRosso
è meglio di x
)valoreSensore
)
NB: il linguaggio è case-sensitive, cioè le lettere maiuscole sono diverse dalle minuscole (ad esempio le variabili led
e Led
sono diverse e IF
non è interpretata come l'istruzione if
).
A seconda del valore che vogliamo memorizzare useremo variabili di tipo:
int
, per i numeri interifloat
, per i numeri con la virgolachar
, per i caratteriboolean
, per le variabili con un valore logico (vero/falso) o che possono avere solo due valoriQuelli appena elencati sono solo i tipi di dati più comuni; la Reference contiene l'elenco completo con una descrizione e degli esempi di utilizzo.
Per scegliere il tipo di dati per una variabile è bene tenere conto che:
'A'
)Le costanti più importanti usate le linguaggio Arduino sono:
false
, cioè falso che corrisponde a zerotrue
, cioè vero che corrisponde a 1 (e più in generale a qualunque numero diverso da zero)HIGH
, cioè il valore alto di tensione che vale 5 Volt se il pin è usato come output e corrisponde a un valore maggiore di 3 Volt se è usato come inputLOW
cioè il valore basso di tensione che vale 0 Volt se il pin è usato come output e corrisponde a un valore minore di 2 Volt se è usato come inputINPUT
e OUTPUT
usati per impostare i pinQueste costanti sono evidenziate col colore blu nell'editor.
Le istruzioni di un programma possono contenere delle espressioni composte da variabili, costanti ed operatori.
Gli operatori matematici sono:
=
, per assegnare un valore+
, -
, *
e /
, per somma, sottrazione, prodotto e divisione%
, per il modulo, cioè il resto di una divisione (ad es. 7 % 5 vale 2)Gli operatori di confronto danno come risultato vero o falso e sono:
==
, uguale a!=
, diverso da<
e >
, “minore di” e “maggiore di”<=
e >=
, “minore o uguale a” e “maggiore o uguale a”Gli operatori logici si usano con operandi logici, danno come risultato vero o falso e sono:
&&
è l'operatore “and” e dà come risultato vero se entrambi gli operandi valgono vero||
è l'operatore “or” e dà come risultato vero se almeno un operando è vero!
è l'operatore “not” e scambia vero e falsoCome in matematica possiamo usare le parentesi per indicare l'ordine delle operazioni. Per chiarire facciamo qualche esempio:
(3 > 2) && (5 < 2)
vale falso perché il secondo operando è falso(3 > 2) || (5 < 2)
vale vero perché il primo operando è vero!((3 + 2) == 5)
vale falso
NB: fare attenzione a non confondere l'assegnazione (=
) con l'uguaglianza (==
)!
Ogni linguaggio di programmazione prevede che le istruzioni possano essere eseguite, oltre che in sequenza, secondo due strutture di controllo fondamentali:
Nel linguaggio Arduino ci sono due modi per realizzare una struttura condizionale:
if
e else
switch
Nel primo caso la sintassi è la seguente:
if (condizione 1) { blocco di codice da eseguire se la condizione 1 è vera } else if (condizione 2) { blocco di codice da eseguire se la condizione 2 è vera } else { blocco di codice da eseguire se le condizioni precedenti sono false }
La condizione che compare tra parentesi è un'espressione che ha come risultato vero o falso (ad esempio punteggio > 5
); se la condizione è vera viene eseguito il blocco di codice delimitato dalle parentesi graffe altrimenti si passa all'istruzione successiva. Il blocco con else if
è opzionale e permette di verificare una seconda condizione alternativa alla prima. Il blocco else
è anch'esso opzionale e contiene le istruzioni da eseguire nel caso in cui tutte le condizioni precedenti siano risultate false. Molto spesso nella selezione compaiono solo il primo e l'ultimo blocco.
Con l'istruzione switch
funziona in maniera leggermente diversa e usa la sintassi seguente:
switch (variabile) { case valore1: istruzioni da eseguire se variabile è uguale a valore1 break; case valore2: istruzioni da eseguire se variabile è uguale a valore2 break; ... default: istruzioni da eseguire se variabile non corrisponde a nessuno dei valori elencati }
In questo caso viene eseguito un determinato blocco di codice se il valore della variabile indicata con l'istruzione switch
è uguale al valore indicato con l'istruzione case
. L'ultimo caso (default
) è opzionale. E' bene notare che i blocchi di codice non sono delimitati da parentesi graffe ma cominciano dopo il simbolo :
e terminano con l'istruzione break;
(che va omessa quando con default
). Questo tipo di struttura permette di esprimere in maniera semplice una selezione con molte opzioni possibili.
Nel linguaggio Arduino ci sono due modi per realizzare una struttura iterativa:
for
, per ripetere un gruppo di istruzioni un certo numero di voltewhile
, per ripetere un gruppo di istruzioni finché una condizione è vera
L'istruzione for
usa una variabile detta contatore che cambia valore ogni volta che viene ripetuto il gruppo di istruzioni e viene usata per stabilire se continuare il ciclo o meno. Nell'istruzione for
troviamo tre elementi separati da un punto e virgola:
La sintassi è la seguente:
for(int contatore = valore; test; incremento del contatore) { blocco di codice da ripetere }
Il contatore viene usato solo all'interno del ciclo for e di solito ha un nome molto semplice (ad esempio “x” o “i”). L'esempio seguente esegue un gruppo di istruzioni 10 volte:
for(int x = 0; x < 10; x++) { blocco di codice da ripetere }
In questo caso il blocco di istruzioni viene ripetuto finché x è minore di 10 - cioè 10 volte - e la variabile x
viene incrementata usando l'operatore ++
che corrisponde all'espressione:
x = x + 1
cioè assegna ad x
il suo valore aumentato di uno.
In questo tipo di ciclo il blocco di istruzioni viene ripetuto fino a che la condizione definita nell'istruzione while
non diventa falsa. La sintassi è la seguente:
while(test) { blocco di codice da ripetere }
NB Per non ripetere il ciclo all'infinito è necessario che nel blocco di codice venga modificato qualcosa che possa rendere falso il test. L'esempio seguente è equivalente al ciclo for visto sopra:
while(x < 10) { blocco di codice da ripetere x = x + 1; }
Il blocco di codice viene ripetuto 10 volte; ogni volta la variabile x aumenta di uno fino a rendere falsa la condizione indicata tra parentesi.
Una funzione è un blocco di codice a cui abbiamo dato un nome che può essere utilizzato in varie parti del programma. Una volta definita una funzione possiamo utilizzarla semplicemente indicandone il nome, cioè chiamando la funzione.
L'ambiente di programmazione Arduino comprende una serie di funzioni utili già definite e pronte da utilizzare; l'elenco completo si trova nella pagina guida di riferimento del sito di Arduino. Possiamo aggiungere altre funzioni definendole nel nostro programma; per farlo dobbiamo assegnare un nome e un tipo alla funzione e scrivere il blocco di codice da eseguire quando la funzione viene chiamata.
Alcune funzioni quando vengono eseguite restituiscono un risultato (ad esempio la funzione sqrt()
che calcola la radice quadrata di un numero), altre invece non restituiscono alcun risultato (ad esempio le funzioni setup()
e loop()
). Il tipo di una funzione è il tipo di dati del valore che viene che viene restituito e può essere:
void
per le funzioni che non restituiscono risultato
Quando una funzione viene chiamata potrebbe essere necessario passare dei parametri alla funzione. I parametri servono a fornire i dati necessari all'esecuzione della funzione; ad esempio per calcolare la radice quadrata del numero 4 è necessario passare il parametro “4” alla funzione in questo modo: sqrt(4)
. I parametri possono essere valori o variabili e vanno indicati tra le parentesi (NB le parentesi vanno sempre indicate, anche quando non ci sono parametri da passare).
In questa sezione descriviamo rapidamente la sintassi di alcune funzioni del linguaggio Arduino. Una panoramica più completa di tutte le funzioni e della loro sintassi è disponibile - sempre in inglese - nella guida di riferimento.
pinMode(numero pin,modo)
, imposta il pin digitale indicato dal numero come INPUT
o OUTPUT
, digitalWrite(numero pin, valore)
, imposta l'uscita del pin digitale come HIGH
o LOW
, cioè alto (5 Volt) o basso (0 Volt)digitalRead(numero pin)
, legge il valore in ingresso del pin digitale indicato, che può essere HIGH
o LOW
analogRead(numero pin)
, legge il valore in ingresso del pin analogico indicato; il risultato è compreso tra 0 e 1023 (0 e 5 Volt)analogWrite(numero pin, valore)
, usa il pin digitale indicato dal numero come uscita analogica PWM; il valore deve essere compreso tra 0 e 255 (0 e 5 Volt)millis()
, calcola il tempo passato da quando è iniziata l'esecuzione del programma in millisecondidelay(valore)
, lascia passare un tempo in millisecondi pari al valore indicato prima di continuare l'esecuzione del programmaSono disponibili molte altre funzioni utili, tra cui:
random(minimo, massimo)
per generare numeri casuali compresi in un intervalloSerial
, per stabilire una comunicazione seriale con un PC attraverso la porta USBRicordare:
;
alla fine di ogni istruzione=
(assegnazione) e ==
(confronto)Inoltre, per rendere più leggibile e comprensibile il codice:
_
al posto degli spazi nel nome di variabili e funzioniQuesti ultimi suggerimenti riguardano lo stile usato per scrivere il programma e, pur non essendo indispensabili, rendono più leggibile e quindi più comprensibile il programma. Per lo stesso motivo non è una buona idea scrivere uno sketch come questo:
int led=13;void setup(){pinMode(led,OUTPUT);}void loop(){digitalWrite(led,HIGH);delay(1000);digitalWrite(led,LOW);delay(1000);}
Il programma - senza commenti, senza spazi e senza “a capo” - è corretto e viene compilato senza errori ma è difficile da leggere e da capire.
Torna all'indice.