Dividing by 1023 or 1024? The final verdict on analogRead

In real life, we all bodge things, but I still think it is better if you know the underlying principles, for those edge cases where it will matter.

I guess I’ll just have to live with my feelings of being superior correct and literate.

Now that my interest has been awoken sufficiently to read the Atmega328 datasheet …

The data sheet clearly states what is in Reply #2
ADC = (VIN * 1024) / VREF

However if you imagine a very crude ADC that can only report the values 0, 1, 2, 3, 4 and 5 for a range of 0v to 5v you can easily see that the only sensible calculation is
ADC = VIN * number of intervals / VREF

For example, if Vref is 5v and Vin is 3v the calculation will be 3 * 5 / 5 = 3

For the Atmega 328 the number of intervals is 1023, not 1024. And if the crude ADC was to mimic the Atmega datasheet the calculation would be 3 * 6 / 5 = 3.6 which should round to 4 and which would be incorrect. Of course an integer only system would report 3 (rounding down) so the error would not appear.

All of which leads me to believe that the Atmega 328 ADC is not sufficiently precise for it to matter whether you use 1023 or 1024. And that the assertion that started this Thread has no basis in theory and (as the OP acknowledged) does not matter in reality.

…R
(Runs for bomb shelter)

TolpuddleSartre: In real life, we all bodge things, but I still think it is better if you know the underlying principles, for those edge cases where it will matter

Knew this years ago. I understand what the device does and how precise it is not.

If I give it 5V and it tells me 1023 that really means 4.995V to 5V if I go by numbers alone. That's a 5mV step.

The difference between 1/1023 and 1/1024 is less than a thousandth of that. Yeah... bodge... uhuh.

Let me know when you figure out the underlying realities including what the ADC is for.

Robin2:
Now that my interest has been awoken sufficiently to read the Atmega328 datasheet …

The data sheet clearly states what is in Reply #2
ADC = (VIN * 1024) / VREF

However if you imagine a very crude ADC that can only report the values 0, 1, 2, 3, 4 and 5 for a range of 0v to 5v you can easily see that the only sensible calculation is
ADC = VIN * number of intervals / VREF

For example, if Vref is 5v and Vin is 3v the calculation will be 3 * 5 / 5 = 3

For the Atmega 328 the number of intervals is 1023, not 1024. And if the crude ADC was to mimic the Atmega datasheet the calculation would be 3 * 6 / 5 = 3.6 which should round to 4 and which would be incorrect. Of course an integer only system would report 3 (rounding down) so the error would not appear.

All of which leads me to believe that the Atmega 328 ADC is not sufficiently precise for it to matter whether you use 1023 or 1024. And that the assertion that started this Thread has no basis in theory and (as the OP acknowledged) does not matter in reality.

…R
(Runs for bomb shelter)

The ADC does have 1024 steps. The zero step covers 0V to Vref/1024 (just under 5mV whenVref is 5V) returning 0.

28.6.3.
ADC Accuracy Definitions
An n-bit single-ended ADC converts a voltage linearly between GND and V REF in 2 n steps (LSBs). The
lowest code is read as 0, and the highest code is read as 2 n -1.

2^0 to 2^(1024-1) and we get n as the return, 1024 possible values.

The fun comes when reducing a range of values to a number treated as volts. We measure a smudge and give it a number.

The most of time closest number would be in the middle of the range and never be either 0V or 5V.

By dividing by 1023, I cover both ends in the math with a calculated 1/1024 error, looking at less than 5 microvolts.
Unless I need to show or calculate down to 6 decimal places, it’s not a problem. But if I do, I want a different ADC.

For more details on ADC, check with Nick;
http://www.gammon.com.au/adc

