<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>nRF52832 SAADC two channels at different sampling rate with burst &amp;amp; oversample</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/43191/nrf52832-saadc-two-channels-at-different-sampling-rate-with-burst-oversample</link><description>Hello, 
 I am sampling two analog signals at different sampling rate with burst and oversample enabled. 
 
 nRF52832 (Rigado BMD-350) 
 SDK 15.2 
 IDE - Segger Embedded Studio 4.12 
 SAADC Config
 
 resolution 12bit 
 oversample 4x 
 interrupt priority</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Mon, 26 Apr 2021 09:01:05 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/43191/nrf52832-saadc-two-channels-at-different-sampling-rate-with-burst-oversample" /><item><title>RE: nRF52832 SAADC two channels at different sampling rate with burst &amp; oversample</title><link>https://devzone.nordicsemi.com/thread/306723?ContentTypeID=1</link><pubDate>Mon, 26 Apr 2021 09:01:05 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:02484b62-a1f9-4317-ba9f-7e6cf23d315e</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;Not sure if I remember the details here anymore, but oversample should not be used at the same time as burst (scan), ref:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52832.ps.v1.1/saadc.html#register.OVERSAMPLE"&gt;https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52832.ps.v1.1/saadc.html#register.OVERSAMPLE&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&amp;quot;OVERSAMPLE should not be combined with SCAN.&amp;quot;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52832 SAADC two channels at different sampling rate with burst &amp; oversample</title><link>https://devzone.nordicsemi.com/thread/306433?ContentTypeID=1</link><pubDate>Thu, 22 Apr 2021 20:29:02 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b32a7eca-bd54-4dfb-86f8-88fc3fcd6e56</guid><dc:creator>MCB</dc:creator><description>&lt;p&gt;Hello, I am trying to achieve the same thing is there any news on this topic?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52832 SAADC two channels at different sampling rate with burst &amp; oversample</title><link>https://devzone.nordicsemi.com/thread/170678?ContentTypeID=1</link><pubDate>Tue, 12 Feb 2019 14:55:45 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:482e77ba-be3b-4f9a-a92a-2badd126589d</guid><dc:creator>Morr</dc:creator><description>&lt;p&gt;Hi Kenneth,&lt;/p&gt;
&lt;p&gt;Thank you very much for your quick reply. I understand now.&lt;/p&gt;
&lt;p&gt;Hope they can find the root cause soon and create a workaround for it.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52832 SAADC two channels at different sampling rate with burst &amp; oversample</title><link>https://devzone.nordicsemi.com/thread/170542?ContentTypeID=1</link><pubDate>Tue, 12 Feb 2019 09:29:46 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:87e9f21a-1029-49b5-9997-dce5dcac4546</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;They are planning on finding the root cause to make sure they understand what is happening here, however this might take a while. The issue only seem to occur if you dynamically init() and uninit() channels, and this also explain why we have not see this issue before, so I believe &amp;quot;always&amp;quot; should work yes.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52832 SAADC two channels at different sampling rate with burst &amp; oversample</title><link>https://devzone.nordicsemi.com/thread/170517?ContentTypeID=1</link><pubDate>Tue, 12 Feb 2019 08:43:00 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:5e0db191-6325-429c-bdfe-ee2c1ada1ab6</guid><dc:creator>Morr</dc:creator><description>&lt;p&gt;Hi Kenneth&lt;/p&gt;
&lt;p&gt;Thank you for confirming the issue. And&amp;nbsp;I have a follow-up question.&lt;/p&gt;
&lt;p&gt;If I init both channels &amp;quot;always&amp;quot; to do the sampling, I can still use&amp;nbsp;BURST = 1, right?&lt;/p&gt;
&lt;p&gt;According to this post, it should work.&amp;nbsp;&lt;a href="https://devzone.nordicsemi.com/f/nordic-q-a/20556/how-does-the-saadc-scan-mode-use-the-burst-1"&gt;https://devzone.nordicsemi.com/f/nordic-q-a/20556/how-does-the-saadc-scan-mode-use-the-burst-1&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52832 SAADC two channels at different sampling rate with burst &amp; oversample</title><link>https://devzone.nordicsemi.com/thread/170462?ContentTypeID=1</link><pubDate>Mon, 11 Feb 2019 20:00:21 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:16d3316f-5060-4a89-8676-96ee617e94c2</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;I can confirm that there is an issue with the hardware, so the specific configuration you are doing here is not possible in combination with init() and uninit() channels dynamically, we will look into create an errata or update the documentation&amp;nbsp;to state that BURST = 1 shall not be used with scan. So in your case you will either need to sample both channels always or reconfigure channel 0 to sample different inputs at different times.&lt;/p&gt;
&lt;p&gt;Sorry for the time this has taken.&lt;/p&gt;
&lt;p&gt;Best regards,&lt;br /&gt;Kenneth&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52832 SAADC two channels at different sampling rate with burst &amp; oversample</title><link>https://devzone.nordicsemi.com/thread/170235?ContentTypeID=1</link><pubDate>Sun, 10 Feb 2019 13:06:30 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:5ddf9d59-c5c4-47e8-8488-5ad7e3ff6429</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;I can see the same behavior here, I will need to contact the designers and get their comment.&lt;/p&gt;
&lt;p&gt;Best regards,&lt;br /&gt;Kenneth&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52832 SAADC two channels at different sampling rate with burst &amp; oversample</title><link>https://devzone.nordicsemi.com/thread/169430?ContentTypeID=1</link><pubDate>Tue, 05 Feb 2019 08:32:27 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:190ae833-0f07-49f9-a364-0404c9574d7d</guid><dc:creator>Morr</dc:creator><description>&lt;p&gt;Hi Kenneth,&lt;/p&gt;
&lt;p&gt;As you can see from my last test code, I already do all &lt;span&gt;uninit() and init() in the main loop, not from the adc callback handler. Moreover I am using non-blocking operations only. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;So, the problem is not from my code?&amp;nbsp;&lt;/span&gt;&lt;span&gt;Then it&amp;nbsp;should be the SDK or SAADC hardware issue.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52832 SAADC two channels at different sampling rate with burst &amp; oversample</title><link>https://devzone.nordicsemi.com/thread/169379?ContentTypeID=1</link><pubDate>Mon, 04 Feb 2019 20:52:06 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b79b42bd-7838-416e-982b-7e3990eb8b3c</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;I don&amp;#39;t have a better suggestion to try and fail a bit, and clean up your code. I would do all uninit() and init() in main, triggering of adc samples only when a channel is initialized, and not from the adc callback handler. Avoid mix non-blocking and blocking adc operations, as for instance the non-blocking may que the next operation while the current is on-going.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52832 SAADC two channels at different sampling rate with burst &amp; oversample</title><link>https://devzone.nordicsemi.com/thread/169329?ContentTypeID=1</link><pubDate>Mon, 04 Feb 2019 14:27:49 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:f3d7658c-88cf-49bc-8185-6f31a8c3c55d</guid><dc:creator>Morr</dc:creator><description>&lt;p&gt;Hello Kenneth,&lt;/p&gt;
&lt;p&gt;Thank you for your reply.&lt;/p&gt;
&lt;p&gt;I modified my test code to i&lt;span&gt;nitialize&amp;nbsp;and&amp;nbsp;un-initialize&amp;nbsp;the channel 1 at the main loop. However I get the same error, after re-init the&amp;nbsp;channel 1 and&amp;nbsp;set the buffer with&amp;nbsp;nrfx_saadc_buffer_convert at the 2nd sample, the SAADC stop response and there is no more callback from the SAADC.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Here is the log:&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;app: ch1 uninit, ch0 cnt: 0, raw: 98
 app: ch1 uninit, ch0 cnt: 1, raw: 89
 app: ch1 uninit, ch0 cnt: 2, raw: 93
 app: ch1 uninit, ch0 cnt: 3, raw: 89
 app: ch1 uninit, ch0 cnt: 4, raw: 94
 app: ch1 uninit, ch0 cnt: 5, raw: 98
 app: ch1 uninit, ch0 cnt: 6, raw: 97
 app: ch1 uninit, ch0 cnt: 7, raw: 100
 app: ch1 uninit, ch0 cnt: 8, raw: 107
 app: ch1 uninit, ch0 cnt: 9, raw: 104
 app: ch1 will init, ch0 cnt: 10, raw: 107
&lt;strong&gt; app: ch1 init at main                                        &amp;lt;---- ch1 init at main 1st time
 app: ch1 will uninit, ch0 cnt: 11, raw: 117
 app: ch1 result, ch1 cnt: 0, raw:3438, value: 4.0298900      &amp;lt;---- ch1 correct result
 app: ch1 uninit at main                                      &amp;lt;---- ch1 un-init at main 1st time&lt;/strong&gt;
 app: ch1 uninit, ch0 cnt: 12, raw: 185
 app: ch1 uninit, ch0 cnt: 13, raw: 111
 app: ch1 uninit, ch0 cnt: 14, raw: 120
 app: ch1 uninit, ch0 cnt: 15, raw: 128
 app: ch1 uninit, ch0 cnt: 16, raw: 127
 app: ch1 uninit, ch0 cnt: 17, raw: 131
 app: ch1 uninit, ch0 cnt: 18, raw: 134
 app: ch1 uninit, ch0 cnt: 19, raw: 135
 app: ch1 uninit, ch0 cnt: 20, raw: 138
 app: ch1 uninit, ch0 cnt: 21, raw: 138
 app: ch1 will init, ch0 cnt: 22, raw: 142
 app: ch1 init at main                                        &amp;lt;---- ch1 init at main 2nd time                                                    &amp;lt;--- SAADC Stop response, no more callback&lt;/pre&gt;
&lt;pre&gt;&lt;span&gt;&lt;br /&gt;&lt;br /&gt;Here is the modified test code to initialize&amp;nbsp;and&amp;nbsp;un-initialize&amp;nbsp;the channel 1 at the main loop.&lt;br /&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;lt;stdbool.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;quot;nrf.h&amp;quot;
//#include &amp;quot;nrf_drv_saadc.h&amp;quot;
#include &amp;quot;nrfx_saadc.h&amp;quot;
//#include &amp;quot;boards.h&amp;quot;
#include &amp;quot;app_timer.h&amp;quot;
#include &amp;quot;app_error.h&amp;quot;
#include &amp;quot;app_util_platform.h&amp;quot;
#include &amp;quot;nrf_pwr_mgmt.h&amp;quot;
#include &amp;quot;nrf_drv_power.h&amp;quot;
#include &amp;quot;nrf_drv_clock.h&amp;quot;
//#include &amp;quot;nrf_drv_rtc.h&amp;quot;
#include &amp;quot;nrfx_rtc.h&amp;quot;
#include &amp;quot;nrf_delay.h&amp;quot;

