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

Battery level measurement without SAADC

Hi!

The nRF52820 chip does not have the SAADC module used to estimate the battery life in its larger counterparts (nrf52840 and nrf52833).
Is there a different way to estimate battery life without an SAADC?
I'm hoping for a method which does not include adding external components, and is measurement based rather then estimation based.

We had considered an estimation method which is a summation of the current estimate per 'time used', 'advertisement cycles' passed, 'connection cycles passed' etc. The problem here is that a. I would need to estimate all possible parameters (TX power for example, time until advertisement is caught etc)
b. I would not be able to catch leaking parts, as the leak is not part of my estimation.

Adding an external ADC is a possibility, but would require us to change our PCB which is not something we want.

we're using the VDD tied to VDDH and expect the Vin to be 1.8-3.3V.

Any other ideas?

Parents
  • Use the following code to measure the battery voltage on the nRF52820 without any external components

    It essentially implements a successive approximation of Vin using the COMP device with the internal VDDH/5 source and modifying the hysteresis threshold:

    void comp_handler1(nrf_comp_event_t event)
    {
    }
    
    uint32_t get_battery_voltage()
    {
          uint32_t ladder = 0; //approximate from below
          uint32_t current = 32;
          nrfx_comp_config_t config = {
              .reference = NRF_COMP_REF_Int1V2, // use 1.2 V reference
              .ext_ref = NRF_COMP_EXT_REF_0,
              .main_mode = NRF_COMP_MAIN_MODE_SE,
              .threshold = {.th_up = ladder+1, .th_down = ladder},
              .speed_mode = NRF_COMP_SP_MODE_Normal,
              .hyst = NRF_COMP_HYST_NoHyst,
              .input = NRF_COMP_VDDH_DIV5, // this mode is unique to the 52820
              .interrupt_priority = NRFX_COMP_CONFIG_IRQ_PRIORITY};
          nrfx_comp_init(&config, comp_handler1); // no handler is used but the API requires a blank handler
    
          while (current > 0) {   
              ladder = ladder | current;         // successive approximation
              nrf_comp_th_t th = {
                .th_up = ladder,
                .th_down = ladder 
              };
              nrfx_comp_stop();   // update the COMP
              nrf_comp_disable();
              nrf_comp_th_set(th);
              nrf_comp_enable();
              nrf_comp_event_clear(NRF_COMP_EVENT_READY);
              nrfx_comp_start(0, 0);
              while(nrf_comp_event_check(NRF_COMP_EVENT_READY) == 0);
              uint32_t sample = nrfx_comp_sample();  // sample 
              if (!sample) { // VDDH/5 is less than VUP
                  ladder = ladder & (~current);  // reset the MSB and continue with lower bits
              }
              current = current >> 1;
          }
          nrfx_comp_uninit();
          uint32_t volt = (3000 * (ladder+3))/32;       // the hysteresis ladder is (th_up+1)*VREF (1.2)
                                                        // theoretically this should be latter+1 - +3 is a fudge factor adjustment
          return volt;
    }

  • Thank you Johannes!

    I'll have a look and see if I can make these suggestions work.

Reply Children
No Data
Related