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

SAADC scans only one sample

Hello,

I am developing a solution that measures values on 2 AIN channels in scan mode with the following setup:

- differential mode

- no oversampling

- no burst mode

- 10 bit precision

- resistors disabled

The channels are configured standard way using nrf_drv_saadc_channel_init() and nrf_drv_saadc_buffer_convert(). I start conversion by calling nrf_drv_saadc_sample() and set low power mode. This I understood to run several scan samples until buffer lasts.

The callback function checks for p_event->type == NRF_DRV_SAADC_EVT_DONE, makes nrf_drv_saadc_buffer_convert() and copies measured values to a separate array for further processing outside of the callback. I am not doing calibration at this stage, as it requires scan to work.

The problem I am facing is that the callback function is called always when only 1 set of samples is done, i.e. 1 sample for each channel. Regardless of what size buffer I set (tried 2x10, 2x20, 2x30 size).

I want to note that nrf_drv_saadc_sample() is triggered from RTC2 timer interrupt handler, setup for 2 kHz frequency of calls.

I would like to know why I am not getting s full scan of those 2 channels through the whole buffer.

I am using nRF 52832, custom design, also DK PCA10040, SDK 14.2 and SD 132, v5.0.0.

What else I forgot to set for running the scan mode / what can block the scan mode to work? Is the scan mode supported under SD? According to the SD documentation open for SAADC. 

Any advice is very much appreciated.

Thanx.

peter

  • The channels are configured standard way using nrf_drv_saadc_channel_init() and nrf_drv_saadc_buffer_convert(). I start conversion by calling nrf_drv_saadc_sample() and set low power mode

     From Prod spec's Analog inputs and channels: "Any one of the available channels can be enabled for the ADC to operate in one-shot mode. If more than one CH[n] is configured, the ADC enters scan mode." 

     

    This I understood to run several scan samples until buffer lasts.

    From Scan mode: "A channel is considered enabled if CH[n].PSELP is set. If more than one channel, CH[n], is enabled, the ADC enters scan mode.

    In scan mode, one SAMPLE task will trigger one conversion per enabled channel."

     

    I am not doing calibration at this stage, as it requires scan to work.

     You need to run calibration fairly often if you want accurate results. 

    I suggest you provide us with the relevant code so that we can see exactly what you've done.

  • Hello Haakonsh,

    thanx for your feedback. I add relevant pieces of the code:

    static nrf_drv_saadc_config_t m_saadc_config =
    {
    .low_power_mode = true,
    .resolution = NRF_SAADC_RESOLUTION_10BIT, 
    .oversample = NRF_SAADC_OVERSAMPLE_DISABLED, 
    .interrupt_priority = APP_IRQ_PRIORITY_LOW
    };

    static nrf_saadc_channel_config_t m_saadc_channel_1_config =
    {
    .reference = NRF_SAADC_REFERENCE_VDD4,
    .gain = NRF_SAADC_GAIN1, 
    .acq_time = SAADC_SCAN_ACQ_TIME,.// (10 us)
    .mode = NRF_SAADC_MODE_DIFFERENTIAL,
    .pin_p = ADC_CHANNEL_1_PIN,.
    .pin_n = ADC_CHANNEL_2_PIN,
    .resistor_p = NRF_SAADC_RESISTOR_DISABLED,
    .resistor_n = NRF_SAADC_RESISTOR_DISABLED 
    };

    similarly channel 2, except pins definitions

    ...

    err_code = nrf_drv_saadc_init(&m_saadc_config, saadc_callback);
    APP_ERROR_CHECK(err_code);

    ...

    err_code = nrf_drv_saadc_channel_init(1, &m_saadc_channel_1_config); 
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(2, &m_saadc_channel_2_config); 
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_measurement_buffer_pool[0], SAADC_SAMPLES_IN_BUFFER); 
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_measurement_buffer_pool[1], SAADC_SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);

    Then in RTC2 timer interrupt handler:

    nrf_drv_saadc_sample(); 

    SAADC callback:

    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, SAADC_SAMPLES_IN_BUFFER);

    copying scanned data to an array for further processing

    I suspect if some of the SDK configuration is correctly set. E.g. I dont have RTC1 enabled as when enabled the compiler gives an error of double definition of IRQ handler (or something similar). RTC1 is responsible for interrupts management, if I am not mistaken?

    Best regards,

    peter

  • What's the value of SAADC_SAMPLES_IN_BUFFER?

    RTC0 is used by the SoftDevice and RTC1 is used by the app_timer in various libraries throughout the SDK. 

    Since you're using the RTC to trigger the sample task I suggest you do it via PPI and not via an interrupt. See the PPI example for how one connects a peripheral event to a task. 

  • Hello Haakonsh,

    I tried SAADC_SAMPLES_IN_BUFFER with multiples of 2. Every 2 samples (1 and 1 on each channel) generate callback. I tried PPI and nrf timer driver as the first version (as one of the examples). The behavior was the same - I was getting multiple of callbacks depending on the buffer size. That's the reason that I suspect some SDK config issue.

    Best regards, peter

Related