Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Hello World: facciamo blinkare un led

La struttura di uno sketch (funzioni setup e loop) e la funzione digitalWrite per accendere i pin
La struttura di uno sketch (funzioni setup e loop) e la funzione digitalWrite per accendere i pin
Link copiato negli appunti

Nell'articolo precedente, abbiamo esaminato l'IDE di Arduino e le funzionalità che mette a disposizione per lo sviluppo. Ora non ci resta che utilizzarlo per realizzare il nostro primo programma che, come tradizione vuole quando si inizia ad utilizzare un nuovo strumento e/o linguaggio di programmazione, non può essere altro che il tipico "Hello World" !

Nel caso dei sistemi embedded, il classico "Hello World" consiste nel far lampeggiare (blinkare) un led, che già di per se significa riuscire ad "animare" la board; nel caso della "Arduino Uno", abbiamo a disposizione un piccolo led a bordo, senza la necessita di iniziare sin da subito ad utilizzare fili "volanti" e/o saldature per le connessioni.

Un minimo prerequisito per questo capitolo è una conoscenza seppur basilare del linguaggio C/C++, almeno per quanto riguarda i tipi di dato (int, void, ...), il concetto di istruzione (terminata con il ";"), il concetto di commento e di blocco di codice (incluso tra le parentesi graffe) oltre che di funzione.

L'applicazione che esaminiamo è fornita tra gli esempi inclusi nell'IDE (esempio "Blink" nella sezione "01.Basics") ma per poter comprendere al meglio la modalità di sviluppo su Arduino, la realizzeremo partendo da zero, studiando in primo luogo la struttura minima di uno "sketch" e successivamente introducendo a piccoli passi tutto il necessario per completare il programma.

La struttura di uno sketch: le funzioni setup e loop

Un programma Arduino è caratterizzato dalle due seguenti funzioni principali che sono assolutamente necessarie :

Metodo Descrizione
setup()   è la funzione che viene eseguita una ed una sola volta quando parte lo "sketch" immediatamente dopo l'accensione (il reset della board). Viene tipicamente utilizzata per effettuare le inizializzazioni necessarie al programma come ad esempio l'impostazione dei valori iniziali delle variabili, le modalità di uso dei pin (input, output, etc.) e l'inizializzazione delle librerie utilizzate.
loop() il nome della funzione è autoesplicativo, essa rappresenta il "loop" principale del programma. Ciò significa che le istruzioni contenute al suo interno vengono eseguite ciclicamente (dalla prima all'ultima per poi ripartire dall'inizio). Probabilmente, quando programmiamo ad alto livello, non ce ne rendiamo conto, ma anche in quel caso esiste sempre un "main loop" che garantisca che l'applicazione sia in vita e che, nel caso di applicazioni Windows ad esempio, effettui il "dispatching" degli eventi.

Ovviamente, a queste due funzioni, che costituiscono la struttura minima di uno "sketch", possiamo aggiungere altre funzioni per poter rendere il nostro programma modulare.

Il nostro obiettivo è quello di far lampeggiare un led, ossia accenderlo e tenerlo acceso per un certo tempo (diciamo un secondo), spegnerlo e tenerlo spento per un certo tempo (sempre un secondo) e ripetere ciclicamente queste azioni.

È immediato intuire che queste operazioni di accensione e spegnimento del led saranno eseguite nella funzione loop() per garantirne l'esecuzione ciclica.

I pin di Arduino e la funzione pinMode

Per quanto riguarda il led a bordo della "Arduino Uno", c'è da dire che esso è collegato al pin numero 13 del microcontrollore che altro non è che un pin digitale:

Stato pin digitale Valore logico Tensione Effetto
"alto" 1 > 3,3V Il led è acceso
"basso" 0 < 3,3V Il led è spento

Come accennato, tutti i pin digitali di Arduino sono configurabili come input oppure come output, così come alcuni di essi anche con funzioni molto più complesse (seriale TTL, bus SPI, bus I2C, ...). La prima operazione da fare consiste nell'impostare il pin 13 come output e per farlo possiamo avvalerci della funzione pinMode, ecco la sintassi:

pinMode(pin, mode)

Prevede due parametri:

Parametro Descrizione
pin il numero del pin da impostare (nel nostro caso 13).
mode la modalità di utilizzo del pin e può assumere i valori INPUT ed OUTPUT. Questi ultimi rappresentano due costanti implicitamente visibili nell'IDE Arduino ed incluse nella libreria di base.

Il codice

Poiché l'inizializzazione di un pin è un'operazione che va eseguita una ed una sola volta nel corso di un programma, possiamo effettuarla all'interno della funzione setup() nel modo seguente.

void setup() {
	// inizializzazione del pin in uscita
	pinMode(13, OUTPUT);
}

Per poter comprendere meglio il codice scritto ed evitare di utilizzare direttamente valori identificativi di tipo numerico nelle nostre istruzioni (in questo caso il valore 13), è utile definire una variabile globale con il nome "led" ed assegnarle il valore 13 per poi utilizzarla come primo parametro per la funzione pinMode().

