I just made a voltage divider and figured out that the ratio is 12.3 so the actual voltage I am measuring is 12.3 times higher than the output voltage. So knowing that value and knowing that the arduino value is 0 to 1024 where 0 is 0v and 1024 is 5v I came up with this formula:
voltage = (analogvalue / 204.8) * 12.3
Which seems to work. Now the thing I noticed is that the actual analog value seems to fluctuate a lot despite the voltage staying the same. I measured the battery to be 12.3 and occasionally jumps to 12.4 but is 12.3 90% of the time. The analog value seems to be jumping between 204 and 207, which gives me 12.251953125 and 12.43212890625. The analog value is jumping way more than the actual reading when I use my volt meter.
Is it the volt meter that is not as accurate to fast jumps, or is my voltage divider/calculations inaccurate? It sure seems to be jumping around way more than the reading on my volt meter (digital).
The ADC, being an analog device, is unlikely to return the same results every time. A couple of counts out would be pretty normal. Plus, your meter may be averaging a bit.
You could possibly reduce the jitter by going into one of the sleep modes during the ADC conversion. This might take a bit more code.
Don't get too carried away with decimal places (eg. 12.251953125). Most of those are spurious considering you are working with an original number of 3 significant digits (ie. 204). Thus the answer can only have 3 significant digits, so you are really getting 12.3 to 12.4, which is what your meter says.
The Arduino has a much higher sampling rate and it would appear you have a little noise too, You might try throwing out those that are more than 2 points momentarily above or below there are several smoothing routines I have seen posted like store and average 10 counts and display that average which was simple enough for me to figure out...
// Example of taking ADC reading while asleep
// Author: Nick Gammon
// Date: 23 June 2012
#include <avr/sleep.h>
const byte adcPin = 0;
volatile int adcReading;
volatile boolean adcDone;
boolean adcStarted;
void setup ()
{
Serial.begin (115200);
// set the analog reference (high two bits of ADMUX) and select the
// channel (low 4 bits). this also sets ADLAR (left-adjust result)
// to 0 (the default).
ADMUX = _BV (REFS0) | (adcPin & 0x07);
} // end of setup
// ADC complete ISR
ISR (ADC_vect)
{
byte low, high;
// we have to read ADCL first; doing so locks both ADCL
// and ADCH until ADCH is read. reading ADCL second would
// cause the results of each conversion to be discarded,
// as ADCL and ADCH would be locked when it completed.
low = ADCL;
high = ADCH;
adcReading = (high << 8) | low;
adcDone = true;
} // end of ADC_vect
void loop ()
{
// if last reading finished, process it
if (adcDone)
{
adcStarted = false;
// do something with the reading, for example, print it
Serial.println (adcReading);
delay (500);
adcDone = false;
}
// if we aren't taking a reading, start a new one
if (!adcStarted)
{
adcStarted = true;
// start the conversion
ADCSRA |= _BV (ADSC) | _BV (ADIE);
set_sleep_mode (SLEEP_MODE_ADC); // sleep during sample
sleep_mode ();
}
// do other stuff here
} // end of loop
I found that with the sleep_mode() call in, the sample changed occasionally (like maybe every 10 or 15 readings). If not asleep, the sample might change every 5 readings. So it made a bit of a difference.
I also found that putting a 0.1 uF capacitor between AREF and GND pins (which are adjacent on the Uno board) the readings were even more stable.
Is it just my inattention here or is it possible to get spurious measurements if the A/D input is a very high impedance... or better practice to place a voltage follower on the A/D input being used??
I wont buy a whole new board, but if averaging the last 10 reads can work, then think I'll just stick with that. That or I can take 10 reads then just throw out the ones that are way out of range. So this is pretty much normal then and is just noise/interference?
Also for the capacitor, how does this work, is this going to fix all readings or does it also have to be connected to my specific input in any way?
Personally I'd tweak the values of the resistors so that the maximum expected voltage is closer to 5 volts coming out of the voltage divider to improve the sensitivity. Then I'd do a 'rolling average' of the form
You are mixing up accuracy and repeatabilty.
For accuracy you need to know the precise values of your referance voltage and resistors, not just the values printed on the 'tin'.
For repeatabilty you need to reduce noise by either software or hardware filtering, and remember that an A/D only ever gives plus or minus the least significant bit.
Still slumming it with us Arduiner's after your raid in Ras Pi territory GM ? I think the code to play Mary Poppins on a glockenspiel would be an order of magnitude simpler on the Arduino.........