6

This is an extract of the official ATMEGA328p data sheet page 261:

enter image description here

As the documentation say

      Vin * 1024
ADC = ----------
         Vref

What I don't understand is an analog pin can provide us 10bits. That's mean a value between 0x0 and 0x3ff (1023)

So I don't understand why the documentation say Vin * 1024 and not 1023. Because for me 0v = 0 and 5v = 1023?

Fpasquer
  • 381
  • 3
  • 15
  • 1
    It should be 1023. Proof: If Vin=Vref (where Vref > 0, obviously), then *1024 won't fit the ADC register 10-bit result. The documentation is wrong as is the last sentence of the accepted answer. – tonypdmtr Aug 18 '19 at 12:30
  • 1
    There is no reason that VIN=VREF has to be exactly representable in the ADC result register. – David Grayson Aug 18 '19 at 16:19
  • 1
    Consider the case of a 1-bit ADC, and then of a 2-bit ADC if you actually want to understand the issue. – Chris Stratton Aug 19 '19 at 16:06

3 Answers3

7

0 counts as a valid reading. 1..1023 is 1023 steps and plus 0 that makes 1024. 0x000 represents analog ground, and 0x3FF represents the selected reference voltage minus one LSB. In reality, ADCs are not perfect as results can have more than 1 count of error and it really does not matter much if 1023 or 1024 is used. In theory using 1024 is more accurate.

Lakshitha Wisumperuma
  • 1,574
  • 1
  • 10
  • 17
  • 3
    "In theory using 1024 is more accurate." No, since 1024 won't fit in 10 bits. – Lundin Aug 19 '19 at 06:51
  • 1
    **When you consider the case of a 2-bit ADC, it becomes obvious that this is indeed the correct answer in that 2^n is the correct multiplier** That 2^n cannot be represented is a irrelevant; 2^n-1 and 0 are each codes representing a *range* of voltages, trying to reserve a code for Vin=Vref (and nothing less) is a fundamental error. – Chris Stratton Aug 19 '19 at 17:02
4

5v = 1024, yes, but you cannot measure 5V with 5V reference, the maximum value you can measure is 1023/1024 of Vref, i.e. if Vref=5V, then max value is 4.995V. This and all voltages above this will read as 1023 (0x3FF).

So, you're right, the Vref voltage requires value 1024 which requires 11 bits to store, but you never can measure that voltage using ADC.

But according to the datasheet (28.9 ADC Characteristics at page 265) Absolute accuracy of the ADC in ATmega328P is typically at 2.2 LSB, so you can be not worried about 1LSB error which appears if use 1023 instead of 1024 as the divisor.

But still, using of 1024 not only more correct in meaning of measurement, but also can be optimized in integer math, thus not requiring complex operations such as the division:

   // convert ADC value into millivolts (assuming Vref is 5000 mV)
   uint16_t result_in_mv = ((uint32_t)adc_result * 5000UL) >> 10;
AterLux
  • 4,566
  • 2
  • 10
  • 13
2

Yeah this is a common mistake. One thinks 10 bits = 2^10 = 1024 and so there will be 1024 steps, right? Nope, 10 bit ADCs only give output up to 1023 (3FFh), because that is the largest number you can fit into 10 bits.

So if you do arithmetic on 1024 instead of 1023, you introduce a very slight inaccuracy in the calculation. I've done this bug myself and it sat in production code for over 10 years without anyone noticing, and when I fixed the bug nobody noticed a difference either :) But naturally we should always strive for program correctness.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 1
    No. To understand why this is mistaken, try it with the case of a 2-bit ADC. In the logic of this posting, the thresholds for achieving each code would be 1/3, 2/3, and 3/3 of Vin - which are obviously wrong. In fact the boundaries should be 1/4, 2/4, and 3/4 of Vin. 2^n is in fact the correct multiplier, it's just that you cannot reach 2^n itself. The mistake originates in trying to reserve 2^n-1 *uniquely* for Vin=Vref (and nothing else), instead of realizing that every code represents a *range* of voltages. – Chris Stratton Aug 19 '19 at 17:00
  • 1
    @ChrisStratton Every code represents a range of voltages derived from 2^n-1 = Vref, 0=GND and it's just linear algebra from there. If you have no code for representing Vref, you can't calculate anything. With your strange 2 bit ADC example you can never measure Vref. With Vref = 5V you wouldn't be able to measure voltages higher than 3.75V. Mildly useful and obviously incorrect. Because when you measure the voltage 5V on the ADC channel, you would get the code 3. To then say that the voltage measured is actually 3.75V isn't helping anyone, least of all your equations. – Lundin Aug 20 '19 at 06:31
  • 1
    Because no code uniquely represents VRef, is is a **fundamental error** to expect a reverse calculation of the voltage from the code to ever yield VRef. If you want to apply a correction so that the maximum code yields the *average* of the voltages that could have converted to it instead of the minimum, then **the proper correction is additive not multiplicative**. Add 1/2 LSB or equivalent voltage to yield the voltage of the middle of each bin instead of the floor. – Chris Stratton Aug 20 '19 at 12:37
  • 1
    @ChrisStratton That's not the point. I realize that a SAR ADC is built on something similar to a resistor ladder and that the bits correspond to the various spots on that ladder compared with the measured voltage, "buckets". But in practice we have two linear functions, one from 0 to 1023 and one from 0V to 5V. Since the SAR ADC can't compare directly against Vref nor GND, we lose that part of the scale in both ends. That doesn't affect the linearity however. – Lundin Aug 20 '19 at 13:11
  • 2
    No, you are mistaken. **5v is not included** - you still haven't realized that, and as a result you keep getting the wrong answer. If you define the voltages of codes by their minimum, the correct answer is to use a factor of 1024. If you wish to define them by their median, you use 1024 and add a half LSB to the code or output voltage. And if you wish to define them by their maximum, you add one LSB. **In no case is it allowed to distort the multiplicative factor itself!!!** . You cannot fix an *additive* concern by *multiplication*, and trying to only distorts things more. – Chris Stratton Aug 20 '19 at 13:15