#include &amp;quot;nrf_log.h&amp;quot;
#include &amp;quot;nrf_log_ctrl.h&amp;quot;
#include &amp;quot;nrf_log_default_backends.h&amp;quot;

#define RTC_FREQUENCY 32
#define RTC_CC_VALUE 8                            //Determines the RTC interrupt frequency and thereby the SAADC sampling frequency

// ADC chnnel1 timer for sampling
APP_TIMER_DEF(appTimerChannel1);

typedef enum _CHANNEL_STATES
{
    channelUninitialized,
    channelWillInitialize,
    channelInitializeAtMain,
    channelInitialized,
    channelUninitializeAtMain,
    
} CHANNEL_STATES;


static const  nrfx_rtc_t           rtc = NRFX_RTC_INSTANCE(2); /**&amp;lt; Declaring an instance of nrf_drv_rtc for RTC2. */
static nrf_saadc_channel_config_t channel_config0 = NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
static nrf_saadc_channel_config_t channel_config1 = NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN6);
static nrf_saadc_value_t       m_buffer_pool[2][2];

static uint32_t countCh0;
static uint32_t countCh1;

static CHANNEL_STATES stateCh1;

static char logChar[64];

static void lfclk_config(void)
{
    ret_code_t err_code = nrf_drv_clock_init();                        //Initialize the clock source specified in the nrf_drv_config.h file, i.e. the CLOCK_CONFIG_LF_SRC constant
    APP_ERROR_CHECK(err_code);
    nrf_drv_clock_lfclk_request(NULL);
}

static void rtc_handler(nrfx_rtc_int_type_t int_type)
{
    uint32_t err_code;
    
    if (int_type == NRFX_RTC_INT_COMPARE0)
    {
        //if(!m_saadc_initialized)
        //{
        //    saadc_init();                                              //Initialize the SAADC. In the case when SAADC_SAMPLES_IN_BUFFER &amp;gt; 1 then we only need to initialize the SAADC when the the buffer is empty.
        //}
        //m_saadc_initialized = true;                                    //Set SAADC as initialized
        
        if ((stateCh1 != channelInitializeAtMain) &amp;amp;&amp;amp;
            (stateCh1 != channelUninitializeAtMain))
        {
            nrfx_saadc_sample();                                        //Trigger the SAADC SAMPLE task
        }
        else
        {
            NRF_LOG_INFO(&amp;quot;stateCh1 at main: %i&amp;quot;, stateCh1);
        }
        
        err_code = nrfx_rtc_cc_set(&amp;amp;rtc, 0, RTC_CC_VALUE, true);       //Set RTC compare value. This needs to be done every time as the nrf_drv_rtc clears the compare register on every compare match
        APP_ERROR_CHECK(err_code);
        nrfx_rtc_counter_clear(&amp;amp;rtc);                               //Clear the RTC counter to start count from zero
    }
}


static void rtc_config(void)
{
    uint32_t err_code;
    
    //Initialize RTC instance
    nrfx_rtc_config_t rtc_config = NRFX_RTC_DEFAULT_CONFIG;
    rtc_config.prescaler = RTC_FREQ_TO_PRESCALER(RTC_FREQUENCY);
    err_code = nrfx_rtc_init(&amp;amp;rtc, &amp;amp;rtc_config, rtc_handler);              //Initialize the RTC with callback function rtc_handler. The rtc_handler must be implemented in this applicaiton. Passing NULL here for RTC configuration means that configuration will be taken from the sdk_config.h file.
    APP_ERROR_CHECK(err_code);
    
    err_code = nrfx_rtc_cc_set(&amp;amp;rtc, 0, RTC_CC_VALUE, true);           //Set RTC compare value to trigger interrupt. Configure the interrupt frequency by adjust RTC_CC_VALUE and RTC_FREQUENCY constant in top of main.c
    APP_ERROR_CHECK(err_code);
    
    //Power on RTC instance
    nrfx_rtc_enable(&amp;amp;rtc);                                          //Enable RTC
}

