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

nRF52833 SAADC with Channel Scanning Settling Time

Hello Nordic Team,

i'm trying to configure the nRF52833 DK to scan through two channels at a high rate (10ksps) with the SAADC module.  i have configured the time to operate at 100us and I am seeing what looks like settling time with the internal mux.  for reference i used the following configuration in the ADC:

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);
    nrf_drv_saadc_config_t saadc_config;
    nrf_saadc_channel_config_t channel_config;
    
    saadc_config.low_power_mode = true;
    saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;
    saadc_config.oversample = NRF_SAADC_OVERSAMPLE_DISABLED;
    saadc_config.interrupt_priority = APP_IRQ_PRIORITY_LOW_MID;
    
    err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
    APP_ERROR_CHECK(err_code);

    channel_config.acq_time = NRF_SAADC_ACQTIME_3US;
    channel_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
    channel_config.gain = NRF_SAADC_GAIN1_2;
    channel_config.mode = NRF_SAADC_MODE_SINGLE_ENDED; 
    channel_config.pin_p = NRF_SAADC_INPUT_AIN1;
    channel_config.pin_n = NRF_SAADC_INPUT_DISABLED;  
    channel_config.resistor_p = NRF_SAADC_RESISTOR_DISABLED;                              //Disable pullup resistor on the input pin
    channel_config.resistor_n = NRF_SAADC_RESISTOR_DISABLED;                              //Disable pulldown resistor on the input pin
    
    err_code = nrf_drv_saadc_channel_init(0, &channel_config);
    APP_ERROR_CHECK(err_code);
    
    channel_config.acq_time = NRF_SAADC_ACQTIME_3US;
    channel_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
    channel_config.gain = NRF_SAADC_GAIN1_2 ;
    channel_config.mode = NRF_SAADC_MODE_SINGLE_ENDED; 
    channel_config.pin_p = NRF_SAADC_INPUT_AIN2;
    channel_config.pin_n = NRF_SAADC_INPUT_DISABLED;  
    channel_config.resistor_p = NRF_SAADC_RESISTOR_DISABLED;                              //Disable pullup resistor on the input pin
    channel_config.resistor_n = NRF_SAADC_RESISTOR_DISABLED;                              //Disable pulldown resistor on the input pin
    
    err_code = nrf_drv_saadc_channel_init(1, &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);

}

the timer is setup as follows:

void saadc_sampling_event_init(void)
{
    ret_code_t err_code;

    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);

    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
    err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, timer_handler);
    APP_ERROR_CHECK(err_code);

    /* setup m_timer for compare event every 100us*/
    uint32_t ticks = nrf_drv_timer_us_to_ticks(&m_timer, 100);  
    nrf_drv_timer_extended_compare(&m_timer,
                                   NRF_TIMER_CC_CHANNEL0,
                                   ticks,
                                   NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                   false);
    nrf_drv_timer_enable(&m_timer);

    uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer,
                                                                                NRF_TIMER_CC_CHANNEL0);
    uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();

    /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
    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,
                                          timer_compare_event_addr,
                                          saadc_sample_task_addr);
    APP_ERROR_CHECK(err_code);
}

i used a 50Hz test tone connected to both of the AIN pins configured.  i get what looks like unsettled data (i plotted only a single channel in this case, using every other sample as ch0, and a similar plot is achieved using ch1).  

if i slow the sample rate down to 1kHz, the results improves as per the below:

I would have thought that the input mux could scan between two samples and settle faster than 10ksps accurately.  I likely have configured something incorrectly.  any guidance or advice is greatly appreciated!

Kind regards,

