Costruisci un Termoigrometro Analogico-Digitale con Arduino

È digitale o è analogico? Questo strumento è entrambe le cose, perché acquisisce temperatura e umidità attraverso sensori digitali e li elabora tramite Arduino, ma poi li rende visibili azionando due lancette con altrettanti servocomandi.

Siamo nell’era del digitale, dove si cerca di discretizzare tutto quello che si può captare e portarlo dentro una CPU per fare in modo che diventi parte di un programma e che quindi possa essere trasformato, elaborato e reso fruibile sui moderni visualizzatori, ormai quasi solo LCD, TFT, IPS.
Sicuramente il digitale ha i suoi pregi, ma per qualcuno potrebbe risultare un po’ freddo e non idoneo a progetti che devono essere messi in casa invece che in un laboratorio o in una sala strumenti.
Ecco perché ci è venuta l’idea di coniugare le due tecnologie, analogica e digitale, per realizzare un misuratore di temperatura e umidità dell’ambiente da mettere in casa o comunque in luoghi chiusi, magari su un mobile o sulla scrivania; con un tocco di fantasia e qualche suggerimento, è possibile utilizzare l’hardware e il software che vi proponiamo, abbinandoli a un pannello di fissaggio e ad un contenitore che daranno a questo termoigrometro un aspetto più essenziale e casalingo.
Proprio per il pannello, abbiamo previsto la stampa 3D in PLA colorato di alcuni particolari da assemblare per ottenere il risultato che vedete nelle foto in queste pagine, lancette comprese.
Visto che si tratta di un circuito elettronico, andiamo con ordine e affrontiamo per prima cosa l’hardware che lo compone, esponendo in un secondo momento la gestione firmware.

Il circuito del termoigrometro con Arduino

L’elettronica che ci serve per questo progetto è tutta reperibile in commercio sotto forma di schede già pronte, vale a dire:
• una breakout board sensore temperatura e umidità HTU21D (codice GY213V);
• una breakout board adattatrice bidirezionale di livelli logici (codice LLCONBI);
• una scheda Arduino Nano (codice ARDUINONANO).
Questi elementi possono sia essere interconnessi mediante cavetti jumper per Arduino, sia trovare posto su un pezzo di basetta millefori, opportunamente innestati in strip femmina a passo 2,54 mm.
Per chi lo desidera e può realizzarlo, abbiamo comunque previsto il montaggio su circuito stampato, del quale rendiamo disponibile per il download la traccia lato rame, al quale fa riferimento lo schema elettrico che trovate in queste pagine e che seguiremo per la descrizione del funzionamento.
Qualunque sia la soluzione che adotterete, ricordate che i collegamenti devono rispecchiare lo schema elettrico, dove sono riportati anche i servocomandi, gestiti dai pin digitali 8 e 9 di Arduino Nano.
A parte i servo, che devono per forza essere collegati a filo (senza scordare che entrambi richiedono, oltre al filo degli impulsi si comando, l’alimentazione a 5V e la massa) dovete collegare il sensore temperatura e umidità tramite adattatore di livelli ai pin I²C-Bus di Arduino Nano, in questo modo:
• al pin A4 (SDA) della Arduino dovrà pervenire la linea facente capo al pin DA della breakout sensore;
• al pin A5 (SCL) della Arduino dovrà pervenire la linea facente capo al pin CL della breakout sensore.
Lo vedete chiaramente nello schema elettrico, dove il sensore di temperatura e umidità è siglato U3 e Arduino Nano U1; notate che il bus I²C viene interfacciato alle rispettive linee di Arduino tramite U2, che è la breakout board adattatrice di livelli, la quale serve per rendere compatibili le linee A4 e A5, operanti a livello TTL (0/5V) con le tensioni del bus I²C della breakout HTU21D, la quale funziona a 3,3Vcc; l’adattatore è un piccolo circuito in grado di convertire livelli logici da 5 V a 3,3 V e viceversa (funziona anche con dispositivi da 2,8 V e 1,8 V) e dispone di quattro linee, ovvero 4 pin per il lato a 5V e altrettanti per il lato a bassa tensione, con due ingressi e due uscite per ogni lato. Può essere utilizzato con qualsiasi segnale digitale (porte seriali TXD/RXD, I²C-Bus ed SPI).
Quanto alla breakout board U3, si tratta di un modulo basato sul sensore di temperatura e umidità digitale HTU21D dotato di interfaccia I²C-Bus.
Il range di misurazione della temperatura va da -40°C a +125°C, mentre quello dell’umidità relativa da 0% RH a 100% RH. Per la misura della temperatura garantisce una precisione di ± 0,3 °C mentre per il rilevamento dell’umidità ha una precisione di ± 2%RH @25°C (20% RH to 80% RH).
La breakout board richiede un’alimentazione di 3,3 Vcc ed assorbe meno di mezzo milliampère, che si riduce a 0,02 µA mettendo l’integrato nella modalità sleep da esso supportata.
L’integrato HTU21D è un sensore combinato incapsulato in package SMD DFN e quindi molto comodo da utilizzare già montato su breakout board; fornisce segnali calibrati e linearizzati in formato digitale su bus I²C, sul quale si comporta come unità Slave. Supporta una funzione di rilevamento della tensione di alimentazione, indicando quando è troppo bassa per garantire un funzionamento affidabile; inoltre la comunicazione è resa più affidabile grazie a un checksum inserito nelle stringhe scambiate con il microntrollore (Master) che nel nostro caso è quello di Arduino.
La risoluzione del sensore può essere modificata tramite un comando di configurazione su I²C-Bus (8/12 bit fino a 12/14 bit per RH/T).
Tornando allo schema elettrico, oltre che al modulo sensore, Arduino Nano si connette ai due servocomandi analogici da modellismo da 12 kg/cm (reperibili all’indirizzo www.futurashop.it col codice SERVO206) che azioneranno le lancette del termometro e dell’igrometro sulla base dei valori letti dal sensore di temperatura e umidità; per l’esattezza, Arduino convertirà i valori digitali ricevuti tramite I²C-Bus in larghezza degli impulsi di comando dei servo e pertanto in deviazioni angolari dell’alberino, nel campo fra -90 e +90° rispetto alla posizione di zero (centrale); ciascun servo azionerà una lancetta indicatrice.
Il servomotore per l’indicazione della temperatura è quello collegato al connettore CN1 (facente capo alla linea D9 di Arduino) mentre quello che aziona la lancetta dell’umidità è pilotato da Arduino attraverso il pin D8, quindi dal connettore CN2.
L’alimentazione dell’intero circuito, almeno nel caso di utilizzo del PCB, viene applicata tramite una presa jack, in serie al cui elettrodo positivo è stato posto un diodo (D1) di protezione ad evitare danni in caso di inversione di polarità.
Al resto delle tensioni di alimentazione, quindi quelle per i servo e le breakout board, provvede U1 con i suoi regolatori interni a 3,3 e 5V; la linea dei 5V l’abbiamo filtrata con un condensatore elettrolitico, dato che i servocomandi potrebbero creare un certo disturbo che non vogliamo sia propagato al resto del circuito (è utile montare tale condensatore anche se optate per il cablaggio volante).

Il firmware

Bene, stabiliti la composizione e il funzionamento dell’hardware, possiamo andare ad analizzare gli aspetti software, andando a descrivere lo sketch Arduino; prima di vedere il firmware completo, riportato nel Listato 1, facciamo un po’ di didattica e andiamo a vedere come si gestisce e si testa individualmente la sezione del sensore e quella dei servo. Più esattamente, scriviamo e descriviamo un codice per ciascuna delle sezioni suddette, che potrete utilizzare distintamente dallo sketch per provare sensore e servomotori.

Listato 1

#include <Wire.h>
#include “SparkFunHTU21D.h”
#include <Servo.h>

HTU21D myHumidity;
Servo myservo; 
Servo myservo2;
float humd = 0;
float temp = 0; 
int pos = 0; 
int pos1 = 0;


/*************SETUP***************/

