NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » ADC with input at ground

July 10, 2010
by esoderberg
esoderberg's Avatar

I have a joystick hooked up with input to ADC0. The basic results from the joystick indicate the ADC is at least working to some degree - full throw one way gives 1012 out, centered gives 678, full throw other way gives 400. Expecting a smaller low end I investigated further by grounding the input to ADC0 yet I still get 400 vice what I expected, 0 or close to. I'm using the same basic code from temp sensor ADC section but with internal AREF connected via ADMUX += (1<<REFS0). Am I wrong to expect output of ADC to be near zero with input at ground? Vin * 1024/Vref? Any ideas why not? Thanks for any suggestions.

ES

July 10, 2010
by mrobbins
(NerdKits Staff)

mrobbins's Avatar

Hi ES,

You are correct to expect a reading of around 0 when the ADC input is grounded. The ~400 is not normal.

Can you verify that pin #22 of the microcontroller connected to ground?

When you wrote

ADMUX += (1<<REFS0);

is it possible that this particular line of code is being run multiple times? We normally use the notation:

ADMUX |= (1<<REFS0);

with the bitwise-OR operator because it is insensitive to being run multiple times. If you are using += and it runs multiple times, the addition result would carry into higher bits, and then overflow, producing strange results.

If this doesn't solve your problem, please let me know if the "tempsensor" setup still works properly. This will tell us whether the issue is in your code/circuit, or has to do with some change to the ADC itself.

Hope that helps!

Mike

July 10, 2010
by esoderberg
esoderberg's Avatar

Mike,

Mostly just needed someone to tell me I wasn't losing it by expecting 0 out of the adc with input at ground.

Circuit was fine, but re looking at tempsensor code as you suggested, I missed setting the time prescaler to 1/128 with ADPS2,1,0.
With ADPS at all zero giving prescale of 1/2 I was getting some funky results. Now I'm getting expected results from both my joystick and an accelerometer attached at ADC0 and ADC2 respectively while toggling back and forth between internal AREF for joystick and external 3.3v AREF for the accelerometer.

BTW updated my code to use |= vice += for register updates as it seems safer/better form, but that wasn't the problem as I was resetting ADMUX to zero between ADC0 and ADC2 readings.

Having you guys providing smart advise for those of use trouble shooting our projects is invaluable, thanks.

Eric S.

July 10, 2010
by Ralphxyz
Ralphxyz's Avatar

Eric, want to share your accelerometer code? Is it analog output or PWM?

I have both types of accelerometers. I am just starting to learn how to program them (and programing in general).

Ralph

July 10, 2010
by esoderberg
esoderberg's Avatar

Ralph,

I also am working with both types of accelerometers.

I posted the code used for the PWM accel output to you earlier on the NK sensor forum.
The above comments are in regards to analog joystick and accel outputs.

Below are the principle elements of code I used for reading joystick on ADC0 and analog accel output on ADC2.

// ADC

void adc_init() {

//set analog to digital converter // analog input

ADMUX = 0;

//ADEN TURNS ON THE ADC //ADPS2,1,0 sets conversion timing, pg 256 datasheet, ADC clock = system clock/128 for ADPS2,1,0

ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);

//ADSC starts a conversion from A to D //ADCSRA = ADSCRA | (1<<ADSC) ie turns bit to 1 or keeps it 1 ADCSRA|= (1<<ADSC);

}

// reading input from ADC0 output via adc

uint16_t adc0_read() {

while(ADCSRA & (1<<ADSC)) {

//Do nothing while ADCSRA ADSC bit is 1. ie wait until last ADC complete to start next. }

//set the source pin to ADC0 via //reset ADMUX to ADC0 while ADSC at 0

ADMUX = 0;

ADMUX |= (1<<REFS0); //sets reference voltage via internal connection // to AVcc(which is connected to Vcc (5v) with a capacitor in parallel on arduino)

//reset ADSC to 1 to complete cycle

ADCSRA |= (1<<ADSC);

while(ADCSRA & (1<<ADSC)) {

//Let adc collect data with ADC0 input

}

//ADCL and ADCH is where the ADC writes output. 2 var used because output greater than 8 bit. //ADCL is low bits ADCH is high bits, hence the 8 bit shift for 16 bit result

return (ADCL +(ADCH<<8));

}

uint16_t adc2_read() {

while(ADCSRA & (1<<ADSC)) {

//Do nothing while ADCSRA ADSC bit is 1. ie wait until last ADC complete to start next. }

//set the source pin to ADC2 via //reset ADMUX to ADC2 while ADSC at 0

ADMUX = 2;

//with REFS0 (in ADMUX) at zero, reference voltage is from external source at AREF //AREF externally set to the 3.3 volts used for my accelerometer

//reset ADSC to 1 to complete cycle

ADCSRA |= (1<<ADSC);

while(ADCSRA & (1<<ADSC)) {

//Let adc collect data with ADC0 input

}

//ADCL and ADCH is where the ADC writes output. 2 var used because output greater than 8 bit.

//ADCL is low bits ADCH is high bits, hence the 8 bit shift for 16 bit result

return (ADCL +(ADCH<<8));

}

// in main

Abias = 0;// Joystick output set in Abias

for(i=0; i<10; i++) {

Abias += (adc0_read()/10.0);}

Axa=0;// analog accel output set in Axa

for(i=0; i<30; i++) {

Axa += (adc2_read()/30.0);}
July 11, 2010
by Ralphxyz
Ralphxyz's Avatar

Well thanks agin, I really need lots of examples (help) and I think it helps other forum members to not just read about what others are doing but to have the associated code. Especially working code, often times people will post broken code they are having a problem with and then just say thanks when they get it to work. They never publish the working code.

So thank you once again, I really do appreciate your help.

Ralph

Post a Reply

Please log in to post a reply.

Did you know that you can input numbers in binary via a DIP switch, and output them to the LCD? Learn more...