SAADC oversampling + burst mode on three channel

Hi,

    Sorry, I accidentally closed my last question and I don't know how to reopen it. So I create a new one to need your support.

I want to use 200ms to get ADC value from three channel and I want to get 30 times ADC value from every channel when 200ms timer trigger.

I change my code for three channel and every channel enable burst mode + oversample is 8x. Below is my setting source code.

static void adc_configure(void)
{
    ret_code_t err_code = nrf_drv_saadc_init(NULL, saadc_event_handler);
    APP_ERROR_CHECK(err_code);

    nrf_saadc_channel_config_t config_current_sense =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
    err_code = nrf_drv_saadc_channel_init(0, &config_current_sense);
    APP_ERROR_CHECK(err_code);
    
    nrf_saadc_channel_config_t config_adc_temp =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
    err_code = nrf_drv_saadc_channel_init(1, &config_adc_temp);
    APP_ERROR_CHECK(err_code);
    
    nrf_saadc_channel_config_t config_em_temp =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN3);
    err_code = nrf_drv_saadc_channel_init(2, &config_em_temp);
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_saadc_buffer_convert(adc_buf_adc[0], 3);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(adc_buf_adc[1], 3);
    APP_ERROR_CHECK(err_code);
}

#define NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(PIN_P) \
    {                                                  \
        .resistor_p = NRF_SAADC_RESISTOR_DISABLED,     \
        .resistor_n = NRF_SAADC_RESISTOR_DISABLED,     \
        .gain       = NRF_SAADC_GAIN1_6,               \
        .reference  = NRF_SAADC_REFERENCE_INTERNAL,    \
        .acq_time   = NRF_SAADC_ACQTIME_10US,          \
        .mode       = NRF_SAADC_MODE_SINGLE_ENDED,     \
        .burst      = NRF_SAADC_BURST_ENABLED,         \
        .pin_p      = (nrf_saadc_input_t)(PIN_P),      \
        .pin_n      = NRF_SAADC_INPUT_DISABLED         \
    }
    
// <o> SAADC_CONFIG_OVERSAMPLE  - Sample period
 
// <0=> Disabled 
// <1=> 2x 
// <2=> 4x 
// <3=> 8x 
// <4=> 16x 
// <5=> 32x 
// <6=> 64x 
// <7=> 128x 
// <8=> 256x 

#ifndef SAADC_CONFIG_OVERSAMPLE
#define SAADC_CONFIG_OVERSAMPLE 3
#endif

Also, I create a 200ms timer to call nrf_drv_saadc_sample(), like as below.

static void data_process_handler(void * p_context)
{
    uint32_t err_code;
   
    //average_adc = true;
    nrf_drv_saadc_sample();
    
    //printf("%.4f-%.4f-%.4f\r\n",real_v_current_sense,real_v_adc_temp,real_v_em_temp);
    printf("%d-%d-%d\r\n",current_sense_vol,adc_temp_vol,em_temp_vol);
}

below is my ADC callback function and calibration function in main()

void saadc_event_handler(nrf_drv_saadc_evt_t const * p_event)
{
    uint32_t err_code;
  
    if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {
        nrf_saadc_value_t adc_result,adc_temp_result,em_temp_result;
        uint32_t          err_code;
        
        if((m_adc_evt_counter % 50000) == 0)               //Evaluate if offset calibration should be performed. Configure the SAADC_CALIBRATION_INTERVAL constant to change the calibration frequency
        {
            m_saadc_calibrate = true;                                           // Set flag to trigger calibration in main context when SAADC is stopped
        }
        
        if(m_saadc_calibrate == false)
        {
            err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, 3);             //Set buffer so the SAADC can write to it again. 
            APP_ERROR_CHECK(err_code);
        }
        
        adc_result = p_event->data.done.p_buffer[0];
        adc_temp_result = p_event->data.done.p_buffer[1];
        em_temp_result = p_event->data.done.p_buffer[2];
        
        //printf("Hello : %d-%d-%d\r\n",adc_result,adc_temp_result,em_temp_result);
        
        current_sense_vol = adc_result;
        adc_temp_vol = adc_temp_result;
        em_temp_vol = em_temp_result;
        
        m_adc_evt_counter++;
    }
    else if (p_event->type == NRF_DRV_SAADC_EVT_CALIBRATEDONE)
    {
        nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
        while(!nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED));
        nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
       
        //Set buffer so the SAADC can write to it again.
        err_code = nrf_drv_saadc_buffer_convert(adc_buf_adc[0], 3);
        APP_ERROR_CHECK(err_code);
        //Need to setup both buffers, as they were both removed with the call to nrf_drv_saadc_abort before calibration.
        err_code = nrf_drv_saadc_buffer_convert(adc_buf_adc[1], 3);
        APP_ERROR_CHECK(err_code);
    }
}

int main(void)
{

    for (;;)
    {
        if (m_saadc_calibrate == true) 
        {
            nrf_drv_saadc_abort();
            while(nrf_drv_saadc_calibrate_offset() != NRF_SUCCESS); //Trigger calibration task
            m_saadc_calibrate = false;
        }
    }
}

I will print my three channel ADC value every 200ms. 

printf("%d-%d-%d\r\n",current_sense_vol,adc_temp_vol,em_temp_vol);

This works is very good and correct.

But I have a issue to need your support.

As described above, My channel 0 is AIN0 / channel 1 is AIN2 / channel 2 is AIN3

I expected that the arrangement of the data I printed should be 0->1->2

But It is 1->2->0. Why?? Maybe I can use it, but i am confused

Thank you.

John.

Parents Reply Children
  • Hi Kazi,

         Good news. After i checked this link from you : https://devzone.nordicsemi.com/f/nordic-q-a/20291/offset-in-saadc-samples-with-easy-dma-and-ble/79053#79053 and I used PPI function. I fixed my issue. But I need more time to test it.

    I pasted my code and please help me to double check it.(Have any problem in my code?)

    I add some PPI init code in below function with my timer init

    static void timer_init(void)
    {
        uint32_t time_ms = 1; //Time(in miliseconds) between consecutive compare events
        uint32_t err_code;
        uint32_t time_ticks;
      
        nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        err_code = nrf_drv_timer_init(&TIMER_PRIXIMITY, &timer_cfg, timer_proximity_event_handler);
        APP_ERROR_CHECK(err_code);
        
        time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_PRIXIMITY, time_ms);
        nrf_drv_timer_extended_compare(
             &TIMER_PRIXIMITY, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
        
        nrf_drv_timer_enable(&TIMER_PRIXIMITY);
        
        uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&TIMER_PRIXIMITY, NRF_TIMER_CC_CHANNEL0);
        uint32_t saadc_sample_event_addr = nrf_drv_saadc_sample_task_get();
    
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
    
        /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel, timer_compare_event_addr, saadc_sample_event_addr);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel0);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_enable(m_ppi_channel0);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel0, nrf_saadc_event_address_get(NRF_SAADC_EVENT_END), nrf_saadc_task_address_get(NRF_SAADC_TASK_START));
        APP_ERROR_CHECK(err_code);
    }

    And I haven't changed anything else

    Thank you.

Related