Sida 1 av 3
Fråga angående ADC på en PIC12F675
Postat: 14 juni 2008, 18:29:47
av unzuf
Hej! Jag har precis börjat experimentera lite med ADC på en PIC12F675. Har bland annat en temperatursensor (MCP9701) som ger ut 19,5 mV/C°.
Det jag undrar är hur man med ADC'n kan veta hur många volt som ligger på ADC-pinnen? Om jag t.ex lägger 3 volt på pinnen, hur representeras det värdet i binärt tal?
Ursäkta om det är luddigt skrivet, och tack för eventuell hjälp!

Postat: 14 juni 2008, 18:52:47
av strombom
Det beror på a/d omvandlarens upplösning samt dess spänningsreferens.
Spänningen = Spänningsreferens / upplösning * mätvärde
I ditt fall är spänningsreferensens värde förmodligen samma som matningsspänningen, 5V ?
Upplösningen på PIC12F675 är 10 bitar = 1024 steg, om du inte har ställt om den.
Spänning = 5V /1024 * mätvärde
Postat: 14 juni 2008, 18:54:17
av thepirateboy
Det beror på vad du har för upplösning på AD-omvandlaren och vilken referensspänning. Vid 10 bitars ADC och 5 volt referens motsvarar 5 volt 1024 bitar. 3 volt motsvarar då 614 bitar.
Postat: 14 juni 2008, 18:54:46
av Icecap
Nästan alla µC har en ADC där referensspänningen är VDD, vissa kan väljas till lite andra alternativ. Om vi utgår ifrån att VDD är 5V och Vref, att ADC'n kör med 10 bit och att de kommer in 3V är resten enkelt:
("Avläst värde" * 1000*VDD)/1024 = inkommande spänning i mV
Edit: "3 volt motsvarar då 614 bitar"... oh fan, jag trodde att ADC'n hade 10 bit...
Menar du kanske att det avlästa värde skulle bli 614?
Hmmh... räkna lite... 614*1000*5 = 3070000, dela sedan med 1024 = 2998mV
Verkar passa.
Glöm dock inte att lägsta upplösning är 5V/1024 = ~4,88mV
Postat: 14 juni 2008, 19:00:30
av thepirateboy
Ja sorry, det var felformulerat.
Postat: 14 juni 2008, 19:01:52
av sodjan
Notera att 5V / 19,5 mV = ca 256.
Så varje steg på en 10-bitars ADC (1024 steg) är alltså 0.25 deg C.
Finessen med att ha just 19,5 mV/dec C är att det blir enkelt
att "översätta" att binärt värde från ADC'n (vid 5V) utan större
beräkningar.
Dividera värdet från ADC'n (d.v.s shifta två steg höger) så har du
värdet i degC.
Så i det här fallet så är det komplett ointressant vilken den
faktiska spänningen på ADC'n är, genom att de har valt
just den "lutningen" på temp-givaren...
Postat: 14 juni 2008, 19:18:09
av unzuf
Oj, många svar på kort tid! Tack så mycket ni som skrivit, detta hjälper mig oerhört! Ska experimentera vidare och hoppas på bättre lycka den här gången
Edit: Och ja, det stämmer, referensen är samma som VDD.
Postat: 14 juni 2008, 19:24:11
av Marta
Var uppmärksam på att denna sensor inte är något precisionsinstrument!
Databladet säger +/- 1 grad typisk avvikelse, men +/- 4 (ojdå!) grader maximum avvikelse för modellen utan "A" på slutet. Med "A" är den "endast" 2 grader....
För att ha något så när garanterad noggrannhet måste Du kalibrera. Som minst en offset, det räker för att ha den som rumstermometer. Skall den användas över ett större temperaturområde behövs nog en kalibreringsabell.
Postat: 14 juni 2008, 20:39:36
av unzuf
Hmm.. vet inte om jag gör rätt.
Såhär ser kodraden som läser ADC'n ut (mikroPascal):
temp := (5000 / 1024 * Adc_Read(2)) shr 2;
Så, låt oss säga att jag vill detektera när temperaturen
är uppe i 35 grader. Ska jag då dividera temperaturen
jag vill känna av med antalet grader per steg (som
sodjan skrev)?
Alltså: 35 / 0,25 = 120 steg.
Eller är jag helt fel ute..?
Postat: 14 juni 2008, 20:47:12
av sodjan
Vad händer då ?
Börja med att bara läs av ADC'n.
Gör sedan några enkla tester på värdet.
När du vet hur det fungerar kan du komplettera
med resten av koden.
Postat: 14 juni 2008, 21:10:34
av unzuf
Jag har i nuläget inget bättre sätt att analysera ADC-värdet än att spara värdet i det interna EEPROM'et och sedan läsa av med Wisp628.
Men hur menade du med att "shifta två steg höger"? Menar du ADC-värdet som det är, eller efter man har gjort beräkningen med spänningsreferensen som strombom och Icecap skrev?
Postat: 14 juni 2008, 21:22:18
av Icecap
Och här kommer det ett annat problem som jag har upplevd ofta:
temp := (5000 / 1024 * Adc_Read(2));
Detta blir fel!
Gör såhär:
unsigned long Calc; (Vad det nu heter i Pascal, en 32-bitars variabel utan förtecken)
Calc := ADC_Read(2);
Calc := Calc * 5000;
Calc := Calc shr 10; ' Samma som att dela med 1024
Temp := Calc;
Orsak:
När ADC_Read(2) utföres är resultatet ett WORD (16 bit utan förtecken). Om man då multiplicerar direkt kan resultatet bli 5.115.000 vilket ju är "liiiite mer" än vad en 16-bitars variabel kan innehålla, resten blir kastat bort.
Vid att överföra till en 32-bitars variabel FÖRST och sedan räkna kommer all "matten" att vara i 32-bit storlek, när man sedan överför till Temp blir det 16 bit igen men då är det lugnt ju.
Postat: 14 juni 2008, 21:24:02
av sodjan
ADC värdet.
D.v.s en division med 4, men shiften är effektivare.
Man nu kör du ju inte assembler, så jag hoppar av här...
Lycka till.
Postat: 14 juni 2008, 21:49:42
av unzuf
Icecap: Tack så mycket! Dessvärre verkar det inte spela någon roll hur jag än gör så funkar det inte

Efter din beräkning, innehåller då variabeln temp temperaturen i grader celcius eller är det "steg" om 0,25 C° som sodjan pratade om?
Såhär ser koden ut:
Kod: Markera allt
var
temp : word;
calc : longint;
begin
calc := Adc_Read(2);
calc := calc * 5000;
calc := calc shr 10;
temp := calc;
if temp > 35 then SetBit(GPIO, 5) // Tänd LED om temperatur > 35 C°.
end.
Detta kanske är fel?
Ska det kanske vara
140 = Antalet 0,25-steg.
Hur jag än gör så lyser den j**la LED'en ändå

Postat: 14 juni 2008, 22:07:03
av sodjan
Ta det lungt...

Du har ju precis *börjat* felsöka.
Självklart at det inte fungerar än...
Börja med att ta reda på vilket värde du får från ADCn.
När det inte fungerar så är det ingen bra ide att försöka
göra allt på en gång. Ta ett steg i taget, få det att fungera
(och förstå det), ta sedan nästa. Börja med att verifiera att
du får rimliga värden från ADCn alls...
Som sagt, bara helt vanlig gammaldags felsökning.