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

How to measure a state of a battery by using saadc example with NRF52832?

Hi everyone, I know that this topic has been mentioned before, but there are a lot of doubts and the situation about measuring a battery is still not clear.

1) First of all, I tried to handle an saadc example that is proposed by Nordic Semiconductors. I have printed (%d \n", p_event->data.done.p_buffer[i]), but I got random values wherever I plugged the battery that state I want to check.  I tired pins 3 (A0), 4 (A1), 28 (A2), 29 (A3), 30 (A4), 31 (A5). 
What I have to change to measure the voltage on pin 3 (A0)? 

2) Also, I tried the shared and recommended code on GitHub. In the post was mentioned that it is only needed to change 22th line to point what pin has to be measured. What channel has to be proposed to measure for example pin 3 (A0)?  

To check the state of the battery I have used the voltage divided consisted of 0,985 MOhm resistor and 1,97 MOhm resistor. At the output I obtain ~ 2,7 voltage. 

Ladies and gentlemen, please give me an advice how I can solve this problem. I have tried many things and I think this post can be helpful also for next generations.

Kind regards from sunny Columbia! Sun with faceMortar board

Parents
  • Try something like this:

    #include "app_timer.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrfx_saadc.h"
    
    #define INPUTS 1
    #define TIMER  1000 // ms
    #define AIN_BATTERY 0 
    
    APP_TIMER_DEF(saadc_timer);
    
    static nrf_saadc_value_t buffer[2][INPUTS];
    static uint8_t battery_level = 0xFF;
    
    static inline uint16_t adc_to_mv(nrf_saadc_value_t adc_result) {
        // http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52840.ps/saadc.html?cp=2_0_0_5_22_2#saadc_digital_output
        // Vresult[mV] = (adc_result * Vref[mV]) / (2^resolution * gain) = (adc_result * 600) / (2^10 * 1/6)
        return (adc_result * 3600) >> 10;
    }
    
    uint8_t get_battery_level() {
        return battery_level;
    }
    
    static void saadc_timeout_handler(void *p_context) {
        UNUSED_PARAMETER(p_context);
        APP_ERROR_CHECK(nrfx_saadc_sample());
    }
    
    void saadc_event_handler(nrfx_saadc_evt_t const *p_event) {
        if (p_event->type != NRFX_SAADC_EVT_DONE)
            return;
        nrf_saadc_value_t *adc_result = p_event->data.done.p_buffer;
        battery_level = battery_level_in_percent(adc_to_mv(adc_result[AIN_BATTERY]));
        APP_ERROR_CHECK(nrfx_saadc_buffer_convert(adc_result, INPUTS));
    }
    
    void saadc_init(void) {
        //  SAADC config & calibrate
        nrfx_saadc_config_t saadc_config = NRFX_SAADC_DEFAULT_CONFIG;
        APP_ERROR_CHECK(nrfx_saadc_init(&saadc_config, saadc_event_handler));
        APP_ERROR_CHECK(nrfx_saadc_calibrate_offset());
        while (nrfx_saadc_is_busy())
            sd_app_evt_wait();
    
        // Channels config
        nrf_saadc_channel_config_t battery_config = NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_VDD);
        APP_ERROR_CHECK(nrfx_saadc_channel_init(AIN_BATTERY, &battery_config));
    
        // double buffering
        APP_ERROR_CHECK(nrfx_saadc_buffer_convert(buffer[0], INPUTS));
        APP_ERROR_CHECK(nrfx_saadc_buffer_convert(buffer[1], INPUTS));
    
        // start SAADC timer
        APP_ERROR_CHECK(app_timer_create(&saadc_timer, APP_TIMER_MODE_REPEATED, saadc_timeout_handler));
        APP_ERROR_CHECK(app_timer_start(saadc_timer, APP_TIMER_TICKS(TIMER), NULL));
    }

    Use saadc_init() (only once!) to start measuring. Then use get_battery_level() to get battery level in percents (0x64 = 100%).

Reply
  • Try something like this:

    #include "app_timer.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrfx_saadc.h"
    
    #define INPUTS 1
    #define TIMER  1000 // ms
    #define AIN_BATTERY 0 
    
    APP_TIMER_DEF(saadc_timer);
    
    static nrf_saadc_value_t buffer[2][INPUTS];
    static uint8_t battery_level = 0xFF;
    
    static inline uint16_t adc_to_mv(nrf_saadc_value_t adc_result) {
        // http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52840.ps/saadc.html?cp=2_0_0_5_22_2#saadc_digital_output
        // Vresult[mV] = (adc_result * Vref[mV]) / (2^resolution * gain) = (adc_result * 600) / (2^10 * 1/6)
        return (adc_result * 3600) >> 10;
    }
    
    uint8_t get_battery_level() {
        return battery_level;
    }
    
    static void saadc_timeout_handler(void *p_context) {
        UNUSED_PARAMETER(p_context);
        APP_ERROR_CHECK(nrfx_saadc_sample());
    }
    
    void saadc_event_handler(nrfx_saadc_evt_t const *p_event) {
        if (p_event->type != NRFX_SAADC_EVT_DONE)
            return;
        nrf_saadc_value_t *adc_result = p_event->data.done.p_buffer;
        battery_level = battery_level_in_percent(adc_to_mv(adc_result[AIN_BATTERY]));
        APP_ERROR_CHECK(nrfx_saadc_buffer_convert(adc_result, INPUTS));
    }
    
    void saadc_init(void) {
        //  SAADC config & calibrate
        nrfx_saadc_config_t saadc_config = NRFX_SAADC_DEFAULT_CONFIG;
        APP_ERROR_CHECK(nrfx_saadc_init(&saadc_config, saadc_event_handler));
        APP_ERROR_CHECK(nrfx_saadc_calibrate_offset());
        while (nrfx_saadc_is_busy())
            sd_app_evt_wait();
    
        // Channels config
        nrf_saadc_channel_config_t battery_config = NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_VDD);
        APP_ERROR_CHECK(nrfx_saadc_channel_init(AIN_BATTERY, &battery_config));
    
        // double buffering
        APP_ERROR_CHECK(nrfx_saadc_buffer_convert(buffer[0], INPUTS));
        APP_ERROR_CHECK(nrfx_saadc_buffer_convert(buffer[1], INPUTS));
    
        // start SAADC timer
        APP_ERROR_CHECK(app_timer_create(&saadc_timer, APP_TIMER_MODE_REPEATED, saadc_timeout_handler));
        APP_ERROR_CHECK(app_timer_start(saadc_timer, APP_TIMER_TICKS(TIMER), NULL));
    }

    Use saadc_init() (only once!) to start measuring. Then use get_battery_level() to get battery level in percents (0x64 = 100%).

Children
No Data
Related