Sei sulla pagina 1di 19

Primi passi con la programmazione in linguaggio C con la scheda Arduino

Traduzione del libro: Arduino programming notebook di Brian W. Evans con modifiche e aggiunte di G. Carpignano e C. Busso

Prefazione
Questo libro serve da riferimento di programmazione che sia comodo, facile da usare per la struttura
di comando e la sintassi di base del microcontrollore Arduino. Per farla semplice, sono state
apportate alcune esclusioni che fanno di questo libro un riferimento adatto a un principiante. Questa
decisione ha portato ad una leggera enfasi sull'utilizzo di Arduino per scopi standalone e, ad
esempio, esclude gli utilizzi pi complessi di matrici o forme avanzate di comunicazione seriale.
Cominciando con la struttura di base del linguaggio di programmazione C Arduino deriva, questo
libro continua a descrivere la sintassi degli elementi pi comuni del linguaggio C e illustra il loro
utilizzo, con esempi e frammenti di codice. Questo include molte funzioni della libreria di base seguita
da un'appendice con schemi di esempio e di programmi di avviamento.
Per una introduzione alla scheda Arduino e design interattivo, fare riferimento a Banzi - Getting
Started with Arduino. Per i coraggiosi e pochi interessati alla complessit di programmazione in C
consultare il libro: Kernighan e Ritchie, The C Programming Language - seconda edizione, oppure
Prinz e Crawford - C in a Nutshell, forniscono una completa comprensione della sintassi di
programmazione.
Questo libro non sarebbe stato possibile senza la grande comunit web con la disponibilit del
materiale che si trova sul sito Arduino allindirizzo http://www.arduino.cc.
Struttura
La struttura di base del linguaggio di programmazione per Arduino abbastanza semplice e viene
eseguito utilizzando almeno due parti. Queste due parti necessarie, o funzioni, racchiudono blocchi di
istruzioni (istruzione= statement)
void setup()
// funzione di configurazione dei Input/Output
{
statements;
}
void loop() // programma principale (main) --> ciclo infinito (loop)
{
statements;
}

Dove setup() la funzione per linizializzazione, mentre loop() la funzione principale per
l'esecuzione. Entrambe le funzioni sono richieste per il programma di lavoro.
La funzione di installazione dovrebbe seguire la dichiarazione delle variabili proprio all'inizio del
programma. La funzione setup() viene eseguita solo una volta, ed usata per impostare le modalit
di funzionamento dei pin come input/output (pinMode) o per inizializzare la comunicazione seriale.
La funzione loop() che segue include il codice che deve essere eseguito in un ciclo infinito (loop), ad
esempio con la lettura degli ingressi, la successiva elaborazione degli stessi e la modifica delle
uscite, ecc. Questa funzione il cuore di tutti i programmi di Arduino e risulta quella che esegue il
software implementato per eseguire un determinato lavoro.
setup()
La funzione setup () viene chiamata una volta quando il programma si avvia. Si usa per inizializzare
le modalit pin, o iniziare la comunicazione seriale. Essa deve essere inclusa nel programma, anche
se non ci sono istruzioni da eseguire.
void setup()
// funzione di configurazione dei Input/Output
{
pinMode(pin, OUTPUT); // setta il 'pin' come uscita (output)
}

loop()
Dopo aver chiamato la funzione setup(), la funzione loop() fa esattamente quello che suggerisce il
suo nome, ovvero esegue un ciclo infinito (loop), permettendo al programma di modificare,
rispondere e controllare la scheda Arduino.
void loop() // programma principale (main) --> ciclo infinito (loop)
{
digitalWrite(pin, HIGH);// forza il pin a livello ALTO = HIGH = ON = 1
delay(1000); // effettua una pausa di 1000 millisecondi = 1 secondo
digitalWrite(pin, LOW);// forza il pin a livello BASSO = LOW = OFF = 0
delay(1000); // effettua una pausa di 1000 millisecondi = 1 secondo
}

{ } parentesi graffe (si scrivono con Alt+123 { e Alt+125 } sul tastierino numerico della tastiera)
Le parentesi graffe (noto anche semplicemente come "parentesi" o "parentesi graffe") definiscono
l'inizio e la fine dei blocchi di funzione e di blocchi delle istruzioni come il void loop() ed anche per le
istruzioni for, if, while, etc.
type function()
{
statements;
}

Una parentesi graffa aperta { deve sempre essere seguita da una parentesi graffa di chiusura }: in
altre parole il numero delle parentesi graffe deve essere sempre pari e il numero delle
parentesi aperte uguale al numero delle parentesi graffe chiuse. Eventuali anomalie nelle
parentesi graffe possono spesso portare a errori difficili da eliminare e rintracciare in un programma
di grandi dimensioni.
L'ambiente di compilazione di Arduino include una comoda funzione per controllare il bilanciamento
di parentesi graffe. Basta selezionare una parentesi, o anche scegliere il punto di inserimento
immediatamente dopo una parentesi graffa, e la sua compagna logica sar evidenziata.
; punto e virgola
Un punto e virgola deve essere utilizzato per terminare una istruzione e separare gli elementi o
istruzioni del programma. Un punto e virgola usato anche per separare le istruzioni sul contatore
allinterno di unstruzione for.
int x = 13; // dichiarazione della variabile x come numero intero 13

Nota: Dimenticare di terminare una riga con un punto e virgola si tradurr in un errore di
compilazione. Lerrore pu essere evidente se si riferisce ad un punto e virgola mancante, altrimenti
non risulta facile determinarlo. Se un errore di compilazione incomprensibile o apparentemente
illogico, una delle prime cose da controllare se manca un punto e virgola al termine dellistruzione
precedente alla linea in cui il compilatore fornisce lerrore.
/* */ commento su pi righe
I commenti a blocco o commenti su pi righe sono aree di testo che vengono ignorate dal
programma e sono usate per le descrizioni di grandi dimensioni di codice o di commenti che aiutano
a far capire ad altre persone tutte le parti del programma. Essi iniziano con /* e finiscono con */.
/* Questo e un commento a blocchi
Effettuato su piu linee
*/

Poich i commenti vengono ignorati dal programma e non occupano spazio di memoria dovrebbero
essere usati con generosit e devono essere usati per "commentare" i blocchi di codice utili in fase di
debug ovvero durante la ricerca degli errori.
// linea di commento
Il commento sulla riga singola inizia con // e termina quando si va a capo. Tutti i commenti vengono
ignorati dal programma e non occupano spazio di memoria.
// questa una singola linea di commento
int x = 13; // dichiarazione della variabile x come numero intero 13

