Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Problema configurazione sensore AVR

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[1] Problema configurazione sensore AVR

Messaggioda Foto UtenteLesStrato » 22 nov 2012, 1:15

Salve gente,
scrivo per segnalarvi un problema riscontrato con il rilevamento di un segnale di tensione con un sensore. Sto lavorando in assembly con un mcu dell'Atmel. Ho settato un display lcd secondo il datasheet dell'hd44780 e dopo qualche piccolo problemino ha funzionato , riesco ad inviare qualunque frase e lui me la mostra. Il problema sorge con l'invio dei dati rilevati da sensore , un comunissimo lm35dz con range [0-100]°C , l'lcd non mi mostra la temperatura rilevata. Non è un problema dell'lcd perché esso funziona con qualunque dato inviato. Il sensore è apposto , ho controllato all'oscilloscopio. L'intero circuito non fa una grinza , i collegamenti sono esatti e come da datasheet. Credendo fosse un problema di potenza del segnale, avevo anche pensato di porre tra sensore e porta dell'adc un operazionale ma neanchè tale soluzione non fu valida. Ergo , il problema sta nel settaggio dell'adc. Il main del programma è il seguente:

ciclo:
rcall posiziona_cursore
rcall invia_temperatura
rjmp ciclo

La prima label non fa altro che posizionare il cursore all'indirizzo della ddram desiderato , mentre nella seconda invio in tale posizione la temperatura contenuta nel registro ADCH (il risultato è left adjusted per cui non prendo in considerazione il registro ADCL).
Ovviamente non posso inviare in maniera diretta ADCH sul bus dati dell'lcd , per cui ho scritto delle linee di codice di compare-branch che mi sdoppiassero il risultato della conversione , contenuto nel registro , in decine e unità in maniera tale da inviare un dato per volta (giusto no???). Un mio dubbio è il seguente: sul datasheet dell'lm35dz ho letto che ad 1°C corrispondono 10mV , per cui se ho 250 mV avrò una temperatura di 25°C. Alla fine di ogni conversione ho il dato (stringa di bit) in ADCH ma tale risultato è ancora una tensione (ad esempio 270mV) o è già un valore di temperatura (cioè 27°C)? perché se così fosse prima di effettuare le operazioni di compare-branch dovrei dividere il valore della conversione per 10, capite cosa intendo dire?
Per il resto non saprei , sul datasheet del mcu ho letto che l'inizializzazione dell'adc prevede il settaggio dei due registri ADMUX e ADCSRA , io li ho settati così:
ADMUX:
REFS0 = 1 , REFS1 = 0 ; tensione di riferimento 5V con condensatore sul pin di aref
ADLAR = 1 ; risultato left-adjusted
MUX[0-4] = 0 ; acquisizione single-ended da ADC0
ADCSRA:
ADEN = 1 ; abilitazione dell'adc
ADSC = 1 ; inizio conversione
ADATE = 0 ; no auto-trigger
ADIF = 1 / ADIE = 1 ; abilitazione degli interrupt
ADPS[0-1] = 0 / ADPS2 = 1 ; fattore di prescaler = 16 (La freq.del sistema è 4MHz per cui la freq.dell'adc sarà 250kHz).

Ho anche settato la modalità di sleep per l'adc reduction noise. Ogni conversione dura 25 cicli di clk a 250kHz sono circa 100uS , per cui mi son creato una routine di delay che richiamo appena pongo ADSC = 1.
Non riesco proprio a capire cosa c'è che non va , spero in qualche prezioso chiarimento :ok:
Avatar utente
Foto UtenteLesStrato
-13 3
 
Messaggi: 35
Iscritto il: 20 mar 2012, 23:48

0
voti

[2] Re: Problema configurazione sensore AVR

Messaggioda Foto Utentecyclone » 24 nov 2012, 13:16

Ciao,
Vuoi apprezzare il 1/2 grado o ti basta la risoluzione di un grado centigrado.

Nel caso in cui vuoi apprezzare il /2 grado dovresti effettuare le seguenti operazioni:

-acquisire il segnale
-moltiplicare *5 il valore acquisito
-calcolare il modulo 10
-dividere *10
-visualizzare sul display la parte intera, [punto], la parte decimale.

pseudo codice:
V = Getadc(0)
volt = V * 5
Volt_d = volt Mod 10
volt = volt / 10
Print volt ; "." ; Volt_d


ciao
Avatar utente
Foto Utentecyclone
86 2
New entry
New entry
 
Messaggi: 64
Iscritto il: 6 feb 2012, 11:38

0
voti

[3] Re: Problema configurazione sensore AVR

Messaggioda Foto UtenteLesStrato » 25 nov 2012, 3:34

Grazie per aver tentato di risolvere il problema, ma non ci siamo...intanto non mi interessa la parte decimale, vorrei visualizzare solo interi...mi sa tanto che ho commesso un errore non nel settaggio dell'adc , ma nella manipolazione del dato convertito e contenuto in ADCH. Intanto dopo ogni conversione mi copio il risultato in un registro temporaneo su cui svolgerò delle operazioni prima dell'invio su lcd:

.def temp = r16
..................
in temp , ADCH

Il risultato della conversione è , come da datasheet:

ADC = (Vin*1024)/Vref

io utilizzo Vref = 5V ; come già detto il sensore rileva 1°C ogni 10mV (0.01 V) , per cui avrò:
ADC = (0.01*1024)/5 = 2.048
questo significa che se la temperatura esterna è 20°C , cioè 0.2 V , in ADCH avrò all'incirca il valore 40 che è il doppio di 20 giusto? Quindi le operazioni dovrebbero essere:

- prendere il valore il ADCH
- dividerlo per 2
- scindere il risultato in decine e unità
- inviare i 2 dati separati all'lcd

...scusate se ho detto eresie , il ragionamento pare che fili anche se potrei aver dimenticato qualche particolare...
Avatar utente
Foto UtenteLesStrato
-13 3
 
Messaggi: 35
Iscritto il: 20 mar 2012, 23:48

0
voti

[4] Re: Problema configurazione sensore AVR

Messaggioda Foto Utentexyz » 25 nov 2012, 13:55

Scusa ma leggi un valore a 8 bit ADCH e poi usi 1024 (2^10) come se il dato fosse a 10 bit, non va bene.

Ti consiglio di leggere il valore a 10 bit (devi configure ADC in modo corretto) in modo da avere la massima precisione possibile e leggere 2 valori a 8 bit contenuti in ADCH e ADCL.

Il numero \[\frac{0.01\,1024}{5}=2.048\] lo puoi approssimare con \[\frac{33}{16}=2.0625\] con un errore di \[1.45\,{10}^{-2}\].

Il vantaggio dell'ultima frazione basta moltiplicare per 33 e la divisione per 16 è uno shift di 4 bit a destra.

LM35 genera tensioni molto basse per le temperature ambiente, se usi come riferimento del ADC 5 V perdi molto di dinamica, consiglio di mettere un circuito analogico per amplificare il segnale in modo da far coincidere la temperatura massima con i 5 V o quasi (per temperature sotto zero le cose si complicano).
Avatar utente
Foto Utentexyz
6.864 2 4 6
G.Master EY
G.Master EY
 
Messaggi: 1778
Iscritto il: 5 dic 2009, 18:37
Località: Italy Turin

0
voti

[5] Re: Problema configurazione sensore AVR

Messaggioda Foto UtenteLesStrato » 25 nov 2012, 14:23

:shock: xyz chiedo umilmente scusa per averla sparata grossa...hai perfettamente ragione , se leggo solo ADCH sto lavorando ad 8bit e quindi non dovrei considerare 1024 ma 256 :ok: così però (sempre utilizzando Vref = 5V) otterrei la risoluzione del mezzo °C , cioè se la temperatura è ad esempio 20°C avrei ADC = 10.24 , circa la metà , dovrei quindi prendere il valore in ADCH e moltiplicarlo per 2 e poi scinderlo in unità e decine.
Come dici tu però è anche vero che lavorando ad 8 bit perderei di precisione , dovrei quidi impostare ADLAR = 0 e leggere anche ADCL? Poi però con due registri non ho idea di come fare a inviare il dato...
Avatar utente
Foto UtenteLesStrato
-13 3
 
Messaggi: 35
Iscritto il: 20 mar 2012, 23:48

0
voti

[6] Re: Problema configurazione sensore AVR

Messaggioda Foto Utentexyz » 25 nov 2012, 18:07

Di solito chi vuole leggere una temperatura vuole la massima precisione possibile. Il micro controllore ha ADC da 10 bit, usalo se sei in grado di farlo.

Se imposti ADLAR a zero hai i registri ADCL e ADCH con un numero 16 bit con i 2 bit più significativi in ADCH. Il datasheet spiega come leggere e scrivere valori a 16 bit utilizzando i soli registri a 8 bit, il paragrafo si intitola "Accessing 16-bit Registers". L'ordine è importante, non devi mai invertire altrimenti rischi di leggere un valore errato.

Il dato è un valore a 16 bit, puoi usare 2 registri o salvarlo nella RAM.
Avatar utente
Foto Utentexyz
6.864 2 4 6
G.Master EY
G.Master EY
 
Messaggi: 1778
Iscritto il: 5 dic 2009, 18:37
Località: Italy Turin

0
voti

[7] Re: Problema configurazione sensore AVR

Messaggioda Foto UtenteLesStrato » 25 nov 2012, 18:53

Si si , so come leggere un dato da 16bit tramite 2 reg a 8bit e so anche che l'ordine è importante. Se metto ADLAR = 0 , a fine conversione dovrei fare ad esempio:

in r16 , ADCL
in r17 , ADCH

così ho un dato a 10bit. Il mio problema non sta nel leggere il dato , forse non mi sono spiegato bene... Il punto è che ho un sensore con range 0-100°C e vorrei visualizzare la temperatura rilevata su lcd ma senza cifre decimali , cioè vorrei vedere solo numeri interi tipo 10°C , 20°C , 25°C ecc ecc...
Il problema mio sta nella manipolazione del dato di fine conversione , se ad esempio la temperatura esterna è 20°C , con Vref = 5V , con 10bit (1024) e considerato che l'lm35 associa ad ogni °C 10mV , avrei ADC = 40.96 è quello 0.96 che mi da problemi ed in generele ogni parte decimale...se invece avessi ADC = 40 prenderei il dato , lo dividerei per 2 , lo scinderei in decine ( 4 ) e unità ( 0 ) e sarebbe fatta! Non riesco a capire come manipolare il risultato finale per inviarlo su lcd :(
Avatar utente
Foto UtenteLesStrato
-13 3
 
Messaggi: 35
Iscritto il: 20 mar 2012, 23:48

1
voti

[8] Re: Problema configurazione sensore AVR

Messaggioda Foto Utentexyz » 26 nov 2012, 18:31

ADC ritorna un numero intero, la parte decimale non esiste, il numero letto è ± 1 la parte intera, quindi per per 20 °C il valore letto è 40 o 41.

Il tuo problema è come calcolare la temperatura dal valore del ADC utilizzando solo e esclusivamente le risorse del micro controllore.

La formula da utilizzare è questa:

\[T=\frac{5}{1024\,0.01}\,ADC\]

dove ADC è il valore a 10 bit del ADC.

semplificata:

\[T=0.48828125\,ADC\]

Il numero può essere approssimato con \[\frac{1}{2} = 0.5\]. La divisione per 2 la puoi fare con una rotazione a destra dei bit, facile e poco costosa.

Con la frazione \[\frac{31}{64}=0.484375\] il calcolo è leggermente più preciso. La divisione per 64 è una rotazione a destra di 6 bit.

Utilizzando le frazioni continue è possibile ricavare il numero razionale:

\[\frac{1}{2+\frac{1}{20+\frac{1}{1+\frac{1}{5}}}} = \frac{125}{256} = 0.48828125 \]

La divisione per 256 è semplicemente il byte alto scartando il byte basso (è come ruotare a destra di 8 bit).

Vedo che usi assembler, in C la AVR-libc ha il codice per il float-point software, si utilizza la libreria matematica, occupano parecchio spazio nella flash e sono molto lente ma qui il calcolo è molto semplice.

Il numero a 16 bit con la temperatura deve essere convertito in una rappresentazione con caratteri ASCII per essere poi visualizzato con un display HD44780. Ci sono anche qui più strade, di tratta sostanzialmente di una serie di divisioni per dieci per ottenere il resto. Un esempio in assembler per AVR si può trovate qui:

http://www.avr-asm-tutorial.net/avr_en/ ... RSION.html

In C basta usare una funziona della libreria standard per I/O la "sprintf", si stampa in un buffer di char e si inviano i caratteri ottenuti al display.

Come ultima cosa per filtrare eventuali errori nella lettura della temperatura di solito non si utilizzano direttamente i valori letti dal sensore ma si effettuano una serie di letture in un determinato tempo e poi si effettua una media sul periodo.
Avatar utente
Foto Utentexyz
6.864 2 4 6
G.Master EY
G.Master EY
 
Messaggi: 1778
Iscritto il: 5 dic 2009, 18:37
Località: Italy Turin

0
voti

[9] Re: Problema configurazione sensore AVR

Messaggioda Foto UtenteLesStrato » 26 nov 2012, 22:31

Grazie xyz veramente chiaro e gentilissimo :D
xyz ha scritto:ADC ritorna un numero intero, la parte decimale non esiste, il numero letto è ± 1 la parte intera, quindi per per 20 °C il valore letto è 40 o 41.

questa si che è una bella notizia :ok: non avevo proprio idea di come lavorare con i numeri con la virgola in assembly.
xyz ha scritto:Il tuo problema è come calcolare la temperatura dal valore del ADC utilizzando solo e esclusivamente le risorse del micro controllore

Ti riferisci a quel circuito analogico esterno che mi consigliavi nello scorso post? Cioè dovrei ad esempio montare un circuito d'amplificazione costituito da un operazionale con un guadagno preciso dato dal rapporto di resistenze di precisione all'1% ?
xyz ha scritto:Vedo che usi assembler, in C la AVR-libc ha il codice per il float-point software, si utilizza la libreria matematica, occupano parecchio spazio nella flash e sono molto lente ma qui il calcolo è molto semplice.

-.- purtroppo si uso l'assembly , ma non per scelta mia , avrei utilizzato C senza pensarci due volte. In assembly anche i progettini più banali diventano un macello da gestire.
Vorrei fare un paio d ultime domande se possibile:

1) Se mi dici che per 20°C il valore in ADC è o 40 o 41 , c'è un modo per saperlo con certezza? Si ha un approssimazione per eccesso o difetto? :?

