Konstig ADC-MUX ATmega88

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
övrigt
Inlägg: 208
Blev medlem: 19 april 2008, 14:18:11
Ort: Lund
Kontakt:

Konstig ADC-MUX ATmega88

Inlägg av övrigt »

Hallå

Jag är fortfarande ganska ny på µC och tänkte be om lite feedback angående muxen till AD omvandlaren på min ATmega88. Jag började med att koppla upp ADCn till en potentiometer som skickade ut värdet på lysdioderna på mitt STK500 vilket funkade bra. Sedan gjorde jag om programmet till att få en lysdiod att lysa proportionellt mot värdet från ADCn med pwm. So far so good. Men sen skulle jag koppla på flera lysdioder som jag ställde med varsin potentiometer på varsin AD-pinne - och då fick jag problem.

Vet inte om det är jag som inte förstår hur en multiplexer ska fungera, men här är min teori.

I databladet hittar man följande (del av) tabell
  • MUX3..0 Single ended input
    0000 ADC0
    0001 ADC1
    0010 ADC2
    0011 ADC3
Man hittar även i beskrivningen av pinkonfigurationen följande
  • PC0 (ADC0) ;Alltså port C pinne 0… om nån inte fatta det :)
    PC1 (ADC1)
osv

Detta tolkar jag som så att om man tex i ett program ska läsa in 2 analoga värden så sätter man tex först muxen på 0000 (de sista bitarna) och gör sen en konvertering och sparar undan det värdet till det registret som är funktionsmässigt är kopplat till PC0. Sen sätter man muxen till 0001 och lägger in det värde man får i registret som har att göra med signalen på PC1. FEL.

