Ho collegato all'arduino un sensore lm335a.
Tramite la porta seriale voglio visualizzare la temperatura rilevata dal sensore però lm335a da un valore in volt che bisogna poi trasformare in gradi celsius.
Eseguendo il seguente sketch sulla porta seriale viene visualizzato sempre il valore -107.46.
leo72:
Secondo me sbagli usando una variabile di tipo "int" (val) in un calcolo con float. Quindi il compilatore converte tutto ad int.
Metti
float val=0.0;
oppure modifica la formula in
gradiC = (((float(val) / 1023.0) * 5.00) - 2.7315) * 100.0;
ho provato a mettere float val=0.0 ma non cambia nulla.
Che forse abbia sbagliato a collegare i piedini dell' lm335 all'arduino?Sono solo agli inizi e mi capita di sbagliare
marco_993:
Qualcuno riesce a risolvere il mio problema? Grazie
Parto dal presupposto che hai collegato correttamente il sensore, fai riferimento al data sheet, la formula che usi per la conversione è inutilmente cervellotica e pesante da eseguire per Arduino, quando è possibile è sempre meglio evitare l'uso dei float.
Il tuo sensore fornisce una tensione con una variazione pressoché lineare in funzione della temperatura pari a 10 mV/k, il che vuol dire che la tensione è 0V a 0k (= -273.15 C°) e 2.7315V a 0 C°.
Per passare dai count ADC, circa 4.88 mV ciascuno, ai gradi Celsius basta eseguire questo semplice calcolo effettuato esclusivamente con valori interi (16 bit).
"Vadc = lettura ADC"
"Gr_celsius" = valore temperatura in gradi celsius
byte Gr_celsius
unsigned int Vadc
Gr_celsius = (Vadc*49 - 27315) / 100
Se vuoi la risoluzione al decimo di grado basta che dichiari Gr_celsius come int e dividi per 10 invece che per cento, il valore ottenuto è pari alla temperatura reale espressa in decimi di grado (20C° = 200), ti conviene tenere questo formato per le eventuali elaborazioni successive.
La divisione per 10 con risultato in decimali la fai solo prima di visualizzarlo su un display o tramite seriale, meglio ancora se invece di dividere per 10 per ottenere un float prima dividi per 10 e assegni il risultato ad una variabile, ed è la parte intera del valore, poi fai il modulo a 10 e lo assegni ad una seconda variabile, ed è la parte decimale, quindi formatti tu la stampa come parte intera + ","+ parte decimale.
Questi sono "trucchi" da programmatore esperto per velocizzare l'esecuzione dei programmi e ottimizzare l'uso delle risorse.
C'è qualcosa che non mi torna...per fare le operazioni con gli interi hai moltiplicato una variabile per 10 (4.88) e una per 100 (273.15), forse dovrebbe essere così:
Però sarebbero cifre "finte" dato che il limite sulla risoluzione lo da l'ADC di arduino, distinguendo al massimo circa 5mV da una risoluzione di mezzo grado.
Se fai l'equivalenza con l'ipotetica uscita del sensore, nella realtà non è possibile perché siamo oltre i limiti di misura:
5V / 10mV = 500K di variazione.
500 - 273.15k° = 226.85 C°
Tenendo conto che la precisione, e la linearità, del sensore è circa 1% il risultato ottenuto col mio calcolo è sufficientemente preciso rispetto all'ipotetica misura reale con un sensore ideale, tieni presente che per una temperatura massima di 100° l'errore del calcolo è minore a 1%.
Però sarebbero cifre "finte" dato che il limite sulla risoluzione lo da l'ADC di arduino, distinguendo al massimo circa 5mV da una risoluzione di mezzo grado.
Questo è vero, ma nulla vieta di usare l'oversampling per aumentare la risoluzione dell'ADC a 11, o meglio 12, bit portando la reale risoluzione fino 0.125C°, in questo caso va modificate la costante della prima moltiplicazione per tenere conto della maggiore risoluzione.
sono un pirla!! perché 4.88 mV sono 0.00488 V, quindi hai moltiplicato anche quelli per lo stesso fattore di scala con cui hai moltiplicato 2.7315!! Ops figuraccia...chiedo scusa
Avevo letto il thread dove avevi descritto l'oversampling...interessantissimo, da mettere in pratica!
Ma quindi per ottenere una risoluzione di 0.1K un'amplificazione del sensore di un fattore almeno 5 sarebbe lecita?
Per aumentare la reale risoluzione ci sono due modi possibili, il primo è traslare la tensione in uscita del sensore verso il basso, in funzione del reale range di misura, in modo da sfruttare completamente la dinamica del ADC.
Se prendiamo in considerazione che il 335 ha un range di misura tra -40C° e 100C° questo ci dice che la tensione in uscita varia tra 2.331V (-40C°) e 3.731V (100C°) pertanto se traslo 2.331V a 0V con un OpAmp e applico a Avref dell'ATmega una tensione di 1.4V ottengo una risoluzione di circa 0.14 C°.
In alternativa è possibile usare lo stesso OpAmp per amplificare di 3.57 la tensione e non utilizzare Avref, se poi il range da misurare è compreso tra 0C° e 100C° l'amplificazione diventa 5x, la risoluzione 0.1° reali, la tensione da traslare a 0V diventa 2.731V.
Il secondo metodo è l'oversampling, che non richiede nessun hardware esterno, il sensore è lento nella risposta quindi non ci sono problemi per campionare 4, o 16, volte per ogni lettura, è anche abbastanza rumoroso di suo per garantire l'applicabilità dell'oversampling per aumentare la risoluzione.
Come al solito si fa confusione tra precisione e risoluzione
Ho già detto prima che la reale precisione del sensore è circa 1%, però questo non toglie che la risoluzione può benissimo essere 0.1K se sono in grado di apprezzare variazioni di 1 mV.
Poi come usare al lato pratico i dati ottenuti dipende dall'applicazione che deve tenere conto del fatto che se leggo 20,4 C° in realtà può essere un qualunque valore compreso tra circa 19.9C° e 20.9C°, però questo errore è quasi costante su tutto il range di misura e se è possibile misurarlo tramite un termometro campione è anche possibile compensarlo.
La calibrazione serve esclusivamente per garantire la variazione di 10.000 mV/K, se non la si fa l'errore è maggiore perché la variazione non è 10 mV esatti per ogni grado, ma comunque quasi costante e compensabile da software.
p.s.
Ovviamente questo sensore non è per misure di alta precisione, se serve realmente il decimo di grado si usano sensori più precisi e, sopratutto, molto più costosi.
credo di aver sbagliato a collegarlo.
Allora al piedino sinistro lo collego a gnd sull'arduino al piedino centrale collego una resistenza da 10k e poi collego quest'ultima all'alimentazione e all'input analogico
che vuol dire che se gliene dai meno di 400µA non funziona bene, se gliene dai più di 5mA lo scaldi...e ovviamente non funziona bene.
con una resistenza da 10KOhm sei nella prima condizione, esempio per il calcolo:
tensione a 0°C = 2.7315V
Caduta di tensione sulla resistenza = 5V - 2.7315 = 2.27 (circa)
Valore della resistenza = Caduta di tensione sulla resistenza /corrente che scegli
supponiamo che ci piacerebbe far passare 1 mA, allora:
Valore della resistenza = 2.27 V /1mA = 2270 Ohm
con una resistenza di quel valore a 0°C scorre 1 mA
Ora, credo che per determinare un valore della resistenza che garantisca di stare entro il range di correnti sulla scala di temperature che vuoi misurarti, dovrai calcolare caso "basso" e caso "alto" e poi adottare una resistenza media.
Per il momento se metti una resistenza da 2.2K sei sicuro che funziona