static void saadc_callback(nrfx_saadc_evt_t const * p_event)
{
    //NRF_LOG_INFO(&amp;quot;SAADC callback\r\n&amp;quot;);
    if (p_event-&amp;gt;type == NRFX_SAADC_EVT_DONE)                                                        //Capture offset calibration complete event
    {
        ret_code_t err_code;
        
        switch (stateCh1) {
            case channelUninitialized:
            {
                err_code = nrfx_saadc_buffer_convert(p_event-&amp;gt;data.done.p_buffer, 1);  //Set buffer so the SAADC can write to it again. This is either &amp;quot;buffer 1&amp;quot; or &amp;quot;buffer 2&amp;quot;
                APP_ERROR_CHECK(err_code);

                NRF_LOG_INFO(&amp;quot;ch1 uninit, ch0 cnt: %i, raw: %i&amp;quot;, countCh0, p_event-&amp;gt;data.done.p_buffer[0]);
                countCh0++;

            } break;

            case channelWillInitialize:
            {
                // init channel 1
                //err_code = nrfx_saadc_channel_init(1, &amp;amp;channel_config1);
                //APP_ERROR_CHECK(err_code);

                // set buffer to 2 for both channels 1&amp;amp;2
                //err_code = nrfx_saadc_buffer_convert(p_event-&amp;gt;data.done.p_buffer, 2);  //Set buffer so the SAADC can write to it again. This is either &amp;quot;buffer 1&amp;quot; or &amp;quot;buffer 2&amp;quot;
                //APP_ERROR_CHECK(err_code);

                NRF_LOG_INFO(&amp;quot;ch1 will init, ch0 cnt: %i, raw: %i&amp;quot;, countCh0, p_event-&amp;gt;data.done.p_buffer[0]);
                countCh0++;
                stateCh1 = channelInitializeAtMain;

            } break;

            case channelInitialized:
            {
                //err_code = nrfx_saadc_channel_uninit(1);
                //APP_ERROR_CHECK(err_code);

                // set buffer to 1 for channels 0
                //err_code = nrfx_saadc_buffer_convert(p_event-&amp;gt;data.done.p_buffer, 1);  //Set buffer so the SAADC can write to it again. This is either &amp;quot;buffer 1&amp;quot; or &amp;quot;buffer 2&amp;quot;
                //APP_ERROR_CHECK(err_code);

                NRF_LOG_INFO(&amp;quot;ch1 will uninit, ch0 cnt: %i, raw: %i&amp;quot;, countCh0, p_event-&amp;gt;data.done.p_buffer[0]);

                // for channel1 adc result
                // gain: 1/4, external voltage divider: 1/2, internal ref. 0.6,
                float ch1Value = (((float) p_event-&amp;gt;data.done.p_buffer[1]) * 8.0f * 0.6f) / 4095.0f;

                sprintf(logChar, &amp;quot;ch1 result, ch1 cnt: %d, raw:%i, value: %.7f&amp;quot;, countCh1, p_event-&amp;gt;data.done.p_buffer[1], ch1Value);
                NRF_LOG_INFO(&amp;quot;%s&amp;quot;, logChar);

                countCh0++;
                countCh1++;
                stateCh1 = channelUninitializeAtMain;

            } break;

            default:
                NRF_LOG_INFO(&amp;quot;stateCh1: %i&amp;quot;, stateCh1);
                break;
        }
    }
}


static void saadc_init(void)
{
    ret_code_t err_code;
    
    //Configure SAADC
    nrfx_saadc_config_t saadc_config;
    saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;                                 //Set SAADC resolution to 12-bit. This will make the SAADC output values from 0 (when input voltage is 0V) to 2^12=2048 (when input voltage is 3.6V for channel gain setting of 1/6).
    saadc_config.oversample = NRF_SAADC_OVERSAMPLE_4X;                                           //Set oversample to 4x. This will make the SAADC output a single averaged value when the SAMPLE task is triggered 4 times.
    saadc_config.interrupt_priority = APP_IRQ_PRIORITY_LOW;                               //Set SAADC interrupt to low priority.
    saadc_config.low_power_mode = true;
    
    //Initialize SAADC
    err_code = nrfx_saadc_init(&amp;amp;saadc_config, saadc_callback);                         //Initialize the SAADC with configuration and callback function. The application must then implement the saadc_callback function, which will be called when SAADC interrupt is triggered
    APP_ERROR_CHECK(err_code);
    
    //Configure SAADC channel 0
    //nrf_saadc_channel_config_t channel_config0 = NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
    channel_config0.gain = NRF_SAADC_GAIN1;
    channel_config0.reference = NRF_SAADC_REFERENCE_VDD4;
    channel_config0.acq_time = NRF_SAADC_ACQTIME_10US;
    channel_config0.burst = NRF_SAADC_BURST_ENABLED;
    err_code = nrfx_saadc_channel_init(0, &amp;amp;channel_config0);
    APP_ERROR_CHECK(err_code);
    
    //nrf_saadc_channel_config_t channel_config1 = NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN6);
    channel_config1.gain = NRF_SAADC_GAIN1_4;
    channel_config1.reference = NRF_SAADC_REFERENCE_INTERNAL;      // internal ref.: 0.6V
    channel_config1.acq_time = NRF_SAADC_ACQTIME_15US;
    channel_config1.burst = NRF_SAADC_BURST_ENABLED;
    //err_code = nrfx_saadc_channel_init(1, &amp;amp;channel_config1);
    //APP_ERROR_CHECK(err_code);
    
    stateCh1 = channelUninitialized;

    err_code = nrfx_saadc_buffer_convert(m_buffer_pool[0],2);    //Set SAADC buffer 1. The SAADC will start to write to this buffer
    APP_ERROR_CHECK(err_code);
    
    //err_code = nrfx_saadc_buffer_convert(m_buffer_pool[1],2);    //Set SAADC buffer 2. The SAADC will write to this buffer when buffer 1 is full. This will give the applicaiton time to process data in buffer 1.
    //APP_ERROR_CHECK(err_code);
}