I singoli commenti vengono spesso utilizzati dopo una dichiarazione valida per fornire maggiori
informazioni su ci che compie la dichiarazione o per fornire un promemoria futuro.
Variabili (definizione, dichiarazione)
Le variabili sono sequenze di caratteri alfanumerici (lettere, numeri e caratteri di punteggiatura) che
identificano uno o pi bytes nella memoria del PC. Il numero di byte pu variare a seconda delluso
che se ne vuole fare, cio si hanno differenti tipi di variabili: intere, con la virgola, caratteri (nella
memoria del PC sono comunque numeri binari). Nel programma bisogna dichiarare di che tipo la
variabile usata prima di utilizzarla (perch occorre dire al compilatore quanto spazio occupa e dove
la variabile nella memoria) e attribuire ad essa un nome: una dichiarazione quindi una riga di
programma del tipo:
int calcolo; // indica che la variabile che si chiama calcolo un intero.

Nella dichiarazione si pu anche dare un valore iniziale (inizializzare) alla variabile


int calcolo=3; // indica che la variabile che si chiama calcolo un intero e a quel
// punto del programma vale 3.

A differenza di una costante il contenuto di una variabile si pu modificare durante il programma


quante volte si desidera.
Nota: alle variabili deve essere dato un nome descrittivo che identifica la stessa in maniera univoca
per rendere il codice pi leggibile. I nomi delle variabili, come tilt_sensor permettono al
programmatore o a chiunque altro effettui la lettura del codice a capire che cosa rappresenta la
variabile stessa. I nomi delle variabili, come var o di valore, d'altro canto, fanno ben poco per rendere
il codice leggibile e sono utilizzati solo come esempi. Una variabile pu essere chiamata in qualsiasi
modo purch non sia gi utilizzata come parola chiave nel linguaggio Arduino. Non possibile
utilizzare lo spazio per identificare il nome delle variabili. Ad esempio: sensore A produce un errore
del compilatore che dovr essere modificato con sensore_A.
Una variabile pu essere dichiarata in differenti posizioni allinterno del programma e in tal modo si
determina quali parti del programma possono utilizzare la variabile stessa (vedi pi avanti)
Operazione di assegnazione
Il simbolo = nella dichiarazione int calcolo=3; indica che il valore o lespressione che sta a
destra viene inserito nella variabile (nelle celle di memoria) che sta a sinistra; non vuol dire
assolutamente che quello che c a destra = a quello che c a sinistra, come in matematica. Se
in una dichiarazione come quella precedente la differenza di definizione non significativa, lo diventa
in unistruzione come i=i+1 espressione che in matematica errata, ma che in linguaggio C
significa che si somma alla variabile i il numero 1 e il risultato viene inserito nella cella dove prima
cera i.
Il simbolo = in C si chiama operazione di assegnazione.
Esiste unaltra situazione in cui si usa il simbolo =:
3

if (x==4)
// se la variabile x e uguale 4
y=y+10; // se la condizione precedente vera allora aggiunge 10 alla variabile y

In questo caso x==4 unoperazione di confronto: si controlla se il numero contenuto nelle celle
di memoria identificate dalla x uguale a 4, ma non si cambia il valore. Notare il doppio uguale.
byte ( usato solo dal compilatore Arduino e sostituisce il char nel compilatore tradizionale)
Il tipo byte permette di memorizzare un valore numerico a 8 bit (1 byte) senza decimali entro un
valore compreso tra 0 e 255.
byte sensore = 180; // dichiara sensore come un tipo byte a 1 byte = 8 bit

int
Il tipo int permette di memorizzare i numeri senza decimali in 2 byte consecutivi (16-bit) entro un
valore compreso tra -32768 e +32767.
int sensore = 25000; // dichiara sensore come un tipo int a 2 byte = 16 bit

Nota: Se il valore delle variabili di tipo Integer viene forzato oltre i loro valori massimi o valori
minimi, per esempio, se x = 32767 ed una successiva istruzione aggiunge +1, ovvero viene eseguita
listruzione x = x + 1; il valore successivo della variabile x pari -32768.
long
Il tipo long permette di memorizzare i numeri senza decimali in 4 byte consecutivi (32-bit) entro un
valore compreso tra -2147483648 e +2147483647.
long sensore = 8900000; // dichiara sensore come un tipo long a 4 byte = 32 bit

float
Il tipo float permette di memorizzare i numeri con decimali che possiedono la virgola mobile in 4
byte consecutivi (32-bit) entro un valore compreso tra -3,4028235+38 e +3,4028235+38.
float sensore = 89.2345; // dichiara sensore come un tipo float a 4 byte = 32 bit

Nota: i numeri in virgola mobile non sono esatti e possono dare risultati strani se confrontati. La
matematica in virgola mobile viene calcolata con un notevole dispendio di software e quindi risulta
molto pi lenta da elaborare rispetto ai numeri interi se utilizzata per i calcoli. Occorre evitare, se
possibile, o quanto meno ridurre notevolemente il loro utilizzo.
Arrays (vettori)
Un array un insieme di valori dello stesso tipo byte, int, float, etc. identificati da un nome e da un
numero tra parentesi quadre (es. mioarray [12]; il numero indica quanti valori contiene larray.
Larray pu essere dichiarato in due modi:
int
int

mioarray[12];
mioarray[]={valore0, valore1, valore2, valore3, valore10, valore11]};

Nel primo caso viene indicato solo di quanti elementi composto larray (operazione che occorre
sempre fare, perch le dichiarazioni servono proprio per dire al compilatore quale lo spazio
occupato dalle variabili), i valori verranno inseriti dopo nel programma. Se non si conosce il numero
esatto di elementi bisogna metterne uno opportuno.
Nel secondo caso i valori sono gi inseriti nella dichiarazione. Notare che il primo si chiama valore 0,
perch nei vettori la prima posizione 0: si dice che i vettori devono essere indicizzati a 0.
Allinterno del programma un istruzione del tipo:
mioarray[8]=25;
oppure

mioarray[8]=a;

