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
  • Terminal voltage measurement doesn't give great results anyhow - especially with Lithium-based batteries.

    Does the nRF52820 have a comparator?

    If you have to add something external, a proper battery monitor or "gas gauge" would be better than an ADC ...

  • Actually there is no external circuity required. One can do an approximation using the hysteresis ladder feature of the COMP peripheral. The nrf52820 can compare VDDH/5 against fractions of the internal 1.2 V reference per the crude unoptimized approach below

    uint32_t get_battery_voltage1()
    {
          uint32_t ladder = 1; //approximate from below
          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, .th_down = ladder-1},
              .speed_mode = NRF_COMP_SP_MODE_Normal,
              .hyst = NRF_COMP_HYST_NoHyst,
              .input = NRF_COMP_VDDH_DIV5, // 
              .interrupt_priority = NRFX_COMP_CONFIG_IRQ_PRIORITY};
          nrfx_comp_init(&config, comp_handler1); // no handler is used but the API requires a blank handler
    
          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();
          while (sample == 1) {   // VDDH/5 is higher than VUP
              ladder++;           // increase ladder until VDDH/5 is larger than VUP
              nrf_comp_th_t th = {
                .th_up = ladder,
                .th_down = ladder -1
              };
              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);
              sample = nrfx_comp_sample();  // sample again
          }
          nrfx_comp_uninit();
          uint32_t volt = (3000 * (ladder+1))/32;       // the hysteresis ladder is (th_up+1)*VREF (1.2)
          return volt;
    }

    With this you can approximate VDDH from 0 to 6V in0.09375V increments

Reply
  • Actually there is no external circuity required. One can do an approximation using the hysteresis ladder feature of the COMP peripheral. The nrf52820 can compare VDDH/5 against fractions of the internal 1.2 V reference per the crude unoptimized approach below

    uint32_t get_battery_voltage1()
    {
          uint32_t ladder = 1; //approximate from below
          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, .th_down = ladder-1},
              .speed_mode = NRF_COMP_SP_MODE_Normal,
              .hyst = NRF_COMP_HYST_NoHyst,
              .input = NRF_COMP_VDDH_DIV5, // 
              .interrupt_priority = NRFX_COMP_CONFIG_IRQ_PRIORITY};
          nrfx_comp_init(&config, comp_handler1); // no handler is used but the API requires a blank handler
    
          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();
          while (sample == 1) {   // VDDH/5 is higher than VUP
              ladder++;           // increase ladder until VDDH/5 is larger than VUP
              nrf_comp_th_t th = {
                .th_up = ladder,
                .th_down = ladder -1
              };
              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);
              sample = nrfx_comp_sample();  // sample again
          }
          nrfx_comp_uninit();
          uint32_t volt = (3000 * (ladder+1))/32;       // the hysteresis ladder is (th_up+1)*VREF (1.2)
          return volt;
    }

    With this you can approximate VDDH from 0 to 6V in0.09375V increments

Children
No Data
Related