Go Down

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

Coding Badly

So your answer is B: The output changes to 1 at Vref / (2^bits) + 1uV.
Ugh.  Neither post includes "1uV".  The answer is no, the output does not change to 1 at Vref / (2^bits) + 1uV.


Cutoff = Vref / (2^bits)

For your example...

Vref = 5 volts
bits = 10

So...

Cutoff = 5 / (2^10) = 0.0048828125

Which means...

For input voltages less than 1 * 0.0048828125 volts, a successive approximation analog-to-digital converter returns a zero.

For input voltages greater than or equal to 1 * 0.0048828125 volts and less than 2 * 0.0048828125 volts the ADC returns a one.

For input voltages greater than or equal to 2 * 0.0048828125 volts and less than 3 * 0.0048828125 volts the ADC returns a two.

Etcetera.


adwsystems

It would have been less typing to just say: C-neither - Vref / (2^bits)

Which I did not derive from either of the posts that you recently linked.

If you wanted to expound, the ADC stays 0 until Vref / (2^bits) -1uV.


Coding Badly


You are welcome.

Oh.  Wait.  You don't appear to be grateful.  Never mind.


GoForSmoke

Say hello to your personal definition of "best fit".

For everyone else, "best fit" happens when ADC counts are interpreted as being at the midpoint in a bucket.

Sure, transistor tolerances just like all manufacturing tolerances and standardization are my personal definition, uhuh.

added:
This must be why there's a thread on denying the utility of dividing by 1023. Because of me. Everyone else knows better. This just gets funnier.

added:
Just because your calculator spits out a string of digits, reality only matches so many in a row.
The ADC step is almost 5mV wide with 5Vref, you can stop at 2 decimal places.
1) http://gammon.com.au/blink  <-- tasking Arduino 1-2-3
2) http://gammon.com.au/serial <-- techniques howto
3) http://gammon.com.au/interrupts
Your sketch can sense ongoing process events in time.
Your sketch can make events to control it over time.

Robin2

Cutoff = Vref / (2^bits)

For your example...

Vref = 5 volts
bits = 10

So...

Cutoff = 5 / (2^10) = 0.0048828125
That seems to be a very helpful way of expressing it, and I believe it is correct.

However, in one sense it is a lot more crude than I had expected, and in another way it answers a doubt that was in my mind when I wrote Reply #67.

If you imagine a 2-bit ADC - which can return values 0, 1, 2,and 3 and if you imagine that Vref is 4v. Then the cutoff will be 4 / (2^2) = 1. Which means that the changeover points will be 1, 2, and 3. The reason I see that as crude is that anything up to 0.999v will be reported as 0. And the answer to my doubt is that, by not having the changeover points at the half-way points there is no need to figure out how the first and last half divisions need to be figured (for example 0.5 and 3.5 in the simple example).

Now, what does that tell us about the process that started this Thread - how to convert the ADC value back to the voltage from which it was derived.

If the simple ADC produces a value of (say) 3 we can convert it back to a voltage either with Vref / 2^n * ADC (the equivalent to using 1024) or Vref / (2^n) - 1 (equivalent to using 1023 - the number of intervals)
4 / 2^2 * 3 = 3 and 4 / (2^2) - 1 = 4
Which is the correct answer?

The ADC would have produced 3 for an input voltage between 3v and 3.999v and we cannot know any closer than that what actually happened. So, in a sense, neither answer is correct and a better answer would the average of them - 3.5v.

Which I think can reasonably be extrapolated to the real 10bit ADC by saying that either calculation will be close enough.

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

GoForSmoke

 It's not like anyone is being forced to only convert to volts one way... yet. But the holy warriors have been triggered. 
1) http://gammon.com.au/blink  <-- tasking Arduino 1-2-3
2) http://gammon.com.au/serial <-- techniques howto
3) http://gammon.com.au/interrupts
Your sketch can sense ongoing process events in time.
Your sketch can make events to control it over time.

GolamMostafa

#81
Mar 31, 2018, 01:05 pm Last Edit: Mar 31, 2018, 01:06 pm by GolamMostafa
Quote
It is possible to know how to do something in practice without knowing the theory. The method by which aircraft wings generate lift is a good example.
The aircraft wings generate upward lift owing to the very universal law of the fluid mechanics. The technician was just lucky that the wings were fit together and the law worked well or the technician was highly intellect like the people of the Feroun's times who built the arches without knowing the geometry and the solid mechanics?

Robin2

The aircraft wings generate upward lift owing to the very universal law of the fluid mechanics.
Perhaps you would be good enough to start a new Thread (in Bar Sport) and explain how it works.

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

Smajdalf

