Pages: [1]   Go Down
Author Topic: AnalogRead Accuracy  (Read 2114 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am trying to do precise measurements of a 12V battery, two decimal places would be fine, three decimals would be great. I run a calibrated voltage divider to lower the input (for when I convert to a floating point, the graph is just the int readings) and do the reading in a for-loop and average it. This worked fine but after serial printing the data to Excel, it has far more variation than I would like. I tried adding a unity gain, low pass filter op amp but the variation was unchanged. Is this the limit of the ADC on the Arduino or are there more tricks to increase accuracy? I am not at all concerned about speed. The following graph shows individual readings, not averages.

« Last Edit: June 12, 2012, 08:16:24 am by Tony_C » Logged

"We realize that we have not answered all your questions and in most cases, our
answers have only served to produce more questions for which

Switzerland
Offline Offline
Faraday Member
**
Karma: 108
Posts: 5144
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The readings of the ADCs are always relative to the Vcc (usually 5V) if not configured for AREF. So if your Vcc varies your readings of the ADC will change appropriately. How stable is your Vcc? Do you use the standard voltage regulator of the Arduino or an external stabilised power supply?

BTW: your readings are more or less withing two decimal places (628-638) with two exceptions.
Logged

Montreal
Offline Offline
Faraday Member
**
Karma: 29
Posts: 2590
Per aspera ad astra.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
12V battery, two decimal places would be fine, three decimals would be great
10 bits ADC (1024 steps) could provide 2 decimal digit, 12V / 1024 = 0.01171875 V. To get third will require ~3 bits more, you still could achieve this using oversampling technics, that outlined in AVR121 App Note.
 Accuracy could be affected  by output impedance of the source and wiring, can you post a drawings of your hardware set-up?
Logged

0
Offline Offline
Shannon Member
****
Karma: 206
Posts: 12076
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Is the battery just sitting there or is it doing something?   Have you compared the readings with a good multimeter?
Logged

[ I won't respond to messages, use the forum please ]

Anaheim CA.
Offline Offline
Faraday Member
**
Karma: 46
Posts: 2883
...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Is there something else going on of a cyclic type as well or a relay or other Vcc load like lot of led's??? does this have it's own power supply and are the grounds good between PSU and computer?

Doc
Logged

--> WA7EMS <--
“The solution of every problem is another problem.” -Johann Wolfgang von Goethe
I do answer technical questions PM'd to me with whatever is in my clipboard

Global Moderator
Netherlands
Online Online
Shannon Member
*****
Karma: 216
Posts: 13672
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

you may smooth readings with a running average - http://arduino.cc/playground/Main/RunningAverage -
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 14
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You can actually increase resolution and lower noise by oversampling and decimation.

2ˆ2n samples will give you n bits of extra resolution. So if you take 1024samples, you'd get 5 extra bits of resolution.

You do this by summing the ADC values (ints) in a long variable which you then bit-shift.

Here's a full explanation of the method: www.atmel.com/Images/doc8003.pdf
"It is important to remember that normal averaging does not increase the resolution of the conversion. Decimation, or Interpolation, is the averaging method, which combined with oversampling, which increases the resolution."

Logged

Global Moderator
Netherlands
Online Online
Shannon Member
*****
Karma: 216
Posts: 13672
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


made sample code some time ago on that note -

Code:
//
//    FILE: analogReadN.pde
//  AUTHOR: Rob Tillaart
//    DATE: 2012-05-10
//
// PUPROSE: higher precission analogRead()
//
// http://www.atmel.com/Images/doc8003.pdf
//

void setup()
{
  Serial.begin(115200);

  for (int b=10; b< 17; b++)
  {
    unsigned int val = analogReadN(A0, b);
    Serial.println(val, DEC);
  }
}

void loop()
{
}

uint16_t analogReadN(uint8_t pin, uint8_t bits)
{
  bits = constrain(bits, 10, 16) -10;

  int samples = 1 << (bits << 1);

  uint32_t sum=0;
  for (int i=0; i< samples; i++) sum += analogRead(pin);     
  return sum >> bits;                             
}

uint16_t analogReadNreferenc(uint8_t pin, uint8_t bits)
{
  bits = constrain(bits, 10, 16) -10;

  int d = 1;
  for (int i=0; i<bits; i++) d *= 2;
  int samples = d*d;

  uint16_t sum=0;
  for (int i=0; i< samples; i++) sum += analogRead(pin);     
  return sum / d;   // rounding => return (sum + d/2) / d;                             
}
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Jr. Member
**
Karma: 0
Posts: 95
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You'll not have a good accuracy using Vcc as the ADC reference, because it will vary a bit depending on several conditions like power supply load and temperature. You'll have to use internal 1.1V nominal reference.

The internal reference is stable but its value is slightly different on each individual chip (can be from 1V to 1.2V), and therefore you'll need to "calibrate" your application, meaning you'll have to read the real value of the internal voltage reference once and save it in EEPROM for later usage (or use directly on the code if you're going to make only 1 unit).

In fact, your scaling down resistors will also introduce an extra error because they are not 0% tolerance so, in fact, you should calibrate your entire system, by feeding it a known voltage in the range you want to measure and seeing what value you read from the ADC - from this you can "correctly" read any other voltage.

Other than this, make averages as already been suggested by others. Put a decoupling capacitor on AREF, which will provide extra stability to the internal voltage reference. Put a small capacitor at the ADC's input to stabilize the input voltage. and you can also enter a special "ADC reading" sleep mode that the AVR supports for low noise ADC reading.
Logged


Pages: [1]   Go Up
Jump to: