This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

SAADC Battery Measurement Low Outliers

Does anyone know why I am getting low outliers on battery measurements with the SAADC?
I am measuring the battery directly every minute. Every seven minutes consistently, I get a low measurement. This goes on for months for the entire life of the battery. Here is a graph of a few minutes of the data:

During this test, there is no Bluetooth or any other connection. It is running on a custom board. Between measurements, it goes to System Off and gets started up again with a GPIO alarm from an external Real-Time Clock alarm. The exact same process is happening every time, as in, I am not (knowingly) doing anything different at the seven-minute mark.

I set up the SAADC to measure the battery with the following code:

static void battery_monitor_adc_configure(void)
{
    ret_code_t err_code;

    err_code = nrf_drv_saadc_init(NULL, battery_monitor_saadc_event_handler);
    APP_ERROR_CHECK(err_code);

    nrf_saadc_channel_config_t config =
                               NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_VDD);
    err_code = nrf_drv_saadc_channel_init(0, &config);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(&m_adc_buf[0], 1);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(&m_adc_buf[1], 1);
    APP_ERROR_CHECK(err_code);
}

I initiate a measurement with the following code:

ret_code_t err_code;
err_code = nrf_drv_saadc_sample();
APP_ERROR_CHECK(err_code);

I get the conversion result here:

void battery_monitor_saadc_event_handler(nrf_drv_saadc_evt_t const * p_event)
{
    if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {
        nrf_saadc_value_t adc_result;
        uint16_t          battery_level_in_milli_volts;
        uint8_t           battery_level_percentage;
        uint32_t          err_code;

        adc_result = p_event->data.done.p_buffer[0];

        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, 1);
        APP_ERROR_CHECK(err_code);

        battery_level_in_milli_volts = (((adc_result * ADC_REF_VOLTAGE_IN_MILLIVOLTS)
                                       / ADC_RES_10BIT) * ADC_PRE_SCALING_COMPENSATION)
                                       + DIODE_FWD_VOLT_DROP_MILLIVOLTS;

        battery_level_percentage = battery_level_percentage_get(battery_level_in_milli_volts);

        battery_level_save(battery_level_percentage);
    }
}

I write the result in flash memory to collect later. I don't think there is anything different going on such as a page erase. I do erase a page each time that I get to a new one, but that is much less often than seven minutes.

I am using an nRF52840 on a custom board with SDK 16.0.

The battery is lithium.

Thank you for your help.

Parents
  • Hello,

    Can you please share what your battery_level_save() function looks like?

    I see that you are doing this on a custom board. Did you test it on a DK as well? Do you see the same behavior there?

    Are you powering anything else from your nRF?

    Did you try to measure the VDD voltage using another tool when the low level occurs? Does the voltage actually drop? 

    Can you think of anything other in your application that can draw current around every 7 minutes?

    Best regards,

    Edvin

Reply
  • Hello,

    Can you please share what your battery_level_save() function looks like?

    I see that you are doing this on a custom board. Did you test it on a DK as well? Do you see the same behavior there?

    Are you powering anything else from your nRF?

    Did you try to measure the VDD voltage using another tool when the low level occurs? Does the voltage actually drop? 

    Can you think of anything other in your application that can draw current around every 7 minutes?

    Best regards,

    Edvin

Children
Related