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

How to implement max sampling with SAADC

I would like to implement a simple code to use SAADC on NRF52 to sample one channel at maximum sample rate (theoretical 200KHz). All the examples I have found use limiting factors such as using function "nrf_drv_timer_ms_to_ticks", slow clocks or others. I intend on sending the measurements using UART. I'm looking for either an example that already exists, or an explanation on how to modify existing examples. Thanks

Parents
  • Instead of nrf_drv_timer_ms_to_ticks you can use nrf_drv_timer_us_to_ticks. To sample at 200kHz you have to set the acquisition time to 5us or less. This you do in the nrf_saadc_channel_config_t::acq_time. For example in the saadc example code:

    nrf_saadc_channel_config_t channel_config =
                NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
    channel_config.acq_time = NRF_SAADC_ACQTIME_3US;
    

    Be aware of the maximum input resistance, see here.

    EDIT 2016.07.28: Using the "free running mode" the sample time is acquisition time + conversion time which will not result in 200KHz. Also updated the code so that it actually works.

    You can also skip using the timer if you configure the SAADC in "Free running mode" (an expression used in AVR chips); when one sample is done the next sample starts immidiately. This can be done by linking the SAMPLE event with the DONE or RESULTDONE event through PPI:

    void saadc_sampling_event_init(void)
    {
        ret_code_t err_code;
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
        
        uint32_t saadc_sample_event_addr = nrf_drv_saadc_sample_task_get();
    
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
        APP_ERROR_CHECK(err_code);
        
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel, (uint32_t)&NRF_SAADC->EVENTS_RESULTDONE, saadc_sample_event_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);
    }
    

    Start the first sample with nrf_drv_saadc_sample().

  • Thanks for the response. I tried only using nrf_drv_timer_us_to_ticks as well as changing the acquisition time. There were problems with this. After reaching "SAMPLES_IN_BUFFER" you lose measurements, that means that I can't get a constant time difference between measurements which prevents me from analyzing the data as I need to. I can get around this by increasing SAMPLES_IN_BUFFER as high as it can go, as well as UART_TX_BUF_SIZE. However at some point (depending on size of buffers) there is an overflow and they lose sync. I also tried the code you gave however there is no output, either because data isn't transferred to UART or there is no actual sampling. What do I need to add to it to get it working?

Reply
  • Thanks for the response. I tried only using nrf_drv_timer_us_to_ticks as well as changing the acquisition time. There were problems with this. After reaching "SAMPLES_IN_BUFFER" you lose measurements, that means that I can't get a constant time difference between measurements which prevents me from analyzing the data as I need to. I can get around this by increasing SAMPLES_IN_BUFFER as high as it can go, as well as UART_TX_BUF_SIZE. However at some point (depending on size of buffers) there is an overflow and they lose sync. I also tried the code you gave however there is no output, either because data isn't transferred to UART or there is no actual sampling. What do I need to add to it to get it working?

Children
No Data
Related