2) La formula inversa che mi hai dato ovviamente è valida solo se ADLAR = 0 e lavoro a 10bit vero? Se decidessi di lavorare a 8bit (per comodità perché ripeto che gestire certe cose in assembly non è semplice) dovrei utilizzare : T = \frac{5}{256\cdot 0.01}\cdot ADC = 1.953125 con ADC valore ad 8bit contenuto in ADCH dico bene?
Se si , potrei approssimare ad esempio con la frazione: \frac{39}{20} = 1.95 per la divisione per 20 potrei utilizzare uno shift a destra , in assembly esiste il comando: " lsr registro " uhm quanti shift in questo caso?
Eh si :( una volta manipolato il dato so bene che mi toccherà convertirlo in ascii -.- mannaggia.
Avatar utente
Foto UtenteLesStrato
-13 3
 
Messaggi: 35
Iscritto il: 20 mar 2012, 23:48

0
voti

[10] Re: Problema configurazione sensore AVR

Messaggioda Foto Utentexyz » 27 nov 2012, 19:20

LesStrato ha scritto:Ti riferisci a quel circuito analogico esterno che mi consigliavi nello scorso post? Cioè dovrei ad esempio montare un circuito d'amplificazione costituito da un operazionale con un guadagno preciso dato dal rapporto di resistenze di precisione all'1% ?

Quello o altre soluzioni servono per migliorare la dinamica di lettura. I Componenti al 1% con una calibrazione precisa successiva possono essere evitati.

LesStrato ha scritto:1) Se mi dici che per 20°C il valore in ADC è o 40 o 41 , c'è un modo per saperlo con certezza? Si ha un approssimazione per eccesso o difetto? :?

Con una sola lettura no, devi fare delle media di letture successive o usare un ADC con più bit.

LesStrato ha scritto:2) La formula inversa che mi hai dato ovviamente è valida solo se ADLAR = 0 e lavoro a 10bit vero?
...


La forma è per i 10 bit è in funzione del numero 1024.

Usare ADC a 8 bit riduci ulteriormente la dinamica in lettura, già quella a 10 bit è molto bassa.

Dividere per un numero non potenza di 2 in assembler non è facile servono molte righe di codice. Se usi le frazioni continue trovi la seguente rappresentazione esatta:

\[1+\frac{1}{1+\frac{1}{20+\frac{1}{3}}} = \frac{125}{64} = 1.953125\]

il denominatore è una potenza di due quindi la divisione è un semplice shift di 6 bit.
Avatar utente
Foto Utentexyz
6.864 2 4 6
G.Master EY
G.Master EY
 
Messaggi: 1778
Iscritto il: 5 dic 2009, 18:37
Località: Italy Turin

Prossimo

Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 19 ospiti