Sida 1 av 2
AVR AD-omvandlingsfråga
Postat: 30 januari 2006, 14:39:12
av mrhedin
Tja!
Jag har exakt 1V på en AD-ingång på min Atmega8. Jag kör med intern 2.56V referens med inget kopplat till AVCC eller AREF. Jag sparar den höga byten i AD-resultatet i EEPROM och skickar seriellt till datorn.
Problemet är att jag får värdet "78" vid 1V och inte "100" som jag borde få.
Dessutom om jag höjer spänningen så minskar värdet.
Vad har jag gjort fel?
Postat: 30 januari 2006, 15:22:39
av sodjan
Med reservation för att jag inte är uppdaterad på ADC'n
i AVR...
Är "78" och "100" HEX eller DEC ?
Hur många bitar har ADC'n ? 10 ?
Varför borde det bli just "100" ?
Om ADC'n har 10 bitar, så kan väll "höga byten"
aldrig bli varken "78" eller "100" ?
En annan sak är att 78 (dec) delar med 2.56 är nästan exakt 200 (dec),
vet inte om det har någon betydelse dock, bara en reflexion...
> Vad har jag gjort fel?
Vi får väll konstatera att någonting *är* fel först...
EDIT : "78 (dec) gånger 2.56", skall det vara...
Postat: 30 januari 2006, 15:51:39
av mrhedin
Tja!
78 är i DEC.
Vart jag fick "100" ifrån är från följande resonemang:
ADC:n är på 10 bitar och har referensen 2.56V.
2.56V / 2^10 = 2,5mV minsta ändring.
Minsta ändring resulterar i att 64 skrivs i ADC:ns resultatregister.
Detta för att 10 bitar skall passa in i ett 2 x 8 bitars register.
1V / 2,5mV innebär att vi har "400" minsta ändringar x 64 = 25600 i hela 16 bitars registret.
Höga byten är 256 gånger större än låga byten vilket ger att 25600 / 256 = "100".
Men jag får 78 som sagt. Jag har grejat med ADC:n förut utan att egentligen stöta på några problem så jag är rätt konfunderad nu. Jag tror jag har fel nån annan stans i seriellöverföringen eller nåt. Kanske har fel värden i UBRRH och UBRRL.
Hur gör man sånt?
Om jag skall ha 2400 baud med 8MHz klocka så skall jag skriva in värdet 207 i UBRR. UBRR består av UBRRH och UBRRL.
I min C-kod har jag bara skrivit UBRRH = 0 och UBRRL = 207. Det kanske är fel?
Postat: 30 januari 2006, 16:30:00
av matseng
För att se om baudratren och seriekommunikationen lirar som den ska är det väl bara att lägga in en utskrift typ "Allan tar kakan i 2400 baud" i början på programmen och sedan köra hypertem i pc'n? Snabbt och enkelt har du uteslutit en möjlig felkälla,
Postat: 30 januari 2006, 16:32:41
av speakman
Det finns en himla fin tabell i databladet över baudrates.
Dom stämmer förvisso inte hos mig, men jag tror jag har nått generalfel i min tiny2313.

Men dom bör ju stämma, så det är bara å prova.
Mvh
speakman
Postat: 30 januari 2006, 16:44:31
av mrhedin
Vänta nu, jag är fan ett skämt =)
Jag glömde koppla en max233:a mellan. Jag ställer mig i skamvrån ett halvår =) om det jävlat räcker...
Postat: 30 januari 2006, 17:11:43
av sodjan
> Minsta ändring resulterar i att 64 skrivs i ADC:ns resultatregister.
> Detta för att 10 bitar skall passa in i ett 2 x 8 bitars register.
Fungerar verkligen ADC'n i AVR så ??
D.v.s att resultat "skalas upp" från 10 bitar till 16 bitar ?
Eller har det med left/right justering att göra ?
Normalt, om man har 10 bitar, så används 8 bitar från
den "låga" byten, och *2* bitar (de "minsta") från den "höga" byten.
Om däremot resultatet är justerat så att man använder 8 bitar
från höga delen och 2 bitar (sannolikt då de två högsta bitarna)
från den låga byten, så finns det en viss logik i det du skriver.
Men, som sagt, jag är inte helt uppdaterad på AVR ADC'n...

