E' possibile usare il solo sensore AD590 con Arduino, senza ricorrere ad op-amp. alimentatori duali, trimmer e altri componenti? La risposta è affermativa, grazie a una tensione di riferimento ADC "segreta" presente in ogni microcontrollore di Arduino; ma occorre un piccolo accorgimento...
L'AD590 è sensore di temperatura a due terminali, che produce in uscita una corrente proporzionale alla temperatura assoluta rilevata. Esso offre ottime prestazioni in
termini di accuratezza (± 0,5 °C) e immunità ai disturbi in virtù del funzionamento in corrente e non in tensione. La sua caratteristica è quella di
fornire, linearmente, 1µA per ogni grado Kelvin rilevato.
Il suo range di misura è molto ampio: −55°C... +150°C . Grazie al fatto che fornisca una corrente proporzionale ai gradi Kelvin, quindi, anche le temperature negative saranno comunque descritte da correnti, e quindi tensioni, di
polarità positiva, il che si traduce in una semplificazione dei successivi stadi
di condizionamento.
L'AD590 può essere alimentato da +4 a +30V e richiede una
resistenza in serie di polarizzazione, che viene anche sfruttata per la necessaria conversione
corrente/tensione.
Per approfondimenti su altre caratteristiche e sulla tecnologia costruttiva, si rimanda al DATASHEET fornito dal Costruttore.
Per una tensione di alimentazione 5V, tipicamente si usa una R=1kΩ, per 12V o
15V, invece, il valore tipico di R è 10kΩ
Il costruttore consiglia di utilizzare un resistore di precisione (da 0,1% ), preferibilmente in serie a un trimmer, in modo da effettuare una taratura hardware in fase di messa a punto del sistema di misurazione:
Vedremo, più avanti, che è possibile usare un resistore fisso e raggiungere lo stesso scopo, via software.
Supponiamo di volere misurare una temperatura compresa fra 0°C e 100°C, usando una R=1kΩ avremo che per T=0°C (273K) ai capi della
resistenza si avranno 0,273V (1kΩ * 273µA), mentre a T=100°C (327K) si avranno 0,373V (1kΩ*373µA).
La dinamica (differenza fra tensione massima e tensione minima) è quindi di soli 0,1V. Volendo misurare questo range di tensione con
Arduino, si rende dunque necessario uno stadio differenziale e
amplificatore con op-amp, che porti il range 0,273...0,373V a 0....5V, in quanto
la tensione di riferimento dell'ADC interno è, di default, pari a 5V; diversamente, il quanto sarebbe molto elevato.
LA TENSIONE DI RIFERIMENTO INTERNA DI 1,1V DI ARDUINO
La soluzione alternativa al condizionamento con amplificatore differenziale è quella di usare una tensione di riferimento più bassa, più "vicina" all'estremo superiore della dinamica del sensore, in modo da ridurre l'errore di quantizzazione e quindi migliorare la risoluzione. Esistono in commercio diversi riferimenti di tensione esterni da 1,2V a 1,25V, ma vorremmo evitarli, sempre in un'ottica di rendere quanto più semplice possibile l'hardware.
Il microcontrollore della scheda UNO R3 (ATmega328) dispone di una tensione di
riferimento interna bandgap, pari a 1,1V nominali, che può essere convenientemente usata a tale
scopo.
Utilizzando una Vref=1,1V si avrà 1LSB teorico pari a circa 1mV e quindi una risoluzione di circa 1K/1°C, nel range indicato, che è sicuramente una specifica accettabile.
HARDWARE
Lo schema è riportato di seguito:
Essendo la resistenza di ingresso del pin dell'ATmega pari a 100 MΩ, la corrente Is del sensore è praticamente la stessa che circola anche nella resistenza da 1KΩ.
MISURA DELLA RESISTENZA R
Avendo usato una resistenza da 1kΩ, 1% (e non da 0,1% - ovvero un trimmer di regolazione - come suggerito dalla Casa costruttrice) occorrerà misurare il valore attuale della stessa per non introdurre un errore non trascurabile nel calcolo della corrente. Mediante un DMM 3 1/2 cifre e usando una portata di 2kΩ (è molto importante usare questa portata, per avere una misura quanto più possibile accurata), nel nostro caso è stato misurato un valore effettivo R=987 Ω. Questo valore è stato dunque assegnato alla costante R dello sketch; esso servirà per il calcolo della corrente Is (mediante la Legge di Ohm: Vs/R)
Per misurare la corrente Is, ci serve, dopo la resistenza, ovviamente la tensione Vs, cioè la caduta di tensione che si localizza ai capi della resistenza R di polarizzazione (precedentemente misurata) e che viene quindi applicata all'ingresso analogico di Arduino, per essere misurata.
Arduino misura la tensione Vs mediante la classica formula di ricostruzione dell'ADC, partendo dal presupposto che Vref sia effettivamente pari al valore nominale 1,1V; ma la tensione di riferimento interno, sebbene molto stabile, ha una tolleranza non trascurabile, cioè il valore effettivo si discosta da quello nominale di 1,1V (secondo il datasheet dell'ATmega il valore può variare, tipicamente, fra 1.0 e 1.2V).
E' stato, dunque, caricato ed eseguito su Arduino, propedeuticamente, uno sketch che misura l'effettiva tensione di riferimento, che determina l'effettivo valore e consente dunque di correggere la differenza fra valore nominale e valore effettivo dovuto alla tolleranza di fabbricazione.
SOFTWARE
N.B. Prima di caricare questo sketch occorre caricare - ed eseguire nel monitor seriale - lo sketch di "correzione" della tensione di riferimento interna, reperibile a questo post.
AD590.INO
/* Misura di una temperatura con Arduino Uno e sensore
* AD590 alimentato a 5V tramite una R=1kOhm,1% => 1mV/K
* Viene usato il fattore correttivo memorizzato
* sulla EEPROM, precedentemente calcolato e salvato.
*/
#include <EEPROM.h>
#define STAMPAVS 1 // 1 stampa VS
#define STAMPATK 1 // 1 stampa T in gradi K
const int EEADD=0; // ind. EEPROM dove è stato memorizzato il fatt. correttivo
const int AD590 = A0; // pin analogico a cui è collegato l'AD590
const int R = 987; // Valore attuale della Resistenza in serie all'AD590
const float VREF = 1.1; // VREF nominale ADC
float CAL; // fattore di correzione VREF: verrà letto dalla EEPROM
const int DELTA_T = 30000; // intervallo di misurazione in ms
int TC; // Temp misurata, in °C
int TK; // Temp misurata, in K
float Vs; // Tensione misurata (ai capi di R) da Arduino
float Is; // Corrente calcolata come Vs/R (in uA)
unsigned long counter=0; // progressivo misurazioni di temperatura
unsigned long prevMillis; // marcatore temporale per millis()
void setup() {
Serial.begin(9600); // Imposta rtx seriale a 9600bps (monitor seriale, PuTTY ecc)
analogReference(INTERNAL); // Vref interna =1,1V nominale
EEPROM.get(EEADD, CAL); // legge locazione EEADD e assegna valore a CAL
prevMillis=millis(); // marca istante iniziale
}
// Effettua una misura ripetuta di Vs:
float misuraVs() {
float somma=0; // somma delle letture singole di V
float vmedio=0; // media delle letture singole di V
float v; // lettura singola di V
int n; // numero restituito dall'ADC
int nlett=5; // quante letture
for (int i=0; i<nlett+1; i++) {
n=analogRead(AD590);
v=CAL*VREF*n/1024;
if (i>0) // scarto prima misura
somma=somma+v;
delay(50);
}
vmedio=somma/nlett; //calcola valore medio delle misure di tensione
return (vmedio); // ritorna la media della misure di I (in uA)
}
void loop() {
/* Misura e stampa periodica della temperatura ogni DELTA_T millisecondi: */
if(millis()-prevMillis >= DELTA_T) {
Vs=misuraVs(); //misura la Vs ai capi di R e l'assegna alla var. Vs
Is=1E6*Vs/R; //calcola Is, con la Legge di Ohm,e la converte in uA
TK = (int)Is ; //es. 298.00 diventa 298K
TC=TK-273; //es. 298K diventa 25°C
Serial.print(++counter);
#if STAMPAVS
Serial.print("\t");
Serial.print(Vs,3);
Serial.print("V");
#endif
#if STAMPATK
Serial.print("\t");
Serial.print(TK);
Serial.print("K");
#endif
Serial.print("\t");
Serial.print(TC);
Serial.println("°C");
prevMillis=millis();
}
/* altri compiti da eseguire: */
}VISUALIZZAZIONE STAMPA DATI
Lanciando il monitor seriale, sarà possibile visualizzare la stampa dei dati:


Nessun commento:
Posta un commento