significa che nella posizione 9 (ricordarsi che si parte da 0) inserisco il numero 25 o la variabile a.
Quindi il numero tra parentesi indica la posizione (ovvero lindice), che si sta considerando allinterno
dellarray , non il contenuto che, dopo listruzione, uguale a 25.
Gli arrays sono spesso usati in cicli for in questo caso lindice tra le parentesi quadre la variabile
contatore, che viene incrementata ad ogni ciclo in modo da prelevare uno dopo laltro i valori
contenuti nelle posizioni con indice crescente nellarray.
L'esempio seguente utilizza un array per accendere e spegnere un LED. Utilizzando un ciclo for, il
contatore inizia dal valore 0, scrive il valore contenuto nella posizione di indice 0 nellarray
denominato blink[], in questo caso 180, al pin 10 (PWM), segue una pausa di 200ms, quindi si
muove verso la posizione di indice successiva.
int ledPin = 10; // LED collegato sul pin 10
byte blink[] = {180, 30, 255, 200, 10, 90, 150, 60};
// memorizza in memoria un array di 8 valori ognuno di essi lungo 1 byte
void setup() // funzione di configurazione dei Input/Output
{
pinMode(ledPin, OUTPUT); // setta il pin come uscita (OUTPUT)
}
void loop() // programma principale (main) --> ciclo infinito (loop)
{
for(int i=0; i<7; i++) // ciclo di ripetizione per 8 differenti valori dellarray
{
analogWrite(ledPin, blink[i]); // setta luscita con il valore letto dallarray
delay(200); // pausa di 200ms
}
}

A volte occorre avere un contenitore (array) che ha allinterno valori tutti dello stesso tipo, ma
suddivisi in gruppi (es. valori che arrivano dalla prima, dalla seconda, dalla terza linea) in questo caso
si preferisce utilizzare un array bidimensionale o tridimensionale etc che si chiama matrice ed
identificata da un nome e pi parentesi quadre i cui indici indicano gli elementi di ciascun gruppo e il
numero di gruppi. Esempio: mioarray[12][3] matrice a 3 righe (gruppi) di 12 elementi per colonna
(elementi per gruppo).
operatori aritmetici
Gli operatori aritmetici inclusi nel compilatore sono addizione, sottrazione, moltiplicazione e divisione
che restituiscono la somma, differenza, prodotto e quoziente (rispettivamente) dei due operandi.
y
x
i
r

=
=
=
=

y
x
j
r

+
*
/

3;
7;
6;
5;

L'operazione condotta utilizzando il tipo dei dati degli operandi, cos, per esempio, 9 / 4 fornisce
come risultato 2 invece di 2,25 se i valori 9 e 4 sono del tipo int e vengono troncati i decimali.
Questo capita anche se l'operazione determina un overflow cio se il risultato pi grande del
valore massimo o pi piccolo del valore minimo che pu essere memorizzato in ogni differente
tipologia di dato.
Se gli operandi sono di tipo diverso (esempio tipo int e di tipo long), viene utilizzata per il calcolo
la tipologia di dato pi grande (nel precedente esempio il tipo long). Per esempio, se uno dei
numeri (operandi) sono di tipo float e l'altra di tipo int (integer), verr utilizzato per il calcolo il tipo
floating point.
Quindi occorre scegliere il tipo delle variabili in modo tale da contenere il risultato pi grande dei
calcoli per non troncare i decimali. Per calcoli che richiedeno le frazioni, oppure i decimali, meglio
utilizzare le variabili di tipo float, ma occorre essere consapevoli dei loro svantaggi: hanno grandi
dimensioni e estrema lentezza nel calcolo.
Nota: l'operatore cast modifica il tipo di variabile allinterno del calcolo ad esempio mionumero
float; se nel programma scrivo x=(int)mionumero converto il float in int e poi lo inserisco in x,
5

senza dover riassegnare la variabile stessa. Altro esempio: i=(int)3.6 sar impostato con la
variabile i uguale a 3.
assegnazione abbreviata (compound assignments)
possibile combinare unoperazione aritmetica con l'assegnazione di una variabile. Questo si trova
comunemente nei cicli for come descritto pi avanti. Le assegnazioni nelle forme pi comuni sono:
x++ //
x-- //
x += y
x -= y
x *= y
x /= y

e
e
//
//
//
//

uguale a scrivere x = x + 1,
uguale a scrivere x = x - 1,
e uguale a scrivere x = x +
e uguale a scrivere x = x e uguale a scrivere x = x *
e uguale a scrivere x = x /

ovvero incremento unitario della variabile x


ovvero decremento unitario della variabile x
y
y
y
y

Nota: per esempio, x *= 3 corrisponde al triplo del valore precedente di x ed in seguito occorre
riassegnare il valore risultante alla variabile x.
operatori di confronto
I confronti tra due variabili o costanti sono spesso utilizzati nelle istruzioni if else per verificare se
una condizione specificata vera. Le operazioni di confronto utilizzate sono:
x
x
x
x
x
x

== y
!= y
< y
> y
<= y
>= y

//
//
//
//
//
//

x
x
x
x
x
x

e uguale a y
non e uguale a y (diverso)
e minore di y
e maggiore di y
e minore o uguale a y
e maggiore o uguale a y

operatori logici
Gli operatori logici sono in genere un modo per confrontare due espressioni e restituiscono un valore
VERO o FALSO a seconda dell'operatore. Ci sono tre operatori logici AND, OR, e NOT, che
sono spesso utilizzati nelle istruzioni if else.
if (x > 0 && x < 5) // logica AND (&&) aggiungi la condizione e VERA solo se entrambe le
//espressioni sono VERE
if (x > 0 || y > 0) // logica OR (||)aggiungi la condizione e VERA quando una o
// entrambe le espressioni sono VERE
if (!x > 0)
// logica NOT (!) aggiungi la condizione e VERA quando lespressione e
//FALSA e viceversa

constanti
Il linguaggio C per la scheda Arduino ha pochi valori predefiniti, che sono stati chiamati costanti.
Sono utilizzati per rendere i programmi pi facili da leggere. Le costanti sono classificati in gruppi.
true / false (vero / falso)
Queste sono le costanti booleane che definiscono i livelli della logica. FALSO (FALSE) definito
come 0 (zero oppure livello logico BASSO = LOW), mentre VERO (TRUE) spesso definito come
1 (uno oppure livello logico ALTO = HIGH).
Volendo utilizzare la logica booleana si ottiene che tutti i numeri diversi da zero corrispondono a
VERO (TRUE) mentre solo il numero 0 corrisponde a FALSO (FALSE).
int b = -1; // assegna alla variabile b il valore -1
if (b == TRUE) // se e VERO (e lo e) esegui la prossima istruzione
{
b = b * 2; // istruzione di moltiplicazione x 2
}

high / low (alto / basso)


Queste costanti definiscono i livelli dei pin come un livello alto o basso e vengono utilizzati durante la
lettura e/o la scrittura dei pin digitali. Il livello ALTO (HIGH) viene definito come livello logico 1, ON
oppure +5V mentre il livello BASSO (LOW) livello logico 0, OFF oppure 0V (GND = GROUND).
digitalWrite(13, HIGH); // scrivi sul pin 13 un livello ALTO (HIGH)

