This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

[mbed] What exactly does the return value of AnalogIn::read_u16() means?

According to this post, and this GitHub source file, in the nRF51 chip's mbed implementation:

  • The ADC reference voltage is 1/3 power supply
  • read_u16() seems to return NRF_ADC->RESULT
  • NRF_ADC->RESULT maximum possible value would be 0x3FF, when ADC input equals to ADC reference voltage.

From an experiment I just ran, I observed the following

  • At ADC input of ~897mV, read_u16() returns ~0x011a, or 282 decimal.
  • At ADC input of ~520mV, read_u16() returns ~0x00b9, or 185 decimal.
  • Leaving the ADC input pin floating, read_u16() returns ~0x00af, or 175 decimal.

Using linear approximation with the first two data points, at read_u16() value of 0x03FF, the ADC input should be >4V.

If using only one of those data points with the assumption that at 0V input, read_u16() returns 0, then 0x03FF still means a voltage >3V.

These numbers certainly cannot be 1/3 power supply! What could be going on here? Am I misunderstanding something?


Just in case this fact is the reason to the problem: To conduct my experiment, I use a (1M - 220k) voltage divider to supply 1/6 of VDD or 5V to the analog input.


On another note, according to mbed's Analog In reference and the AnalogIn.h header file, read_u16() returns "input voltage, represented as an unsigned short in the range [0x0, 0xFFFF]". This description sucks. But at the same time it doesn't seem to be what nRF51's implementation of the function is returning. Is there any comment on this?

Parents
  • Hello.

    From analogin_init in the github document you linked:

    (ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) |
    (ADC_CONFIG_REFSEL_SupplyOneThirdPrescaling << ADC_CONFIG_REFSEL_Pos) |
    

    This prescales both the input and reference by 1/3. The reference is VDD (3v). I find this to match your numbers.

    The maximum value is 0x3FF because the nRF51 ADC support maximum 10 bit resolution.

    Update 1:

    Let me give you an example.

    • You have 3v VDD, this is scaled to 1V.
    • The input voltage is 500 mV = 0.5 V. This is scaled to about 167 mV.
    • The adc will give you (0.167/1) * 1023 = ~170.

    With your numbers:

    • We have about 3V VDD. We apply the scaling in the equation (*0.33)
    • 897 mV input gives (897 * 0.33/3000 * 0.33) *1023 = ~305. Your result of 282 is given because VDD is not exactly 3v, but a bit higher.
    • 520 mV input gives (520 * 0.33/3000 * 0.33) *1023 = ~177. Here your result is slightly higher. This can either be explained by a lower VDD (unlikely), or uncertainty in the measurement of the 520 mV. It can also be other factors in the external circuit, which might be worth investigating.
    • Wee see that the scaling of 1/3 can be removed from the equation. This means that the result you get from the adc is the input, divided by VDD, multiplied by 1023.

    -Anders

Reply
  • Hello.

    From analogin_init in the github document you linked:

    (ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) |
    (ADC_CONFIG_REFSEL_SupplyOneThirdPrescaling << ADC_CONFIG_REFSEL_Pos) |
    

    This prescales both the input and reference by 1/3. The reference is VDD (3v). I find this to match your numbers.

    The maximum value is 0x3FF because the nRF51 ADC support maximum 10 bit resolution.

    Update 1:

    Let me give you an example.

    • You have 3v VDD, this is scaled to 1V.
    • The input voltage is 500 mV = 0.5 V. This is scaled to about 167 mV.
    • The adc will give you (0.167/1) * 1023 = ~170.

    With your numbers:

    • We have about 3V VDD. We apply the scaling in the equation (*0.33)
    • 897 mV input gives (897 * 0.33/3000 * 0.33) *1023 = ~305. Your result of 282 is given because VDD is not exactly 3v, but a bit higher.
    • 520 mV input gives (520 * 0.33/3000 * 0.33) *1023 = ~177. Here your result is slightly higher. This can either be explained by a lower VDD (unlikely), or uncertainty in the measurement of the 520 mV. It can also be other factors in the external circuit, which might be worth investigating.
    • Wee see that the scaling of 1/3 can be removed from the equation. This means that the result you get from the adc is the input, divided by VDD, multiplied by 1023.

    -Anders

Children
  • Anders, I understand that the number 0x3FF comes from, and that ADC reference voltage is 1.1V. However, that is the basis of my question. The problem is that those does not match my numbers. Once again, I am observing these data points: (897mV, 0x11a ADC), (520mV, 0xb9 ADC) and (-float-, 0xaf). However I tried to apply linear approximation, it does not suggest anything even close to (1.1V, 0x3FF ADC).

    I am afraid your answer unfortunately didn't answer my question.

  • I have updated my answer, with some examples. I agree that from the two data points, your numbers do not add up 100%. Can you do some more tests where you measure VDD, ADC input, and note dwn adc output?

  • @anders-strand: Thanks for the update. It does seem like I have some misunderstanding of how the ADC value is calculated. I will review the nRF51 reference manual to get a better understanding of this and check back with you. Regarding more detailed data, unfortunately weekend has started where I am now, so I won't be able to get to that until Monday. Perhaps I will update with more data on Monday then.

  • @anders-strand: I reviewed the reference manual and has understood the ADC better now. It turns out I have not understood the prescaler properly when I wrote my question. Sorry about that.

    I also run a few experiments again and observed the same data points: (~900mV, ~284), (~523mV, ~188). I also got (GND, ~1).


    That leaves only the inaccuracy of the 520mV data point that doesn't make sense. Here are the details of my experiment for your reference. Hope it helps you get an idea what is going on.

    I use the nRF51 DK along with a voltage divider. The voltage divider has two resistors in series, one is 220kOhm and one is 1MOhm. The voltage divider is used with VDD, 5Vout and GND pins of the nRF51 DK to supply about 1/6 of VDD or 5Vout to ADC input, which is where I got the value of ~520mV and ~900mV Also, VDD is measured to be 2.9V. 5V out is measured to be about ~5V.

Related