Dividing by 1023 or 1024? The final verdict on analogRead

The correct answer is: 1024 (but the error is so small if you use 1023, it actually doesn't matter since the reference volt will vary with a much larger margin of error than your calculation will introduce).

But in case you are still wondering why not 1023, here it is.

After reading many responses from many posts on this exact issue (and some go into very technical detail why it should be one or the other), the bottom line is this:

The confusion boils down to a simple miss interpretation of the facts (and some confusion caused by the math).

NB: The result from analogRead() is not a value (as we would like to think of it when measuring something), its an index. Its an index to a bin number in which the measured value fits, and there are 1024 bins (which has to represents the whole range of values you want to measure).

The first bin number (or bin ID number) is 0, the second bin is 1, the third is 2 etc. until the 1024th bin which has an ID number of 1023.

When you use the equation of (1023/1024)*5 to prove me wrong, since the answer is not 5 (as you want it to be when measuring 5Volt with a 5Volt reference and analogRead()=1023; then you are missing my point!

This is the issue with converting analog values into digital values. With Digital values, there are no in-betweens. A lot of the detail actually gets lost, and more so when we have fewer bins to fit a large range of values into.

Example: If the reference voltage Vref is 5Volt, and the input value is 5Volt, I expect analogRead to provide me with 1023 (the last or highest bin number in the range) so I can interpret that at as 5Volt.
When analogRead gives me 0, I expect the value to be 0 Volt.

BUT now, in which bins would you like to put 0.0001 Volt or 4.999 Volt? When is the value measured too big for the first bin or too small for the last bin?

The fact of the matter is, you only have 1024 bins to put all the values in from 0 to 5 Volt, which is good enough for most things, but it does show a bit of a problem when we want to work back from the digital bin number to the original measured analog number.

With only 1024 bins, and if the range of volt values we want to measure goes from 0 to 5 Volt, it means each bin is 5/1024 = 0.0048828125 Volts "big", which means, measured values from 0 to 0.004882812 will fit in the first bin (bin 0) and values from 4.9951171875 to 5 (and more) will fit in the last bin (bin 1023).

So, the bottom line is that in the analog world, there can be millions of different measured volt values between 0 and 5 volt, but in this 10bit digital system of ours, there can only be 1024.

This means unfortunately that if I read a value of 0 using analogRead(), the value can be anything from 0 to 0.00482...V and if I read a value of 1023, the actual value can be anything from 4.995112... to 5 volt (and more).

So back to the original question: 1023 or 1024?

If you use 1023, your bins are actually larger because you use 1 less bin and 1/1023=0.0009775...V versus 1/1024=0.0009765...V). This means that when analogRead()=1023, the value you calculate may be 5volt using the formula "value/1023*5", but it actually also include smaller values down to 4.995112...V, since those values will also fit in the same bin.

When you use 1024, the bins are smaller, and thus 5*1023/1024=4.995117, which is the smallest value that will fit in the same bin.

In short, 1024 is actually more accurate to use, eventhough the math may let you to believe its wrong!

1 Like

(deleted)

Or you could simply read the processor's datasheet, where the section on the ADC states:

ADC = (VIN * 1024) / VREF

and

"0x000 represents analog ground, and 0x3FF represents the selected reference voltage minus one LSB."

And you can divide by 1024 with >>10

...R

...which is probably what the compiler does for you.

... unless you are using float

TolpuddleSartre:
...which is probably what the compiler does for you.

I don't think it converts divisions by powers of 2 into right-shifts

...R

Robin2:
I don't think it converts divisions by powers of 2 into right-shifts

...R

Write a test sketch, the proof is in the pudding test ....

Interesting - I doubt the AVR has a barrel shifter.

Smaller powers of two divides will be done with shifts though, unless the compiler is exceptionally dumb.

robtillaart:
Write a test sketch, the proof is in the pudding test ....

I believe I did some time ago - hence my comment, but I am not certain.

...R

NB: The result from analogRead() is not a value (as we would like to think of it when measuring something), its an index. Its an index to a bin number in which the measured value fits, and there are 1024 bins (which has to represents the whole range of values you want to measure).

Because the values returned by analogRead() are the indices, we need to calibrate these indices with respect to two known points in order to figure out the exact value of the unknown input voltage of the ADC. What are these two known points:

1. 0V at the input of the ADC ----> ADC produces 00 0000 0000
2. 5V (equal to VREF = Full Scale) at the input of ADC ----> ADC produces 11 1111 1111
3. VDC (unknown voltage) at the input of ADC -----> ADC produces ? (say, ADC)

ADC = ((11 1111 1111)/5)*VDC = (1023/5)*VDC

  1. 5V (equal to VREF = Full Scale) at the input of ADC ----> ADC produces 11 1111 1111

As does 5 - (5/1024) V.

See my earlier quote from manufacturer's datasheet.

What are these two known points

So then you go and list three points ! :smiley:

1023 or 1024, no significant difference, 1024 would be the # as per manufacture.

Seems like this thread has turned inside out, we are better than this.

I don't know what "inside out" means in this respect, but I suspect this thread doesn't belong in this section, and I'd be happy for it to be closed or moved.
I'm pretty sure this must have been discussed before, but yes, it is a bit of a "Angels on a pinhead" sort of thread.

So then you go and list three points !

A linear system like the ADC of the ATmega328 requires only two point responses for calibration?

If you want your results to read 0 to Vref and are willing to live with less error than you can measure, divide by 1023.

If you want to be a pedantic-retentive obsessed with correctness you can never show or use, divide by 1024 and feel superior.

GoForSmoke:
If you want your results to read 0 to Vref and are willing to live with less error than you can measure, divide by 1023.

If you want to be a pedantic-retentive obsessed with correctness you can never show or use, divide by 1024 and feel superior.

Doing things deliberately wrong/incorrect would make me feel dumb, how about you?

Whandall:
Doing things deliberately wrong/incorrect would make me feel dumb, how about you?

Can I give you a hug?
Would that be awkward?

Whandall:
Doing things deliberately wrong/incorrect would make me feel dumb, how about you?

First I make sure it's actually "wrong", noting that slavishness to one form of error is not "right".

When the error is below the noise level of somebody's idea of "right", that's how insubstantially small their claim is.

I'd feel dumb claiming either way to be right when both ways yield errors when used to convert ADC to analog values.
I'd feel even more dumb if I couldn't see that as fact and then decide which one serves my app best.

If you want your results to read 0 to Vref and are willing to live with less error than you can measure, divide by 1023.

If you can't stand knowing that the hardware has 1024 steps and you have a need to keep that from abstraction then you should know that you have not improved accuracy and now can't get any result showing signal in either the 1st Vref/1024 or the last Vref/1024 part of the range regardless of the voltage measured, which seems a bit funny for "right" doesn't it?

When I compare the two, I prefer the first since the error is less than noise and at least near 0 gives me 0 and near Vref gives me Vref.

Purity to hardware that is supposed to be approximating something else, it's the something else that I want. If the way I get that does not cause actual as opposed to supposed bad data and that way covers a GAP in the supposed right way at the same time, no I don't feel dumb taking that bit of win at all. I wonder at the ones who don't! Perhaps 3 factors at once confuse them?

PS -- I get a big laugh at people who go on about preserving the "purity" of what is not pure.

So my question for those is: Why does analog oversampling work?

1/1024 = 0.000976562
1/1023 = 0.000977517
Difference when Vref is 5V is less than 5 microvolts.

THINK

1 Like

GoForSmoke:
PS -- I get a big laugh at people who go on about preserving the "purity" of what is not pure.

Reminds me of the story about the engineer, the mathematician and the economist who were at the door to a room with an attractive woman (or man, I guess) in the room at the opposite wall. They were told that they could kiss the woman if they could get to her by following a simple rule.

They could start to cross the room with the longest step they could make, but each subsequent step would have to half the distance of the previous step.

The engineer asked how would he know what direction to go.

The mathematician said it was impossible.

The economist said that after 4 steps he would be close enough.

...R