Sensore di temperatura: GUIDA PASSO PASSO (pt. 2)
In questa seconda parte di questa guida, vedremo come scrivere il codice analizzandone ogni parte.
Scriviamo il codice
Per poter scrivere il codice, avremo bisogno delle seguenti tre librerie:
- DHT.h;
- LiquidCrystal.h;
- DS3231.h.
Il download delle librerie si può effettuare tramite i seguenti link di GitHub e non:
- https://github.com/adafruit/DHT-sensor-library
- https://github.com/adafruit/Adafruit_LiquidCrystal
- DS3231.zip
Le foto mostrano la procedura corretta di installazione: scaricare il file .zip, aprirlo con WinRar o 7z (o altri) ed estrarre tutto nella cartella Documenti\Arduino\libraries.
Se avevate già aperto l’Arduino IDE, riavviate per permettere un corretto caricamento delle librerie nel nostro progetto.
Per librerie, si intende un insieme di funzioni e strutture dati che possono essere collegate a diversi programmi che le possono usare per vari scopi. La loro comodità risiede nel permettere al programmatore di non dover definire ogni volta, per ogni programma, le stesse operazioni.
Facendo un esempio al limite del ridicolo, quando vogliamo mangiare del pane e vogliamo tagliarne una fetta utilizziamo il coltello: metaforicamente il pane è il dato da elaborare, soddisfare la fame il risultato che vogliamo ottenere e il coltello la funzione che opererà sui dati. Avremmo due strade: scrivere la funzione coltello da soli (cioè costruire il coltello) o andare nel cassetto a prenderne uno già costruito: il cassetto rappresenta la libreria, in cui tra le tante funzioni (le posate), sfruttiamo solo quella che ci serve.
Un funzionamento richiesto ad Arduino e di conseguenza ai vari sensori può essere quello di alternare letture di temperatura e umidità a letture di data e ora correnti, ed è quello che in questo progetto verrà programmato.
Prima di cominciare a scrivere il codice si può pensare di dividere le istruzioni nei seguenti blocchi:
- Procurarsi gli strumenti adatti, cioè importare le librerie;
- Definire quante e quali cose la scheda Arduino si troverà a dover gestire e far comunicare, cioè creare le variabili da associare ai vari componenti del circuito;
- Eventualmente definire dove Arduino deve andare a cercare i componenti, indicando il pin corrispondente;
- Definire variabili ausiliarie;
- Eventualmente impostare i componenti tramite funzioni di libreria specifiche;
- Eseguire le operazioni in maniera continua.
Dopo aver definito questi step ci si può addentrare nella scrittura vera e propria.
Come prima cosa, occorrerà importare le librerie. Per farlo, bisogna scrivere “#include "nome_lib.h"
(oppure con i simboli di maggiore e minore)” per ogni libreria necessaria, mettendone una per riga.
Avrete notato che è necessario importare anche la libreria "Wire.h"
: questa contiene delle funzioni di base per la comunicazione tra Arduino e componenti che vengono sfruttate anche dalle altre librerie.
Al secondo passo definiamo che tipo di sensore di temperatura/umidità stiamo utilizzando. Nell’immagine sotto abbiamo utilizzato il comando “#define nome val
“: la comodità di questa scrittura è che una variabile globale che non cambia mai durante l’esecuzione del programma e non occupa memoria. In questa sede la memoria disponibile non è un problema, ma con progetti più complessi può essere utile salvare qualche byte. Un altro modo per dichiarare le variabili in figura è “const type nome=val;
” anche se quest’assegnazione porta via un po’ di spazio disponibile. Notare come con “#define
” non serve terminare la riga con “;”, al contrario di “const type...
“.
Gli altri componenti si possono dichiarare allo stesso modo come in figura sopra: “type name(properties)
” è un format abbastanza comune. Per l’LCD i numeri corrispondono ai pin di autorizzazione di scrittura/lettura (i primi due) e di passaggio di informazioni (i restanti): l’ordine in cui vengono scritti è importante in quanto, come si può vedere dal file “LiquidCrystal.cpp
ognuna delle posizioni di quella funzione va a richiamare specifici pin dell’LCD. Dichiariamo anche il sensore di temperatura e l’orologio come in figura in basso: notiamo che il componente non richiede proprietà particolari in quanto è già stato assegnato a dei pin specifici e la libreria va automaticamente a “cercare” l’orologio lì.
Come ultima, dichiariamo una variabile contatore, il cui funzionamento sarà spiegato a breve.
Ora passiamo a scrivere il setup, la parte di programma che inizializza Arduino ogni volta che lo accendiamo/resettiamo. La dicitura “void setup()
” sta ad indicare che questa funzione non restituisce risultati (void
) e non ne vuole in ingresso ( () ). Tutto il corpo di operazioni deve essere contenuto tra le parentesi graffe.
Nel setup, vogliamo definire le seguenti operazioni:
- Dire ad Arduino quanti caratteri possono entrare nello schermo;
- Impostare l’inizio di alcune righe e scrivere dei messaggi iniziali;
- Avviare l’orologio, impostando data ed ora.
Notiamo subito, dalla figura sopra, che il DHT11 non ha bisogno di inizializzazioni (i primi valori vengono automaticamente letti dalla scheda) e che nell’orologio data ed ora vengono impostati con una funzione specifica: la scrittura “setDateTime(__DATE,__TIME__)
” è responsabile dell’impostazione del DS3231 sull’orario del computer da cui viene caricato il programma. Fatto questo, possiamo passare a dare i comandi veri e propri.
Essendo dei comandi che vogliamo ripetuti ad ogni passaggio, andiamo a definire la funzione void loop()
in cui come prima cosa vogliamo reperire le informazioni che ci servono. Le funzioni atte a questo scopo sono readTemperature()
, readHumidity()
, getDateTime()
. Avendo definito i tre oggetti sensor, screen, Clock appare chiaro come quelli che contengono le informazioni siano sensor e Clock. Questo ci consentirà di allocare nelle variabili dinamiche i valori che ci servono. Le variabili sono dinamiche perché vengono dichiarate ad ogni ciclo di esecuzione del “loop”. Si può notare che i valori di temperatura e umidità sono delle semplici variabili “float
” (cioè numeri in virgola mobile), mentre la variabile “infos” è di un tipo specifico che viene gestito dalla libreria DS3231, con particolari membri della classe RTCDateTime (similmente al Java, definire una classe consente di assegnare determinate “proprietà” per gli oggetti; in questo caso “data”, “ora”, “giorno” sono concetti già “insiti” e quindi assegnati a tutti gli oggetti di questo tipo).
Abbiamo detto all’inizio che il comportamento che vogliamo dare al nostro dispositivo nell’ambito di questo progetto è quello di mostrare alternativamente le informazioni. La variabile “count
” servirà a questo scopo: ad ogni chiamata della funzione “loop()
” possiamo agire su questa variabile (che abbiamo inizialmente posto uguale a zero): ad esempio, possiamo impostare il comportamento di Arduino in modo da fargli compiere un’azione piuttosto che un’altra al variare del valore di “count
“. Un modo “economico” può essere quello di dire “se la variabile è pari, mostra temperatura e umidità; se dispari, data e ora“. Per valutare un’operazione di confronto, possiamo costruire un blocco if
dove vediamo se il resto dell’operazione di divisione è 0 o 1. Questo può essere fatto tramite l’operatore % (modulo), che restituisce solo il resto di una divisione.
E’ evidente che, siccome dobbiamo mostrare tutti i risultati sul display, andremo a riferirci solo alla variabile screen
. Partendo dal blocco per cui il resto è zero, cominciamo col pulire lo schermo dai precedenti messaggi tramite la funzione “clear()
“. Di default, la scrittura sullo schermo comincia dalla prima casella che, in riferimento agli array di dimensioni 16×2 (che è la rappresentazione usata dalla libreria), si trova in posizione (0,0). Da questa posizione vogliamo stampare a video il testo “Temp:”, tenendo conto che il testo è lungo 5 caratteri (contano anche i due punti!), le posizioni della prima riga fino a (0,4) saranno impiegate. Per scrivere, si usa la forma screen.print(“Temp:”).
Per andare alla riga sotto, utilizziamo la funzione “setCursor(0,1)
” che, sempre in analogia con gli array, ci posiziona alla seconda riga (1), prima colonna (0). Qui, come prima, stampiamo il testo (“Humid:”).
Le ultime due cose da fare sono impostare un tempo di attesa, ad esempio 4 secondi, tramite la funzione delay(tempo)
(dove tempo è in millisecondi) ed incrementare la variabile “count
“.
Per evitare che la variabile “count
” diventi un numero talmente grande da non poter essere più rappresentato (il più grande intero rappresentabile è 32767), possiamo impostare un controllo che riazzeri il valore di count
raggiunta una certa soglia.
Assicuratevi, prima di caricare lo sketch, di aver scelto la scheda e la porta giuste, in modo da non incorrere in problemi di compilazione. Caricate il programma e il vostro dispositivo comincerà a funzionare.
IMPORTANTE
In merito a data e ora di setup, c’è una considerazione da fare: per come è scritto il programma, Arduino fornirà al dispositivo data e ora del computer che usiamo per il caricamento. L’orologio verrà quindi riportato a quelle “__DATE__
” e “__TIME__
” e comincerà a contare il tempo. Supponiamo quindi che, finito il tutto, vogliamo tenere staccato dal computer ed alimentare esternamente il progetto. Se non togliamo questa riga, al successivo riavvio nell’orologio verranno ancora caricati data e ora dell’ultimo caricamento da pc, ripartendo a contare il tempo da quel punto. Per garantire un corretto funzionamento, quindi, la procedura da seguire sarà questa:
- finito il codice, carichiamolo una prima volta sulla scheda per fornire data e ora correnti;
- verifichiamo che sia tutto corretto (data e ora);
- se è “tutto ok”, commentiamo la riga del setup in cui si impostano data e ora (“
//Clock.setDateTime...
“). In questo modo, questa riga verrà saltata e quindi l’orologio non più riavviato.
In questo modo, anche quando il dispositivo resterà spento, l’orologio continuerà a segnare l’ora giusta e, alla riaccensione, non verrà resettato ma solo letto il nuovo orario a cui questo è arrivato.
Codice completo
Il codice completo è disponibile a fondo pagina del precedente articolo.
Salve,
ho trascritto lo sketch riga per riga e ricontrollato tutto, durante la funzione di verifica ricevo: errore durante la compilazione per la scheda Arduino Nano, lo sketch completo per la verifica non è presente nel sito pertanto non è stato possibile verificare se quanto descritto nelle tue spiegazioni fosse completo.
Hardware in uso : Arduino Nano V3, IDE 1.8.10
Salve, può scriverci direttamente all’indirizzo [email protected] o [email protected] allegando gli screen dell’errore e vediamo di capire cosa è andato storto!