Battery level Reading Error

Hi,

I am trying to use cr2032 battery with nrf52840 to measure the battery level.

To begin with, I first integrated the battery level measuring code in my  application from ble_app_hrs which is located in the examples/ble_peripheral/ which did not work at all and then i tried to code normally using 14 bit resolution for better accuracy.

For simulation, I am using DC Power Supply to change the voltage, NRF_SAADC_INPUT_VDD as the input channel and nrf connect app so as to validate the measurement. However, battery percentage is 100  from 3.3V to 2.5V / 2.4V and started to decrease only after 2.5V from 100%.It was showing 98% for 2.4V, 80% for 2.1 V and decreasing further up to 58% for 1.8V Could anyone please help me on how to accurately measure battery level of nrf52840 with CR2032 battery from 3.3V? Code Snippets are attached .

Parents
  • Hi,

    The HRS example in the nRF5 SDK use dummy battery values, so there is no wonder you found that it did not work. However, I would recommend to take a look at the proximity example, which demonstrate how to read the VDD voltage via the SAADC, and convert that to a battery percentage using a simple CR2032 battery discharge curve. Specifically, look in examples\ble_peripheral\ble_app_proximity\main.c.

    (Note that there are some fundamental issues with using battery voltage to calculate the battery state, so this will only give you ballpark numbers. But without additional HW, that is all you can do.)

  • I have implemented the battery code in my application as per the ble_app_proximity application which was mentioned above .  

  • Worth checking: If using the default SAADC reference VDD then the sampling of VDD will not work as expected. Use of the fixed reference 0.6 volts is required, with typically a gain of 1/6

    //                Ref     Gain   Full Scale               14-bit sampling
    //                =====   ====   =======================  =======================
    // Input range = (0.6 V)/(1/6) = 3.600 V or 16384 counts  4,551.1 counts per volt
    // Example SAAADC reading:
    // 2.90 volts -> 13,198 ADC counts at 4,551.1 counts per volt

Reply
  • Worth checking: If using the default SAADC reference VDD then the sampling of VDD will not work as expected. Use of the fixed reference 0.6 volts is required, with typically a gain of 1/6

    //                Ref     Gain   Full Scale               14-bit sampling
    //                =====   ====   =======================  =======================
    // Input range = (0.6 V)/(1/6) = 3.600 V or 16384 counts  4,551.1 counts per volt
    // Example SAAADC reading:
    // 2.90 volts -> 13,198 ADC counts at 4,551.1 counts per volt

Children
  • Hi,

    This is the configuration I am using. Please let me know if there is any need for modification. Thanks in advance.

      

  • The configuration is not correct, but it's hard to help with this when using the long-winded Nordic example code. There is no diode compensation needed; the default 1024 is incorrect as that refers to 10-bit resolution; the full-scale of 3.3 volts is incorrect, it is 3.6 volts.

    My advice is to avoid trying to fix the example (unless Nordic engineers jump in) but instead first just get a bare-metal version working then later maybe update the example code. Have a look at this saadc/main.c link for a guide

  • Hi,

    Thanks for the repo. Baremetal code worked perfectly fine. However, I faced a challenge with high frequency clock, I just commented out that high frequency clock and integated the code, as I do not need the values to be too accurate . Still that is a problem which I am not bale to get it into my head along with the api's issue with which this thread started. I tried to apply the same concept of the baremetal code in the api, but still I faced the same challenge.

  • Hi,

    Shouri said:
    I faced a challenge with high frequency clock, I just commented out that high frequency clock and integated the code, as I do not need the values to be too accurate

    As the SoftDevice is enabled here, you need to use the SoftDevice APIs for clock control, or alternatively (or perhaps better), use the clock driver, which will use the SoftDevice APIs. Accessing the clock registers directly will cause the SoftDevice to assert.

    Shouri said:
    Still that is a problem which I am not bale to get it into my head along with the api's issue with which this thread started. I tried to apply the same concept of the baremetal code in the api, but still I faced the same challenge.

    Which APIs are you referring to here? If you got the ADC reading workign, the only thing left is to use a function that maps the voltage to a battery percentage (which will be very inaccurate, but that is how it is), and then update the battery percentage characteristic. For the first, you can use battery_level_in_percent() if that is good enough for you, or make your own. Lastly, call ble_bas_battery_level_update() with  the new battery level. This is demonstrated in the proximity example (examples/ble_peripheral/ble_app_proximity/main.c).

Related