input / output (ingressi / uscite)


Le costanti utilizzate con la funzione pinMode() definiscono la modalit di un pin digitale sia come
ingresso (INPUT) o uscita (OUTPUT).
pinMode(13, OUTPUT); // definisci il pin 13 come una uscita (OUTPUT)

funzioni
Una funzione una porzione di codice che ha un nome e contiene un blocco di istruzioni che
vengono eseguite quando la funzione viene richiamata.
Si possono costruire funzioni personalizzate per eseguire compiti ripetitivi e ridurre la confusione in
un programma. Nellesecuzione della funzione ci sono delle variabili che arrivano da qualche altra
parte del programma e devono entrare nel blocco (sono i parametri dellesempio sotto) e ci pu
essere un valore che esce dal blocco per essere utilizzato altrove (il tipo di variabile che esce
nellesempio). Le funzioni vengono dichiarate prima del loro utilizzo nel seguente modo:
tipo nome_funzione(parametri); //tipo =tipo di variabile in uscita es. int nome_funzione
//es,inverno, parametri es, int,float variabili in ingresso

se dalla funzione non viene riportato nessuna variabile il tipo void (contenitore vuoto) e se non
entra nessuna variabile, le parentesi sono vuote.
void loop();

La funzione deve poi essere chiamata allinterno del programma quando necessario svolgere il
compito ripetitivo e infine, al di fuori del programma principale, deve essere definita, cio bisogna
spiegare al compilatore che compito effettivamente svolge quel blocco di programma (la funzione).
Es. La seguente funzione denominata delayVal() viene utilizzata per impostare un valore di ritardo
in un programma leggendo il corrispondente valore di un potenziometro. Si dichiara prima un
variabile v locale (vedi sotto), imposta la v con il valore del potenziometro che dar un numero
compreso tra 01023, occorre dividere quindi tale valore per 4 per ottenere un valore finale
compreso tra 0255, e infine, la funzione restituisce tale valore al programma principale.

int delayVal(); //dichiaro la funzione dal nome delayVal che non riceve alcun parametro
// in ingresso e fa uscire una variabile intera
void loop() //programma principale (main) --> ciclo infinito (loop)
{

s1=delayVal(); //chiamata della funzione

s2=delayVal(); //chiamata della funzione

} //fine programma principale


int delayVal(); //definizione della funzione
{
int v; // creazione della variabile temporanea denominata v
v = analogRead(pot); // lettura della tensione relativa al cursore del potenziometro
v /= 4; // conversione dal valore 01023 (10 bit) al valore 0255 (8 bit)
return v; // restituzione al programma principale del valore finale acquisito
}

s1 e s2 sono le variabili in cui viene inserito il valore che stato restituito dalla funzione (dove si
chiamava v) al programma principale. Se non viene restituito alcun valore, o c un parametro in
ingresso la struttura leggermente diversa.
Arduino possiede una certa quantit di funzioni gia costruite che basta solamente chiamare in un
certo punto del programma.
digitalWrite(13, HIGH);
delay(ms);

Utilizzo delle variabili


Una variabile pu essere dichiarata all'inizio del programma prima della funzione void setup(),
all'interno delle funzioni, e, talvolta, all'interno di un blocco di istruzioni come nei cicli for.
Se la variabile dichiarata all'inizio del programma prima della funzione void setup() detta
globale perch pu essere letta e scritta da ogni funzione e da qualsiasi istruzione nel programma.
Se la variabile dichiarata allinterno del programma principale o in una funzione (come nelles.
precedente in v) detta locale ed visibile e pu essere utilizzata solo all'interno della funzione in
cui stata dichiarata. quindi possibile avere due o pi variabili con lo stesso nome in diverse parti
dello stesso programma che contengono valori diversi o di tipo diverso. Le variabili locali servono
perch pi programmatori possono scrivere funzioni da utilizzare in un programma senza
necessariamente concordare come si chiamano le variabili interne .
Il seguente esempio mostra come dichiarare alcuni tipi differenti di variabili e dimostra la visibilit di
ogni variabile:
int sensore; // la variabile sensore e visibile in ogni funzione
void setup() // funzione di configurazione dei Input/Output
{
// non e richiesta nessuna configurazione dei input/output
}
void loop() // programma principale (main) --> ciclo infinito (loop)
{
float frequenza; // la variabile frequenza e visibile solo nella funzione loop()
for (int i=0; i<20;) // la variabile i e visibile solo allinterno del for
{
i++; // incremento unitario della varaiabile i = i + 1;
}
}

if (se)
Listruzione if controlla se una certa condizione si verificata, ad esempio se una variabile
analogica ha superato un certo valore ed esegue le istruzioni all'interno delle parentesi graffe se
l'affermazione VERA. Se la condizione FALSA, il programma salta alla prima istruzione dopo la
chiusura della parentesi graffa.
int a = 10, b = 20; // assegna alla variabile a il valore 10 e alla b il valore 20
..
.. //in queste istruzioni il valore di a pu cambiare
if (a == 10) // se e VERA la condizione che la variabile a vale 10
// esegui la prossima istruzione
{
a = a + b; // dopo listruzione la variabile a vale 30
}
b = 10; // dopo listruzione la variabile b vale 10

L'esempio precedente confronta la variabile a con un numero, (ma potrebbe essere anche una
variabile). Se il confronto, o la condizione in parentesi tonda VERA, le istruzioni all'interno delle
parentesi graffe vengono eseguite. In caso contrario, il programma salta e continua dopo la chiusura
della parentesi graffa.
8

Nota: Attenzione a non scrivere la seguente istruzione if (a = 10), perch assegna alla variabile x il
valore 10 (cio pone x = 10) che di conseguenza sempre vero. Occorre utilizzare il doppio simbolo
==, come nellistruzione if (a == 10), che effettua il confronto se la variabile a coincide con il
valore 10.
if else (se altrimenti)
Listruzione if else permette di effettuare una scelta in base alla condizione dellespressione
contenuta nelle parentesi tonde. Ad esempio:
int a = 10, b = 20; // assegna alla variabile a il valore 10 e alla b il valore 20
if (inputPin == HIGH) // se la condizione e VERA, cioe se linput e ALTO (HIGH),
{
// effettua listruzione a = a / 2;
a = a / 2; // questa istruzione viene eseguita se la condizione e VERA
}
else
// altrimenti effettua listruzione b = b * 2;
{
// se la condizione e FALSA
b = b * 2; // questa istruzione viene eseguita se la condizione e FALSA
}

