1
\$\begingroup\$

I'm trying to measure the battery voltage of 30V using the ADC of an AVR Atmega8, AVCC is connected to 5V.

I connected a suitable voltage divider: R1 is 270k, R2 is 10k. The result I get is wrong at all, at 30V I get 23V. The equation I use is batteryvoltage = 5*1023/adcReading.

// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}
unsigned int adcReading = 0;

adcReading = read_adc(0);
batteryVoltage = 5*1023/adcReading;
\$\endgroup\$
  • \$\begingroup\$ Why are you dividing by the adcReading? \$\endgroup\$ – pjc50 Jan 23 '13 at 10:24
  • \$\begingroup\$ @pjc50 to get the full reading of the battery ? \$\endgroup\$ – Mahmoud Jan 23 '13 at 10:25
  • \$\begingroup\$ adcReading should be numerator, not the denominator. Configured as it is, the result will decrease with increasing voltage. \$\endgroup\$ – Nick Johnson Jan 23 '13 at 10:29
  • \$\begingroup\$ @NickJohnson The result is always zero... How also can I modify it to bte the result increase with decreasing voltage? \$\endgroup\$ – Mahmoud Jan 23 '13 at 10:32
5
\$\begingroup\$

Your calculation for the battery voltage is wrong. Assuming adcReading varies from 0 to 1023, it should look like this:

batteryVoltage = (adcReading * 30) / 1023

Note though that denoting voltage like this, with integer volts, will only give you 31 possible readings (0 to 30). A more useful result might be in millivolts:

batteryVoltageMillivolts = (adcReading * 30000) / 1023

Note that in this case batteryVoltageMillivolts will have to be a long, not an int.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ can you help me with the voltage divider issure please? I think its also affecting.. \$\endgroup\$ – Mahmoud Jan 23 '13 at 10:35
  • \$\begingroup\$ What voltage divider issue? You didn't specify one in the question. \$\endgroup\$ – Nick Johnson Jan 23 '13 at 10:37
  • \$\begingroup\$ I have specified R1 = 50k, R2=10k, this gives 5V at 30V, but still the output is wrong using your equations above. \$\endgroup\$ – Mahmoud Jan 23 '13 at 10:38
  • 2
    \$\begingroup\$ You said R1=270k above! What's the actual reading at the adc input pin with a voltmeter? \$\endgroup\$ – pjc50 Jan 23 '13 at 10:40
  • \$\begingroup\$ You want to ensure that the divider allows some "overflow" - if you want to measure 32V but your ADC input voltage is 5V (ie max) at 30V you will have a problem! \$\endgroup\$ – Andrew Jan 23 '13 at 12:21
1
\$\begingroup\$

@Mahmoud - depending on the resolution of your ADC (10 bit, 12 bit?) I'd be minded to divide by 10 using your resistor divider - so 32V == 3.2V at the ADC

This gives a possible range of 50V == 5.0V at the ADC therefore no overloading of the input.

For the 10 bit ADC this then gives you a resolution of 0.049V for a 50V input

If you need a bit more accuracy, divide to 35V == 5.0V at the input which gives you a resolution of 0.034V

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ its 10bit of the AVR Atmega8 \$\endgroup\$ – Mahmoud Jan 24 '13 at 8:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.