static void appTimerCallbackChannel1(void * p_context)
{
    // do nothing
    UNUSED_PARAMETER(p_context);
    
    if (stateCh1 == channelUninitialized)
    {
        stateCh1 = channelWillInitialize;
    }
    
    return;
}


static void app_timer_config(void)
{
    ret_code_t err_code;
    
    // init application timer
    err_code = app_timer_init();
    APP_ERROR_CHECK(err_code);

    // Create timers for adc channel1 sampling
    err_code = app_timer_create(&amp;amp;appTimerChannel1, APP_TIMER_MODE_REPEATED, appTimerCallbackChannel1);
    APP_ERROR_CHECK(err_code);
    
    // channel1 sample every 3 second
    err_code = app_timer_start(appTimerChannel1, APP_TIMER_TICKS(3000), NULL);
    APP_ERROR_CHECK(err_code);

    return;
}


/**
 * @brief Function for main application entry.
 */
int main(void)
{
    ret_code_t err_code;
    
    // log init
    err_code = NRF_LOG_INIT(NULL);
    APP_ERROR_CHECK(err_code);
    NRF_LOG_DEFAULT_BACKENDS_INIT();
    
    //initializing power management.
    err_code = nrf_pwr_mgmt_init();
    APP_ERROR_CHECK(err_code);

    //Enabling the DCDC converter for lower current consumption
    NRF_POWER-&amp;gt;DCDCEN = 1;
    
    NRF_LOG_INFO(&amp;quot;Test \r\n&amp;quot;);
    
    //Configure low frequency 32kHz clock
    lfclk_config();
    
    // init saadc
    countCh0 = 0;
    countCh1 = 0;
    saadc_init();
    
    // init app timer
    app_timer_config();
    
    //Configure RTC. The RTC will generate periodic interrupts. Requires 32kHz clock to operate.
    rtc_config();
    
    while(1)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
        
        switch (stateCh1) {
            case channelInitializeAtMain:
            {
                // uninit channel 0
                //err_code = nrfx_saadc_channel_uninit(0);
                //APP_ERROR_CHECK(err_code);

                // reinit channel 0
                //err_code = nrfx_saadc_channel_init(0, &amp;amp;channel_config0);
                //APP_ERROR_CHECK(err_code);

                // init channel 1
                err_code = nrfx_saadc_channel_init(1, &amp;amp;channel_config1);
                APP_ERROR_CHECK(err_code);
                
                // set buffer to 2 for both channels 1&amp;amp;2
                err_code = nrfx_saadc_buffer_convert(m_buffer_pool[0], 2);  //Set buffer so the SAADC can write to it again. This is either &amp;quot;buffer 1&amp;quot; or &amp;quot;buffer 2&amp;quot;
                APP_ERROR_CHECK(err_code);
                
                NRF_LOG_INFO(&amp;quot;ch1 init at main&amp;quot;);
                stateCh1 = channelInitialized;
                
            } break;

            case channelUninitializeAtMain:
            {
                // uninit channel 0
                //err_code = nrfx_saadc_channel_uninit(0);
                //APP_ERROR_CHECK(err_code);
                
                // uninit channel 1
                err_code = nrfx_saadc_channel_uninit(1);
                APP_ERROR_CHECK(err_code);

                // re-init channel 0
                //err_code = nrfx_saadc_channel_init(0, &amp;amp;channel_config0);
                //APP_ERROR_CHECK(err_code);

                // set buffer to 1 for channels 0
                err_code = nrfx_saadc_buffer_convert(m_buffer_pool[0], 1);  //Set buffer so the SAADC can write to it again. This is either &amp;quot;buffer 1&amp;quot; or &amp;quot;buffer 2&amp;quot;
                APP_ERROR_CHECK(err_code);

                NRF_LOG_INFO(&amp;quot;ch1 uninit at main&amp;quot;);
                stateCh1 = channelUninitialized;
                
            } break;

            default:
                break;
        }
    }

}

