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

nRF52 SAADC VDD Sampling Not Working

Hi everyone,

I am currently working on a project where I need to sample the SAADC continuously on 5 channels: channels 4,5,6,7 and VDD, which on my board is channel 9. I am using timer 2 that is PPI'd into my SAADC and everything works perfectly IF I don't sample the VDD Channel.

As soon as I add a call to nrf_drv_saadc_channel_init for my VDD channel, the SAADC won't trigger anymore and won't go into it's callback function. When I remove the VDD channel init, everything works again, the callback function is being called, and my values get correctly read from the SAADC.

Here's is a snippet of my code:

enum adc_channel{
    in_1,
    in_2,
    in_3,
    in_4,
    vdd,
    num_adc_channels
};

#define NUM_SAMPLES           1                             /*< Number of samples per ADC capture. >*/
#define SAMPLES_IN_BUFFER     num_adc_channels*NUM_SAMPLES  /*< Number of samples in SAADC buffer. >*/

void saadc_sampling_event_init(void)
{
    ret_code_t err_code;
    
    // PPI Driver init
    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
    APP_ERROR_CHECK(err_code);

    // Timer & SAADC interconnection via PPI
    uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer_adc,
                                                                                NRF_TIMER_CC_CHANNEL2);
    uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();

    err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,              /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
                                          timer_compare_event_addr,
                                          saadc_sample_task_addr);
    APP_ERROR_CHECK(err_code);
}

void saadc_sampling_event_enable(void)
{
    ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
    APP_ERROR_CHECK(err_code);
}

void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
    if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {
        #ifdef WATTZA_DEBUG
        m_adc_evt_counter+=1;
        #endif
        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 < num_adc_channels; i++)
        {  
            switch (i){
                case(in_1):
                    in_1_val = p_event->data.done.p_buffer[i];
                    break;
                
                case(in_2):
                    in_2_val = p_event->data.done.p_buffer[i];
                    break;

                case(in_3):
                    in_3_val = p_event->data.done.p_buffer[i];
                    break;
                
                case(in_4):
                    in_4_val = p_event->data.done.p_buffer[i];
                    break;

                case(vdd):
                    vdd_val = p_event->data.done.p_buffer[i];
                    break;
        }
    }
}

void saadc_init(void)
{
    ret_code_t err_code;

    // SAADC Channel configuration
    // VDD Level Channel Config
    nrf_saadc_channel_config_t vdd_ch_conf =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_VDD);
    vdd_ch_conf.resistor_n = NRF_SAADC_RESISTOR_PULLDOWN;
    vdd_ch_conf.reference = NRF_SAADC_REFERENCE_VDD4;
    vdd_ch_conf.gain = NRF_SAADC_GAIN1_4;
    
    // in 1 Channel Config
    nrf_saadc_channel_config_t in_1_ch_conf = 
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN4);
    in_1_ch_conf.resistor_n = NRF_SAADC_RESISTOR_PULLDOWN;
    in_1_ch_conf.reference = NRF_SAADC_REFERENCE_VDD4;
    in_1_ch_conf.gain = NRF_SAADC_GAIN1_4;
    
    // in 2 Channel Config
    nrf_saadc_channel_config_t in_2_ch_conf = 
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN5);
    in_2_ch_conf.resistor_n = NRF_SAADC_RESISTOR_PULLDOWN;
    in_2_ch_conf.reference = NRF_SAADC_REFERENCE_VDD4;
    in_2_ch_conf.gain = NRF_SAADC_GAIN1_4;

    // in 3 Channel Config
    nrf_saadc_channel_config_t in_3_ch_conf = 
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN6);
    in_3_ch_conf.resistor_n = NRF_SAADC_RESISTOR_PULLDOWN;
    in_3_ch_conf.reference = NRF_SAADC_REFERENCE_VDD4;
    in_3_ch_conf.gain = NRF_SAADC_GAIN1_4;
    
    // in 4 Channel Config
    nrf_saadc_channel_config_t in_4_ch_conf = 
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN7);
    in_4_ch_conf.resistor_n = NRF_SAADC_RESISTOR_PULLDOWN;
    in_4_ch_conf.reference = NRF_SAADC_REFERENCE_VDD4;
    in_4_ch_conf.gain = NRF_SAADC_GAIN1_4;
    
    // SAADC Initialization
    err_code = nrf_drv_saadc_init(NULL, saadc_callback);
    APP_ERROR_CHECK(err_code);
    
    // ADC Channels initialization
    err_code = nrf_drv_saadc_channel_init(in_1_CH, &in_1_ch_conf);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(in_2_CH, &in_2_ch_conf);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(in_3_CH, &in_3_ch_conf);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(in_4_CH, &in_4_ch_conf);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(NRF_SAADC_INPUT_VDD, &vdd_ch_conf);
    APP_ERROR_CHECK(err_code);
    
    // Non-blocking mode - Buffer initialization
    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);
    
}

Let me know if you need any more info!

Cheers,
Yacin

Related