void setup() {

Serial.begin(9600);
delay(500);
Serial.println(“Avvio”);

myservo2.attach(8); 
myservo.attach(9);
myHumidity.begin();

Serial.println(“Test Servo”);
for(int i=180; i>0 ; i--){
myservo.write(i);
myservo2.write(i);
delay(10);
}

myservo.write(90);
myservo2.write(90);

}


/**************** SENSORE ****************/

float sensore(float &temperatura, float &umd){

temperatura = myHumidity.readTemperature();
umd = myHumidity.readHumidity(); 
Serial.print(“Tempo:”);
Serial.print(millis());
Serial.print(“ Temperatura: “);
Serial.print(temperatura, 1);
Serial.print(“C”);
Serial.print(“ Umidità: “);
Serial.print(umd, 1);
Serial.println(“%”);

}


/************ 1° servo (temperatura) ************/

void servo1 (float temperatura){ 
myservo.attach(9); 
int pos;

temperatura = myHumidity.readTemperature();

if(temperatura>40){
temperatura = 40;
}

if(temperatura<15){
temperatura = 15;
}
pos = map(temperatura, 40, 15, 0, 180);
Serial.print(“ Temp: “);
Serial.println(pos);
myservo.write(pos);

}


/************** 2° servo (umidita) **************/

void servo2 (float umidita){ 

myservo2.attach(8); 
int pos2;

umidita = myHumidity.readHumidity();

if(umidita<20){
umidita = 20;
}

if(umidita>80){
umidita = 80;
} 

pos2 = map(umidita, 20, 80, 180, 0);
Serial.print(“ Umd: “);
Serial.println(pos2);
myservo2.write(pos2);

}

/******************** MAIN ********************/

void loop(){

sensore(temp,humd);
delay(300);

servo1(temp);
delay(15);

servo2(humd);
delay(15); 
delay(5000);

}
Iniziamo con le librerie necessarie al sensore di temperatura e umidità:
#include <Wire.h>

#include “SparkFunHTU21D.h”

#include <Servo.h>




HTU21D myHumidity;
Questo codice permette di includere la libreria Wire per la gestione dell’I2C bus e la libreria sviluppata da SparkFun (SparkFunHTU21D.h) che integra tutte le istruzioni necessarie al corretto funzionamento del sensore.
Quest’ultima deve essere installata manualmente tramite il gestore librerie dell’IDE Arduino, accessibile dal menù Strumenti.
Includiamo anche la libreria per la gestione dei servocomandi (servo.h).
Il passaggio successivo all’inclusione delle librerie, come si può vedere, è la creazione dell’oggetto “myHumidity”, operazione a noi utile per richiamare all’occorrenza il sensore per la lettura di temperatura e umidità.
Definiamo quindi una sezione di “Setup” (già presente all’apertura del programma Arduino nell’IDE, in quanto ogni Sketch non può prescindere dal Setup), nella quale andremo ad inizializzare il monitor seriale.
La seconda istruzione che vedete scritta è la begin invocata sull’oggetto sensore, che permette di inizializzare il sensore stesso affinché possa iniziare le misurazioni.
La porzione di codice attinente al test sensore di temperatura e umidità è questa:
void setup() {

Serial.begin(9600);




myHumidity.begin();

}

                                                     

void loop(){




float humd = myHumidity.readHumidity();

float temp = myHumidity.readTemperature();




Serial.print(“Tempo:”);

  Serial.print(millis());

  Serial.print(“ Temperatura: “);

  Serial.print(temp, 1);

  Serial.print(“C”);

  Serial.print(“ Umidità: “);

  Serial.print(umd, 1);

  Serial.println(“%”);

  delay(3000);

}
Passiamo alla sezione Loop, ovvero il fulcro del programma, nella quale dichiariamo due variabili float per memorizzare la temperatura e l’umidità misurata; difatti come si può notare richiamiamo di seguito la funzione “readHumidity”, la quale restituisce l’umidità misurata e la memorizza nella variabile apposita.
Stessa procedura viene fatta per quanto riguarda la temperatura, soltanto che si utilizza la funzione “readTemperature”, la quale restituisce la temperatura e la memorizza nella variabile apposita.
Una volta dichiarate le variabili, possiamo procedere con le stampe sul monitor seriale dei dati misurati. Il comando utilizzato è “Serial.print”, tuttavia se si vuole stampare e successivamente andare a capo si utilizza “Serial.println”.
Alla fine di tutto utilizzeremo una funzione “delay” per stabilire un tempo che deve trascorrere tra una misura e l’altra.
Questo è quanto riguarda la parte firmware relativa al sensore; ora vediamo la porzione che attiene alla gestione del movimento dei servomotori.
Per testare velocemente il corretto funzionamento dei servomotori, riportiamo questo breve codice che permette di farli ruotare in senso orario e antiorario continuamente:
#include <Servo.h>