I was planning to start a thread with similar title for a long time. Now I feel I must act now and support GoForSmoke against "1024 holy warriors".
Often when someone shows a code where 1023 divider is used to convert ADC reading to volts a "holy warrior" jumps up and tell them 1024 is the right divider and using 1023 is utterly wrong. I believe this advice is evil and should be punished with eternal torment. These are main reasons for this:

1) The advice implies the ADC is so precise difference between 1023 and 1024 matters. A noob often expects to get 5mV resolution and accuracy from the Arduino's ADC. But since default reference is noisy and poorly regulated 5V from a USB port total accuracy of Arduino is very poor. And there is a lot of other sources of error much more important than 1023 vs 1024.

2) Also it implies converting ADC reading to "real voltage" is the right way how to work with the result. In most applications there is no reason to convert the integer ADC result to float "real voltage". It only costs a lot of resources and adds nothing. Usually you want to compare the measured voltage to a threshold. "The right way" is to calculate (or find experimentaly) the threshold value directly in ADC "units".

2b) Only reason I can imagine to convert ADC result to "real voltage" is to show something to the user. For example you measure a wiper of a pot and show its position in %. When you use 100.0*ADCResult/1024 formula I expect the user to be quite disappointed to have range of values from 0 to 99.9%. When you use 100.0*ADCResult/1023 you get the expected range 0-100%.

3) Supporters of the 1024 divisor claim it is "the correct number". Since one ADC value represents a whole interval of possible voltages - (uncountable!) infinity of values - there is no single correct voltage corresponding to given ADC result. You can define criteria how to choose "the best value" from the infinity of possibilities. But then "the best value" depends on the chosen criteria. And there are good reasons for both 1024 and 1023 divisors. Let alone many other possibilities how to choose the right value. (For example I often use ADCResult*5 to show measured voltage in mV. Since my USB provides more than 5V it gives results closer to real value than "correct" ADCResult*5.0/1024).

In short - telling a noob to use 1024 instead of 1023 will not help them to get better results but will support bad habits and wrong beliefs. And that is evil.
How to insert images: https://forum.arduino.cc/index.php?topic=519037.0

lastchancename

#84
Apr 01, 2018, 01:37 am Last Edit: Apr 01, 2018, 01:38 am by lastchancename
While we're here...
How many of your Arduinos are running at a rock-solid EXACTLY 5.00V (or 3.30V)

I doubt many at all.
So that lost resolution is fairly academic unless you're using an external precision AREF
Which is fair enough - but worth considering
Experienced responders have a nose for laziness, (they were beginners once)... Sure, there are trolls, chest-beaters, and pretenders - but the help you'll get here is about as good as it gets - if you try to help youself!.

GoForSmoke

Turning ADC 10 bit to voltage different ways, it's okay to use what fits your app.

mV = Vref * ADC / 1024 

mV = Vref * ADC / 1023

mV = Vref * ( ADC / 1024 + 1/2 step )  ---- best guess


I see far more people use analog to check the rough position of a pot. They don't need to calculate volts but so many do!

If the analog read is to be processed with a fixed calculation or one from several then I would pre-calculate and table all the possibilities to look up. If the result is a float then think of the cycles saved. The result could as easily point to a function to run.

1) http://gammon.com.au/blink  <-- tasking Arduino 1-2-3
2) http://gammon.com.au/serial <-- techniques howto
3) http://gammon.com.au/interrupts
Your sketch can sense ongoing process events in time.
Your sketch can make events to control it over time.

larryd

No technical PMs.
The last thing you did is where you should start looking.

zoomx

I know that this topic is most academic but in my mind a question arise.
If I apply only a linear fit using data 0,0V 1023,5V it seems that I have to use 5/1023  (Vref is 5V)
The datasheet (and some other reasons) states that instead I have to use 1024

My question is: maybe the ADC is not able to recognise well values just below Vref, 5V in my example? If I use the bucket example there is a possibility that the last bucket is bigger than the previous, it is large 2*5/1024 instead of 1*5/1024?

Robin2

If there is any message coming out of this Thread it is that it does not matter in practice whether you use 1023 or 1024.

Using 1024 has the advantage that the maths can be much faster (but not using map() ).

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

adwsystems

#89
Apr 01, 2018, 06:27 pm Last Edit: Apr 01, 2018, 06:44 pm by adwsystems Reason: Added step=ADC count
This may be a case of you can't have your cake and eat it too.

Based on the conclusions by CodingBadly, there are in fact 1024 steps and each step covers a voltage range. So what voltage value do you choose to ouptut?

Step (count) 0 0 to 4.8828124mV
Step (count) 1 4.8828125 to 9.765624
...
Step (count) 1023 4.9951171875 to 5.0 V

If you make step 0 output 0mV, and step 1 output 4.8828125mV, then step 1023 would output 4.9951171875V. The ADC would never return an output of 5V.

How do you justify step 0 output the "lower bound" of the range and the last step output the "upper bound" of the range?

Go Up