Postat: 30 januari 2006, 17:27:11
av karlstedt
Ett adc-resultat i AVR blir aldrig mer än just 10 bitar.
Vid left adjust ligger de 8 mest signifikanta bitarna i höga registret och de två minst signifikanta bitarna ligger i de två msb i det låga registret.
vid right adjust ligger de två mest signifikanta bitarna på de två minst signifikanta positionerna i det höga registret och resten ligger i det låga registret.
Postat: 30 januari 2006, 17:38:41
av mrhedin
Jo, jag håller med er om att så där står det i databladet och jag kan inte förstå varför det inte verkar fungera så.
Testa att koppla upp en lcd och se vad som kommer ut från ADCL respektive ADCH när ni varierar spänningen på ingången.
ADCL kommer att visa värden "0, 64, 128, 192" och
ADCH "0 - 255"
0 i ADCH är 0V och 255 är när ingången blir samma som AREF.
Detta är när jag har vänsterjusterat resultat och det kanske är en slump att det blir så här men jag skulle gärna vilja veta varför för jag är klart förbryllad...
Kanske har att göra med hur man läser ut resultatet? Efter en adomvandling tar jag ut värdet till 2 globala unsigned int med:
adc_lagbyte=ADCL;
adc_hogbyte=ADCH;
Postat: 30 januari 2006, 17:49:29
av karlstedt
Varför har du resultatet vänsterjusterat om du tänker använda 10 bitar?
Postat: 30 januari 2006, 17:55:33
av sodjan
karlstedt, helt logiskt och stämmer precis med hur PIC'arna justerar resultatet.
Mitt intryck är att *right* adjust är det vanligaste om man vill ha alla 10 bitarna.
Left adjust är praktiskt om man bara vill ha en 8-bitars resultat, eftersom
de 8 högsta bitarna hamnar direkt i höga registret, däremot är left adj lite
opraktiskt om man vill ha alla 10 bitarna...
mrhedin > Detta är när jag har vänsterjusterat resultat och det kanske är en
slump att det blir så här men jag skulle gärna vilja veta varför för jag är klart
förbryllad...
Vad är förbryllande ?
Men som sagt, om du *vill* använda alla *10* bitarna så är det betydligt mer
logiskt att använda right adjust...
Postat: 30 januari 2006, 18:02:49
av mrhedin
Jaha, nu tror jag jag ser hur det funkar. Men vill man använda alla 10 bitarna är väl left adjust smart?
Men jag hänger nog med på hur ni tänker ändå, att det känns mer logiskt å fylla på från första biten och ha de 2 mest värda bitarna för sig.
Postat: 30 januari 2006, 18:08:08
av karlstedt
>Men vill man använda alla 10 bitarna är väl left adjust smart?
Vad är det för smart med det?
Postat: 30 januari 2006, 18:15:08
av monstrum
Jag tycker det känns extremt logiskt att om man vill ha 10 bitars upplösning så kör man högerjustering och så läser man direkt ur 16-bitars-registret och får då ett tal mellan 0-1023.
(För att få tag i vilket spänningsnivå detta motsvarar tar du helt enkelt kvoten mellan det utlästa värdet och 1023 och multiplicerar med referensspänningen.)
Obs om du programmerar direkt i assembler! Tänk på att du måste läsa det höga registret först om du vill vara säker på att det ska bli rätt, detta för att AVR:en latchar 16-bitars-registrets låga byte då den höga läses. Läser du i omvänd ordning kommer den låga byten från föregående sample att ligga kvar till nästa och det kan ställa till det lite.
Postat: 30 januari 2006, 18:29:32
av sodjan
> Men vill man använda alla 10 bitarna är väl left adjust smart?
Snarare osmart. Det blir bökigare att ta hand om det hela...