Det fungerar om man i programmet bara gör EN inläsning, men inte med två. Lösningen för två fungerar inte heller för 3 osv. Följande koppling mellan port-pinne och muxen har jag kommit fram till gäller (som funktion av # AD-pinnar som används).

Kod: Markera allt

MUX	Single ended input
0000	PC0	PC1	PC1	PC1
0001		PC0	PC2	PC3
0010			PC0	PC2
0011				PC0

Fler orkade/kunde jag inte testa. (fick lägga det som "code" för att få med tab)

Allså. Om jag tex ska läsa in två analoga värden så får jag ”korsa” registren eller i muxen mot fallet där jag bara läser in 1. Allt fungerar som det ska i övrigt i mina program, det är bara just denna korsning som förbryllar mig. Och det var ju inte sådär direkt som jag hittade felet heller…

Bifogar kodavsnittet som hämtar det analoga. Funktionen GET_ANALOG är tillfälligt ersatt för att underlätta debuggning, men MAIN anropar dessa 2 direkt efter varandra. Använder vänsterjustering.

Kod: Markera allt

;GET_ANALOG:
;Returns the  analog value on PC0..1 to digital 8 bit
;values in reg OutPwmL and OutPwmR resp. 

;FAULTY? Will work correct  but it seams as if the ADCMUX 
;mixes the signals somehow?? See comment and look in 
;to before final version. 

Get_Left:
ldi Temp,0b00100001	;For some reason this reads PC0 when use 2 first ADCX. 
sts ADMUX,Temp		;Set mux to read left phototr, on PC0. 

ldi Temp,0b11000000	;Keep ADC enabled and start conversion. 
sts ADCSRA,Temp

WAIT_L:				;Wait for conversion to finish. 
sbic ADSC,6
rjmp WAIT_L 

lds OutPwmL,ADCH

rcall GENERAL_DLY	;Let ADC reset. 
ret


Get_Right:

ldi Temp,0b00100000	;For some reason this reads PC1 when use 2 first ADCX. 
sts ADMUX,Temp		;Set mux to read right phototr, on PC1. 

ldi Temp,0b11000000	;Keep ADC enabled and start conversion on PC1. 
sts ADCSRA,Temp

WAIT_R:
sbic ADSC,6
rjmp WAIT_R

lds OutPwmR,ADCH

rcall GENERAL_DLY
ret

Nån kommentar eller erfarenhet kring detta? Kan jag ha missat nått enkelt? För antar ändå fortfarande att det ska vara så som jag trodde först. Eller?
mvh
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

På din beskrivning låter det som att det är en inställning för att välja
hur *många* analoga pinnar man vill ha, och en annan för att välja
*vilken* analog pinne som för tillfället ska användas. Den första
inställningen görs normal bara en gång i "init" delen av koden, den
andra görs hela tiden i anslutning till själva mätningen.

Svårt att veta helt säkert eftersom du inte har någon länk till
databladet...
thepirateboy
EF Sponsor
Inlägg: 2109
Blev medlem: 27 augusti 2005, 20:57:58
Ort: Borlänge

Inlägg av thepirateboy »

Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4750
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Inlägg av Swech »

Kolla ADIF istället för startbiten om ADn är klar...

Bit 6 – ADSC: ADC Start Conversion
In Single Conversion mode, write this bit to one to start each conversion. In Free Running mode,
write this bit to one to start the first conversion. The first conversion after ADSC has been written
after the ADC has been enabled, or if ADSC is written at the same time as the ADC is enabled,
will take 25 ADC clock cycles instead of the normal 13. This first conversion performs initialization
of the ADC.
ADSC will read as one as long as a conversion is in progress. When the conversion is complete,
it returns to zero. Writing zero to this bit has no effect.

- denna bit kan bli 0 innan data registren är uppdaterade, och du läser såpas snabbt att du sannorlikt får in föregående värde istället för det nya....

Läs av denna istället

Bit 4 – ADIF: ADC Interrupt Flag
This bit is set when an ADC conversion completes and the Data Registers are updated. The
ADC Conversion Complete Interrupt is executed if the ADIE bit and the I-bit in SREG are set.
ADIF is cleared by hardware when executing the corresponding interrupt handling vector. Alternatively,
ADIF is cleared by writing a logical one to the flag. Beware that if doing a Read-Modify-
Write on ADCSRA, a pending interrupt can be disabled. This also applies if the SBI and CBI
instructions are used.



SWECH
övrigt
Inlägg: 208
Blev medlem: 19 april 2008, 14:18:11
Ort: Lund
Kontakt:

Inlägg av övrigt »

Hallå igen och tack för era förslag! Problemet är nu löst.

Skulle ha tänkt på att ha lagt en länk till databladet. Bra tolkning annars av problemet, men vad jag har förstått så finns där ingen funktion som sätter antalet pinnar man använder som insignal. Alla är så att säga på default.

Jag läste igenom hela länken på avrfreaks, men hittade inget som direkt löste just mitt problem. Dock en bra guide för att komma igång med ADCn, bättre imho än databladet.

Provade ditt förslag Swech, men inte heller det gav mig rätt resultat direkt. Däremot hade du troligen rätt i din tolkning av beteendet. Det jag behövde göra var enkelt nog bara att byta plats på delayen. Provade iofs bara med upp till tre ingångar men de fungerade så detta är nog rätt.

Följande kod fungerar nu, och är lätt att antingen utöka till fler inläsningar eller dela upp i flera som sker oberoende av varandra. Hittade inget liknande på forumet tidigare så hoppas nån mer kan bli hjälpt av den.

Kod: Markera allt

GET_ANALOG:
;Returns the  analog value on PC0..1 to digital 8 bit
;values in reg OutPwmL and OutPwmR resp. 


ldi Temp,0b00100000	;This reads the PC0.  
sts ADMUX,Temp		;Set mux to read left phototr, on PC0. 

ldi Temp,0b11000000	;Keep ADC enabled and start conversion. 
sts ADCSRA,Temp

WAIT_L:				;Wait for conversion to finish. 
sbic ADIF,4			;"ADIF,4" and "ADSC,6" will work with short delay after. 
rjmp WAIT_L 

rcall GENERAL_DLY	;Needed! 

lds OutPwmL,ADCH

;* Left value done, get right. 

ldi Temp,0b00100001	;Read PC1. 
sts ADMUX,Temp		;Set mux to read right phototr, on PC1. 

ldi Temp,0b11000000	;Keep ADC enabled and start conversion on PC1. 
sts ADCSRA,Temp

WAIT_R:
sbic ADIF,4			;"ADIF,4" and "ADSC,6" will work with short delay after. 
rjmp WAIT_R

rcall GENERAL_DLY	;Must have this. 

lds OutPwmR,ADCH

ret

GENERAL_DLY:
push J
ldi J,0x05
GENERAL_DLY_T:
dec J
brne GENERAL_DLY_T
pop J
ret
Kan jag förresten ändra rubriken? Till att problemet är löst och att fungerande kod finns el liknande? Annars får gärna någon moderator fixa det.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> men vad jag har förstått så finns där ingen funktion som sätter antalet pinnar

Nej, jag såg det också efter att länken hade postats...

Att vänta lite mellan byte av ADC-ingång är normalt.
Man måste ge S/H kretsen lite tid för att svänga in till den nya spänningen.
Jag vet inte om AVR-databladet säger något specifikt om det, men på en
PIC kallas det "acquisition time" (och är dokumenterat och beskrivet
hur man räknar ut den), och jag antar att en AVR har liknande krav vid
byte av ADC-ingång...
Skriv svar