Servo myservo;  

Servo myservo2;

int pos = 0; 




void setup() {

Serial.begin(57600);

myservo2.attach(8); 

myservo.attach(9);

}




void loop(){




for (pos = 0 ; pos <= 90 ; pos ++) 

{

  myservo2.write(pos);

  myservo.write(pos);

  Serial.println(pos);

  delay(15);

}




for (pos = 90 ; pos >= 0 ; pos --) 

 {

  myservo2.write(pos);

  myservo.write(pos);

  Serial.println(pos);

  delay(15);

 }

}
Vediamo nel dettaglio come funziona questo semplice codice.
Come prima operazione c’è sempre l’inclusione della libreria “servo.h”: trattandosi di una libreria già presente nell’ambiente Arduino, non dovete scaricarla e installarla come fatto per quella di gestione del sensore HTU21D.
Successivamente vedete la creazione dei due oggetti che servono per gestire gli altrettanti  servomotori: si tratta di due oggetti virtuali, ognuno corrispondente ad un servo; per distinguere a quale servo è abbinato ogni oggetto, utilizziamo la funzione “Attach” e indichiamo il pin dove è attaccato ogni singolo servo (in questo caso avviene una sorta di abbinamento tra l’oggetto virtuale e l’oggetto reale).
Svolta questa operazione, possiamo passare alla sezione “loop”, noteremo 2 cicli for, ovvero una struttura iterativa che permette di eseguire delle operazioni per un numero definito di volte e senza una condizione.
All’interno di questi cicli “for” inizializzeremo un indice, che in questo caso indicherà la posizione, inizializzata a 0, del servo motore, un’operazione logica da rispettare: in questo caso “ pos < 90 “, che farà muovere il servo fino alla posizione di 90° e l’incremento dell’indice “pos” per permettere al servo di muoversi.
Una volta definito il ciclo for, andremo a richiamare la funzione “ write “ sugli oggetti servo (virtuali), la quale scriverà le indicazioni ricavate dal ciclo for, in questo caso la variabile “pos”, e il servo si muoverà a seconda dei parametri stabili.
Una volta concluso ed eseguito il primo ciclo for, dobbiamo far tornare alla posizione di partenza il servo, ovvero portarne l’alberino nella posizione 0.
Allo scopo utilizzeremo sempre un ciclo for, soltanto che inizializzeremo l’indice del ciclo a 90 gradi (pos = 90) e fin tanto che la posizione sarà maggiore o uguale a 0, la posizione del servo sarà decrementata: questo perché dobbiamo far tornare la posizione del servo motore a 0.
Con un nuovo utilizzo della funzione “write”, scriviamo quello che sarà il nuovo parametro “ pos “.

Lo sketch Arduino

Elenco Componenti:
C1: 100 µF 16 VL elettrolitico

D1: 1N4007

U1: Arduino Nano o Compatibile

U2: Adattatore di livello (cod. LLCONBI)

U3: Modulo Sensore Temperatura/Umidità 

(cod. GY213V)

Varie:

- Pin strip maschio 3 vie (2 pz.)

- Strip femmina 4 vie

- Strip femmina 6 vie (2 pz.)

- Strip femmina 15 vie (2 pz.)

