Dividing by 1023 or 1024? The final verdict on analogRead

Paulnaude01:
3) If there are 10 people living in each house, we will still not know who's bottle it was, but with 1 bin per house, at least we can narrow it down a bit.

That is one of the unanswered questions. 10 people in one house, but you have to pick one person to report. Which person? The oldest, youngest, shortest, tallest? Whichever person you choose must be the same person for all the houses. You can't pick the youngest for the first house and the oldest for the last.

Robin2:
Except that Atmel was not brave enough to explain (in the Atmega 328 datasheet at least) how to convert an ADC reading back to the voltage from which the reading was obtained.

I don't think any of the subsequent comments have improved on @CodingBadly's Reply #75

...R

No, really, really RTFM. As in, download the datasheet, and read it.

The ADC converts an analog input voltage to a 10-bit digital value through successive approximation. The minimum value represents GND and the maximum value represents the voltage on the AREF pin minus 1 LSB.

TolpuddleSartre:
No, really, really RTFM. As in, download the datasheet, and read it.

I have had the datasheet for years. It is my constant bedtime companion.

It clearly explains how it converts voltages to ADC values. It does NOT explain how to convert ADC values to voltages.

...R

Maybe is written here

The minimum value represents GND and the maximum value represents the voltage on the AREF pin minus 1 LSB.

so 1023 represent aref-(aref/1024)?
So, as I wrote in #87, the last bucket is larger than the previous?

Paulnaude01:
I didn't expect any replies on this topic...

Surprise!

Paulnaude01:
In this image above...

The last bucket is bounded by the voltage limits of the device (VCC + 0.5 for AVR processors). If VREF is 1.1 and VCC is 5.0 then the last bucket is 1.1 - cut off to 5.5 for an AVR processor.

Paulnaude01:
a difference of 4.77microVolt (0.00477mV), much smaller than the expected fluctuations in the reference voltage in any case.

That may be true for your references but it is not true for mine.

Robin2:
I don't think any of the subsequent comments have improved on @CodingBadly's Reply #75

Thanks!

zoomx:
So, as I wrote in #87, the last bucket is larger than the previous?

The final bucket is larger than all the others. Correct. It is bounded by the physical limits of the device.

No matter whether you use 1023 or 1024 the bucket size is the same for each step. 5/1023 or 5/1024.

If you use 1023, then voltage value returned has a progressive shift from returning the minimum value to returning the maximum value. Count = 0 returns 0V for voltages from 0 V to just short of 4.887586mV (5/1023), but count = 1023 returns a value of 5V, and is returned for any voltage from 4.995112 through 5V.

If you follow the datasheet, then each bucket is 5/1024 volts and count = 0 returns 0 V for input voltage up to 4.8828124mV and count = 1023 returns 4.995117V for all input voltages from there to 5V. Using 1024, 5V is never returned; that is what the datasheet is saying.

This just shows how incompetent you are for this discussion. Using such precise reference for Arduino's poor ADC (typical error is 2 LSB!) is wasteful. You could get better resolution by using worse reference and better ADC for the same money. Or you can get the same resolution much cheaper when you use worse reference.

Robin2:
It clearly explains how it converts voltages to ADC values. It does NOT explain how to convert ADC values to voltages.

It does not say that because the whole idea of converting ADC result to voltage is silly. It gives hints how the ADC value is obtained. It is trivial to reverse the process. I don't understand why there is so much emotions about it.

adwsystems:
No matter whether you use 1023 or 1024 the bucket size is the same for each step. 5/1023 or 5/1024.

The bucket size is always Vref/1024.

adwsystems:
If you use 1023, then voltage value returned has a progressive shift from returning the minimum value to returning the maximum value. Count = 0 returns 0V for voltages from 0 V to just short of 4.887586mV (5/1023), but count = 1023 returns a value of 5V, and is returned for any voltage from 4.995112 through 5V.

Using 1023 divider you read 0V from 0V to 5/1024V. You read 5/1023V for input from 5/1024V to 10/1024V etc. But you are right the returned value is "drifting" in the correct range.

adwsystems:
If you follow the datasheet, then each bucket is 5/1024 volts and count = 0 returns 0 V for input voltage up to 4.8828124mV and count = 1023 returns 4.995117mV for all input voltages from there to 5V. Using 1024, 5V is never returned; that is what the datasheet is saying.

The datasheet does not say you should use 1024 and so you cannot get 5V! It just says 1023 represents voltage higher than Vref-1LSB. It is up to you what value you assign to this range.

Smajdalf:
Using 1023 divider you read 0V from 0V to 5/1024V. You read 5/1023V for input from 5/1024V to 10/1024V etc. But you are right the returned value is "drifting" in the correct range.

Not following you here. Where did you get 10 volts from?

I'm only looking at the math.
count 0 = 0/10235 = 0
count 1 = 1/1023
5 = 4.887586mV
count 1023 = 1023/1023 * 5 = 5V

As you can see count=0 returns the low end of the first range but count=1023 returns the top end of the last range. From that it can be concluded the values in the middle are on a sliding scale. Such that at count=512 the voltage computes to 512/10235 = 2.5024437V; just a smidgen higher than 512/10245=2.5V but not quite to the upper bound value.

Smajdalf:
The datasheet does not say you should use 1024 and so you cannot get 5V! It just says 1023 represents voltage higher than Vref-1LSB. It is up to you what value you assign to this range.

The value assigned to the voltage range where count = 1023 is Vref-1LSB.