anche possibile avere un numero illimitato di questi rami in cascata uno dentro l'altro.
for (ciclo)
L'istruzione serve per ripetere un blocco di istruzioni racchiuso tra le parentesi graffe per un numero
specificato di volte. Una variabile utilizzata come contatore viene incrementata normalmente di una
unit e confrontata per determinare la fine del ciclo. Nellespressione for ci sono tre parti, separate
da punto e virgola ;.
for(int i=0; i<7; i++) // ciclo di ripetizione per 8 differenti valori dellarray
{
analogWrite(ledPin, blink[i]); // setta luscita con il valore letto dallarray
delay(200); // pausa di 200ms
}

Ad ogni iterazione del ciclo, viene testata la condizione i<7. Se la condizione rimane vera, le
istruzioni che seguono vengono eseguite e la condizione viene verificata nuovamente. Quando la
condizione diventa falsa, il ciclo termina.
L'esempio successivo inizializza la variabile i come numero intero a partire dal valore 0, verifica se
ancora inferiore a 20 e se vero, incrementa di 1 ed esegue le istruzioni racchiuse tra le parentesi:
for (int x=0; x<20; x++) // dichiarazione della variabile x con partenza
// dal valore 0 fino a raggiungere il valore intero 19 con un incremento
// unitario (+1), quindi in totale vengono eseguiti 20 interazioni ovvero
// il blocco delle istruzioni tra le parentesi graffe verra eseguito per 20 volte
{
digitalWrite(13, HIGH); // forza un livello ALTO (HIGH) sul pin 13
delay(250);
// pausa di 1/4 secondi = 250 msec
digitalWrite(13, LOW);
// forza un livello BASSO (LOW) sul pin 13
delay(250);
// pausa di 1/4 secondi = 250 msec
}

Nota: Nel linguaggio C listruzione del ciclo for molto pi flessibile rispetto ad altri cicli che
trovano in alcuni linguaggi di altri computer, compreso il BASIC. Uno o tutti e tre gli elementi
intestazione possono essere omessi, anche se i punti e virgola sono necessari. Anche
dichiarazioni per l'inizializzazione, la condizione e l'espressione pu essere qualsiasi istruzione
valida con le variabili indipendenti.

si
di
le
C

while (finch)
Listruzione while un ciclo continuo (loop), fino a quando l'espressione contenuta tra le parentesi
tonde diventa FALSA. Se la variabile che viene tenuta sotto condizione non cambia allinterno del
ciclo, non si esce pi dal ciclo stesso. Quindi se il numero di iterazioni del ciclo , ad es. determinato
da una condizione esterna, come la tensione acquisita da un sensore, contenuta allinterno del ciclo,
se non si acquisisce il valore desiderato il ciclo si ripete allinfinito. Riassumendo si ricordi che finch
la condizione risulta VERA, cio finch lespressione contenuta tra le parentesi tonde VERA,
vengono eseguite tutte le istruzioni presenti tra lapertura della parentesi graffa e la chiusura della
parentesi graffa. Appena la condizione dellespressione diventa FALSA viene eseguita la prima
istruzione che segue la chiusura della parentesi graffa del ciclo while e si prosegue nel programma.
int x = 10;
while (x < 200)
{ // finche la condizione e VERA esegui le istruzioni tra le parentesi graffe
digitalWrite(13, HIGH);
// forza un livello ALTO (HIGH) sul pin 13
delay(250);
// pausa di 1/4 secondi = 250 msec
digitalWrite(13, LOW);
// forza un livello BASSO (LOW) sul pin 13
delay(250);
// pausa di 1/4 secondi = 250 msec
x++;
// incremento unitario della variabile x
}

Nellesempio seguente se la variabile y inferiore a 200, quindi la condizione VERA, esegue tutte
le istruzioni all'interno delle parentesi graffe e continua fino a quando la variabile y non pi
inferiore a 200.
int x = 10, y;
while (y < 200) // controlla se la variabile y e inferiore a 200
{
delay(250); // pausa di 1/4 secondi = 250 msec
y++;
// incremento unitario della variabile y
}

do while (finch)
Listruzione do while un ciclo (loop) di ripetizione che funziona nello stesso modo come il ciclo
while, con l'eccezione che la condizione viene verificata alla fine del ciclo, in modo che listruzione
do while verr sempre eseguita almeno una volta.
int y, x = 10; // assegna alla variabile y il valore 0 e alla x il valore 100
do
{
delay(250); // pausa di 1/4 secondi = 250 msec
} while (y != 0);
// controlla se la variabile y e diversa da 0, siccome la y vale 0,
// quindi la condizione e FALSA, si ottiene che listruzione delay(250); verra
// eseguita una sola volta per passare allistruzione successiva alla parentesi graffa
// chiusa che risulta x = x / 2;.
x = x / 2; //

L'esempio seguente assegna alla variabile x il livello acquisito sul sensore_a, si ferma per 50
millisecondi, poi a tempo indeterminato effettua il ciclo di ritardo fino a quando la 'x' non sar a livello
BASSO (LOW).
do
{
x = sensore_a;
// assegna alla variabile x la lettura del sensore_a
delay (50);
// pausa di 50 millisecondi
} while (x == HIGH); // effettua il ritardo di 50 msec finche la variabile x e VERA
// ovvero risulta a livello ALTO (HIGH)

Riassumendo listruzione for si utilizza quando si conosce gi il numero di cicli; il while e il


dowhile quando non si conosce a priori il numero di ripetizioni.
10

pinMode(pin, mode)
Viene utilizzato nella funzione void setup() per configurare il pin specificato come ingresso
(INPUT) oppure come uscita (OUTPUT).
pinMode(pin, OUTPUT); //

stabilisce che la variabile pin unuscita

La scheda Arduino configura di default i pin digitali come ingressi (INPUT), in modo che non devono
essere esplicitamente dichiarati come ingressi con listruzione pinMode(). I pins configurati come
ingressi si dice che sono in uno stato di alta impedenza.
Internamente al chip del microcontrollore Atmega ci sono dei resistori definiti di pull-up (forzano un
livello alto in assenza di segnale allingresso) da 20 K integrati che risulta possibile attivare con un
controllo del software nel seguente modo:
pinMode(13, INPUT);
// setta il pin 13 come ingresso (input)
digitalWrite(13, HIGH); // attiva sul pin 13 il resistore di pullup interno al micro

