I'm getting an incorrect reading when trying to read voltage using a voltage divider with two known resistors in a very simple circuit using an Arduino Uno and two 6.8K ohm resistors. When validating with a multimeter i'm measuring the expected voltage after the first resistor/ voltage drop.
I'm using the simple circuit below. Vin = 5V. Both resistors are 6.8KOhm. This circuit is just to validate the correct way of measuring the voltage drop using a divider and analog read op Pin A0.
When using the Multimeter, i'm measuring the expected 2.5V (since both resistors are equal = 50% voltage drop).
When using analog read on A0 i'm measuring the raw value of 440. When converting this to voltage using (440/1023)*5V, im getting 2.15V.
I would expect a raw reading on A0 of approximately 512, leading to the expecterd 2.5V
What am i doing wrong? Or what is the explanation for this unexpected reading result on A0 pin?
Please, do one more experiment and report the result: 1. With your DVM, measure the voltage of the of the 3.3V test point of the UNO Board. 2. Using a jumper, connect this test voltage with A3-pin. 3. Read the signal from A3-pin as count in decimal. 4. Convert the count of Step-3 into voltage. 5. How much have you got in Step-4?
That's weird... Usually the Arduino is very linear, and accurate if the ADC reference is accurate, within one or two counts. And since (presumably) you're using voltage-divided Vcc as your reference you should always read Vcc/2 if the resistors are accurate.
I'd expect the biggest source of error to be the resistor tolerance but you measured with your multimeter.
As another experiment you can try swapping the resistors around (or just swap the 5V and ground connections). If the resistors are exactly equal nothing will change.
If you can't find anything, show us your code.
It's unlikely that the Arduino is bad but that is a possibility.
Thanks a lot for your comments and advise! Highly appreciated!
My final project will run on an ESP board (DFROBOT FireBeetle 2 ESP32-E). Since i was having trouble with reading of the analog pin, i transferred to an Arduino Uno board (like said above) to verify. However in the sketch i forgot to change the pin for reading the analog signal to A0/0 and left it on pin 34 (like my ESP is using). I changed for the uno the code now to pin A0 and the readings were perfect again and in line with my Multimeter.. sorry this was my mistake!
However the problem remains on my ESP board like i described in original post for the Uno board: The analog reading is not as expected but now with 3.28V as Vin. Analog pin 34 i'm reading a converted voltage of 1.50V instead of the expected 1.63V. I validated the 3.28V on Vin and the 1.63V on pin 34 with Multimeter but can't get it working with the sketch / output. Below is my code snippet. Circuit is similar to the Arduino Uno scheme in original post.
Normally, for most devices, Vin is a higher voltage than the MCU operating voltage. It's usually passed through a regulator. So, are you connecting power to the right pin?
From here, it says the default ADC attenuation is 11db. There's some functions you could use to adjust...
analogSetAttenuation(); // Sets the attenuation for all ADC channels
analogSetPinAttenuation(); // Sets the attenuation for a specific analog channel pin
After @dlloyd suggestion i further deepdived into ESP32 specific configuration. However this did not result in a different reading on the pin.
Apparently the issue is the way the polynomial value (V) is calculated from the measured value.
When using the following calculation method I was able to calculate the expected 1.63V!
However still don't understand why there is a different way in calculating for the ESP (method above) vs. Arduino Uno with the following: Vout = (buffer)/4096.0;
Happy to learn if anyone can explain what I accidentally found out to be the correct method.
I don't completely understand it, but it's a calibration/correction (which may not be needed).
i.e. If you're reading 440 at 2.5V and you know it should be 512, you can correct for the error. And you can correct multiple points along the line.
But... If you are reading 440 when you expect 512 you've got a serious problem and it should be solved and not simply calibrated-out!
You have to calibrate with known voltages (which means you need a good-calibrated voltmeter) and for a particular-individual device. Not every Uno or ESP can be calibrated the same. Every single ADC/processor needs it's own separate calibration. So if you go into-production every unit has to be individually calibrated. And if you're building something for yourself you can't use someone else's calibration data.
Where I work we have a precision multimeter connected to a computer and the calibration is part of a simi-automated test that every unit goes-through. (This is not Arduino-related, it's just ADC & DAC calibration.)
It's more common to have simple straight-line calibration with an offset (usually measured at zero) added/subtracted from the reading, plus a slope correction which is a multiplication factor. (If the device is perfect and doesn't need calibration you'd have an offset of zero and a slope correction of 1.0)
Usually the slope is corrected at maximum, or around the measurement-of interest... If you expect to be measuring 2.5V you can correct the slope at 2.5V and the offset at zero. If you are making a general-purpose voltmeter, you'd usually calibrate zero and maximum.
So you'd normally read 0V (or close to zero) and if you don't read zero, add or subtract to read zero. Then read the maximum (or higher) voltage with the offset applied to the reading, and calculate the required multiplication factor to make that reading "perfect".
The Uno's 10-bit ADC shouldn't normally need any calibration except for taking the actual reference voltage into-account. It should be accurate and linear to within one or two counts.
With 12-bits you may benefit from more-precise calibration/correction.