The conversion formula in the datasheet is the count divided by the count range times Vref.

count 0 = 0/10245 = 0
count 1 = 1/1024
5 = 4.8828124mV
count 1023 = 1023/1024 * 5 = 4.995117V (which is exactly what the datasheet says)

Unless you put an if statement to check for 1023 and force it to return 5.

Smajdalf:
This just shows how incompetent you are for this discussion.

Either that or you grossly misunderstood the message.

Smajdalf:
It does not say that because the whole idea of converting ADC result to voltage is silly

I agree with that, and we established that way back when.

And, assuming that is also your view I don't understand the purpose of your Reply #102

...R

It's almost like most of the conversation never happened. I've even seen the same lame strawman raised again to a slightly different tune with the small number of bins.

It's almost like people can only interpret ADC data to hardware purity standards. You can get an answer that rounds up to 5V, just whatever you do, don't use shortcuts that profane the holy 1024!

There is no holy in 1024. The datasheet says that the ADC range is not 0-Vref but 0-(Vref-Vref/1024). The difference is very little because we have 10 bits but if, for example, we have only 2 bit it mean that the ADC range, if Vref is 5V, is only 0-4V because the ADC in Atmega328 works in this way.

I know. I just think that the purpose of the coder does not always require the most probable voltage (measured mid-step) nor does it follow the least approximation of Vref x ADC/1024.

0 - ( Vref - Vref / 1024 )

There's really 10 steps that get compared and 10 bits only ever adds up to 1023, 0 is the 1024th. I think there may need to be a voltage difference to read a step at all in which case the ADC can never measure Vref.

You could round up to the nearest 8 or 10 mV. If that's acceptable, you could divide by 1023 and be well within tolerance.

This is how I see this - may be we will get everyone to agree

Let's assume everything is perfect from a hardware perspective and no bias is introduced

  • you input a voltage [color=blue]V[/color] between GND and V[sub]cc[/sub]
  • analogRead() gives you a value of x

As documented in the datasheet, x represents any voltage between x * V[sub]cc[/sub] / 1024 and (x+1)* V[sub]cc[/sub] / 1024

That means that if you take [color=blue]V[sub]est[/sub][/color] = x * V[sub]cc[/sub] / 1024 as the measure, you are saying that you always take the lowest value of the interval as your estimated voltage read so you are always undershooting. It means that your max absolute error can be as big as V[sub]cc[/sub] / 1024 for every possible value of x. You have a constant distribution of the error

Now if you were to take the value divided by 1023: [color=blue]V[sub]est[/sub][/color] = x * V[sub]cc[/sub] / 1023 to represent a fair possible value, what does that mean?

There are two key questions:

#1/ Is this [color=blue]V[sub]est[/sub][/color] a fair possible original voltage value, ie are you within the right interval for every possible value of x?

#2/ what is the distribution of the max error for every possible value of x

for #1 it's easy to prove that for every possible value of x in [0, 1023]

x * V[sub]cc[/sub] / 1024 <= x * V[sub]cc[/sub] / 1023 <= (x+1)* V[sub]cc[/sub] / 1024

--> So [color=blue]V[sub]est[/sub][/color] = x * V[sub]cc[/sub] / 1023 is a possible value and thus mathematically as correct as any other value in the interval

for #2, it's best to see how [color=blue]V[sub]est[/sub][/color] moves across the possible interval depending on x


With this approach one sees (the blue arrow) that [color=blue]V[sub]est[/sub][/color] will vary between the min of the interval and the max when x varies between 0 and 1023

--> thus whilst it means that your max absolute error can be as big as V[sub]cc[/sub] / 1024 for x = 0 or x = 1023, for the other values of x, the max absolute error will be less and at x~511 you have divided by 2 the max absoute error compared to the other approach.

Conclusions:

  1. dividing by 1023 or 1024 gives in both cases a likely estimate of the original input value [color=blue]V[/color] and thus are both correct. everyone wins :slight_smile:

  2. dividing by 1023 statistically minimizes the maximum absolute error and thus it's fair then to assume that you get statistically a better approximation of your true original input value [color=blue]V[/color] if you use 1023

----> THIS IS WHY I THINK 1023 IS BETTER THAN 1024 (and you get a nice 5V for 1023)

That being said, the assumption we made initially that everything is perfect is never true...
error.png
so in practice you can do what you want, it does not matter much or if this level of precision is important for your project, then you probably need to invest in better hardware...

J-M-L:
This is how I see this - may be we will get everyone to agree

I reckon we had got there in Reply #75 and my summary in Reply #79.

Here's to the next 30 replies :slight_smile:

...R

Robin2:
I reckon we had got there in Reply #75 and my summary in Reply #79.

Here's to the next 30 replies :slight_smile:

...R

Not exactly expressed the same way, right? was a different attempt

How long since anything NEW was added that isn't a new rehashing of what was posted before.

Yeah OP, lay the "final verdict" down on us like you would have it. Now, Build That Wall!

J-M-L:
2. dividing by 1023 statistically minimizes the maximum absolute error and thus it's fair then to assume that you get statistically a better approximation of your true original input value [color=blue]V[/color] if you use 1023

The "statistical minimum" is obtained when the value is assumed to be in the middle of the bucket: VEST = (x + 0.5) * VREF / 1024

Yes that could be another formula :slight_smile:

The whole idea that people might have uses for hardware that don't completely match the hardware to the full set of not just significant digits but the insignificant digits as well simply never occurs to datasheet fetishists.