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;
    }

  • 逐次逼近法是否需要修改?因为我用了之后不准确,请问uint32_t volt = (3000 * (ladder+3))/32有什么解释吗?

Reply Children
Related