I resistori di pull-up sono normalmente utilizzati per collegare gli ingressi agli interruttori e pulsanti. Si
noti che nell'esempio sopra non si pu cambiare il pin di uscita, ma semplicemente un metodo per
attivare il resistore di pull-up interno.
I pins configurati come uscita (OUTPUT) possiedono uno stato a bassa impedenza che pu fornire
fino a 40 mA (milliampere) di corrente ad altri dispositivi e/o circuiti. Questa corrente sufficiente per
accendere un diodo LED (non dimenticare la resistenza in serie), ma purtroppo non fornisce
abbastanza corrente per controllare la maggior parte dei rel o dei motori.
Si consideri che un cortocircuito sui pin della scheda Arduino o la richiesta di una corrente eccessiva
pu danneggiare e distruggere il pin di uscita o danneggiare l'intera scheda Aruino. una buona idea
utilizzare, per collegare un pin di uscita ad un dispositivo esterno, una resistenza in serie di
limitazione della corrente del valore di 470 oppure di 1K.
digitalRead(pin)
Legge il valore digitale da un pin specificato con il risultato che potr essere un livello ALTO (HIGH)
oppure BASSO (LOW). Il pin pu essere specificato come una variabile o una costante il cui valore
numerico deve essere compreso tra 0 e 13.
pinMode(13, INPUT);
sensore_a = digitalRead(13);

// setta il pin 13 come ingresso (input)


// setta la variabile sensore_a con il livello
// del pin 13 che risulta un ingresso (INPUT)

digitalWrite(pin, value)
Permette di forzare le uscite digitali sia a livello logico ALTO (HIGH) oppure BASSO (LOW). Il pin
pu essere specificato come una variabile o una costante il cui valore numerico deve essere
compreso tra 0 e 13.
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);

// setta il pin 13 come uscita (output)


// setta alto (HIGH) il livello del pin 13

Il seguente esempio legge un pulsante collegato ad un ingresso digitale e accende un LED collegato
ad una uscita digitale quando il pulsante stato premuto.
int led = 13; // il LED e collegato al pin 13
int pulsante = 7; // il pulsante e collegato al pin 7
int leggi_pulsante = 0; // variable utilizzata per memorizzare lo stato del pulsante
void setup() // funzione di configurazione dei Input/Output
{

11

pinMode(led, OUTPUT);
// setta il pin 13 come output
pinMode(pulsante, INPUT); // setta il pin 7 come input

}
void loop() // programma principale (main) --> ciclo infinito (loop)
{
leggi_pulsante = digitalRead(pulsante); // memorizza lo stato del pulsante leggendo
// il relativo pin di input
digitalWrite(led, leggi_pulsante); // accendi o spegni il led in base al livello
// acquisito dallinput collegato al pulsante
}

analogRead(pin)
Legge il valore da un pin analogico specificato convertendo il valore della tensione analogica letta
con una risoluzione di 10 bit. Questa funzione attiva solo sui pin analogici definiti da 0 a 5. I valori
restituiti sono un numero intero compreso tra 0 e 1023 (210-1).
sensore_a = analogRead(0); // leggi il pin analogico 0 e memorizza nella variabile
// denominata sensore_a la corrispondente conversione
// della tensione di ingresso

Nota: i pin analogici a differenza di quelli digitali, non hanno bisogno di essere dichiarati come uscita
(OUTPUT) oppure come entrata (INPUT).
analogWrite(pin, value)
Listruzione scrive un valore pseudo-analogico utilizzando la tecnica a modulazione di larghezza di
impulso (Pulse With Modulation vedi es. sul PWM) ad un pin di uscita contrassegnato PWM. La pi
recente scheda di Arduino con il chip ATmega328P lavora sui pin 3, 5, 6, 9, 10 e 11, mentre con
schede di Arduino pi vecchie ad esempio con un ATmega8 supportano solo i pin 9, 10 e 11. Il
valore pu essere specificato in una variabile o costante con un valore compreso tra 0 e 255.
int led = 125; // utilizza la variabile led con valore di 125
// per variare la luminosita del led
analogWrite(11, led); // scrive il valore 125 sulluscita PWM
// corrispondente al pin 11

Un valore pari a 0 genera un output costante di 0V (GND) al pin specificato, un valore pari a 255
genera un output costante +5V sul pin specificato. Per valori compresi tra 1 e 254, il pin PWM oscilla
periodicamente tra 0V e 5V, considerando che pi alto il valore, pi il tempo il pin risulta a livello
alto. Ad esempio, un valore di 64 rimane a livello basso (LOW) per tre quarti del tempo e rimane a
livello alto (HIGH) per un quarto del tempo, mentre un valore di 128 fornisce un livello basso (0V) per
la met del tempo e a livello alto (+5V) per laltra met del tempo. Si consideri che questa una
funzione hardware perch il pin generer londa fino a quando non riceve una ulteriore chiamata alla
successiva analogWrite.
Nota: i pin analogici a differenza di quelli digitali, non hanno bisogno di essere dichiarati prima come
uscita oppure come entrata.
Nell'esempio seguente viene letto un valore analogico da un pin di ingresso analogico, converte il
valore dividendo per 4, e fornisce un segnale PWM su un pin con la caratteristica del PWM.
int led = 10; // collega un LED con un resistore da 220 ohm sul pin 10
int potenziometro = 0; // collega un potenziometro con il cursore centrale sul pin
// analogico 0 mentre un terminale dovra essere collegato a massa e laltro a +5V
int leggi_potenziometro; // variabile per memorizzare il valore della tensione letta
// sul pin 0 che risulta collegato al potenziometro
void setup() // funzione di configurazione dei Input/Output
{
}
void loop() // programma principale (main) --> ciclo infinito (loop)

12

leggi_potenziometro = analogRead(potenziometro); // leggi il valore della tensione


// letta sul pin 0 che risulta collegato al potenziometro
leggi_potenziometro /= 4; // converti il valore da 0-1023 a 0-255 (dividendo per 4)
analogWrite(led, leggi_potenziometro); // poni in uscita sul pin 10 analogico
// il corrispondente valore letto

delay(ms)
Mette in pausa un programma per la quantit di tempo specificato in millisecondi, dove 1000 pari a
1 secondo.
delay(1000); // aspetta per 1000 millisecondi = 1 secondo

millis()
Restituisce il numero di millisecondi da quando la scheda Arduino ha iniziato l'esecuzione del
programma corrente come un valore di tipo unsigned long.
valore_iniziale = millis(); // setta la variabile valore_iniziale uguale
// alla funzione millis()

Nota: il valore restituito dalla funzione raggiunge il valore massimo (overflow ovvero viene
reimpostato a zero) dopo circa 9 ore.
min(x, y)
Determina il minimo di due numeri di qualsiasi tipo di dati e restituisce il numero pi piccolo.
valore_minimo = min(20, 100); // la variabile valore_minimo contiene il numero
// piu piccolo tra i due specificati (uguale a 20).

max(x, y)
Determina il valore massimo di due numeri di qualsiasi tipo di dati e restituisce il numero pi grande.
valore_massimo = max(20, 100); // la variabile valore_massimo contiene il numero
// piu grande tra i due specificati (uguale a 100).

randomSeed(seed)
Imposta un valore come il punto di partenza per la funzione di generazione casuale dei numeri.
valore_iniziale = millis(); // setta la variabile valore_iniziale uguale
// alla funzione millis()
randomSeed(valore_iniziale); // setta il valore iniziale da cui partire
// a generare i numeri casuali

Siccome la scheda Arduino non in grado di creare un numero veramente casuale, la funzione
randomSeed permette di inserire una variabile (o una costante o ad un altra funzione) nella
funzione random, che aiuta a generare una serie veramente casuale di numeri. Ci sono una variet
di semi diversi, o funzioni, che possono essere utilizzati in questa funzione come le funzioni millis()
o anche la funzione analogRead() per leggere il rumore elettrico attraverso un pin analogico.
random(max)
random(min, max)
La funzione random permette di restituire dei numeri pseudo-casuali all'interno di una gamma
specificata da un valore minimo e uno massimo.
valore_random = random(100, 200); // nella variabile denominata valore_random ci sara

13

// un numero casuale compreso tra i due valori 100 e 200

Nota: utilizzare questa funzione dopo aver utilizzato la funzione randomSeed().


L'esempio seguente crea un valore casuale compreso tra 0255 e fornisce un segnale PWM su un
pin PWM pari al valore casuale.
int numero_casuale; // varibile per memorizzare il numero casuale (random)
int led = 10; // collega un LED con un resistore da 220 ohm sul pin 10
void setup() // funzione di configurazione dei Input/Output
{
}
void loop() // programma principale (main) --> ciclo infinito (loop)
{
randomSeed(millis()); // inizializza la funzione randomSeed con una
//funzione millis() che legge il tempo trascorso in millisecondi
numero_casuale = random(255); // genera un numero casuale compreso tra 0 e 255
analogWrite(led, numero_casuale); // poni in uscita PWM il valore casuale
delay(500); // pausa di 500 msec = 0,5 secondi
}

Serial.begin(rate)
Configura la porta seriale RS232 e imposta il baud rate (velocit di trasmissione dei simboli,pu
essere diversa dalla bit rate perch un simbolo pu essere composto da pi bit)) per la trasmissione
seriale dei dati. Il valore tipico di trasmissione e ricezione per comunicare con il computer di 9600
baud, anche se altre velocit sono supportate.
void setup() // funzione di configurazione dei Input/Output
{
Serial.begin(9600); // configura la porta seriale RS232 alla velocita di 9600 baud
}

Nota: Quando si utilizza la comunicazione seriale i pin digitali 0 (RX) e 1 (TX) non possono essere
utilizzati contemporaneamente.
Serial.println(data)
Stampa i dati sulla porta seriale RS232, seguita da un ritorno automatico a capo e avanzamento di
riga. Questo comando ha la stessa forma della funzione Serial.print(), ma pi facile per la
visualizzazione e lettura dei dati su standard Serial Monitor.
Serial.println(analogValue); // trasmetti il valore della variabile analogValue sulla
RS232

Nota: per ulteriori informazioni sulle varie possibili scelte della funzione Serial.println() e
Serial.print() occorre fare riferimento al sito web di Arduino.
Il semplice esempio che segue utilizza una lettura dal pin analogico 0 e invia i dati al computer ogni 1
secondo.
void setup() // funzione di configurazione dei Input/Output
{
Serial.begin(9600); // setta la seriale a 9600 bps
}
void loop() // programma principale (main) --> ciclo infinito (loop)
{
Serial.println(analogRead(0)); // trasmetti sulla RS232 il valore del pin analogico 0
delay(1000); // pausa di 1 secondo
}

14

digital output

Questo il programma di base 'ciao mondo' utilizzato per commutare semplicemente dallo stato
acceso a quello spento. In questo esempio, un LED collegato al pin13 e oscilla una volta al
secondo. La resistenza pu essere omessa su questo pin in quanto la scheda Arduino prevede una
limitazione della corrente massima fornita in uscita.
int led = 13; // LED collegato alluscita digitale del pin 13
void setup() // funzione di configurazione dei Input/Output
{
pinMode(led, OUTPUT); // setta il pin 13 come output per controllare un LED
}
void loop() // programma principale (main) --> ciclo infinito (loop)
{
digitalWrite(led, HIGH); // accende il LED (on)
delay(1000); // pausa di 1 secondo
digitalWrite(led, LOW); // spegne il LED (off)
delay(1000); // pausa di 1 secondo
}

digital input

Questa la forma pi semplice di ingresso con solo due possibili stati dellinterruttore o pulsante:
chiuso (on) o aperto (off). Questo esempio legge un semplice interruttore o pulsante collegato al pin
2. Quando l'interruttore chiuso sul pin di ingresso si avr un livello ALTO (HIGH) che accende il
LED collegato al pin 13 (vedi circuito del programma precedente).
int led = 13; // LED collegato alluscita digitale del pin 13 (output)
int interruttore = 2; // collegamento allinterruttore (switch) pin 2 (input)
void setup()
// funzione di configurazione dei Input/Output
{
pinMode(led, OUTPUT); // dichiara il LED come output
pinMode(interruttore, INPUT); // dichiara lo switch come input
}
void loop() // programma principale (main) --> ciclo infinito (loop)
{
if (digitalRead(interruttore) == HIGH) // controlla se linput e a livello HIGH
{
digitalWrite(led, HIGH); // accendi il LED
delay(1000); // pausa di 1 secondo
digitalWrite(led, LOW); // spegni il LED
delay(1000); // pausa di 1 secondo
}
}

15

high current output

A volte necessario avere una corrente superiore a 40mA, tipica delle uscite presenti sulla scheda
Arduino per controllare un dispositivo (ad es. un motore). In questo caso un transistor MOSFET pu
essere utilizzato per lavorare con carichi di corrente pi elevati. Lesempio seguente permette la
commutazione da on a off del MOSFET con una cadenza di 5 volte ogni secondo.
Nota: Lo schema elettrico visualizzato indica la presenza di un diodo di protezione in parallelo al
motore per evitare la distruzione del MOSFET dovuta alle sovratensioni di chiusura e apertura
quando si utilizzano dei carichi induttivi in presenza di elevate correnti.
int motore = 5; // output pin for the MOSFET
void setup()
// funzione di configurazione dei Input/Output
{
pinMode(motore, OUTPUT); // sets pin5 as output
}
void loop()
// programma principale (main) --> ciclo infinito (loop)
{
for (int i=0; i<=5; i++) // effettua un ciclo per 5 volte
{
digitalWrite(motore, HIGH); // attiva il MOSFET (saturazione)
delay(250); // pausa di 1/4 secondo
digitalWrite(motore, LOW); // disattiva il MOSFET (interdizione)
delay(250); // pausa di 1/4 secondo
}
delay(1000); // pausa di 1 secondo
}

