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

Measuring Vbat (2xAAA cell) with nRF52

Hello, I tryed to find in Q&A something that can help me understand how it is possible to measure battery voltage with nRF52, but i am not sure i found the exact explanations. I am using primary 2xAAA cell (meaning 3v when fresh and it is going low until ~ 1.6v , although we will probably stop system operation below 2v). I would like to perform as accurate measurements as possible with A/D of nRF52. Do i need to add additional hardware? Basically, usually A/D demands low impedance input to operate properly and some capacitor is recommended at its input. If i had higher voltage, i would probably add some resistor devider network with some N-MOS in order to save energy and have the lowest current consumption possible, but what about the case where the power voltage is the same as Vcc of the chip?

thank you for your help. BR, Yulya

  • Here is all the code you need to measure Vdd. It is up to you how you want to configure the app timer.

    #include "nrf_drv_saadc.h"
    void saadc_init(void)
    

    { ret_code_t err_code; nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_VDD); err_code = nrf_drv_saadc_init(NULL, saadc_callback); APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_channel_init(0, &channel_config);
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0],SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1],SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);
    

    }

  • This is the handler:

    volatile uint8_t state = 1;
    

    static nrf_saadc_value_t m_buffer_pool[2][SAMPLES_IN_BUFFER];

    void saadc_callback(nrf_drv_saadc_evt_t const * p_event) { uint32_t bat_level;

    if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {
        ret_code_t err_code;
        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
    
        for (int i = 0; i < SAMPLES_IN_BUFFER; i++)
        {
    				bat_level = p_event->data.done.p_buffer[i]>>2;
        }
    

    //At this point your battery level is captured in bat_level. You can do whatever you want with it now

    nrf_drv_saadc_uninit(); //Turns off SAADC
        NRF_SAADC->INTENCLR = (SAADC_INTENCLR_END_Clear << SAADC_INTENCLR_END_Pos);
        NVIC_ClearPendingIRQ(SAADC_IRQn);
    

    }

  • Finally this is the handler that you will trigger on an app timer to get the battery level. The callback handler is the bit above here:

    static void bat_timer_handler(void * p_context)
    

    { UNUSED_PARAMETER(p_context); saadc_init(); nrf_drv_saadc_sample(); }

  • Sorry that the pagination is a little weird. Sometimes the code formats oddly on this website.

  • thank you for the code info, i'll pass it to our firmware guy. My question initially was regarding hardware points. thank you for help. By the way i read the chapter on SAADC in spec before i published my question. thanks anyway. BR, Yulya

Related