L'ESP32-wroom integra due ADC (Analog to Digital Converter) a 12 bit di tipo SAR (Successive Approximation Register) che permettono fino a 18 diverse misurazioni. Questo articolo vuole mostrare come attraverso la lettura di un canale ADC della scheda ESPertino, possiamo ricavare una misura della temperatura, impiegando un termistore NTC. Verrà realizzato uno sketch di esempio in ambiente Arduino utilizzando una libreria realizzata appositamente, che si basa sulle API offerte dalle official development framework for ESP32 da parte dell'azienda produttrice Espressif Systems.
Misuriamo la temperatura utilizzando la libreria ESP32_ADC
Il primo passo da compiere è aggiornare la libreria per arduino, operazione già spiegata nell'articolo di qualche tempo fa, per cui dal seguente link, apparirà la schermata come in Figura 1:
- Posizionarsi nella cartella d’installazione di Arduino (nel mio caso C:\Program Files (x86)\Arduino\hardware\espressif\esp32) scompattare il file appena scaricato:
arduino-esp32-master.zip
- Scaricare il file board.zip da questo link, e scompattarlo sempre nella cartella di installazione di Arduino;
- Aprire l’ide Arduino e dal menu Strumenti---> Scheda--->ESPertino new lib
La scelta di aggiornare le librerie, è duplice, da un lato installare l’ultima versione, permette di tenere un software in cui sono risolti una serie di bug rilevati nel tempo, e dall’altro, accantonare ad esempio delle funzioni dichiarate deprecated, e utilizzare al loro posto altre più efficienti come indicato dalla documentazione ufficiale.
La misurazione della temperatura con un termistore, avviene attraverso la lettura di un canale ADC, e poiché espertino possiede 18 canali suddivisi in due gruppi ADC1 e ADC2, i primi 8 possono essere sempre utilizzati, i restanti al momento della stesura di quest'articolo,non sono ancora supportati. Dalla documentazione ufficiale, sono evidenziate le limitazioni dell’uso dei canali ADC2, in particolare è indicato espressamente che non possono essere utilizzati questi canali, quando è avviata la parte riguardante il modulo WIFI.
La mappatura dei canali ADCs, con le porte sono le seguenti:
ADC1_CHANNEL_0 = 0, ADC1 channel 0 is GPIO36
ADC1_CHANNEL_1, ADC1 channel 1 is GPIO37
ADC1_CHANNEL_2, ADC1 channel 2 is GPIO38
ADC1_CHANNEL_3, ADC1 channel 3 is GPIO39
ADC1_CHANNEL_4, ADC1 channel 4 is GPIO32
ADC1_CHANNEL_5, ADC1 channel 5 is GPIO33
ADC1_CHANNEL_6, ADC1 channel 6 is GPIO34
ADC1_CHANNEL_7, ADC1 channel 7 is GPIO35
ADC2_CHANNEL_0 = 0, ADC2 channel 0 is GPIO4
ADC2_CHANNEL_1, ADC2 channel 1 is GPIO0
ADC2_CHANNEL_2, ADC2 channel 2 is GPIO2
ADC2_CHANNEL_3, ADC2 channel 3 is GPIO15
ADC2_CHANNEL_4, ADC2 channel 4 is GPIO13
ADC2_CHANNEL_5, ADC2 channel 5 is GPIO12
ADC2_CHANNEL_6, ADC2 channel 6 is GPIO14
ADC2_CHANNEL_7, ADC2 channel 7 is GPIO27
ADC2_CHANNEL_8, ADC2 channel 8 is GPIO25
ADC2_CHANNEL_9, ADC2 channel 9 is GPIO26
Comunque è da sottolineare nuovamente che i canali relativi all'ADC2, al momento non sono supportati, ma lo saranno in futuro, e in quel caso, aggiornerò la libreria per un loro immediato utilizzo.
Mi sono proposto di usare direttamente le API (basate su quelle del 24 aprile 2018) messe a disposizione dall’ultimo rilascio ufficiale da parte di Espressif, e quindi ho realizzato un wrapper che faciliti l'utilizzo delle diverse funzionalità per i canali ADC1, scaricabile al seguente link ESP32_ADC.zip.
Un po' di teoria
Benché i concetti di base per gli ADC e termistori sono noti a molti, ritengo cosa utile fare un piccolo ripasso, rivolto soprattutto per chi si avvicina al loro utilizzo per la prima volta, mediante una trattazione semplificata.
Il primo problema da affrontare è la scelta della risoluzione dell’ADC (l'ESP32 wroom permette le risoluzioni 9,10,11,12 bit), ed in tale fase possono essere d’aiuto degli esempi in Figura 2,Figura 3,Figura4:
La loro importanza è notevole, in quanto indicano, una volta fissata la risoluzione, come varia la grandezza letta dall’ADC con la tensione misurata, al variare delle diverse attenuazioni.
Lo schema classico da utilizzare per i nostri scopi come in Figura 5, è quello di porre una resistenza nota (10KΩ) in serie al termistore:
Per cui è fondamentale comprendere, quale sia il punto di funzionamento del circuito, che risulta stabilito attraverso la misura della tensione ai capi della resistenza in serie, ed in base a questa:
- quale risoluzione dell’ADC utilizzare (9,10,11,12 bit);
- quale attenuazione utilizzare piuttosto che un’altra, che per una tensione di ingresso pari a 3.3V:
- attenuazione di 0dB che permette di avere una tensione di fondo scala pari a 1.1V
- attenuazione di 2.5dB che permette di avere una tensione di fondo scala pari a 1.5V
- attenuazione di 6dB che permette di avere una tensione di fondo scala pari a 2.2V
- attenuazione di 11dB che permette di avere una tensione di fondo scala pari a 3.9V
Dove come tensione di fondo scala, si intende il valore massimo che può essere letto dall'ADC, e questo valore è strettamente legato alla sua risoluzione:
- risoluzione a 9 bit ------> 29 -1 = 511 valore max
- risoluzione a 10 bit ------> 210 -1 = 1023 valore max
- risoluzione a 11 bit ------> 211 -1 = 2047 valore max
- risoluzione a 12 bit ------> 212 -1 = 4095 valore max
Per quanto riguarda il termistore, esso non è altro che un resistore, il cui valore di resistenza è dipendente fortemente dalla temperatura dell’ambiente che lo circonda, ne possiamo trovare di due tipi NTC e PTC, dove le sigle indicano:
-NTC (Negative Temperature Coefficient) dipendenza negativa della temperatura ovvero, al crescere di essa il valore della resistenza diminuisce, come si osserva dalla Figura 6.
-PTC (Positive Temperature Coefficient) dipendenza positiva della temperatura ovvero, al crescere di essa il valore della resistenza aumenta, come si osserva dalla Figura 7.
In questo circuito è stato utilizzato un termistore M52 NTC, la cui natura è descritta da una relazione matematica, in cui vi è un legame della resistenza con la temperatura di questo tipo:
- Rtermistore = resistenza offerta dal termistore;
- Ro = resistenza nominale del termistore alla temperatura di riferimento 25°C (298.15K);
- T1= la temperatura espressa in gradi kelvin, della temperatura da misurare;
- T2= la temperatura 25°C (298.15K) ambiente a cui si misura una resistenza = 10KΩ;
- β parametro caratteristico del termistore (3470)
Siccome, il legame tra la temperatura kelvin e gradi centigradi è il seguente:
K= °C + 273,15
Si ricava la temperatura del termistore:
Da cui dal partitore di tensione, si ha:
Per cui risolvendo rispetto alla Rt, otteniamo :
Supponendo che il termistore si trova esattamente alla temperatura di 25°C, esso assume un valore pari a quella di Rs,cioè 10KΩ, e si ottiene considerando che Vin = 3.3V:
Ipotizzando che il termistore deve essere utilizzato in un ambiente in cui il range di temperature sia pare a [-10°C,50°C],possiamo calcolare il valore della sua resistenza applicando la formula:
R-10°C = 47018,618 Ω
R50°C = 4064,112 Ω
E quindi la caduta di tensione sul termistore calcolata agli estremi del range di utilizzo è:
Se ne deduce che il range in cui varia la tensione che insiste sul termistore Vt è compreso nell’intervallo [0.95V, 2.72V]. Osservando le curve caratteristiche dell’ADC mostrate in precedenza, si comprende facilmente che dovendo utilizzarle nel tratto lineare, la scelta cade verso:
- una risoluzione a 12 bit;
- con una attenuazione 11Db.
Nella Figura 8, è indicato in giallo, l’area in cui la tensione varia:
Sebbene la curva relativa a 11db risulta essere affetta leggermente da rumore, questa resta congruente con il ragionamento condotto sino a questo punto, comunque è consigliabile lavorare con attenuazioni 2.5db/6db.
Schema di cablaggio
Il circuito di test, mostrato in Figura 9, è molto semplice:
- le due estremità del termistore vanno collegate una alla tensione +3.3V,l’altra estremità alla resistenza di = 10KΩ ;
- a sua volta nel punto di connessione con il resistore, va collegato alla GPIO 33 della scheda, e l’altra estremità a massa;
- infine in ultimo vanno collegati i fili per prelevare i 3.3V richiesti.
Sketch
Una volta assemblato il tutto, ed installata la libreria ESP32_ADC.zip indicata precedentemente, passiamo a commentare lo sketch di prova, scaricabile al seguente link ESP32_ADC_Test.zip.
Cominciamo osservando la parte iniziale:
/**************************************************************** ** File name: ESP_ADC_test.ino ** Descrizione: Misurazione della temperatura mediante ** un termistore ** Versione: 1.0 ** E-mail: [email protected] ** Autore: Salvatore Urciuolo ** Data: 06/06/2018 ****************************************************************/ #include <ESP32_ADC.h> // riferimento della libreria ESP32_ADC //creazione di una istanza dell'oggetto ADC di tipo ESP32_ADC ESP32_ADC ADC; //dichiarazione di variabili float Vs; float Rt; float tempC;
Poi la parte di inizializzazione:
void setup() { Serial.begin(115200); //si configura la velocità della seriale Serial.println(""); Serial.print(""); Serial.println(ADC.getVersion()); //configura ADC1 la risoluzione in bit //imposta il canale e la sua attenuazione //ed il numero di campioni necessari, nella fase di subsampling int iEsito= ADC.init(ADC_WIDTH_12Bit,ADC1_CHANNEL_5,ADC_11db,64); Serial.print("esito init ADC ="); Serial.println(iEsito); //pausa di almeno un secondo delay(1000); }
Ed infine la parte di elaborazione:
void loop() { //lettura della tensione ai capi della resistenza nota // di 10 KOhm Vs=ADC.readVoltage(); Serial.print("Valore letto dal canale ADC [V]: "); Serial.println(Vs); //calcolo della resistenza del termistore Rt = 10000.00*(3.30-Vs)/Vs; Serial.print("Resistenza termistore [Ohm]: "); Serial.println(Rt); //calcolo della temperatura rilevata dal termistore tempC = (3470./(log(Rt/10000.)+(3470./(298.15)))) - 273.15; Serial.print("temperatura [°C]: "); Serial.println(tempC); Serial.println("---------------------------------"); //si attende 5 secondi delay(5000); }
Conclusioni
Al termine della lettura di quest’articolo, saremo in grado di aggiornare con le dovute cautele, le librerie ufficiali ESP32 per arduino, da utilizzare per il nostro “espertino”, ma soprattutto si è acquisita una maggiore familiarità sull’utilizzo della parte relativa di ADC e di termistori. Spero che i concetti illustrati nell'articolo siano chiari e solo una base di partenza per applicazioni più complesse, magari arricchendo con altri elementi come led, buzzer, display... insomma basta dare via libera alla propria fantasia, per divertirsi con tanti altri avvincenti progetti.
Ciao, ottimo articolo. Nell’articolo dici che comunque è consigliabile lavorare con attenuazioni 2.5db/6db, ma come ti rapporti poi con la non linearità della curva?
Ciao Andrea !!!
In realtà la mia asserzione era riferita al fatto che per attenuazioni di 2.5db/6db abbiamo un tratto di curva perfettamente lineare, ciò però comporta un intervallo di variazione della tensione sul termistore più piccolo, e di conseguenza una riduzione del range di temperatura da poter misurare.
ok grazie per la risposta
Bellissimo articolo. Complimenti.
Vorrei sapere se la funzione ADC.readVoltage()
può essere rimpiazzata da quella proprietaria di ESPertino,
specificando ovviamente i parametri di bits, canale, attenuazione, ecc..
Grazie
Ciao Giovanni,
certamente è possibile rimpiazzarla con le api primitive di espertino, basta utilizzare un congruo numero di campioni per la fase di subsampling.
Ottimo articolo, complimenti. E’ sicuramente importante utilizzare sempre una versione aggiornata di Arduino Core per ESP32, come indicato nell’articolo, in quanto i fix e le commit sul branch Git sono tuttora in corso e molto frequenti. Come ho spiegato nelle mie lezioni del Corso Embedded, l’ambiente Arduino Core per ESP32 si appoggia direttamente sul framework ESP32 di EspressIf (ESP-IDF, un po’ più ostico da utilizzare per i principianti ma sicuramente più completo e performante). E’ un peccato che la funzione analogWrite non sia ancora stata implementata in Arduino Core.
Ciao Stefano,
ti ringrazio per i complimenti, e si …mi trovi perfettamente d’accordo sul fatto che vi sono continui fix sul branch Git. E’ da notare l’ottimo lavoro svolto dai tecnici di Espressif, che supportano continuamente l’ESP32.
Complimenti per l’articolo, davvero utile ed interessante.
Grazie Giancarlo,
mi fa molto piacere che è piaciuto anche a te !
Articolo molto istruttivo grazie, io credo di aver installato male la libreria che hai fatto (la scheda espertino new me la vede correttamente) tanto che in compilazione mi da un errore perchè non riesce a trovare un file pins_arduino.cpp…
Ad ogni modo ho fatto una prova senza le vostre librerie, sempre con il termistore NTC ed utilizzando come in un altro articolo del sig. Di Maria: analogSetAttenuation(ADC_11db); e analogReadResolution(12); e sembra che il letto da monitor seriale circa 1.32V sia lontano da quello reale ai piedi del temistore 1.48V. Diminuendo l’attenuazione il risultato peggiora, qualche suggerimento?
Grazie
Articolo semplice e preciso.
Vorrei chiedere, se per la misura della temperatura utilizzo una sonda tipo ni1000, quindi con valori di variazione di resistenza di circa 1000 +- 100 ohm, sono costretto ad amplificare il segnale?
Grazie