- Circuito stampato S1696 (56x56 mm)
Ora che abbiamo visto e descritto il codice individuale per testare e gestire i servo, possiamo andare a spiegare lo sketch vero e proprio, nel quale sostanzialmente si fonde la sostanza delle due porzioni di codice appena descritte, allo scopo di muovere gli alberini dei servo a seconda della temperatura e dell’umidità letta.
La prima parte del codice è quella che contiene le “include” già spiegate e nella quale vengono definite le variabili myHumidity, myservo e myservo2: myHumidity è abbinata al sensore di temperatura e umidità e quindi ai dati che esso produce, myServo riguarda il primo servomotore (quello che azionerà la lancetta indicante la temperatura collegato al pin digitale D9) e myServo2 è abbinata al secondo servocomando (quello che muoverà la lancetta dell’igrometro e che risulta collegato al pin D8).
Successivamente avviene la dichiarazione delle cosiddette variabili globali, ovvero quelle variabili che sono utilizzabili in tutto il programma e non solo in una porzione di codice, come vederemo in seguito. Tali variabili sono float humd = 0; float temp = 0; int pos = 0 e int pos1 = 0.
Andiamo quindi alla porzione successiva del listato, che corrisponde all’implementazione del Setup: qui inizializzeremo il monitor seriale (come nei codici precedenti) e specificheremo i pin  cui sono collegati i servocomandi, attraverso la funzione “attach”, dopodiché inizializziamo il sensore tramite la funzione “begin”.
Successivamente troviamo l’utilizzo di due funzioni “write” per la calibrazione della posizione di avvio dei servo, che in questo caso corrisponderà a un’angolazione di 90° e pertanto alla posizione centrale della lancetta sul quadrante.
Veniamo ora alla prima funzione (un sottoprogramma che permette di suddividere il programma in più punti) implementata: in questa circostanza la funzione è stata utilizzata per azionare il primo servo allo scopo di fargli indicare la temperatura che viene fornita dal sensore termoigrometro.
La porzione di codice interessata è la seguente:
void servo1 (float temperatura){             

  myservo.attach(9);    

  int pos;

  

  temperatura = myHumidity.readTemperature();




    if(temperatura>40){

      temperatura = 40;

    }

    

    if(temperatura<15){

      temperatura = 15;

    }

  

    pos = map(temperatura, 40, 15, 0, 180);  

  }
Nella prima riga, tra parentesi passeremo come parametro la variabile “float temperatura” che in questo caso sarà una variabile locale (per locale si intende che viene utilizzata solamente all’interno della funzione) nella quale memorizzeremo la temperatura che andremo a leggere con la funzione “readTemperature” anch’essa richiamata sull’oggetto “myHumidity”.
Successivamente utilizzeremo la funzione “map”, che ci è utile per andare a mappare il valore letto dal sensore, sul quadrante inerente alla temperatura; mappare significa posizionare i servo su un valore in un certo intervallo di valori e in pratica l’operazione calcola automaticamente la posizione corrispondente alla temperatura letta dal sensore.
Tutto questo lo andremo a stampare sul monitor seriale così da poterlo vedere sullo schermo del computer, laddove ci occorra.
Per evitare che il servo sforzi per andare oltre un valore prestabilito del quadrante, utilizzeremo due cicli if, che rappresentano una condizione verificata o meno con conseguente istruzione eseguita se la stessa istruzione sia verificata o meno.
Analogamente facciamo per l’altro servo, attraverso una funzione che gestisce il servo2 allo scopo di far indicare alla lancetta corrispondente il valore dell’umidità rilevata dal sensore su breakout.
Passeremo come pararmetro una variabile adibita alla lettura dell’umidità, con l’utilizzo della funzione “ReadHumidity”, utilizzeremo sempre la funzione “map” per andare a mappare il valore ricevuto dal sensore e successivamente le dovute stampe sul monitor seriale.
In coda allo sketch abbiamo la sezione loop, dove andremo a richiamare tutte le funzioni scritte, in questa maniera:
servo1(temp,humd);        // nome della funzione e 

   //parametri utilizzati
In questo modo, eseguiamo quelle che sono le istruzioni all’interno della funzione.
Una serie di delay è stata inserita per stabilire una frazione di tempo che deve trascorrere tra un’operazione e la successiva.

Realizzazione pratica