Parents
  • It all depends on the external impedance and input capacitance; NRF_SAADC_ACQTIME_3US only allows 3uSec for switching channels and will introduce crosstalk between the channels if the impedance is such that the charge time is more than 5 RC time constants (for 12-bit). Options are to incease this 3uSec sample time (SAADC setting), add external capacitance to the analogue pins if the external signals are always stable, or reduce the external resistive impedance.

    There is always going to be some crosstalk; this can be made predictable and constant by selecting a ground channel between each signal channel - ie now scanning 4 channels - or address CR as above until the crosstalk is less than a single SAADC count.

    Edit: I may have misunderstood the question: if the two signals on the 2 input pins are identical then the above comments don't apply - but still worth trying increasing sample time, say 40uSecs

  • Hello, and thanks for the responses.

    for the 40us acquisition time, I have tried this and the result stays the same.  I slowly decreases the timer period until this behaviour started to show up.  using the same code I decreased the time in 100us steps from 1ms to 500us to increase the sample rate.  my target sample rate is 10kHz for sampling two analog inputs.  

    when I decrease the timer period to below 700us (~1.5ksps output) this starts to appear.  I suspect that it has to do that the timer is interrupting the ADC.  in this case i dont think the ADC is using the EasyDMA; i couldn't tell from the example if it's actually setting that up or not.  i would think the EasyDMA would help eliminate the issue and ping-pong the data.  

    I read a few posts, it doesn't seem that there are any examples using the EasyDMA and the SAADC, is that right?  

  • Two things to consider, do you have a 'scope available? It's just possible that the BLE current pulse is affecting the analogue value as seen by the ADC; easy to check the voltage on a pin with a 'scope. Speeding up the sample rate would make that effect worse as more "incorrect" samples are taken during the voltage droop. If the reference were dropping, the pulse would be positive, so for a negative pulse as shown above the ADC pin voltage must be dropping. You could prove this issue by changing to a VDD-derived reference instead of the fixed voltage reference SAADC_CH_CONFIG_REFSEL_VDD1_4 since then the reference would track the same voltage drop and the problem should go away.

    The second is maybe post the handler code for both SAADC and timer, in case there is something obvious there. Regarding the priorities, you could also give the SAADC higher priority than the Timer to test your theory of exclusion.

    Otherwise maybe Nordic has a suggestion; I use low-level drivers and not the library code, not quite sure how the library handles the scanning.

  • Hi, 

    i'm not currently using the BLE and i am using the internal reference (0.6V). there are no significant load pulses to be seen in this case.  the only thing running on my program is the debug UART to print the SAADC samples.  

    i did change the interrupt priority and increased the size of the buffer.  what i find in this case is that if increase the buffer to say 1024 samples, i can get a few cycles of my input signal that look correct and then when the next buffer is submitted, it looks to get phase misaligned.  To me this implies that the ISR is either too long and the double buffered is not ping-ponging correctly.  

    I'm not committed to using the library functions, if the only way to get this to work fast enough to demonstrate a 10ksps ADC throughput with two channels enabled that's fine, but an example would be really helpful and how to use the EasyDMA correctly.  

    thanks,

  • Hi,

    Could you upload your project? I would like to take a closer look at it.

    regards

    Jared 

  • Hi Jared,

    please see attached

    /**
     * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    /** @file
     * @defgroup nrf_adc_example main.c
     * @{
     * @ingroup nrf_adc_example
     * @brief ADC Example Application main file.
     *
     * This file contains the source code for a sample application using ADC.
     *
     * @image html example_board_setup_a.jpg "Use board setup A for this example."
     */
    
    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <string.h>
    #include "nrf.h"
    #include "nrf_drv_saadc.h"
    #include "nrf_drv_ppi.h"
    #include "nrf_drv_timer.h"
    #include "boards.h"
    #include "app_error.h"
    #include "nrf_delay.h"
    #include "app_util_platform.h"
    #include "nrf_pwr_mgmt.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #define SAMPLES_IN_BUFFER 1024
    volatile uint8_t state = 1;
    
    static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(0);
    static nrf_saadc_value_t     m_buffer_pool[2][SAMPLES_IN_BUFFER];
    static nrf_ppi_channel_t     m_ppi_channel;
    static uint32_t              m_adc_evt_counter;
    
    
    void timer_handler(nrf_timer_event_t event_type, void * p_context)
    {
    
    }
    
    
    void saadc_sampling_event_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
        err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, timer_handler);
        APP_ERROR_CHECK(err_code);
    
        /* setup m_timer for compare event every 100us*/
        uint32_t ticks = nrf_drv_timer_us_to_ticks(&m_timer, 100);  
        nrf_drv_timer_extended_compare(&m_timer,
                                       NRF_TIMER_CC_CHANNEL0,
                                       ticks,
                                       NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                       false);
        nrf_drv_timer_enable(&m_timer);
    
        uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer,
                                                                                    NRF_TIMER_CC_CHANNEL0);
        uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();
    
        /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
        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,
                                              timer_compare_event_addr,
                                              saadc_sample_task_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);
    }
    
    
    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
            ret_code_t err_code;
    
            err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
            APP_ERROR_CHECK(err_code);
    
            int i;
            //NRF_LOG_INFO("ADC event number: %d", (int)m_adc_evt_counter);
    
            for (i = 0; i < SAMPLES_IN_BUFFER; i++)
            {
                NRF_LOG_RAW_INFO("%d \n", p_event->data.done.p_buffer[i]);
            }
            m_adc_evt_counter++;
        }
    }
    
    
    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);
        nrf_drv_saadc_config_t saadc_config;
        nrf_saadc_channel_config_t channel_config;
        
        saadc_config.low_power_mode = false;
        saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;
        saadc_config.oversample = NRF_SAADC_OVERSAMPLE_DISABLED;
        saadc_config.interrupt_priority = APP_IRQ_PRIORITY_HIGH;
        
        err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
        APP_ERROR_CHECK(err_code);
    
        channel_config.acq_time = NRF_SAADC_ACQTIME_10US;
        channel_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
        channel_config.gain = NRF_SAADC_GAIN1_6;
        channel_config.mode = NRF_SAADC_MODE_SINGLE_ENDED; 
        channel_config.pin_p = NRF_SAADC_INPUT_AIN1;
        channel_config.pin_n = NRF_SAADC_INPUT_DISABLED;  
        channel_config.resistor_p = NRF_SAADC_RESISTOR_DISABLED;                              //Disable pullup resistor on the input pin
        channel_config.resistor_n = NRF_SAADC_RESISTOR_DISABLED;                              //Disable pulldown resistor on the input pin
        channel_config.burst = NRF_SAADC_BURST_ENABLED; 
        
        err_code = nrf_drv_saadc_channel_init(0, &channel_config);
        APP_ERROR_CHECK(err_code);
        
        channel_config.acq_time = NRF_SAADC_ACQTIME_10US;
        channel_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
        channel_config.gain = NRF_SAADC_GAIN1_6 ;
        channel_config.mode = NRF_SAADC_MODE_SINGLE_ENDED; 
        channel_config.pin_p = NRF_SAADC_INPUT_AIN2;
        channel_config.pin_n = NRF_SAADC_INPUT_DISABLED;  
        channel_config.resistor_p = NRF_SAADC_RESISTOR_DISABLED;                              //Disable pullup resistor on the input pin
        channel_config.resistor_n = NRF_SAADC_RESISTOR_DISABLED;                              //Disable pulldown resistor on the input pin
        channel_config.burst = NRF_SAADC_BURST_ENABLED;
        
        err_code = nrf_drv_saadc_channel_init(1, &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);
    
    }
    
    
    /**
     * @brief Function for main application entry.
     */
    int main(void)
    {
        uint32_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        ret_code_t ret_code = nrf_pwr_mgmt_init();  
        APP_ERROR_CHECK(ret_code);
    
        saadc_init();
        saadc_sampling_event_init();
        saadc_sampling_event_enable();
        NRF_LOG_INFO("SAADC HAL simple example started.");
    
        while (1)
        {
            nrf_pwr_mgmt_run();
            NRF_LOG_FLUSH();
        }
    }
    
    
    /** @} */
    

