0
\$\begingroup\$

let's consider this simple piece of code:

void setup() {   
    Serial.begin (9600); 
}

void loop() {  
    int code = analogRead (A2);   
    double voltage = code *5/1024;   

    Serial.print("Voltage is  ");   
    Serial.println(voltage);   
    delay (500); 
}

It is simply the A/D conversion of a voltage applied between A2 and GND. Unfortunately I saw that this reading is not so accurate. Precisely, if I use a battery of 3.5V, on the serial monitor I will see the value voltage = 3.00. If I use a battery of 1.5V, I will see 1.00 V.

This means that the program works correctly, but it is not accurate. Which is the reason for this and how can I solve it? I do not understand the reason for this since the resolution of Arduino as ADC is equal to 5/1024 = 4.88 mV, so I think that we may have a quantizazion error of 4.88mV, and not of 0.5V.

\$\endgroup\$
3
  • \$\begingroup\$ You should try taking 10-20 readings and averaging them, I'm sure your accuracy will improve... You don't have to wait between readings. I'm not sure but I hope that whoever wrote the Arduino analog library made analogRead a blocking call on a conversion complete. \$\endgroup\$
    – Ron Beyer
    Sep 21, 2019 at 2:08
  • \$\begingroup\$ What board are you using? is there anything between the pin and the arduino? \$\endgroup\$
    – Voltage Spike
    Sep 21, 2019 at 2:10
  • \$\begingroup\$ Do you get any results that are not X.00? Is your calculation being done using integer math and then converted to a double? Write out the raw values for code and do the calculation by hand to verify. \$\endgroup\$ Sep 21, 2019 at 2:11

1 Answer 1

8
\$\begingroup\$

The problem is how your calculation is being expressed. The calculation for voltage will be done using integer math and then the result is converted to a double, resulting in the values you report. Corrected code:


void setup() {
Serial.begin (9600); }

void loop() {
int code = analogRead (A2);
double voltage = (double)code * 5.0 / 1024.0;
Serial.print("Voltage is ");
Serial.println(voltage);
delay (500); }
\$\endgroup\$
4
  • \$\begingroup\$ Thank you! Now I got 1.42V on my measurement of a battery of 1.5V. perfect. Only a general question: so is the problem of my code the fact that inside operations not all variables are double? It seems to me that if there is an integer (although all other operands are double), the result will have the accuracy of an integer (also if I declare the result as a double). Is it correct? \$\endgroup\$
    – Kinka-Byo
    Sep 21, 2019 at 3:03
  • \$\begingroup\$ @Kinka-Byo There's no need, with one of the operands to be double it's computed as double. Beware that (double)code * 5.0 / 1024.0 are two operations, (double)code * 5.0 and (result) / 1024.0 you can leave it as code * 5.0 / 1024 as the result of the first operation is already a double, but if you leave code * 5 / 1024.0 the first part would be computed as integer (in fact it would work but because the first op is a multiplication and it will not give any decimals even if it's a double).. \$\endgroup\$
    – Gusman
    Sep 21, 2019 at 4:16
  • \$\begingroup\$ @Gusman you are correct, I do little enough work with Arduino to know what the evaluation rules are so I used the sledge hammer solution. It should also be noted that a better solution would be to leave everything as an integer and calculate the number of millivolts instead of the number of volts. That would be orders of magnitude faster on the arduino. \$\endgroup\$ Sep 21, 2019 at 16:27
  • \$\begingroup\$ Yep, that's right, integer operations are way faster as the ATMEGA328 doesn't has a FP unit. Or at least using a float instead of a double would speed it up, using 64 bit precission floating point is unnecessary in this case as the error from the ADC will be bigger than the float's instrinsic one. \$\endgroup\$
    – Gusman
    Sep 21, 2019 at 18:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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