Sari la conținut
ELFORUM - Forumul electronistilor

Citire temperatura/tensiune cu Vref


Postări Recomandate

Cum nu ma descurc, va trebui sa deschid un alt topic...incerc sa fac o citire pe intrarea RA0, a unui uC (PIC16F877), si ca mijloc de referinta sa fie un 2,5V de pe intrarea RA3....problema este ca nu ma descurc deloc...rog ajutor...partea de hw nu este o problema, ci doar soft...Motivul este cel din filmare...adica miscarea zecimalelor rapid la citire/afisare...

 

View My Video

Editat de catalin004
Link spre comentariu
  • Răspunsuri 24
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

Top autori în acest subiect

daca cond.de 2.2uF( cam mare dupa parerea mea) a ajutat un pic, inseamna ca ai ceva zgomot pe intrarea ADC.

Incearca sa pui un filtru trece jos pasiv cu 1 sau 2 poli( R=1k-2k + 1 cond. de 100nF) la intrarea ADC si vezi cum este.

Ptr.2 poli, R =1k

In extremis, incerci un FTJ activ( Sallen Key)

 

In cazul in care experimentezi pe un breadboard e normal sa ai zgomot, semnalul de citit fiind mic.

 

Daca nici filtrul nu ajuta, atunci revezi setarile ptr. ADC ( de exeplu intre 2 citiri treb. sa ai un delay de 2TAD min.)

Editat de tic5
Link spre comentariu

TAD= Timpul necesar conversiei A/D.ptr .1 bit. Valoarea minima =1,6us.

Daca ai intrebat despre TAD, recomand sa citesti si explicatiile despre timpul de achizitie necesar.Este posibil ca nici pe acesta sa nu-l fi ales corect.

 

Info. le gasesti clar explicate in DS pag.114 - 116.

Link spre comentariu

Pai eu cam asa il citesc...:

void get_ADC(){ 
static int i;
tmp = ADC_Read(1);              //Read ADC voltage  
tmp = 0;
//make an averrage for 10 reads
for(i = 0;i<10;i++){
                     tmp=tmp+ADC_Read(1);
                   }
tmp = tmp/10;
temp = ((long)tmp*4900)>>10;
}

void tempToStr(float, char*);
//buffer function for show float temperature
void tempToStr(float temp, char *buffer) {
  value = (int)temp;
  buffer[3] = value % 10+48;
  buffer[1] = value/10 % 10+48;
  buffer[0] = value/100 % 10+48;
}

void display_temp(){
tempToStr(temp, &strTemp);       // convert FLOAT to STRING
LCD_Out(1,4, "Temp=");
LCD_Out(1, 9, strTemp);          // show string value
LCD_Chr_Cp(223);                 //simbol character for degrees
LCD_Chr_Cp('C');                 //Celsius character to end of row
}}
Editat de catalin004
Link spre comentariu

Te rog hotareste-te ce fel de Vref folosesti: exerna sau interna.

Ai spus ca folosesti mikroc drept compiler.

In acest caz ADC_Read nu merge cu referinta externa(v. explicatiile din microc referitoare la ADC_Read )

 

Cand pui codul e bine sa dai si setarile ptr. ADCON. asa se poate vedea si ce folosesti.

Link spre comentariu

Faptul ca iti fluctueaza citirea intrarii ADC se poate atribui zgomotului fie ambiant fie celui generat de functionarea uC insusi. Cei pe AVRfreaks faceau la un moment dat o chestie, punand uC-ul in standby cat timp se faceau citirile ADC.

 

Folosind o referinta externa de 2.5V fata de o referinta de 5V, intr-adevar devine mai sensibila intrarea ADC citind trepte mai fine de tensiune doar ca pretul platit este o susceptibilitate mai mare la zgomot (practic tot intervalul ADC merge mai aproape de zona unde zgomotul este semnificativ). Se creste precizia de masurare daca se foloseste o sursa de referinta externa cu performante bune (invulnerabilitate la schimbarea temperaturii, la tensiunea de alimentare a referintei etc) dar zgomotul tot este prezent.

 

Dar, chiar daca folosesti o sursa de referinta externa, zgomot tot o sa ai.

 

Solutia este sa folosesti un filtru trece jos pe intrarea ADC, mediind astfel citirile pe intrare in domeniul timp. Acest filtru trece jos poate fi unul hardware sau poate fi unul software.

Sau folosesti tehnica de oversampling si la final arunci bitii obtinuti suplimentari de la LSB in sus.

 

Daca tot ce te deranjeaza este oscilatia foarte rapida a valorilor si faptul ca nu poti citi valoarea, atunci poti sa faci afisarea la un interval de timp, sa zicem afisezi valorile pe ecran de 4 ori pe secunda. Aceasta o faci cu un Timer asa cum cred ca am mai facut pe aici.

 

Nu am timp ca sa ofer implementari la ceea ce am sugerat mai sus, daca un coleg preia ideile cu atat mai bine.

Succes!

Editat de mars01
Link spre comentariu

Ba s-ar putea sa constati acelasi lucru. Si asta din cauza ratei mari de citire, data de bucla while. Foloseste un timer care sa-ti permita sa faca citiri de 2-4 ori pe secunda si sa actualizeze datele afisate

o sa incerc si acest lucru....adica la 250ms sa face ADC_Read, apoi sa actualizez display-ul la cat timp?1 secunda?

Link spre comentariu

Pseudocod:

Timr_ISR:
++tick_10ms;
if (tick_10ms=25) then flag_Adc=1;
if (tick_10ms =100) then update_data = 1;
end ISR

main:
while(1){
if (flag_Adc)
flag_Adc =0;
read_ADC();
if (update_data)
update_data=0;
tick_10ms=0;
old_data = new_data;
refresh_display(old_data);
}

Cam asa ar trebui sa arate programul.
Si 4880 reprezinta valoarea LSB = 1/1024 = 4.88mV x 1000, pentru a nu lucra cu variabile de tip float.
Si este 1024, nu 1023 cum am vazut scris eronat in muuulte locuri pe net, deoarece sunt 1024 de valori, de la 0 la 1023.

Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări