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

Measuring the battery voltage with nRF52832

Hi!

To measure the voltage level of a coin cell CR2450 can be done in different ways. You can use the comparator, the low power comparator or the ADC. I wonder which one is the most adequate to use and affects least the current consumption? The CR2450 is the only power supplay in the system and the voltage is 3,0V when it has full capacity and 2,0V when it's discharged.

BR, Nixon

Parents Reply Children
  • Try this; I wrote it for polled mode for occasional low-power monitoring of CR2032 coin cells with no external components; that assumes of course no regulator or LDO or series schottky diode between coin cell and nRF52832:

    // Input range of internal Vdd measurement = (0.6 V)/(1/6) = 3.6 V
    // 3.0 volts -> 14486 ADC counts with 14-bit sampling: 4828.8 counts per volt
    #define ADC12_COUNTS_PER_VOLT 4551
    
    /**
     * @brief Function for 14-bit adc init in polled mode
     */
    void Adc12bitPolledInitialise(void)
    {
        uint32_t timeout = 10;
        nrf_saadc_channel_config_t myConfig =
        {
            .resistor_p = NRF_SAADC_RESISTOR_DISABLED,
            .resistor_n = NRF_SAADC_RESISTOR_DISABLED,
            .gain       = NRF_SAADC_GAIN1_6,
            .reference  = NRF_SAADC_REFERENCE_INTERNAL,
            .acq_time   = NRF_SAADC_ACQTIME_40US,
            .mode       = NRF_SAADC_MODE_SINGLE_ENDED,
            .burst      = NRF_SAADC_BURST_ENABLED,
            .pin_p      = NRF_SAADC_INPUT_VDD,
            .pin_n      = NRF_SAADC_INPUT_DISABLED
        };
    
        nrf_saadc_resolution_set((nrf_saadc_resolution_t) 3);   // 3 is 14-bit
        nrf_saadc_oversample_set((nrf_saadc_oversample_t) 2);   // 2 is 4x, about 150uSecs total
        nrf_saadc_int_disable(NRF_SAADC_INT_ALL);
        nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
        nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
        nrf_saadc_enable();
    
        NRF_SAADC->CH[1].CONFIG =
                  ((myConfig.resistor_p << SAADC_CH_CONFIG_RESP_Pos)   & SAADC_CH_CONFIG_RESP_Msk)
                | ((myConfig.resistor_n << SAADC_CH_CONFIG_RESN_Pos)   & SAADC_CH_CONFIG_RESN_Msk)
                | ((myConfig.gain       << SAADC_CH_CONFIG_GAIN_Pos)   & SAADC_CH_CONFIG_GAIN_Msk)
                | ((myConfig.reference  << SAADC_CH_CONFIG_REFSEL_Pos) & SAADC_CH_CONFIG_REFSEL_Msk)
                | ((myConfig.acq_time   << SAADC_CH_CONFIG_TACQ_Pos)   & SAADC_CH_CONFIG_TACQ_Msk)
                | ((myConfig.mode       << SAADC_CH_CONFIG_MODE_Pos)   & SAADC_CH_CONFIG_MODE_Msk)
                | ((myConfig.burst      << SAADC_CH_CONFIG_BURST_Pos)  & SAADC_CH_CONFIG_BURST_Msk);
    
        NRF_SAADC->CH[1].PSELN = myConfig.pin_n;
        NRF_SAADC->CH[1].PSELP = myConfig.pin_p;
    }
    
    /**
     * @brief Function for 14-bit adc battery voltage by direct blocking reading
     */
    uint16_t GetBatteryVoltage1(void)
    {
        uint16_t result = 9999;         // Some recognisable dummy value
        uint32_t timeout = 10000;       // Trial and error
        volatile int16_t buffer[8];
        // Enable command
        nrf_saadc_enable();
        NRF_SAADC->RESULT.PTR = (uint32_t)buffer;
        NRF_SAADC->RESULT.MAXCNT = 1;
        nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
        nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
        nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
    
        while (0 == nrf_saadc_event_check(NRF_SAADC_EVENT_END) && timeout > 0)
        {
            timeout--;
        }
        nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
        nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
        nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
        // Disable command to reduce power consumption
        nrf_saadc_disable();
        if (timeout != 0)
        {
            result = ((buffer[0] * 1000L)+(ADC12_COUNTS_PER_VOLT/2)) / ADC12_COUNTS_PER_VOLT;
        }
        return result;
    }
    
    

  • Yes, if you mean can you copy it - feel free. If the battery voltage read fails note it returns the value 9999 as a warning/error - easily spotted in a log.

Related