int led = 13;
void setup() {
	// inizializzazione del pin in uscita
	pinMode(led, OUTPUT);
}

In questo modo, se dovessimo prendere tra le mani il codice dopo molto tempo, riusciremmo subito a comprenderne il significato e a capire che l'istruzione ha il compito di impostare il pin collegato al led come ouput per pilotare l'accensione e lo spegnimento del led stesso.

All'avvio della board, il led risulta inizialmente spento, per cui la prima operazione da eseguire è la sua accensione. Accendere il led significa impostare il valore "alto" sul pin corrispondente mentre viceversa il valore "basso" per spegnerlo; in pratica è necessaria un'istruzione che ci permetta di modificare il valore di uscita del pin (e quindi la corrispondente tensione).

Impostare i pin: digitalWrite

L'istruzione a disposizione è digitalWrite(pin, value) che prevede in ingresso i seguenti parametri:

Parametro Descrizione
pin il numero del pin di cui modificare il valore (nel nostro caso 13, tramite la variabile led).
value il valore da assegnare al pin che può essere HIGH o LOW che rappresentano due costanti corrispondenti rispettivamente al valore "alto" e "basso".

Accendiamo e spegnamo il led

Detto ciò, quindi, la funzione loop() inizia a prendere forma nel modo seguente :

void loop() {
	digitalWrite(led, HIGH); // accende il led
}

Dopo averlo acceso, il passo successivo è quello di spegnere il led e come si può intuire basta utilizzare la medesima funzione ma impostando il secondo parametro al valore LOW nel modo seguente :

void loop() {
	digitalWrite(led, HIGH); // accende il led
	digitalWrite(led, LOW);  // spegne il led
}

Potremmo erroneamente pensare di aver terminato il programma ed aver raggiunto il risultato desiderato... ma purtroppo non è così! Le due istruzioni vengono eseguite in sequenza alla velocità del microcontrollore e per questioni di propagazione dei segnali il risultato potrebbe non essere predicibile; potremmo avere un led sempre spento o sempre acceso (a pieno oppure con luce fioca).

Temporizzare le operazioni: delay

Ciò che ci manca è garantire che il led rimanga acceso oppure spento per un certo tempo e per fare questo è necessario utilizzare delay una funzione che ci garantisce un ritardo tra un'istruzione e l'altra, la sintassi è molto semplice

delay(ms)

Essa non fa nient'altro che mettere in "pausa" il programma per un certo tempo (in millisecondi) specificato come parametro.

Entrando nel dettaglio, va sottolineato che il microcontrollore non va mai in "pausa" ma all'interno della funzione delay esegue ciclicamente delle istruzioni in linguaggio macchina che non producono risultato (es. NOP in Assembly) ma che hanno lo scopo di far trascorrere un numero ben definito di cicli di clock in modo da ottenere il ritardo desiderato.

Tornando al nostro esempio, l'istruzione di delay (utilizzando un secondo di ritardo) va aggiunta immediatamente dopo ciascuna delle due istruzioni di set del pin, per cui la funzione loop() assume la forma seguente :

void loop() {
	digitalWrite(led, HIGH); // accende il led
	delay(1000);
	digitalWrite(led, LOW); // spegne il led
	delay(1000);
}

Il programma può considerarsi terminato! Non ci resta che compilarlo e trasferirlo sulla board per vederlo in esecuzione.

Caricare l'applicazione sulla board

Eseguiamo la compilazione attraverso il menu Sketch > Verifica/Compila oppure con il primo pulsante Verifica della barra superiore; non dovrebbe esserci alcun errore a meno di eventuali errori di battitura e come possiamo osservare dalla figura seguente, il programma occupa solo circa 1 KB !

Esito della compilazione

Colleghiamo la board "Arduino Uno" (accertandoci che sia correttamente riconosciuta dal sistema operativo grazie ai driver già installati), selezioniamo la porta seriale a cui è collegata e clicchiamo sul pulsate "Carica". Dopo pochi secondi, vedremo lampeggiare magicamente il led!

Lo sketch, una volta caricato, viene ovviamente salvato nella memoria Flash del microcontrollore, per cui possiamo tranquillamente chiudere il nostro IDE e riavviare la board utilizzando eventualmente un alimentatore esterno in luogo della connessione al PC mediante il cavo USB. Ad ogni riavvio, lo sketch presente in memoria sarà eseguito fino allo spegnimento della board.

Grazie a questo semplice esempio abbiamo acquisito maggiore padronanza dell'IDE ed abbiamo conosciuto le prime semplici funzioni della libreria di base che Arduino ci mette a disposizione. Dal prossimo capitolo, inizieremo a fare sul serio, iniziando a capire in che modo i sensori possano rappresentare un modo per interagire con il mondo esterno e sfruttare Arduino per farlo; parleremo di "Physical Computing"!

Ti consigliamo anche