ADC calculator and reference sheet

I often find myself having to rouse a few extra brain cells to remember the math for getting a meaningful number from a raw ADC value. When I'm measuring voltages to check on supply voltage or for some other reason, late in the afternoon the voltage divider, voltage reference and resolution figures go around and around until I eventually remember how to mash them together to get an accurate number for my code to use. To that end I realised its probably time to throw a quick calculator together to make this quick and painless. And being an open source fan I thought it might be helpful for someone else having afternoon brain fade.

So here it is, a simple spreadsheet with some numbers and some reference material, and even a picture! Put in your resolution, voltage reference, voltage divider resistor values and it will give you the multiplier values to turn a raw ADC result into a float in volts or millivolts! It will even highlight if you are trying to measure a voltage that is out of range, so you can fiddle with voltage divider resistor values till something works. Here's a screenshot and the .xlsx file is attached here:

Edited to calculate resolution from total number of possible values instead of full scale value (ie. divide by 1024 instead of 1023 for a 10 bit resolution) thanks to the patient forum members who pointed this out to me :slight_smile:

ADC_calc.zip (18.7 KB)

1 Like

3.3 / 1024 = 0.00322265625, aka 3.22265625mV

Just saying...

@anon56112670 yes you are correct, however when calculating mV per ADC step, we need to look at the total number of voltage steps or transitions and not the total number of possible values, and this is always total number of possible values minus 1 (1023 for a 10 bit resolution). A simplified way to see this is if we reduce our resolution all the way down to 1 bit. Technically a 1 bit resolution still has two possible values, however if we divide 3.3 by 2 we end up with 1650mV. A result of 0 calculates to 0V as expected, but a result of 1 calculates to 1.65V instead of 3.3V as it should.

Realistically no-one is going to see a scale error of 1 in a 10 bit setup (the noise is usually at least 2-4 LSB in the real world with no filtering anyway). So it's not exactly a major problem if you go with 1024 instead of 1023 :grin:

No.
Wrong.
A reading of one represents 1.65V or more

1 Like

Incorrect.

You can both calculate it that way if you like, however you will never reach full scale by calculating it that way. Using 1024 as the divider and reading 3.3V will give you a result of 3.297V, whereas calculating with 1023 as divider gives the correct value, so.... Whatever you like :slight_smile:

There is no "correct value" if the ADC reads 1023.

The integer returned by an ADC always represents a range of possible values, and a value of 1023 simply means that the input voltage is equal to or above the threshold.

1 Like

So how many people actually read a value and then treat it as a range instead of a figure in the real world? To me FSD = VREF is more logical than FSD = VREF - 1LSB.

Unfortunately, few Arduino users understand how an ADC works, and many of them make the mistake of assuming that the answer is exact. This means that they also don't understand why resolution is important.

It is not a good idea to pander to those mistaken assumptions. Instead, point them to decent tutorials, like this one. Gammon Forum : Electronics : Microprocessors : ADC conversion on the Arduino (analogRead)

To me FSD = VREF is more logical than FSD = VREF - 1LSB

Neither is correct, though. The "correct" value is unknown.

2 Likes

O.M.G. ... we must be careful about pointing one off in the Internet will just confuse them more ...
ADC, use 1023 or 1024? at DuckDuckGo

Did you look at that excellent tutorial? Scroll down to the section entitled "How to interpret the results".

Yep.
Tell 'em over at Adafruit, they obviously think differently:

Adafruit engineers, Nick Gammon and I agree that 1024 is the correct divisor.

1 Like

Add me... I did not scroll down nearly far 'nuff on Nick's page... just catching the highlighted 1023

Thanks @jremington for linking this in, my humble apologies for previous ignorant posts. That makes sense now, I'm embarrassed to say I've been calculating it this way since the days of programming PIC MCU's in ASM 15 odd years ago, so haven't spent alot of time googling this - amazing to see how much discussion there is around one 1024th of a number haha :laughing: Amending spreadsheet... Thanks for your patience!

Yes! Unfortunately , as many people have pointed out, the difference between 1023 and 1024 is usually insignificant compared to other popular but wrong assumptions, for example, assuming that Vref for the ADC is "exactly" 5.000 V.

That can be off by as much as 10% in some cases.

Yes that's true, at the end of the day it is still important to not be misleading, which is what I was originally doing (albeit unintentionally).

I like Nick Gammon’s numerator of (ADC+0.5) along with Alvy Ray Smith’s “a pixel is not a little square”

Taken together, Nick’s numerator and denominator:

Vadc = Vref * ( ADC + 0.5 ) / 1024;

…names each of the 1024 boxes between 0 and Vcc with their midpoints and has the happy side effect of avoiding divides by zero and logs of 0 for things like voltage dividers and thermistor calculations.

Alternately, you can name the 1024 intervals by their 'floors' using Vref*ADC/1024 to name the bottom interval zero; or name the 1024 intervals by their 'ceilings' with Vref*(ADC+1)/1024, to get a the top interval named Vref; or finally, the bastardized mix of the bottom interval named by its floor and the top interval named by its ceiling using Vref*ADC/1023 but that madness is susceptible to off-by-one errors.

My take on 1023 or 1024: If the ADC result shifts by 1, the input value (or range of values) shifts by 1/1024 of the full scale. Yes, a result higher than 0x3F (1023) is impossible, but the shift-per-step remains 1/1024.
I will use 1024 anyday.

1 Like

Oh dear. The main "error" wasnt the 1023 - it was this:

A 10 bit adc with an analog reference of 3.30V DOES NOT give 3.2226563mV.
NOR does it give this: 0.00322265625V

you cant get 12 decimal digit resolution from a 10 bit digital value.

Nor is the ADC precise or linear to that degree of accuracy. Especially near zero.

So why give a conversion fator that would lead an inexperienced user to believe his reading of 1 from the adc means their input voltage is 0.00322265625V?