Getting Accurate Values from Arduino Analog Pin Measurements
At The Mad Scientist Hut I am currently building a battery capacity data logging system with the Arduino so that I can get discharge curves. I plan on discharging batteries at different load rates and since I would be spending days to many weeks and even months with each battery in discharge, I did not think it would be very useful if the data was inaccurate . I was not really surprised to find out how far the raw measurement on the analog pin was from the actual value presented to the pin. I made a quick two point gain and offset calibration that will correct the measurements and make them fairly accurate. After implementing the gain and offset calibration I compared the values from the Arduino to the Fluke 87 DMM and across the range I was using (1.5V to 0.6V) I saw no more than a 2mV difference from the multimeter compared to readings from the analog pin.
To use the code you will need to define these variables in the beginning of the program:
int meas_ch = 0;// channel used for measuring voltage
int val = 0;//used for averaging the voltage measured
//using the mega 2560 2.56V internal reference with this command
// "analogReference(INTERNAL2V56);"
double ref = 2.56;//reference voltage
double Voltage ;//reported voltage after being averaged
double average= 1000;//how many measurements to take for averaging
double gain ;// gain value for ADC
double offset ;// Offset value for ADC
In the setup() routine I placed this code:
gain = 1.0;
offset = 0.0;
//gain = (mv1-mv2)/(fv1-fv2) //fv = force voltage, mv = measure voltage
//offset = fv2 - (gain * mv2)
// example:
//I set a power supply to 1.5V and I used a multimeter to measure the analog pin input
//voltage at 1.5v, running the the readV() routine the analog pin measured 1.534V
//then I set the supply to read on 0.9V the meter and the arduino
//analog pin measured 0.916v
//gain = (1.50 - 0.9)/(1.534 - 0.916);
//offset = 0.90 - (gain*0.916);
// to use this section of code for the first time comment out the gain and offset example
// below, since you will have different values
gain = (1.50 - 0.9)/(1.5406 - 0.921);
offset = 0.90 - (gain*0.921);
The following routine is what I use to read the voltage back from the analog pin defined as ‘meas_ch’:
void readV()
{
Voltage =0.0;
val = analogRead(average); // read the input pin
for (int i=0;i<average;i++)
{
val = analogRead(meas_ch); // read the input pin
Voltage = Voltage +(ref*(double(val)/1023.0));
}
Voltage = (Voltage/average);
Voltage = Voltage*gain+offset;
//to report back to serial port use the following:
// Serial.print"Volts:");
// Serial.println(Voltage,3); // debug value
//to report back to LCD use the following:
// lcd.setCursor(0, 0);
// lcd.print("Volts:");
// lcd.print(Voltage,3);
}
The following is an example of reading the voltage from the analog pin in the main code: (this code is using the the SD card write logfile.print:
readV();
if (Voltage <= 0.6)
{
V_stop++;
}
logfile.print(Voltage,4);
In the next blog I will discuss the auto ranging feature that I am adding to the system, so that when I hook up a battery such as a Li-Ion that is at 4V the system will switch in a divider and read the correct voltage.
[wp_bannerize categories=”12,146,4,47,77,58,68,9,102,111,1″]