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

About SAADC, Easy-DMA and channels (nRF5_SDK)

There's an example saadc_pca10036 in the SDK. I am wondering how this piece of code works in that example:

void saadc_init(void)
{
    ret_code_t err_code;
    nrf_saadc_channel_config_t channel_config =
            NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
    err_code = nrf_drv_saadc_init(NULL, saadc_callback);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_channel_init(0, &channel_config);
    APP_ERROR_CHECK(err_code);

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

Specifically, why there are two calls of same function, nrf_drv_saadc_buffer_convert()? Does it set some kind of double-buffering?

In my case, I have four ADC-inputs I want to sample 200 times per second each. How should I configure the SAADC subsystem?

EDIT: Also, how do I know which channel was triggered when I get into the callback (below)?

void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
   if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
   ...
  • Hi,

    Please refer to the infocenter documentation for the SAADC driver.

    Yes, you are correct, this is double buffering. "The driver supports double buffering, which means that nrf_drv_saadc_buffer_convert can be called twice and the buffer that is provided in the second call will be used immediately after the first one is filled."

    "To trigger sampling, call the function nrf_drv_saadc_sample or, through PPI, use the task SAMPLE from SAADC. nrf_drv_saadc_sample_task_get can be used to get the task address." The most power efficient way would be to set up a timer with compare events that line up with 200 times per second, and then trigger the SAMPLE task via PPI on this timer event.

    When you get NRF_DRV_SAADC_EVT_DONE you can read the data from the buffer specified in the call to nrf_drv_saadc_buffer_convert().

    Best regards,

    Øyvind

  • It is still unclear for me how to set-up several channels. For example, if I need two channels, the code is maybe something like this:

    #define CHANNELS       2
    #define BUFFERSIZE   128
    int16_t Buffers[CHANNELS][2][BUFFERSIZE];
    
    void init_adc(void)
    {
        nrf_drv_saadc_init(NULL, saadc_callback);
    
        // set up first channel
        nrf_saadc_channel_config_t channel_config =
             NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
        nrf_drv_saadc_channel_init(0, &channel_config);
        // set-up double buffering for the first channel
        nrf_drv_saadc_buffer_convert(Buffers[0][0], BUFFERSIZE);
        nrf_drv_saadc_buffer_convert(Buffers[0][1], BUFFERSIZE);
    
        // set up second channel
        nrf_saadc_channel_config_t channel_config =
            NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);
        nrf_drv_saadc_channel_init(1, &channel_config);
        // set-up double buffering for the second channel
        nrf_drv_saadc_buffer_convert(Buffers[1][0], BUFFERSIZE);
        nrf_drv_saadc_buffer_convert(Buffers[1][1], BUFFERSIZE);
    }
    

    And the event handler:

    static
      void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
      {
          if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
          {
              nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, BUFFERSIZE);
              // TODO: How do I know which of the two channels was triggered?
          }
      }
    

    As said in the TODO-line, how do I know which of the two channels was triggered? Do I need to compare the pointer p_event->data.done.p_buffer against the pointers I set earlier with the call to *_buffer_convert() at my init_adc()?

  • Thanks for answer :) I am still a bit confused, can you please read my more detailed explanation below (did not fit here).

  • When you send the sample command you will get data for the channel you triggered in the correct buffer, if scan mode is enabled you will get data on all channels. If you want to trigger an event when the SAADC channel goes beyond or below a certain level, have a look at limit detection which is described in the documentation for the driver.

  • Thanks for comment. How do I enable scan mode?

Related