pwm output

La tecnica Pulse width Modulation (PWM Modulazione a larghezza dimpulso) un modo per
simulare una tensione analogica in uscita utilizzando semplicemente un valore digitale ALTO e
BASSO in uscita. Al dispositivo viene inviata unonda rettangolare il cui duty cycle (D.T. = T1/T dove
16

T1 la durata della parte alta dellonda e T il periodo totale) legato al valore della tensione
analogica che si vorrebbe mandare. Il periodo molto importante e la sua durata dipende dal
problema che stiamo trattando, perch se il periodo troppo lungo, nel caso del led locchio si
accorge che il led si spegne quando luscita va bassa e, nel caso del motore, questo si ferma.
Occorre che il tempo di persistenza dellimmagine sulla retina (<20ms) o linerzia del motore siano
pi lunghi del periodo. Questa tecnica permette di ridurre o aumentare la luminosit di un LED
oppure di controllare la velocit di un motore. Il seguente esempio permette il lento incremento della
luminosit di un diodo LED fino al valore massimo e successivamente la progressiva diminuzione
della luminosit fino a spegnersi totalmente.
int led = 9;
// LED collegato alluscita digitale del pin 9 (output PWM)
void setup()
// funzione di configurazione dei Input/Output
{
}
void loop() // programma principale (main) --> ciclo infinito (loop)
{
for (int i=0; i<=255; i++) // incremento della luminosita con il contatore
{
analogWrite(led, i); // settaggio del livello di luminosta sul LED (pin
delay(100); // pausa di 100ms
}
for (int i=255; i>=0; i--) // decremento della luminosita con il contatore
{
analogWrite(led, i); // settaggio del livello di luminosta sul LED (pin
delay(100); // pausa di 100ms
}
}

i
9)
i
9)

potentiometer input

Utilizzando un potenziometro collegato ad un ingresso analogico della scheda Arduino possibile


convertire la tensione presente tra mass (GND) e linput del pin 0 per leggere il corrispondente valore
digitale della conversione (ADC) compreso tra 0 e 1024. L'esempio seguente utilizza un
potenziometro per il controllo della frequenza di un LED lampeggiante.
int potenziometro = 0; // pin 0 di ingresso per il cursore del potenziometro
int led = 13;
// LED collegato alluscita digitale del pin 13
void setup()
// funzione di configurazione dei Input/Output
{
pinMode(led, OUTPUT); // dichiara la variabile led come OUTPUT
}
void loop() // programma principale (main) --> ciclo infinito (loop)
{
digitalWrite(led, HIGH); // accendi il LED
delay(analogRead(potenziometro) / 4);
// pausa del programma dipendente dalla posizione del cursore del potenziometro (cioe
// dalla tensione applicata al pin 0 e convertita in digitale da 0 a 1024 che viene
// ridotta da 0 a 255 tramite la divisione per 4)
digitalWrite(led, LOW); // spegni il LED
delay(analogRead(potenziometro) / 4);
// pausa del programma dipendente dalla posizione del cursore del potenziometro (cioe

17

// dalla tensione applicata al pin 0 e convertita in digitale da 0 a 1024 che viene


// ridotta da 0 a 255 tramite la divisione per 4)

variable resistor input

Alcune tipologie di sensori ad esempio foto resistori, termistori, sensori di flessione, etc. possono
essere considerate come delle resistenze variabili. In questo esempio si utilizza una funzione per
leggere il valore analogico e impostare un tempo di ritardo. Questo controlla la velocit con cui un
LED si illumina e cambia di intensit in base al valore letto dal sensore.
int led = 9; // PWM pin for the LED
int sensore = 0; // resistore variabile (esempio fotoresistenza) sul pin 0 analogico
void setup() // funzione di configurazione dei Input/Output
{
}
void loop()
// programma principale (main) --> ciclo infinito (loop)
{
for (int i=0; i<=255; i++) // incremento della luminosita con il contatore i
{
analogWrite(led, i); // settaggio del livello di luminosta sul LED (pin 9)
delay(ritardo()); // pausa dipendente dalla funzione ritardo()
}
for (int i=255; i>=0; i--) // decremento della luminosita con il contatore i
{
analogWrite(led, i); // settaggio del livello di luminosta sul LED (pin 9)
delay(ritardo()); // pausa dipendente dalla funzione ritardo()
}
}
int ritardo()
{
int v; // variabile temporanea
v = analogRead(sensore); // lettura della tensione analogica del sensore
v /= 8;
// converte il valore 0-1024 nel valore 0-128
return v; // restituisce il valore finale
}

servo output

18

Il servo un motorino con una parte meccanica in movimento che permette di ruotare da 0 fino a
180. Per effettuare la rotazione serve un impulso di tensione che venga inviato al servo ogni 20 ms.
In questo esempio viene utilizzata la funzione servo_impulso per spostare il servo dal 10 -170 e
viceversa.
int servo_pin = 2; // servo collegato al pin 2 digitale
int angolo; // angolo del servo circa 0-180
int larghezza_impulso; // larghezza impulso (funzione variabile)
void setup() // funzione di configurazione dei Input/Output
{
pinMode(servo_pin, OUTPUT); // setta il pin 2 come output
}
void servo_impulso(int servo_pin, int angolo)
{
larghezza_impulso = (angolo * 10) + 600; // calcolo del tempo di ritardo
digitalWrite(servo_pin, HIGH); // setta loutput del servo ALTA (high)
delayMicroseconds(larghezza_impulso); // pausa espressa in microsecondi
digitalWrite(servo_pin, LOW); // resetta loutput del servo BASSO (low)
}
void loop() // programma principale (main) --> ciclo infinito (loop)
{
// valore iniziale del servo = 10 e ruota fino a 170
for (angolo = 10; angolo <= 170; angolo++)
{
servo_impulso(servo_pin, angolo); // trasmetti al pin di output langolo calcolato
delay(20); // ritardo di 20 millisecondi
}
// valore iniziale del servo = 170 e ruota fino a 10
for (angolo = 170; angolo >= 10; angolo--)
{
servo_impulso(servo_pin, angolo); // trasmetti al pin di output langolo calcolato
delay(20); // ritardo di 20 millisecondi
}
}

19