This all needs to be in the 'Introductory tutorials' forum. :(

Perhaps the OP will consider replies, but seems pretty set from the start.

Most users want to be able to jumper 5V and see 5V displayed or jumper GND and see 0V displayed.

Now another person might make quicker and easier sense just viewing the ADC value, coding to it and never converting it to volts. And divide by what ceases to be an issue.

GoForSmoke: The ADC does have 1024 steps. The zero step covers 0V to Vref/1024 (just under 5mV whenVref is 5V) returning 0.

In the range 0 1 2 3 4 5 there are 5 intervals. 5 - 0 = 5

I am inclined to think that if I wrote out all of the numbers from 0 to 1023 I would have 1023 - 0 = 1023 intervals.

...R

char buff[ 1024 ]; // has how many elements and what is the high index?

GoForSmoke:
char buff[ 1024 ]; // has how many elements and what is the high index?

I agree there are 1024 numbers. But there are only 1023 intervals between those numbers.

…R

Do you mean?

Divide 1024 by 1024 and you can cover one end (0V to 4.995V) or the other (0.4883 to 5V) and either way the range is open-ended.

Divide by 1024 by 1023 and you have 1 extra that closes the end.

The error is 6 decimal places down, Arduino floats guarantee 6 places total and ... they're dirt-in-the-sand IEEE 32-bit FP.

At least work to the ADC value where possible, it's the conversion of ranges to values that forces errors.

I'll just leave this here. (Drops mic)

If you can't answer points, imply everything comes down to a single issue.

With a 1.024V ref I can work the 10 bits of the ADC ladder value as factors of 1 mV, knowing instrument error from specs. Please understand that doing so does not involve conversion to volts and treats the ADC value as a range.

If you fixate on hardware details you may lose signt of the what you're doing with them part. Or you're a EE.

GoForSmoke: Do you mean?

Look back at the 0-5 example in Reply #21

At least work to the ADC value where possible, it's the conversion of ranges to values that forces errors.

I agree 100%. I am just pursuing this Thread for intellectual fun.

...R

The fun part is that with a 1.024V Vref, just going by 1mV x ADC the most you get is 1.023mV.

AVR has a built-in 1.1V Vref for 1.074mV steps x highest possible read 1023 = 1.099V.

If that 1.1V could be voltage divided to a 1.023Vref (perfect world), that would be conversion-friendly IF you're into converting.

ADC/1024 is correct, and ADC/1023 is wrong!

Let say we have just 1 bit ADC, 0 or 5V. Just two possible values. Should be /0 used?

And here is for n=5:

First *x/(n-1) math:                                                              
input voltage   ADC value   ADC*x/(n-1)   result   average error   output
4.00-4.99       4           *5/4          5.00     +0.50           5          
3.00-3.99       3           *5/4          3.75     +0.25           3
2.00-2.99       2           *5/4          2.50      0.00           2
1.00-1.99       1           *5/4          1.25     -0.25           1
0.00-0.99       0           *5/4          0.00     -0.50           0
Note that for the 5 possible ADC values, the output scale now has 6 values (0-5)
and the value 4 can never occur! And although the average error might look to be
nicely distributed +/- the centre of scale, the actual output result proves to be
much uglier. For slowly increasing voltage, the ADC would read; 0, 1, 2, 3, 5!!!
The maximum error in real world use is 2V, because that very tiny change of
3.999V - 4.001V would cause an output change of 3V -> 5V or a change of 2V!
Correct scaling math *x/n: 
input voltage   ADC value   ADC*x/n       result   average error   output   
4.00-4.99       4           *5/5          4.00     -0.50           4           
3.00-3.99       3           *5/5          3.00     -0.50           3           
2.00-2.99       2           *5/5          2.00     -0.50           2           
1.00-1.99       1           *5/5          1.00     -0.50           1           
0.00-0.99       0           *5/5          0.00     -0.50           0                                                                                            #
All output values are properly scaled and all are represented. The average error
is never greater than 0.5 (no more average error than the /(n-1) example),      
the average error is always one fixed value (-0.5) making it very easy
to compensate. The maximum error at any time is 1V, this is half the max error of
the /(n-1) example, which can introduce extra error up to 1 in high value ADC
readings

Referring to Reply #34 ...

I think the assumption that 4.00 to 4.99 gives 4 and 3.00 to 3.99 gives 3 is incorrect. I would expect 4.5 to 4.99 to give 5 and 3.5 to 4.49 to give 4

...R

Please, can someone put this thread out of its misery?
Oh, the humanity!

Let say we have just 1 bit ADC, 0 or 5V. Just two possible values. Should be /0 used?

No, because 21 is 2, so by GoForSmoke’s logic, we would divide by 1.

Maybe it is time to move it to Bar Sport ?

...R

...and this thread explains why binary logic wins! We don’t need no stinkin’ analog!

Zero or One - none of this warm, fuzzy stuff. It just confuses things. ;) Can we kill this thread? Although it has had interesting moments!

Maybe it is time to move it to Bar Sport ?

It's very interesting that the OP has not yet made any comment; but, you want move to the Bar Sport leaving him behind?