Reply
  • Hi Jared,

    please see attached

    /**
     * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    /** @file
     * @defgroup nrf_adc_example main.c
     * @{
     * @ingroup nrf_adc_example
     * @brief ADC Example Application main file.
     *
     * This file contains the source code for a sample application using ADC.
     *
     * @image html example_board_setup_a.jpg "Use board setup A for this example."
     */
    
    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <string.h>
    #include "nrf.h"
    #include "nrf_drv_saadc.h"
    #include "nrf_drv_ppi.h"
    #include "nrf_drv_timer.h"
    #include "boards.h"
    #include "app_error.h"
    #include "nrf_delay.h"
    #include "app_util_platform.h"
    #include "nrf_pwr_mgmt.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #define SAMPLES_IN_BUFFER 1024
    volatile uint8_t state = 1;
    
    static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(0);
    static nrf_saadc_value_t     m_buffer_pool[2][SAMPLES_IN_BUFFER];
    static nrf_ppi_channel_t     m_ppi_channel;
    static uint32_t              m_adc_evt_counter;
    
    
    void timer_handler(nrf_timer_event_t event_type, void * p_context)
    {
    
    }
    
    
    void saadc_sampling_event_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
        err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, timer_handler);
        APP_ERROR_CHECK(err_code);
    
        /* setup m_timer for compare event every 100us*/
        uint32_t ticks = nrf_drv_timer_us_to_ticks(&m_timer, 100);  
        nrf_drv_timer_extended_compare(&m_timer,
                                       NRF_TIMER_CC_CHANNEL0,
                                       ticks,
                                       NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                       false);
        nrf_drv_timer_enable(&m_timer);
    
        uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer,
                                                                                    NRF_TIMER_CC_CHANNEL0);
        uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();
    
        /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
        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,
                                              timer_compare_event_addr,
                                              saadc_sample_task_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);
    }
    
    
    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
            ret_code_t err_code;
    
            err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
            APP_ERROR_CHECK(err_code);
    
            int i;
            //NRF_LOG_INFO("ADC event number: %d", (int)m_adc_evt_counter);
    
            for (i = 0; i < SAMPLES_IN_BUFFER; i++)
            {
                NRF_LOG_RAW_INFO("%d \n", p_event->data.done.p_buffer[i]);
            }
            m_adc_evt_counter++;
        }
    }
    
    
    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);
        nrf_drv_saadc_config_t saadc_config;
        nrf_saadc_channel_config_t channel_config;
        
        saadc_config.low_power_mode = false;
        saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;
        saadc_config.oversample = NRF_SAADC_OVERSAMPLE_DISABLED;
        saadc_config.interrupt_priority = APP_IRQ_PRIORITY_HIGH;
        
        err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
        APP_ERROR_CHECK(err_code);
    
        channel_config.acq_time = NRF_SAADC_ACQTIME_10US;
        channel_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
        channel_config.gain = NRF_SAADC_GAIN1_6;
        channel_config.mode = NRF_SAADC_MODE_SINGLE_ENDED; 
        channel_config.pin_p = NRF_SAADC_INPUT_AIN1;
        channel_config.pin_n = NRF_SAADC_INPUT_DISABLED;  
        channel_config.resistor_p = NRF_SAADC_RESISTOR_DISABLED;                              //Disable pullup resistor on the input pin
        channel_config.resistor_n = NRF_SAADC_RESISTOR_DISABLED;                              //Disable pulldown resistor on the input pin
        channel_config.burst = NRF_SAADC_BURST_ENABLED; 
        
        err_code = nrf_drv_saadc_channel_init(0, &channel_config);
        APP_ERROR_CHECK(err_code);
        
        channel_config.acq_time = NRF_SAADC_ACQTIME_10US;
        channel_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
        channel_config.gain = NRF_SAADC_GAIN1_6 ;
        channel_config.mode = NRF_SAADC_MODE_SINGLE_ENDED; 
        channel_config.pin_p = NRF_SAADC_INPUT_AIN2;
        channel_config.pin_n = NRF_SAADC_INPUT_DISABLED;  
        channel_config.resistor_p = NRF_SAADC_RESISTOR_DISABLED;                              //Disable pullup resistor on the input pin
        channel_config.resistor_n = NRF_SAADC_RESISTOR_DISABLED;                              //Disable pulldown resistor on the input pin
        channel_config.burst = NRF_SAADC_BURST_ENABLED;
        
        err_code = nrf_drv_saadc_channel_init(1, &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);
    
    }
    
    
    /**
     * @brief Function for main application entry.
     */
    int main(void)
    {
        uint32_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        ret_code_t ret_code = nrf_pwr_mgmt_init();  
        APP_ERROR_CHECK(ret_code);
    
        saadc_init();
        saadc_sampling_event_init();
        saadc_sampling_event_enable();
        NRF_LOG_INFO("SAADC HAL simple example started.");
    
        while (1)
        {
            nrf_pwr_mgmt_run();
            NRF_LOG_FLUSH();
        }
    }
    
    
    /** @} */
    

Children
  • Hi,

    So I looked over your code and it's mostly correct. I do have some suggestions/questions that I want you to try/answer:

    1.I see that you're using BURST mode but at the same time has disabled OVERSAMPLE on the channel. Could try without using the BURST mode?

    2.Are you able to reproduce the issue if you only use one channel?

    3.We have seen some issues when switching buffers in the SAADC. This can be the case if another tasks preempts the ongoing task before it's able to trigger the START task in nrf_drv_saadc_buffer_convert(). The suggested solution is to use PPI to bind the START task with the END event. The bug and solution is described in more detail here. Could you try the suggested solution?

    4. Regarding the plot that you've shared. It seems that the issue happens somewhat periodically and at the same place. It's difficult to tell based on the plot if this coincides with the switching of buffers. It would therefore be better if you could provide the raw data from the buffer? Maybe you could print out the raw data in the buffer and signalize when you switch buffers. That way, we could see if there is a certain pattern. 

    regards

    Jared 

Related