&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52832 SAADC two channels at different sampling rate with burst &amp; oversample</title><link>https://devzone.nordicsemi.com/thread/169266?ContentTypeID=1</link><pubDate>Mon, 04 Feb 2019 10:22:04 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e61fec09-1c34-4265-85bb-1843d3866d31</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;My suggestion is that you set a flag in the&amp;nbsp;&lt;span&gt;SAADC callback function, and then you in main&amp;nbsp;initialize&amp;nbsp;and&amp;nbsp;un-initialize&amp;nbsp;the channel 1 and 2 as you see fit depending on the flag. I think the problem is that the callback handler is called from&amp;nbsp;nrfx_saadc_irq_handler(), and that occurs before the&amp;nbsp;nrfx_saadc_irq_handler is finished executing and you thereby create a bad state if you uninit and init the saadc from the callback handler.&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52832 SAADC two channels at different sampling rate with burst &amp; oversample</title><link>https://devzone.nordicsemi.com/thread/169203?ContentTypeID=1</link><pubDate>Mon, 04 Feb 2019 05:30:23 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:1a3313b4-751c-4d00-af67-4074b80ca9d9</guid><dc:creator>Morr</dc:creator><description>&lt;p&gt;Hello Kenneth,&lt;/p&gt;
&lt;p&gt;Thank you for your reply.&lt;/p&gt;
&lt;p&gt;However, according to the documentation, oversampling with scan mode is supported,&amp;nbsp;&lt;span&gt;if burst is enabled on all channels.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;quot;&lt;span&gt;Scan mode can be combined with BURST=1, if burst is enabled on all channels.&amp;quot;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;And also according to this post,&amp;nbsp;&lt;a href="https://devzone.nordicsemi.com/f/nordic-q-a/20556/how-does-the-saadc-scan-mode-use-the-burst-1"&gt;https://devzone.nordicsemi.com/f/nordic-q-a/20556/how-does-the-saadc-scan-mode-use-the-burst-1,&lt;/a&gt;&amp;nbsp;it also answered that&amp;nbsp;when burst is enabled for all the active channels, scan mode with&amp;nbsp;oversampling will work correctly.&lt;/p&gt;
&lt;p&gt;I did a test with following code for scan mode with oversampling and burst enabled for channel 1 &amp;amp; 2 at the SAME sampling rate (250ms). From the log, the SAADC does appear to work correctly.&lt;/p&gt;
&lt;p&gt;Moreover, for the &amp;quot;oversampling then only one channel can be enabled at any time&amp;quot;,&amp;nbsp;according to this post, &lt;a href="https://devzone.nordicsemi.com/f/nordic-q-a/26659/saacd-scan-oversample/104878#104878"&gt;https://devzone.nordicsemi.com/f/nordic-q-a/26659/saacd-scan-oversample/104878#104878,&lt;/a&gt;&amp;nbsp;although&amp;nbsp;the&amp;nbsp;&lt;span&gt;SAADC driver in the SDK is not support the multichannel oversampling yet, it can&amp;nbsp;&lt;/span&gt;&lt;span&gt;be quite simple to add&amp;nbsp;this function by following the&amp;nbsp;J&amp;oslash;rgen&amp;#39;s&amp;nbsp;instructions. To simplify my test, I just&amp;nbsp;comment out the Line 293 &amp;amp; 294 at&amp;nbsp;nrfx_saadc_channel_init of nrfx_saadc.c.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Therefore my question is: F&lt;span&gt;or sampling two analog signals at different sampling rate in scan mode with&amp;nbsp;oversampling and burst enabled, how to&amp;nbsp;initialize and un-nitialize&amp;nbsp;the channel 1 &amp;amp; 2 correctly?&amp;nbsp;&lt;/span&gt;&lt;span&gt;Thanks!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Here is the log for scan mode with oversampling and burst enabled for channel 1 &amp;amp; 2 at the SAME sampling rate:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&amp;lt;info&amp;gt; app: ch0 result cnt: 0, raw: 100&lt;br /&gt;&amp;lt;info&amp;gt; app: ch1 result cnt: 0, raw:3522, value: 4.1283521&lt;br /&gt;&amp;lt;info&amp;gt; app: ch0 result cnt: 1, raw: 164&lt;br /&gt;&amp;lt;info&amp;gt; app: ch1 result cnt: 1, raw:3517, value: 4.1224913&lt;br /&gt;&amp;lt;info&amp;gt; app: ch0 result cnt: 2, raw: 163&lt;br /&gt;&amp;lt;info&amp;gt; app: ch1 result cnt: 2, raw:3517, value: 4.1224913&lt;br /&gt;&amp;lt;info&amp;gt; app: ch0 result cnt: 3, raw: 167&lt;br /&gt;&amp;lt;info&amp;gt; app: ch1 result cnt: 3, raw:3516, value: 4.1213188&lt;br /&gt;&amp;lt;info&amp;gt; app: ch0 result cnt: 4, raw: 177&lt;br /&gt;&amp;lt;info&amp;gt; app: ch1 result cnt: 4, raw:3530, value: 4.1377291&lt;br /&gt;&amp;lt;info&amp;gt; app: ch0 result cnt: 5, raw: 179&lt;br /&gt;&amp;lt;info&amp;gt; app: ch1 result cnt: 5, raw:3567, value: 4.1810994&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Here is my code for testing&amp;nbsp;scan mode with oversampling and burst enabled for channel 1 &amp;amp; 2 at the SAME sampling rate:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;lt;stdbool.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;quot;nrf.h&amp;quot;
//#include &amp;quot;nrf_drv_saadc.h&amp;quot;
#include &amp;quot;nrfx_saadc.h&amp;quot;
//#include &amp;quot;boards.h&amp;quot;
#include &amp;quot;app_timer.h&amp;quot;
#include &amp;quot;app_error.h&amp;quot;
#include &amp;quot;app_util_platform.h&amp;quot;
#include &amp;quot;nrf_pwr_mgmt.h&amp;quot;
#include &amp;quot;nrf_drv_power.h&amp;quot;
#include &amp;quot;nrf_drv_clock.h&amp;quot;
//#include &amp;quot;nrf_drv_rtc.h&amp;quot;
#include &amp;quot;nrfx_rtc.h&amp;quot;
#include &amp;quot;nrf_delay.h&amp;quot;

#include &amp;quot;nrf_log.h&amp;quot;
#include &amp;quot;nrf_log_ctrl.h&amp;quot;
#include &amp;quot;nrf_log_default_backends.h&amp;quot;