Giunti a questo punto possiamo spendere qualche paragrafo per i consigli pratici: del circuito abbiamo già spiegato che potete optare per il cablaggio puro e semplice, per l’utilizzo di una basetta millefori o potere realizzare un PCB come abbiamo fatto noi; comunque facciate, connettete tutto come mostrato nello schema elettrico e alla fine verificate che sia tutto a posto.
Per facilitare l’utilizzo e il montaggio delle breakout board dotatele di pin-strip da inserire nei rispettivi fori e stagnatele.
Ricordate che la breakout adattatrice di livelli (della quale proponiamo la piedinatura in Fig. 3) richiede due alimentazioni: quella sul lato a tensione maggiore (High Voltage) ossia 5V (da prelevare dal pin omonimo di Arduino Nano) e quella sul lato a bassa tensione (Low Voltage, da connettere al pin 3V3 della Arduino Nano).

Fig. 3 Piedinatura della breakout adattatrice di livelli vista dal lato componenti.

Delle quattro linee potete sceglierne due a piacimento, ma se vi atterrete al nostro schema di cablaggio non dovrete pensare ad altro; resta inteso che CL (SCL) e DA (SDA) della breakout board sensore dovranno essere collegati sul lato Low Voltage (per esempio alle linee 1 e 2) e che le due corrispondenti linee High Voltage dovranno andare ad SCL e SDA di Arduino Nano.
Per chi volesse, abbiamo disegnato un circuito stampato per collegare il tutto senza ricorrere a cablaggi volanti o millefori.
Potete utilizzarlo per avere il vostro circuito stampato tramite il servizio di produzione PCB (cod. PCBPRODUCTION).
Se invece preferite realizzare il circuito in maniera “tradizionale”, dovrete stampare il lato rame del gerber su carta da lucido o acetato per procedere con la fotoincisione. Inciso e forato quest’ultimo potete inserire e saldare i pin-strip che occorrono a sostenere e collegare il sensore di temperatura e umidità con Arduino Nano, la stessa scheda Arduino e il traslatore di livelli.
Montate poi la presa jack, il diodo al silicio e il condensatore elettrolitico, seguendo il verso indicato per ciascuno nel relativo piano di montaggio.
Per l’alimentazione potete semplicemente collegare al connettore microUSB della Arduino Nano  il cavetto di uscita di un alimentatore stabilizzato capace di fornire 5V e una corrente di 300÷400 milliampere. Se avete optato per la realizzazione su circuito stampato, avendo previsto su di esso una presa jack per alimentare il circuito, utilizzerete un alimentatore da rete con uscita a 9÷12Vcc (in grado di erogare una corrente pari a quanto indicato poche righe addietro) con cavetto terminante con un jack idoneo, avente il positivo sull’elettrodo interno.
Per quanto riguarda il contenitore o comunque la struttura meccanica dell’insieme, potete prendere suggerimento dal nostro prototipo, che è stato stampato in 3D in più parti, ossia un pannello di fissaggio dei servocomandi, una parte decorativa (il sole che spunta in alto a sinistra) sul cui retro potete fissare mediante un paio di squadrette il circuito stampato dell’elettronica e i numeri dei quadranti: lo vedete in Fig. 4 visto dal davanti e nella
Fig. 5 da dietro, dove sono stati fissati i servo.

Fig. 4 Pannello frontale (stampato in 3D) dello strumento con le lancette applicate ai servo.

Fig. 5 Il retro del pannello con applicati i servocomandi.

Comunque la stampa 3D non è l’unica soluzione, perché il pannello può essere ottenuto da una lastra di materiale plastico o da un pezzo di legno compensato, che conferisce un aspetto più “green”.
è anche possibile ricorrere a un contenitore in plastica variamente sagomato, anche di quelli per elettronica. Insomma, avete la massima flessibilità.
Se prevedete un contenitore chiuso, fate in modo di montare la scheda a ridosso di una parete, da forare, per consentire l’introduzione dello spinotto di alimentazione nella presa jack. Al solito, i servocomandi vanno fissati con piccole viti al pannello frontale, ma è anche possibile incollarli con della colla a caldo, evitando di interessare l’alberino.

Lascia un commento

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

Menu