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

Parents
  • 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

Reply
  • 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

Children
Related