#define RTC_FREQUENCY 32
#define RTC_CC_VALUE 8                            //Determines the RTC interrupt frequency and thereby the SAADC sampling frequency

// ADC chnnel1 timer for sampling
APP_TIMER_DEF(appTimerChannel1);

static const  nrfx_rtc_t           rtc = NRFX_RTC_INSTANCE(2); /**&amp;lt; Declaring an instance of nrf_drv_rtc for RTC2. */
//static nrf_saadc_channel_config_t channel_config1 = NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN6);
static nrf_saadc_value_t       m_buffer_pool[2][2];

static uint32_t countCh0;
static uint32_t countCh1;

static char logChar[64];

static void lfclk_config(void)
{
    ret_code_t err_code = nrf_drv_clock_init();                        //Initialize the clock source specified in the nrf_drv_config.h file, i.e. the CLOCK_CONFIG_LF_SRC constant
    APP_ERROR_CHECK(err_code);
    nrf_drv_clock_lfclk_request(NULL);
}

static void rtc_handler(nrfx_rtc_int_type_t int_type)
{
    uint32_t err_code;
    
    if (int_type == NRFX_RTC_INT_COMPARE0)
    {
        //if(!m_saadc_initialized)
        //{
        //    saadc_init();                                              //Initialize the SAADC. In the case when SAADC_SAMPLES_IN_BUFFER &amp;gt; 1 then we only need to initialize the SAADC when the the buffer is empty.
        //}
        //m_saadc_initialized = true;                                    //Set SAADC as initialized
        
        nrfx_saadc_sample();                                        //Trigger the SAADC SAMPLE task
        
        err_code = nrfx_rtc_cc_set(&amp;amp;rtc, 0, RTC_CC_VALUE, true);       //Set RTC compare value. This needs to be done every time as the nrf_drv_rtc clears the compare register on every compare match
        APP_ERROR_CHECK(err_code);
        nrfx_rtc_counter_clear(&amp;amp;rtc);                               //Clear the RTC counter to start count from zero
    }
}


static void rtc_config(void)
{
    uint32_t err_code;
    
    //Initialize RTC instance
    nrfx_rtc_config_t rtc_config = NRFX_RTC_DEFAULT_CONFIG;
    rtc_config.prescaler = RTC_FREQ_TO_PRESCALER(RTC_FREQUENCY);
    err_code = nrfx_rtc_init(&amp;amp;rtc, &amp;amp;rtc_config, rtc_handler);              //Initialize the RTC with callback function rtc_handler. The rtc_handler must be implemented in this applicaiton. Passing NULL here for RTC configuration means that configuration will be taken from the sdk_config.h file.
    APP_ERROR_CHECK(err_code);
    
    err_code = nrfx_rtc_cc_set(&amp;amp;rtc, 0, RTC_CC_VALUE, true);           //Set RTC compare value to trigger interrupt. Configure the interrupt frequency by adjust RTC_CC_VALUE and RTC_FREQUENCY constant in top of main.c
    APP_ERROR_CHECK(err_code);
    
    //Power on RTC instance
    nrfx_rtc_enable(&amp;amp;rtc);                                          //Enable RTC
}

static void saadc_callback(nrfx_saadc_evt_t const * p_event)
{
    //NRF_LOG_INFO(&amp;quot;SAADC callback\r\n&amp;quot;);
    if (p_event-&amp;gt;type == NRFX_SAADC_EVT_DONE)                                                        //Capture offset calibration complete event
    {
        ret_code_t err_code;
        
        err_code = nrfx_saadc_buffer_convert(p_event-&amp;gt;data.done.p_buffer, 2);  //Set buffer so the SAADC can write to it again. This is either &amp;quot;buffer 1&amp;quot; or &amp;quot;buffer 2&amp;quot;
        APP_ERROR_CHECK(err_code);
        
        NRF_LOG_INFO(&amp;quot;ch0 result cnt: %i, raw: %i&amp;quot;, countCh0, p_event-&amp;gt;data.done.p_buffer[0]);
        
        // for channel1 adc result
        // gain: 1/4, external voltage divider: 1/2, internal ref. 0.6,
        float ch1Value = (((float) p_event-&amp;gt;data.done.p_buffer[1]) * 8.0f * 0.6f) / 4095.0f;
        
        sprintf(logChar, &amp;quot;ch1 result cnt: %d, raw:%i, value: %.7f&amp;quot;, countCh1, p_event-&amp;gt;data.done.p_buffer[1], ch1Value);
        NRF_LOG_INFO(&amp;quot;%s&amp;quot;, logChar);
        
        countCh0++;
        countCh1++;
    }
}


