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

nRF52832 SAADC and BLE

Hello,

I'm using following code to read two channels of SAADC. It works fine when device is not connected to BLE central device. As soon as it's connected, the saadc_callback function stops executing despite the fact that nrf_drv_saadc_sample(); returns NRF_SUCCESS. In the log, I can see that saadc_callback() being called when device is not connected to BLE and no saadc_callback() when device connected to BLE.

One thing more, the saadc_callback() gets being called from a timer in the main() (although with incorrect values) function but not being called when saadc_voltage_get() is used other than main(). 

I have tried changing the priority of SAADC IRQ in the sdk_config.h from 7 to 3, still no success. The code otherwise works fine and at device startup, when it's not connected, SAADC reads values.

The code is here:

#include "nrf_drv_saadc.h"
#include "nrf_log.h" 
#include "nrf_log_ctrl.h"
#include "nrf_delay.h"

#include "adc_driver.h"

#define SAMPLES_IN_BUFFER 2

static nrf_saadc_value_t m_buffer[2][SAMPLES_IN_BUFFER];
uint16_t drive_V, batt_V;

void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
    NRF_LOG_INFO("SAADC event: %d", p_event->type);

    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);

        drive_V = p_event->data.done.p_buffer[0];
        batt_V = p_event->data.done.p_buffer[1];
        
        NRF_LOG_INFO("Drive voltage=%d", drive_V);
        //NRF_LOG_INFO("Sys volatge=%d", batt_V);

    }
}

void saadc_init(void)
{
    ret_code_t err_code;

    nrf_saadc_channel_config_t channel_config_1 
        = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);
    nrf_saadc_channel_config_t channel_config_2 
        = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);

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

    err_code = nrf_drv_saadc_channel_init(1, &channel_config_1);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(2, &channel_config_2);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_buffer[0], SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_buffer_convert(m_buffer[1], SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);

    
    // get values
    saadc_voltage_get();


    // Analog PIN assignments
    // P0.02/AIN0
    // P0.03/AIN1 --> Drive_V
    // P0.04/AIN2 --> Batt_V
}

void saadc_voltage_get(){
    ret_code_t err_code;

    err_code = nrf_drv_saadc_sample();
    if (err_code == NRF_SUCCESS){
        NRF_LOG_INFO("SAADC getting voltage...");
    }
    else{
        NRF_LOG_INFO("SAADC sampling issue.");
    }
    
    nrf_delay_ms(2);
}

void saadc_voltage_get_drive(uint16_t *voltage){
    saadc_voltage_get();
    *voltage = drive_V;
}

void saadc_voltage_get_battery(uint16_t *voltage){
    saadc_voltage_get();
    *voltage = batt_V;
}

Parents Reply Children
  • , I am having a different issue all together in the same code. Unfortunately the thread you are referring does not answer my question.

    My issue is not SAADC basic function, rather SAADC is working in certain conditions while not working in other conditions. There are two places from where I'm calling saadc_voltage_get_drive().

    1. main() function at startup, when saadc_voltage_get_drive() is called, I can clearly see saadc_callback() being called and I can clearly see ADC values.

    2. But I call the same saadc_voltage_get_drive() from another function periodically, saadc_callback() does not fire. It seems like ADC buffer full event takes infinite time to complete, hence I don't get right values, instead previously converted value is returned. 

    So my problem is why saadc_callback() behaves differently when called from different function, periodically. 

  • Can it be a interrupt priority issue, where you are trying to wait for a saadc callback from a function that is at the same interrupt priority level? In such case it is not possible for a interrupt to preempt an interrupt of same priority level.

  • If you are calling the function from an app_timer or other peripheral interrupt, then you would need to check the interrupt priority level of the app_timer or peripheral interrupt you set during initialization. If you are calling the function from a while()-loop in main(), then it's not running from an interrupt.

  • I changed my code to use Timer 4 to call ADC conversions through PPI instead of calling from APP_TIMER.

    I can see the function works fine when called from "while" loop of main. But this causes unwanted delays in other BLE functions. So I called it from Timer 4 (used for ADC as well) after, say 2 sec. Also set the priority like: NVIC_SetPriority(TIMER4_IRQn, 0);

    But it still doesn't work. 

Related