PPI with multiple SAADCs and multiple TIMERs

Dear Nordic Support,

I am using PPI to link 2 timers (10ms & 5s) with 2 SAADC channel (AIN1 - channel 0 & AIN2 - channel 1). 

The nrf_drv_saadc_init function is only called once so it means there is only one callback for the sampling event. In case I am using 2 channels, how do I know that which channel has completed its sampling event in the callback function? When I printed out the ADC value, all I saw is CH0 and CH1 are read at the same time while I expect CH0 every 10ms and CH1 every 5s.

I am using nRF52840 + nRF5 SDK 15.3 + SD 6.1.1.

Thank you and best regards,

           Duy

            

void saadc_transducer_callback(nrf_drv_saadc_evt_t const * p_event)
{
    uint8_t idx;

    if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {
        APP_ERROR_CHECK(nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, RAW_ADC_BUFF_SIZE));

        NRF_LOG_INFO("T.ADC event number: %d", (int)m_transducer_evt_counter);

        for (idx = 0; idx < RAW_ADC_BUFF_SIZE; idx++)
        {
            NRF_LOG_INFO("%d", p_event->data.done.p_buffer[idx]);
        }
        m_transducer_evt_counter++;
    }
}


static void saadc_sampling_event_init(void)
{
    uint32_t transducer_timer_compare_event_addr, battery_timer_compare_event_addr;
    uint32_t saadc_sample_task_addr;

    APP_ERROR_CHECK(nrf_drv_ppi_init());

    nrf_drv_timer_enable(&TRANSDUCER_TIMER);
    nrf_drv_timer_enable(&BATTERY_TIMER);

    transducer_timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&TRANSDUCER_TIMER, NRF_TIMER_CC_CHANNEL0);
    battery_timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&BATTERY_TIMER, NRF_TIMER_CC_CHANNEL0);
    
    saadc_sample_task_addr = nrf_drv_saadc_sample_task_get();
    /* Setup ppi channel so that timer compare event is triggering sample tasks in SAADC */
    APP_ERROR_CHECK(nrf_drv_ppi_channel_alloc(&TORQUE_SAADC_TIMER_PPI_CHANNEL));
    APP_ERROR_CHECK(nrf_drv_ppi_channel_alloc(&BATTERY_SAADC_TIMER_PPI_CHANNEL));

    APP_ERROR_CHECK(nrf_drv_ppi_channel_assign(TORQUE_SAADC_TIMER_PPI_CHANNEL, transducer_timer_compare_event_addr, saadc_sample_task_addr));
    APP_ERROR_CHECK(nrf_drv_ppi_channel_assign(BATTERY_SAADC_TIMER_PPI_CHANNEL, battery_timer_compare_event_addr, saadc_sample_task_addr));
}


static void saadc_init(void)
{
    nrf_saadc_channel_config_t adc_channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);
    nrf_saadc_channel_config_t battery_channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);

    APP_ERROR_CHECK(nrf_drv_saadc_init(NULL, saadc_transducer_callback));

    APP_ERROR_CHECK(nrf_drv_saadc_channel_init(0, &adc_channel_config));
    APP_ERROR_CHECK(nrf_drv_saadc_channel_init(1, &battery_channel_config));

    APP_ERROR_CHECK(nrf_drv_saadc_buffer_convert(m_buffer_pool[0], RAW_ADC_BUFF_SIZE));
    APP_ERROR_CHECK(nrf_drv_saadc_buffer_convert(m_buffer_pool[1], RAW_ADC_BUFF_SIZE));
}

Parents
No Data
Reply
  • Hi,

     

    If you want one SAADC channel to run every 5ms, and another to run every 5 seconds, you need to use two timers.

    This is because the timer itself will not count to 5 ms, fire the event for sampling your first channel, then run for another 4.995 seconds before triggering the event to sample your second channel.

    Could you try to run a individual timer per event and see if that works better?

     

    Kind regards,

    Håkon