static void saadc_init(void)
{
    ret_code_t err_code;
    
    //Configure SAADC
    nrfx_saadc_config_t saadc_config;
    saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;                                 //Set SAADC resolution to 12-bit. This will make the SAADC output values from 0 (when input voltage is 0V) to 2^12=2048 (when input voltage is 3.6V for channel gain setting of 1/6).
    saadc_config.oversample = NRF_SAADC_OVERSAMPLE_4X;                                           //Set oversample to 4x. This will make the SAADC output a single averaged value when the SAMPLE task is triggered 4 times.
    saadc_config.interrupt_priority = APP_IRQ_PRIORITY_LOW;                               //Set SAADC interrupt to low priority.
    saadc_config.low_power_mode = true;
    
    //Initialize SAADC
    err_code = nrfx_saadc_init(&amp;amp;saadc_config, saadc_callback);                         //Initialize the SAADC with configuration and callback function. The application must then implement the saadc_callback function, which will be called when SAADC interrupt is triggered
    APP_ERROR_CHECK(err_code);
    
    //Configure SAADC channel 0
    nrf_saadc_channel_config_t channel_config0 = NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
    channel_config0.gain = NRF_SAADC_GAIN1;
    channel_config0.reference = NRF_SAADC_REFERENCE_VDD4;
    channel_config0.acq_time = NRF_SAADC_ACQTIME_10US;
    channel_config0.burst = NRF_SAADC_BURST_ENABLED;
    err_code = nrfx_saadc_channel_init(0, &amp;amp;channel_config0);
    APP_ERROR_CHECK(err_code);
    
    nrf_saadc_channel_config_t channel_config1 = NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN6);
    channel_config1.gain = NRF_SAADC_GAIN1_4;
    channel_config1.reference = NRF_SAADC_REFERENCE_INTERNAL;      // internal ref.: 0.6V
    channel_config1.acq_time = NRF_SAADC_ACQTIME_15US;
    channel_config1.burst = NRF_SAADC_BURST_ENABLED;
    err_code = nrfx_saadc_channel_init(1, &amp;amp;channel_config1);
    APP_ERROR_CHECK(err_code);
    
    err_code = nrfx_saadc_buffer_convert(m_buffer_pool[0],2);    //Set SAADC buffer 1. The SAADC will start to write to this buffer
    APP_ERROR_CHECK(err_code);
    
    err_code = nrfx_saadc_buffer_convert(m_buffer_pool[1],2);    //Set SAADC buffer 2. The SAADC will write to this buffer when buffer 1 is full. This will give the applicaiton time to process data in buffer 1.
    APP_ERROR_CHECK(err_code);
}


/**
 * @brief Function for main application entry.
 */
int main(void)
{
    ret_code_t err_code;
    
    // log init
    err_code = NRF_LOG_INIT(NULL);
    APP_ERROR_CHECK(err_code);
    NRF_LOG_DEFAULT_BACKENDS_INIT();
    
    //initializing power management.
    err_code = nrf_pwr_mgmt_init();
    APP_ERROR_CHECK(err_code);

    //Enabling the DCDC converter for lower current consumption
    NRF_POWER-&amp;gt;DCDCEN = 1;
    
    NRF_LOG_INFO(&amp;quot;Test \r\n&amp;quot;);
    
    //Configure low frequency 32kHz clock
    lfclk_config();
    
    // init saadc
    countCh0 = 0;
    countCh1 = 0;
    saadc_init();
    
    //Configure RTC. The RTC will generate periodic interrupts. Requires 32kHz clock to operate.
    rtc_config();
    
    while(1)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }

}

&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52832 SAADC two channels at different sampling rate with burst &amp; oversample</title><link>https://devzone.nordicsemi.com/thread/168925?ContentTypeID=1</link><pubDate>Thu, 31 Jan 2019 15:49:42 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:53d06ab5-5c1b-4e05-be0e-12e9785d9caa</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;If I understand you correctly you are trying to execute a combination that is not supported in hardware. From the documentation you can find:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52832.ps.v1.1/saadc.html?cp=2_1_0_36_4#saadc_operationmodes"&gt;http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52832.ps.v1.1/saadc.html?cp=2_1_0_36_4#saadc_operationmodes&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;quot;&lt;span&gt;Scan mode and oversampling cannot be combined.&lt;/span&gt;&amp;quot;&lt;/p&gt;
&lt;p&gt;So if you are using oversampling then only one channel can be enabled at any time (only one &lt;span&gt;CH[n].PSELP is set)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Best regards,&lt;br /&gt;Kenneth&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52832 SAADC two channels at different sampling rate with burst &amp; oversample</title><link>https://devzone.nordicsemi.com/thread/168792?ContentTypeID=1</link><pubDate>Thu, 31 Jan 2019 08:11:39 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c371f9d0-8d93-4a74-ba0a-16552e8dd981</guid><dc:creator>Morr</dc:creator><description>&lt;p&gt;I forgot to mention, for enable the oversample for two channels, I comment out Line 293 &amp;amp; 294 at&amp;nbsp;nrfx_saadc_channel_init of nrfx_saadc.c.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Line 293 &amp;amp; 294&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span class="Apple-converted-space"&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;// Oversampling can be used only with one channel.&lt;/p&gt;
&lt;p&gt;&lt;span class="Apple-converted-space"&gt;&amp;nbsp; &amp;nbsp; //&lt;/span&gt;NRFX_ASSERT((nrf_saadc_oversample_get() == NRF_SAADC_OVERSAMPLE_DISABLED) ||&lt;/p&gt;
&lt;p&gt;&lt;span class="Apple-converted-space"&gt;&amp;nbsp; &amp;nbsp; // &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;(m_cb.active_channels == &lt;span&gt;0&lt;/span&gt;));&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>