The voltage sensor value is different from the multimeter

Hello, I measured the voltage of 18650 batteries with a voltage sensor module, and the values ​​seem to be different from the multimeter.

The voltage sensor module I used was this module.
image

However, if the multimeter says, for example, 3.8 V, the voltage sensor shows that the voltage is higher than 3.8, so it comes out as 3.91.

The code used in Arduino was as follows:

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



void loop() {
  float V_ADC_A = analogRead(A0);
  float V_A = V_ADC_A * 5.0 / 1024.0 / 0.2;
  Serial.print(V_A,4);
  delay(1000);
}

Are the calculation values ​​used in V_A wrong? Or is it that the exact value cannot be obtained due to the characteristics of Arduino Uno?

You are making an assumption that the voltage the A/D unit is comparing to is EXACTLY 5.0 volts. That is very rarely the case. Measure the 5 volts the Arduino is using with your DVM and use that value in the calculation and see if the computed voltage is closer.

1 Like

Welcome to the forum

 float V_A = V_ADC_A * 5.0 / 1024.0 / 0.2;

Where did you get this calculation from ?

5.0 is presumable the assumed voltage that the sensor is working at, but is that really the case ?

1 Like

That sensor is just a 7500ohm:30000ohm voltage divider, and the 0.2 comes from 7500/(30000*7500)=0.200. Given the way you wired it up ( + to 5V) and programmed it, it should always show you 0.2 * Vref, or analogRead(A0)=204, no matter what the voltage of the battery pack is.

For that purpose, maybe try @nickgammon's VCC measuring code that measures the internal 1.1 against VCC:

const float InternalReferenceVoltage = 1.096; // as measured

void setup ()
{
  Serial.begin (115200);
  ADCSRA =  bit (ADEN);   // turn ADC on
  ADCSRA |= bit (ADPS0) |  bit (ADPS1) | bit (ADPS2);  // Prescaler of 128
  ADMUX = bit (REFS0) | bit (MUX3) | bit (MUX2) | bit (MUX1);
  
  delay (10);  // let it stabilize
  
  bitSet (ADCSRA, ADSC);  // start a conversion  
  while (bit_is_set(ADCSRA, ADSC))
    { }
  
  float results = InternalReferenceVoltage / float (ADC + 0.5) * 1024.0; 
  Serial.print ("Voltage = ");
  Serial.println (results);  
}  // end of setup

void loop () { }

How long since the multimeter was calibrated? You're assuming that it shows a correct voltage but that might not be the case.

1 Like

Wishful thinking to print that voltage with four decimal places, if you only have about 200 A/D values to work with (1024 * 0.2). You can't even get two decimal places with that sketch.

Measuring with 1.1volt Aref is the way to go, but that restricts the range of that sensor voltage divider to about 5.5volt.
Leo..

1 Like

What is the voltage of your VREF pin?

1 Like


Sorry for the late reply. I assumed 5V because I wrote 5V by referring to the codes on the internet.

I don't know if it was calibrated because I measured it with a multimeter that was in the lab. I checked more than 3 multimeters, including the Fluke 17B+ and other models.

I thought that if I expressed it as 4 decimal places, I would get a more precise value, but it was a meaningless action. And when I measured Aref on the Uno board, it was displayed as 4.89~4.90V.

when I measured Aref on the Uno board, it was displayed as 4.89~4.90V.
Is it true that you asked me to measure the voltage here?

Now that you have measured the voltage on the AREF pin, you can put this value into the formula you use to calculate the voltage.

Change:

float V_A = V_ADC_A * 5.0 / 1024.0 / 0.2;

To:

float V_A = V_ADC_A * 4.89 / 1024.0 / 0.2;

And then the project is plugged into a different power source, and he has to do it all over again.
A more sensible way is to determine Vcc on the fly using the 1.1V internal reference as outlined earlier. This way the system compensated to a large extent for any supply voltage fluctuations.
An even better way would be to use an ultra stable reference of known value, but I guess we all know that this is likely overkill for this particular application.