Children
  • Hello ,

    Thank you for your answer, I am running 2 different timers running in different periods (10ms and 5s). If I run only 1 ADC channel + 1 TIMER with PPI, everything works fine.

    Warm regards,

          Duy

    #define APP_ADV_INTERVAL                32                                          /**< The advertising interval (in units of 0.625 ms. This value corresponds to 25 ms). */
    #define ADC_ACQUISITION_INTERVAL        10          
    #define BATTERY_LEVEL_MEAS_INTERVAL     10000                                       /**< Battery level measurement interval (ticks). */
    
    #define APP_ADV_DURATION                18000                                       /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
    
    static void saadc_init(void)
    {
        nrf_saadc_channel_config_t adc_channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);
        nrf_saadc_channel_config_t battery_channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
    
        APP_ERROR_CHECK(nrf_drv_saadc_init(NULL, saadc_transducer_callback));
    //    APP_ERROR_CHECK(nrf_drv_saadc_init(NULL, saadc_battery_callback));
    
        APP_ERROR_CHECK(nrf_drv_saadc_channel_init(0, &adc_channel_config));
        APP_ERROR_CHECK(nrf_drv_saadc_channel_init(1, &battery_channel_config));
    
        APP_ERROR_CHECK(nrf_drv_saadc_buffer_convert(m_buffer_pool[0], RAW_ADC_BUFF_SIZE));
        APP_ERROR_CHECK(nrf_drv_saadc_buffer_convert(m_buffer_pool[1], RAW_ADC_BUFF_SIZE));
    }
    
    
    /**@brief Function for the Timer initialization.
     *
     * @details Initializes the timer module. This creates and starts application timers.
     */
    static void timers_init(void)
    {
        nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    
        /* Enable app timer */
        APP_ERROR_CHECK(app_timer_init());
    
        /* Create ADC timer */
        APP_ERROR_CHECK(nrf_drv_timer_init(&TRANSDUCER_TIMER, &timer_cfg, adc_acquisition_timeout_handler));
        nrf_drv_timer_extended_compare(&TRANSDUCER_TIMER, NRF_TIMER_CC_CHANNEL0, nrf_drv_timer_ms_to_ticks(&TRANSDUCER_TIMER, ADC_ACQUISITION_INTERVAL), NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
    
        /* Configure BATTERY TIMER */
        APP_ERROR_CHECK(nrf_drv_timer_init(&BATTERY_TIMER, &timer_cfg, battery_level_meas_timeout_handler));
        nrf_drv_timer_extended_compare(&BATTERY_TIMER, NRF_TIMER_CC_CHANNEL0, nrf_drv_timer_ms_to_ticks(&BATTERY_TIMER, BATTERY_LEVEL_MEAS_INTERVAL), NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
    }
    
    
    static void saadc_sampling_event_init(void)
    {
        uint32_t transducer_timer_compare_event_addr, battery_timer_compare_event_addr;
        uint32_t saadc_sample_task_addr;
    
        APP_ERROR_CHECK(nrf_drv_ppi_init());
    
        nrf_drv_timer_enable(&TRANSDUCER_TIMER);
        nrf_drv_timer_enable(&BATTERY_TIMER);
    
        transducer_timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&TRANSDUCER_TIMER, NRF_TIMER_CC_CHANNEL0);
        battery_timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&BATTERY_TIMER, NRF_TIMER_CC_CHANNEL0);
        
        saadc_sample_task_addr = nrf_drv_saadc_sample_task_get();
        /* Setup ppi channel so that timer compare event is triggering sample tasks in SAADC */
        APP_ERROR_CHECK(nrf_drv_ppi_channel_alloc(&TORQUE_SAADC_TIMER_PPI_CHANNEL));
        APP_ERROR_CHECK(nrf_drv_ppi_channel_alloc(&BATTERY_SAADC_TIMER_PPI_CHANNEL));
    
        APP_ERROR_CHECK(nrf_drv_ppi_channel_assign(TORQUE_SAADC_TIMER_PPI_CHANNEL, transducer_timer_compare_event_addr, saadc_sample_task_addr));
        APP_ERROR_CHECK(nrf_drv_ppi_channel_assign(BATTERY_SAADC_TIMER_PPI_CHANNEL, battery_timer_compare_event_addr, saadc_sample_task_addr));
    }