Go Down

### Topic: Dividing by 1023 or 1024? The final verdict on analogRead (Read 8041 times)previous topic - next topic

#### GolamMostafa

#90
##### Apr 01, 2018, 06:40 pm
Quote
Step 0 0 to 4.8828124mV
Step 1 4.8828125 to 9.765624
...
Step 1023 4.9951171875 to 5.0 V
First of all, we need to be agreed on the definition of what a step is.

A step is to be counted before making the step or after making the step?

In the quoted text, a step has been counted before making the step; so, there are 1023 steps.

If the steps were counted after making the steps,there would be 1024 steps?

Step 1 0 to 4.8828124mV
Step 2 4.8828125 to 9.765624
...
Step 1024 4.9951171875 to 5.0 V

#91
##### Apr 01, 2018, 06:50 pm
I was not clear in my post that step number = count number. So I can't replay the second half.

If a step is "counted before" making the step there are still 1024 steps just as there are 1024 possible input values (counts, steps).

If you wrote the steps
Step (count) 0 0 to 4.8828124mV
Step (count) 1 4.8828125 to 9.765624
...
Step (count) 1023 4.9951171875 to 5.0 V
with if statements or a case statement there would be 1024 options.

The question is what voltage do you select to output for each step. If you want step 1023=5.0V, then step 0=4.88125mV, and the ADC would never output 0V.

How is it justified to output 0V for count=0 and 5.0V for count = 1023 when each count spans a range of voltages?

#### Smajdalf

#92
##### Apr 01, 2018, 07:40 pm
Using 1024 has the advantage that the maths can be much faster (but not using map() ).
When you make the mistake to convert ADC result to float you are wasting so much time. The improvement gained by using /1024 instead of /1023 is small if any.
If you want to make the code fast you should use raw ADC result and avoid the division at all. If you want easily readable result you probably do not care about speed (presenting the result to the user will be more likely your bottleneck).
How to insert images: https://forum.arduino.cc/index.php?topic=519037.0

#### Paulnaude01

#93
##### Apr 02, 2018, 01:46 pmLast Edit: Apr 02, 2018, 01:49 pm by Paulnaude01
I didn't expect any replies on this topic, I thought it would be old news by now! If I could end this thread I would, but let me see if I can put it to rest with a few pictures, explaining what we are dealing with.

In this image above, I show the possible Analog input (readings) and two possible digital conversions: 4bit (for simplicity sake) and 10bit, what the Arduino uses.

When any analog Volt value is read, it is converted to digital by simply putting it in the bin directly below it.

To be clear, the bin number, is NOT a volt value. It's an ID number, just like a trash can in the street with your house number on it.

Let me work on the house and trash can analogy a bit:
Imagine your are the cleaner who needs to empty the bins, and you find a rare empty bottle of Wiskey in one of the bins. You will be able to tell from which house this comes by simply looking at the bin number, right?

But what if some of the houses shares a bin? How will know from which house it comes then?

This example tries to show 3 things:

1) The more bins we have, the better change we have at estimating where the bottle comes from.
2) If we know there are four houses, but give them only 3 bins to put their trash in, we will be less sure where the bottle comes from.
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.

Now back to the measurements:

In the example above (just looking for now at the 2 bit A2D conversion), the first two measurements (0.3 and 1.1) will land in bin 0, nothing in bin 1, 2.6 in bin 2, and 3.9, 4.1 and 4.9 in bin 3.

Now remember, once we have the digital (bin) numbers, we know nothing anymore of the original values.

All we know now is this:

NB: No matter what you do, once the value is converted to digital, there is now way of going accurately back to the original analog value (only more or less inaccurate ways)!

The same holds true for the 10bit (1024 bins) system. Your Arduino reports a bin number, not a voltage.

Since there are 1024 bins, that is the number to use, but, if you argue that 1023 is more convenient, since it can produce both 0 and 5Volt output values in your display, there is some merit to your madness, since lets be honest, the error is really small:

5/1024 = 4.883mV
5/1023 = 4.888mV

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

But just understand, that when using 1023, although it might be convenient, adds to the inaccuracy since more measurements will be reported as 0 than when using 1024, as well as more values that will be reported as being a full 5V when in fact it should have been less.

So make your bed, and sleep in it!

Good night.
Paul

#### TolpuddleSartre

#94
##### Apr 02, 2018, 01:55 pm
Or, put more succinctly, you could RTFM, and see what the device's own manufacturer recommends..

Just a thought.

#### Robin2

#95
##### Apr 02, 2018, 03:18 pm
Or, put more succinctly, you could RTFM, and see what the device's own manufacturer recommends..
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.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

#96
##### Apr 02, 2018, 03:49 pm
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.

#### TolpuddleSartre

#97
##### Apr 02, 2018, 03:54 pm
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.

...R
Quote
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.

#### Robin2

#98
##### Apr 02, 2018, 06:25 pm
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
Two or three hours spent thinking and reading documentation solves most programming problems.

#### zoomx

#99
##### Apr 02, 2018, 09:01 pm
Maybe is written here
Quote
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?

#100
##### Apr 02, 2018, 09:04 pmLast Edit: Apr 02, 2018, 09:13 pm by Coding Badly
I didn't expect any replies on this topic...
Surprise!

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.

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.

Thanks!

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.

#101
##### Apr 02, 2018, 09:11 pmLast Edit: Apr 02, 2018, 10:42 pm by adwsystems
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.

#### Smajdalf

#102
##### Apr 02, 2018, 09:48 pm
That may be true for your references but it is not true for mine.
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.

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.
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.

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.

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.
How to insert images: https://forum.arduino.cc/index.php?topic=519037.0

#103
##### Apr 02, 2018, 10:42 pmLast Edit: Apr 02, 2018, 10:51 pm by adwsystems
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/1023*5 = 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/1023*5 = 2.5024437V; just a smidgen higher than 512/1024*5=2.5V but not quite to the upper bound value.

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/1024*5 = 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.