<?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>SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/64615/saadc-scan-burst</link><description>On SDK16.0.0 + Mesh SDK 4.1.0 
 I know that oversampling when using the SADDC in scan mode on multiple channels does not work because the buffer gets all out of order. 
 But I believe burst mode can be used in scan mode where it samples the channel multiple</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Fri, 04 Sep 2020 14:46:47 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/64615/saadc-scan-burst" /><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/268104?ContentTypeID=1</link><pubDate>Fri, 04 Sep 2020 14:46:47 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:4197f4e1-4a27-49af-8efc-66c9b92bb177</guid><dc:creator>ftjandra</dc:creator><description>&lt;p&gt;Thanks for the update and all your hard work in getting to the bottom of this!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/268022?ContentTypeID=1</link><pubDate>Fri, 04 Sep 2020 10:49:39 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:92a5f676-ae3d-4409-869a-bf5099c0c49c</guid><dc:creator>Karl Ylvisaker</dc:creator><description>&lt;p&gt;Hello again,&lt;br /&gt;&lt;br /&gt;The HW engineers have taken an initial look at the demonstration I provided, and they concur that this is an issue that must be looked into further.&lt;br /&gt;However, some of the HW engineering team are out of office this and the following week, so it will probably take some time to investigate and debug this fully.&lt;br /&gt;Thank you for your continued patience. Please know that we are determined to get to the bottom of this.&lt;br /&gt;&lt;br /&gt;I will update this ticket as soon as I have any new information. In the meantime, please do not hesitate to reach out to&amp;nbsp;your contact Gene if there should be anything you would like to discuss.&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Karl&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/267219?ContentTypeID=1</link><pubDate>Mon, 31 Aug 2020 11:52:47 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:ecd227c6-a708-4202-a784-7eed09e37b72</guid><dc:creator>Karl Ylvisaker</dc:creator><description>&lt;p&gt;Hello again,&lt;br /&gt;&lt;br /&gt;Thank you for your patience.&lt;br /&gt;&lt;br /&gt;I just wanted to update you that I have spoken with our HW engineers and provided them with a minimal application to demonstrate the problem.&lt;br /&gt;They will take a look and get back to me shortly, before scheduling a deeper investigation into the issue.&lt;br /&gt;I will keep your updated.&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Karl&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/266920?ContentTypeID=1</link><pubDate>Fri, 28 Aug 2020 09:11:54 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:697883a6-a71b-4037-88be-2207b9882c17</guid><dc:creator>Karl Ylvisaker</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
[quote user="ftjandra"]I can confirm that adding the 3ms delay stops the buffer shift. But isn&amp;#39;t it odd that before adding the delay it only shifted once after the first calibration and never again? I would expect it to shift every time.[/quote]
&lt;p&gt;Yes, I too find this odd as I would expect it to happen at other times also. All my tests thus far indicate that it does not, however. So, it is absolutely interesting.&lt;br /&gt;I am in the process of creating a bare-metal demonstration of this behavior, to begin debugging of the hardware and to isolate the driver from the problem.&lt;br /&gt;I hope to know more about this soon.&lt;/p&gt;
[quote user="ftjandra"]I will wait for your follow up before I put this into production firmware.[/quote]
&lt;p&gt;Great, I will get back to you on this as soon as I have got something to share.&lt;br /&gt;I have asked for a meeting with the HW and SAADC driver engineers as soon as possible to discuss this.&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Karl&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/266826?ContentTypeID=1</link><pubDate>Thu, 27 Aug 2020 18:45:50 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:431832ee-332e-49f0-924e-ebe5bd536b1a</guid><dc:creator>ftjandra</dc:creator><description>&lt;p&gt;I can confirm that adding the 3ms delay stops the buffer shift. But isn&amp;#39;t it odd that before adding the delay it only shifted once after the first calibration and never again? I would expect it to shift every time.&lt;/p&gt;
&lt;p&gt;I will wait for your follow up before I put this into production firmware.&lt;/p&gt;
&lt;p&gt;Thanks.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/266691?ContentTypeID=1</link><pubDate>Thu, 27 Aug 2020 10:21:01 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:4b9ff4cb-1443-4b74-8511-b0cf6ae93fcf</guid><dc:creator>Karl Ylvisaker</dc:creator><description>&lt;p&gt;Hello again,&lt;br /&gt;&lt;br /&gt;I have done some more testing, and I might have identified the source of the error.&lt;br /&gt;The START task seems to be called too fast after the CALIBRATE DONE event happens.&lt;br /&gt;I observe that adding a &amp;gt;= 3 ms delay to the CALIBRATE DONE event handler, in before the buffer convert function calls, negates the buffer shift all together.&lt;br /&gt;I have ran this multiple times now, for extended periods, and not seen any buffer shifts happening. Please try this on your end as well, and let me know what you observe.&lt;br /&gt;This is the addition which you might make to your project:&lt;br /&gt;&lt;br /&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;    else if(p_event-&amp;gt;type == NRF_DRV_SAADC_EVT_CALIBRATEDONE) {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, &amp;quot;SAADC calibration complete\n&amp;quot;);
        saadc_calibrate_stage = 0; //reset
      
        // INSERTED DELAY
        // 2 ms delay yields buffer shift by 1 position following 2nd calibration.
        // 3 ms delay yields constant buffer, no shift.
        nrf_delay_ms(3);

        //Need to setup both buffers, as they were both removed with the call to nrf_drv_saadc_abort before calibration
        ERROR_CHECK(nrf_drv_saadc_buffer_convert(saadc_buffer_pool[0], SAADC_SAMPLES_IN_BUFFER));
        ERROR_CHECK(nrf_drv_saadc_buffer_convert(saadc_buffer_pool[1], SAADC_SAMPLES_IN_BUFFER));

        nrf_drv_timer_enable(&amp;amp;m_saadc_timer);
    }&lt;/pre&gt;&lt;br /&gt;You will also have to add the nrf_delay.h file to your project.&lt;br /&gt;&lt;br /&gt;This issue is especially strange since the way you have implemented the CALIBRATE DONE event handler is the normal way to setup the buffers following a calibration, which leads me to believe this might be an artifact of the scan + oversampling + burst configuration. This is just my current suspicion, which I will continue working on to verify. I have opened an internal request to have this reviewed by the module&amp;#39;s engineers too.&lt;br /&gt;Thank you for bringing this up, this is absolutely an interesting find!&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Karl&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/266473?ContentTypeID=1</link><pubDate>Wed, 26 Aug 2020 11:57:00 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:5d54bed7-e645-49d8-8749-fee6d49cacac</guid><dc:creator>Karl Ylvisaker</dc:creator><description>&lt;p&gt;Hello,&lt;br /&gt;&lt;br /&gt;Thank you for your patience.&lt;br /&gt;I just ran the project you provided. My only modifications were to some of the preprocessor include directories, and setting the DEBUG flag.&lt;br /&gt;I am able to reproduce the issue, and I clearly see the behavior you have described about the buffer being shifted by one following the first calibration, and afterwards staying consistent.&lt;/p&gt;
[quote user="ftjandra"]I set the PPI to trigger every second. You make it sound like when low_power_mode is set to 1, it should take longer to sample, but when I set it to 1, it is sampling much faster, around 10 times per second.[/quote]
&lt;p&gt;I tested with LP_mode as well, with the same result.&lt;br /&gt;I was not able to see the behavior you described here regarding seemingly more frequent sampling occurring in Low-Power mode, but on my end the buffer shift happens with Low-Power mode as well.&lt;br /&gt;&lt;br /&gt;I will now&amp;nbsp; delve deeper into this issue, and see if I can not figure out its root cause and how to negate it. I will update you as soon as I have something.&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Karl&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/266073?ContentTypeID=1</link><pubDate>Mon, 24 Aug 2020 23:51:52 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:1f76b3c5-81a3-4164-bd21-14e87a2fe432</guid><dc:creator>ftjandra</dc:creator><description>&lt;p&gt;Adding DEBUG to the preprocessor defines didn&amp;#39;t change anything, no assert.&lt;/p&gt;
&lt;p&gt;I set the PPI to trigger every second. You make it sound like when low_power_mode is set to 1, it should take longer to sample, but when I set it to 1, it is sampling much faster, around 10 times per second.&lt;/p&gt;
&lt;p&gt;Thanks.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/266015?ContentTypeID=1</link><pubDate>Mon, 24 Aug 2020 14:04:22 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:a3afe8c9-673a-4036-856a-8a3790b7b3a8</guid><dc:creator>Karl Ylvisaker</dc:creator><description>&lt;p&gt;Hello,&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
[quote user="ftjandra"]Ok, I started from a fresh light switch server and only added what was needed to test this. The project is attached (&lt;span&gt;SDK16.0.0 + Mesh SDK 4.1.0)&lt;/span&gt;[/quote]
&lt;p&gt;Thank you for providing me with this project. I have allocated time to test this tomorrow.&lt;br /&gt;&lt;br /&gt;I have just gotten back from conferring with our SAADC expert, and he had some thoughts on the matter:&lt;br /&gt;&lt;br /&gt;First, on the subject of Low-Power mode negating the buffer shift:&lt;br /&gt;This might be because Low-Power mode stops the SAADC between every sample, which in turn ensures that the workaround for the Errata 237 is in place.&lt;br /&gt;&lt;br /&gt;To test if this is the case, could you define DEBUG in your preprocessor defines ( like showed in the included picture ) and see if your call to _abort asserts due to hardware timeout when waiting for the SAADC to be stopped?&lt;br /&gt;In this case, it points to the fact that the SAADC never truly was stopped, and thus the calibration is called as described in the errata I mentioned earlier, leaving an unexpected sample in the buffer.&lt;br /&gt;&lt;img alt=" " src="https://devzone.nordicsemi.com/resized-image/__size/320x240/__key/support-attachments/beef5d1b77644c448dabff31668f3a47-aa9ee46c66bb4f068b0cb24737a23f96/enabling_5F00_debug_5F00_SES.PNG" /&gt;&lt;/p&gt;
[quote user="ftjandra"]What is low power mode?[/quote]
&lt;p&gt;The documentation is indeed a little sparse on this, so it is good that you ask! Low-power mode stops the SAADC between each sample.&lt;br /&gt;It is ideal for low-frequency sampling, however it does add some time to the conversion time.&lt;/p&gt;
[quote user="ftjandra"]With low_power_mode set to 1, it looks like the buffer stays correct, but the timing is not working anymore.[/quote]
&lt;p&gt;What is your sampling frequency? Since you are using PPI, there is a change when using Low-Power mode. Instead of the PPI trigger TASK_SAMPLE, it will instead trigger TASK_START, which will add some time to your conversion time.&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Karl&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/265414?ContentTypeID=1</link><pubDate>Wed, 19 Aug 2020 20:06:59 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:0b386982-ea33-4e39-8139-780fe67ae152</guid><dc:creator>ftjandra</dc:creator><description>&lt;p&gt;Ok, I started from a fresh light switch server and only added what was needed to test this. The project is attached (&lt;span&gt;SDK16.0.0 + Mesh SDK 4.1.0)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;With low_power_mode set to 0, you can see that the buffer gets offset by one after the first calibration.&lt;/p&gt;
&lt;p&gt;With low_power_mode set to 1, it looks like the buffer stays correct, but the timing is not working anymore. It&amp;#39;s not sampling every second, but instead it seems to be sampling continuously as fast as possible? What is low power mode?&lt;/p&gt;
&lt;p&gt;Thanks.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;a href="https://devzone.nordicsemi.com/cfs-file/__key/communityserver-discussions-components-files/4/server_5F00_light_5F00_switch_5F00_saadc.zip"&gt;devzone.nordicsemi.com/.../server_5F00_light_5F00_switch_5F00_saadc.zip&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/265302?ContentTypeID=1</link><pubDate>Wed, 19 Aug 2020 12:06:19 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:58f974e9-1f3a-4919-9bee-380893702168</guid><dc:creator>Karl Ylvisaker</dc:creator><description>&lt;p&gt;Hello,&lt;br /&gt;&lt;br /&gt;Thank you for the clear illustration.&lt;/p&gt;
[quote user="ftjandra"]Instead of&amp;nbsp;nrf_pwr_mgmt_run(), I used&amp;nbsp;sd_app_evt_wait(). I think they do the same thing when the Soft Device is used.[/quote]
&lt;p&gt;Yes, using sd_app_evt_wait will function just as well - the CPU will be sleeping until an application event is generated.&lt;/p&gt;
[quote user="ftjandra"]I just realized, isn&amp;#39;t nrf_drv_saadc_calibrate_offset() being non-blocking already being taken care of in the&amp;nbsp;&lt;span&gt;saadc_event_handler() event handler. This is where I reset the buffers and restart the timer.&lt;/span&gt;[/quote]
&lt;p&gt;Yes, come to think of it this should already be taken care of, actually. Keenly spotted.&lt;br /&gt;Then, only the _abort needs to be called from the main context, not the wait_for_calibrate_done.&lt;br /&gt;&lt;br /&gt;A colleague of mine mentioned that he had experienced something similar when testing some combination of burst + scan + oversampling and LP modes.&lt;br /&gt;Are you currently using the SAADC Low Power mode? -If not, could you set it to 1 and see if this changes anything in regards to your buffers?&lt;br /&gt;&lt;br /&gt;Perhaps you could share you project with me, so that I could attempt to replicate and debug this on my end?&lt;br /&gt;I can convert the ticket to private if you would like me to, just let me know.&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Karl&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/265183?ContentTypeID=1</link><pubDate>Tue, 18 Aug 2020 16:44:15 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b8943a59-6888-4590-aed3-55d9c7bd13d6</guid><dc:creator>ftjandra</dc:creator><description>&lt;p&gt;Instead of&amp;nbsp;nrf_pwr_mgmt_run(), I used&amp;nbsp;sd_app_evt_wait(). I think they do the same thing when the Soft Device is used.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;    for (;;)
    {
        //SAADC Calibration
        if(saadc_calibrate_stage == 1) {
            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, &amp;quot;Calling nrf_drv_saadc_abort()\n&amp;quot;);
            nrf_drv_saadc_abort();
            saadc_calibrate_stage = 2;
        }
        else if(saadc_calibrate_stage == 4) {
            saadc_calibrate_stage++;
            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, &amp;quot;Starting new SAADC calibration\n&amp;quot;);
            while(nrf_drv_saadc_calibrate_offset() != NRF_SUCCESS); //trigger calibration task
            while(!nrf_saadc_event_check(NRF_SAADC_EVENT_CALIBRATEDONE)) {
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, &amp;quot;a\n&amp;quot;);
                //nrf_pwr_mgmt_run();
                (void)sd_app_evt_wait();
            }
        }
        (void)sd_app_evt_wait();
    }&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;After initiating the first recalibration, It gets stuck in that new while loop and never gets out. Everything looks like it&amp;#39;s still running since it&amp;#39;s no different than the &amp;#39;outer&amp;#39;&amp;nbsp;sd_app_evt_wait(). Except that it doesn&amp;#39;t do any more recalibrations after the first time because it doesn&amp;#39;t get out to check &amp;#39;saadc_calibration_stage&amp;#39;.&lt;/p&gt;
&lt;p&gt;But, this didn&amp;#39;t make a difference because the values are still shifted after calibration:&lt;/p&gt;
&lt;p&gt;Right before Calibration&lt;br /&gt;00&amp;gt; saadc_value_current[0]: 987&lt;br /&gt;00&amp;gt; saadc_value_current[1]: 2384&lt;br /&gt;00&amp;gt; saadc_value_current[2]: 0&lt;br /&gt;00&amp;gt; saadc_value_current[3]: 381&lt;/p&gt;
&lt;p&gt;Right after calibration&lt;br /&gt;00&amp;gt; saadc_value_current[0]: 986&lt;br /&gt;00&amp;gt; saadc_value_current[1]: 986&lt;br /&gt;00&amp;gt; saadc_value_current[2]: 2383&lt;br /&gt;00&amp;gt; saadc_value_current[3]: 0&lt;/p&gt;
&lt;p&gt;2nd reading after calibration, buffer values are shifted by one spot&lt;br /&gt;00&amp;gt; saadc_value_current[0]: 381&lt;br /&gt;00&amp;gt; saadc_value_current[1]: 986&lt;br /&gt;00&amp;gt; saadc_value_current[2]: 2384&lt;br /&gt;00&amp;gt; saadc_value_current[3]: 4294967295&lt;/p&gt;
&lt;p&gt;Stays shifted by one spot (even after subsequent recalibrations)&lt;br /&gt;00&amp;gt; saadc_value_current[0]: 381&lt;br /&gt;00&amp;gt; saadc_value_current[1]: 987&lt;br /&gt;00&amp;gt; saadc_value_current[2]: 2384&lt;br /&gt;00&amp;gt; saadc_value_current[3]: 0&lt;/p&gt;
&lt;p&gt;I just realized, isn&amp;#39;t nrf_drv_saadc_calibrate_offset() being non-blocking already being taken care of in the&amp;nbsp;&lt;span&gt;saadc_event_handler() event handler. This is where I reset the buffers and restart the timer.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;    else if(p_event-&amp;gt;type == NRF_DRV_SAADC_EVT_CALIBRATEDONE) {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, &amp;quot;SAADC calibration complete\n&amp;quot;);
        saadc_calibrate_stage = 0; //reset

        //Need to setup both buffers, as they were both removed with the call to nrf_drv_saadc_abort before calibration
        ERROR_CHECK(nrf_drv_saadc_buffer_convert(saadc_buffer_pool[0], SAADC_SAMPLES_IN_BUFFER));
        ERROR_CHECK(nrf_drv_saadc_buffer_convert(saadc_buffer_pool[1], SAADC_SAMPLES_IN_BUFFER));

        nrf_drv_timer_enable(&amp;amp;m_saadc_timer);
    }&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Thanks.&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/265061?ContentTypeID=1</link><pubDate>Tue, 18 Aug 2020 10:48:20 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c21e7dc7-c650-4702-8746-1b29ae1cba54</guid><dc:creator>Karl Ylvisaker</dc:creator><description>&lt;p&gt;[quote user="ftjandra"][/quote]&lt;/p&gt;
&lt;p&gt;Then in main() when the calibrate flag is set, I call&amp;nbsp;nrf_drv_saadc_abort().&lt;/p&gt;
&lt;p&gt;Then 2 seconds later&amp;nbsp;also from main I re-initiate the calibration with&amp;nbsp;while(nrf_drv_saadc_calibrate_offset() != NRF_SUCCESS). I picked two seconds to&amp;nbsp;account for any pending&amp;nbsp;NRFX_SAADC_EVT_DONE events.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;This is better, but please keep in mind that the &lt;a href="https://infocenter.nordicsemi.com/index.jsp?topic=%2Fsdk_nrf5_v17.0.0%2Fgroup__nrfx__saadc.html&amp;amp;cp=7_1_6_8_0_30_1_14&amp;amp;anchor=gabebf4b2245bff5bc767b0e679702708d"&gt;nrfx_saadc_calibrate_offset&lt;/a&gt;&amp;nbsp;function is non-blocking, so the program will move on before the calibration necessarily is finished.&lt;br /&gt;Could you attempt to add these lines right below your while(!=NRF_SUCCESS) call?&lt;br /&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;while(!nrf_saadc_event_check(NRF_SAADC_EVENT_CALIBRATEDONE ))
{
    nrf_pwr_mgmt_run();
}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
[quote user="ftjandra"]After the calibration everything in the buffer is still shifted by spot.[/quote]
&lt;p&gt;Is it a particular number they are shifted by?&lt;br /&gt;Some samples may be placed in the buffer during / following calibration, so please make sure that you supply new buffers to the SAADC following a completed calibration.&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Karl&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/264942?ContentTypeID=1</link><pubDate>Mon, 17 Aug 2020 19:12:12 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d1908484-b75d-4a07-83e3-fe9808ba5862</guid><dc:creator>ftjandra</dc:creator><description>&lt;p&gt;Ok, still no luck.&lt;/p&gt;
&lt;p&gt;I am now calling&amp;nbsp;nrf_drv_timer_disable(&amp;amp;m_saadc_timer) and setting a calibrate flag from within the SAADC event handler.&lt;/p&gt;
&lt;p&gt;Then in main() when the calibrate flag is set, I call&amp;nbsp;nrf_drv_saadc_abort().&lt;/p&gt;
&lt;p&gt;Then 2 seconds later&amp;nbsp;also from main I re-initiate the calibration with&amp;nbsp;while(nrf_drv_saadc_calibrate_offset() != NRF_SUCCESS). I picked two seconds to&amp;nbsp;account for any pending&amp;nbsp;NRFX_SAADC_EVT_DONE events.&lt;/p&gt;
&lt;p&gt;After the calibration everything in the buffer is still shifted by spot.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/264914?ContentTypeID=1</link><pubDate>Mon, 17 Aug 2020 14:38:44 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b391d0ab-6d64-4819-a9ab-d5021a6f59dd</guid><dc:creator>Karl Ylvisaker</dc:creator><description>&lt;p&gt;Hello again,&lt;/p&gt;
[quote user="ftjandra"]My nRF52840 is rev2.[/quote]
&lt;p&gt;Great, thank you for confirming this. There is only &lt;a href="https://infocenter.nordicsemi.com/topic/errata_nRF52840_Rev2/ERR/nRF52840/Rev2/latest/err_840_new.html"&gt;2 SAADC erratas for the rev 2&lt;/a&gt;, one of which is not the issue in question here, and the other one which we have already spoken about.&lt;/p&gt;
[quote user="ftjandra"]Eventually I will trigger calibration on temperature change, but for testing it&amp;#39;s easier to just do it every xx samples.[/quote]
&lt;p&gt;I understand, this is all right during the testing and development phase.&lt;/p&gt;
[quote user="ftjandra"]Do I need to disable the timer, ppi channel, both? Seems like disabling the timer should be enough.[/quote]
&lt;p&gt;This is correct, by disabling the task trigger you have disabled sampling.&lt;br /&gt;However, it seems you might be using the _abort incorrectly - please see the &lt;em&gt;&lt;a href="https://infocenter.nordicsemi.com/index.jsp?topic=%2Fsdk_nrf5_v17.0.0%2Fgroup__nrfx__saadc.html&amp;amp;anchor=ga480525496e0676a598b828789104fdf6"&gt;nrfx_saadc_abort&lt;/a&gt;&amp;nbsp;&lt;/em&gt;&lt;em&gt;&lt;/em&gt;documentation, it reads:&lt;/p&gt;
&lt;dl&gt;
&lt;dd&gt;Note&lt;/dd&gt;
&lt;dd&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;a href="https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.0.0/group__nrfx__saadc.html#ga40b21459a4cbd52d9c1fea7582a884bba5afba4cb6f732fc83add1c16b3878562"&gt;NRFX_SAADC_EVT_DONE&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;event will be generated if there is a conversion in progress. Event will contain number of words in the sample buffer.&lt;/dd&gt;
&lt;/dl&gt;
&lt;dl&gt;
&lt;dd&gt;Warning&lt;/dd&gt;
&lt;dd&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; This function must not be called from the context of event handler of the SAADC driver or from the context of interrupt with priority equal to or higher than priority of the SAADC interrupt.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;You can not call _abort from the event handler of the SAADC, or from an interrupt with priority equal to or higher than the SAADC interrupt.&lt;br /&gt;So, for instance, if you call it from main ( or anywhere else with lower priority ) then it will work.&lt;/p&gt;
[quote user="ftjandra"]Do I need the&amp;nbsp;nrf_drv_saadc_abort()?[/quote]
&lt;p&gt;Yes, but it can not be used as you are using it now.&lt;/p&gt;
[quote user="ftjandra"]I know you mentioned that I need to wait for the END event before calibrating, how do I do that?[/quote]
&lt;p&gt;My apologies, when using the NRFX driver it is the &lt;a href="https://infocenter.nordicsemi.com/index.jsp?topic=%2Fsdk_nrf5_v17.0.0%2Fgroup__nrfx__saadc.html&amp;amp;anchor=ga40b21459a4cbd52d9c1fea7582a884bba5afba4cb6f732fc83add1c16b3878562"&gt;DONE event&lt;/a&gt; you will have to wait for.&lt;br /&gt;The END event is from the HAL, which you should not use directly together with the NRFX driver, since this may place the driver in an invalid state.&lt;/p&gt;
[quote user="ftjandra"]After trying the above, I followed this thread and stopped and restarted everything so it would start from the very beginning with the initial calibration, but the buffer was out of order again![/quote]
&lt;p&gt;As I said, you can not call abort from the SAADC event handler context.&lt;br /&gt;Please resolve this, and let me know if this resolves the issue of getting stuck in the calibrate loop for earlier.&lt;br /&gt;&lt;br /&gt;Looking forward to resolving this issue together!&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Karl&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/264664?ContentTypeID=1</link><pubDate>Fri, 14 Aug 2020 16:32:08 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:49957096-3c34-4e88-874a-2704172f4750</guid><dc:creator>ftjandra</dc:creator><description>&lt;p&gt;My nRF52840 is rev2. Eventually I will trigger calibration on temperature change, but for testing it&amp;#39;s easier to just do it every xx samples.&lt;/p&gt;
&lt;p&gt;I modified the&amp;nbsp;saadc_event_handler() as follows:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static void saadc_event_handler(nrf_drv_saadc_evt_t const * p_event) {
    static uint16_t saadc_event_counter = 1;

    if(p_event-&amp;gt;type == NRF_DRV_SAADC_EVT_DONE) {
        //Read buffer
        for(int i=0; i&amp;lt;SAADC_SAMPLES_IN_BUFFER; i++) {
            saadc_value_current[i] = p_event-&amp;gt;data.done.p_buffer[i];
        }
        
        if((saadc_event_counter % SAADC_CALIBRATION_INTERVAL) == 0) {
            saadc_event_counter = 0;    //reset
            nrf_drv_timer_disable(&amp;amp;m_saadc_timer);
            nrf_drv_saadc_abort();
            while(nrf_drv_saadc_calibrate_offset() != NRF_SUCCESS); //trigger calibration task
        }
        else {
            //Set buffer, double-buffering
            ERROR_CHECK(nrf_drv_saadc_buffer_convert(p_event-&amp;gt;data.done.p_buffer, SAADC_SAMPLES_IN_BUFFER));
        
            //Print samples
            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, &amp;quot;\nsaadc_value_current[0]: %u\nsaadc_value_current[1]: %u\nsaadc_value_current[2] %u\nsaadc_value_current[3]: %u\n&amp;quot;, saadc_value_current[0], saadc_value_current[1], saadc_value_current[2], saadc_value_current[3]);
        }
        
        saadc_event_counter++;
    }
    else if(p_event-&amp;gt;type == NRF_DRV_SAADC_EVT_CALIBRATEDONE) {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, &amp;quot;SAADC calibration complete\n&amp;quot;);

        //Need to setup both buffers, as they were both removed with the call to nrf_drv_saadc_abort before calibration
        ERROR_CHECK(nrf_drv_saadc_buffer_convert(saadc_buffer_pool[0], SAADC_SAMPLES_IN_BUFFER));
        ERROR_CHECK(nrf_drv_saadc_buffer_convert(saadc_buffer_pool[1], SAADC_SAMPLES_IN_BUFFER));

        nrf_drv_timer_enable(&amp;amp;m_saadc_timer);
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Do I need to disable the timer, ppi channel, both? Seems like disabling the timer should be enough. I also moved enabling the timer to the&amp;nbsp;NRF_DRV_SAADC_EVT_CALIBRATEDONE event instead of in saadc_init(). So the timer gets started after the initial calibration and&amp;nbsp;after any re-calibration.&lt;/p&gt;
&lt;p&gt;But with the above code, it gets stuck in the&amp;nbsp;while(nrf_drv_saadc_calibrate_offset() != NRF_SUCCESS);&lt;/p&gt;
&lt;p&gt;Do I need the&amp;nbsp;nrf_drv_saadc_abort()?&lt;/p&gt;
&lt;p&gt;I know you mentioned that I need to wait for the END event before calibrating, how do I do that?&lt;/p&gt;
&lt;p&gt;Edit: After trying the above, I followed this thread and stopped and restarted everything so it would start from the very beginning with the initial calibration, but the buffer was out of order again!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://devzone.nordicsemi.com/f/nordic-q-a/32982/can-t-stop-saadc/127979#127979"&gt;https://devzone.nordicsemi.com/f/nordic-q-a/32982/can-t-stop-saadc/127979#127979&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static void saadc_event_handler(nrf_drv_saadc_evt_t const * p_event) {
    static uint16_t saadc_event_counter = 1;

    if(p_event-&amp;gt;type == NRF_DRV_SAADC_EVT_DONE) {
        //Read buffer
        for(int i=0; i&amp;lt;SAADC_SAMPLES_IN_BUFFER; i++) {
            saadc_value_current[i] = p_event-&amp;gt;data.done.p_buffer[i];
        }
        
        if((saadc_event_counter % SAADC_CALIBRATION_INTERVAL) == 0) {
            saadc_event_counter = 0;    //reset
            nrf_drv_timer_disable(&amp;amp;m_saadc_timer);
            nrf_drv_timer_uninit(&amp;amp;m_saadc_timer);
            nrf_drv_ppi_channel_disable(m_saadc_ppi_channel);
            nrf_drv_ppi_uninit();
            nrf_drv_saadc_abort();
            nrf_drv_saadc_uninit();
            while(nrf_drv_saadc_is_busy());
            saadc_init();
            saadc_sampling_event_init();
            saadc_sampling_event_enable();
        }
        else {
            //Set buffer, double-buffering
            ERROR_CHECK(nrf_drv_saadc_buffer_convert(p_event-&amp;gt;data.done.p_buffer, SAADC_SAMPLES_IN_BUFFER));
        
            //Print samples
            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, &amp;quot;\nsaadc_value_current[0]: %u\nsaadc_value_current[1]: %u\nsaadc_value_current[2] %u\nsaadc_value_current[3]: %u\n&amp;quot;, saadc_value_current[0], saadc_value_current[1], saadc_value_current[2], saadc_value_current[3]);
        }
        
        saadc_event_counter++;
    }
    else if(p_event-&amp;gt;type == NRF_DRV_SAADC_EVT_CALIBRATEDONE) {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, &amp;quot;SAADC calibration complete\n&amp;quot;);

        //Need to setup both buffers, as they were both removed with the call to nrf_drv_saadc_abort before calibration
        ERROR_CHECK(nrf_drv_saadc_buffer_convert(saadc_buffer_pool[0], SAADC_SAMPLES_IN_BUFFER));
        ERROR_CHECK(nrf_drv_saadc_buffer_convert(saadc_buffer_pool[1], SAADC_SAMPLES_IN_BUFFER));

        nrf_drv_timer_enable(&amp;amp;m_saadc_timer);
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Thanks.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/264587?ContentTypeID=1</link><pubDate>Fri, 14 Aug 2020 09:40:54 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:cbfbf14d-40c2-45f7-9404-aae13911e273</guid><dc:creator>Karl Ylvisaker</dc:creator><description>[quote user="ftjandra"]Also, when does&amp;nbsp;saadc_timer_handler() get called. In the example it was empty and I see that it never gets called.[/quote]
&lt;p&gt;I did not see this question when writing my last post, sorry.&lt;br /&gt;The timer handler can be empty since the CC event is directly tied to the SAADC START task through PPI, which is all it is meant to do.&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Karl&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/264586?ContentTypeID=1</link><pubDate>Fri, 14 Aug 2020 09:39:08 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:8f5d4b14-e7b8-47e9-80f9-acc07595dba8</guid><dc:creator>Karl Ylvisaker</dc:creator><description>[quote user="ftjandra"]I am now successfully triggering the sample via PPI.[/quote]
&lt;p&gt;I am glad to hear that, well done!&lt;/p&gt;
[quote user="ftjandra"]lets say every 1000 samples?[/quote]
&lt;p&gt;Is there a particular reason for why you would like a calibration to be done every 1000 samples? Is the temperature changing during this time?&lt;/p&gt;
[quote user="ftjandra"]What is now the correct process to trigger a calibration[/quote]
&lt;p&gt;Which &lt;a href="https://infocenter.nordicsemi.com/topic/comp_matrix_nrf52840/COMP/nrf52840/nRF52840_ic_revision_overview.html"&gt;nRF52840 SoC revision&lt;/a&gt; are you working with?&lt;br /&gt;As I mentioned before, calibration should be done when you enable the SAADC and when the temperature has changed significantly.&lt;br /&gt;You will also need to make sure that CTASKS_ALIBRATEOFFSET is never called between TASKS_START and EVENT_END, due to &lt;a href="https://infocenter.nordicsemi.com/index.jsp?topic=%2Ferrata_nRF52840_Rev1%2FERR%2FnRF52840%2FRev1%2Flatest%2Fanomaly_840_237.html&amp;amp;anchor=anomaly_840_237"&gt;Errata 237&lt;/a&gt;.&lt;br /&gt;So, to calibrate every 1000 sample you will need to make a counter that keeps track of the sampled number, and when it reaches 1000 samples the START task PPI timer is stopped, and when the END event is generated calibration can start.&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Karl&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/264537?ContentTypeID=1</link><pubDate>Thu, 13 Aug 2020 22:53:14 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:0a3c28f2-c512-409a-9ab0-35bcbe9b5ca0</guid><dc:creator>ftjandra</dc:creator><description>&lt;p&gt;Ok, I am now successfully triggering the sample via PPI. All my SAADC code is below. What is now the correct process to trigger a calibration, lets say every 1000 samples?&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static void saadc_event_handler(nrf_drv_saadc_evt_t const * p_event) {
    if(p_event-&amp;gt;type == NRF_DRV_SAADC_EVT_DONE) {
        //Read buffer
        for(int i=0; i&amp;lt;SAADC_SAMPLES_IN_BUFFER; i++) {
            saadc_value_current[i] = p_event-&amp;gt;data.done.p_buffer[i];
        }
        
        //Set buffer, double-buffering
        ERROR_CHECK(nrf_drv_saadc_buffer_convert(p_event-&amp;gt;data.done.p_buffer, SAADC_SAMPLES_IN_BUFFER));

        //Print samples
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, &amp;quot;\nsaadc_value_current[0]: %u\nsaadc_value_current[1]: %u\nsaadc_value_current[2] %u\nsaadc_value_current[3]: %u\n&amp;quot;, saadc_value[0], saadc_value[1], saadc_value[2], saadc_value[3]);
    }
    else if(p_event-&amp;gt;type == NRF_DRV_SAADC_EVT_CALIBRATEDONE) {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, &amp;quot;SAADC calibration complete\n&amp;quot;);

        //Need to setup both buffers, as they were both removed with the call to nrf_drv_saadc_abort before calibration
        ERROR_CHECK(nrf_drv_saadc_buffer_convert(saadc_buffer_pool[0], SAADC_SAMPLES_IN_BUFFER));
        ERROR_CHECK(nrf_drv_saadc_buffer_convert(saadc_buffer_pool[1], SAADC_SAMPLES_IN_BUFFER));
    }
}

static void saadc_timer_handler(nrf_timer_event_t event_type, void * p_context) {
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, &amp;quot;saadc_timer_handler\n&amp;quot;);
}

static void saadc_init(void) {
    nrf_drv_saadc_config_t saadc_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
    saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;
    saadc_config.oversample = (nrf_saadc_oversample_t)NRF_SAADC_OVERSAMPLE_256X;
    saadc_config.interrupt_priority = NRFX_SAADC_CONFIG_IRQ_PRIORITY;
    saadc_config.low_power_mode = NRFX_SAADC_CONFIG_LP_MODE;

    nrf_saadc_channel_config_t channel_0_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
    channel_0_config.gain = NRF_SAADC_GAIN1_6;
    channel_0_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
    channel_0_config.burst = NRF_SAADC_BURST_ENABLED;

    nrf_saadc_channel_config_t channel_1_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);
    channel_1_config.gain = NRF_SAADC_GAIN1_6;
    channel_1_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
    channel_1_config.burst = NRF_SAADC_BURST_ENABLED;

    nrf_saadc_channel_config_t channel_2_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN5);
    channel_2_config.gain = NRF_SAADC_GAIN1_6;
    channel_2_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
    channel_2_config.burst = NRF_SAADC_BURST_ENABLED;

    nrf_saadc_channel_config_t channel_3_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN4);
    channel_3_config.gain = NRF_SAADC_GAIN1_6;
    channel_3_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
    channel_3_config.burst = NRF_SAADC_BURST_ENABLED;

    ERROR_CHECK(nrf_drv_saadc_init(&amp;amp;saadc_config, saadc_event_handler));

    ERROR_CHECK(nrf_drv_saadc_channel_init(0, &amp;amp;channel_0_config));
    ERROR_CHECK(nrf_drv_saadc_channel_init(1, &amp;amp;channel_1_config));
    ERROR_CHECK(nrf_drv_saadc_channel_init(2, &amp;amp;channel_2_config));
    ERROR_CHECK(nrf_drv_saadc_channel_init(3, &amp;amp;channel_3_config));

    //https://devzone.nordicsemi.com/f/nordic-q-a/63074/buffer-order-swap-of-saadc-used-with-nrf-mesh
    nrf_ppi_channel_t saadc_buffer_swap_ppi_channel;
    ERROR_CHECK(nrf_drv_ppi_init());
    ERROR_CHECK(nrf_drv_ppi_channel_alloc(&amp;amp;saadc_buffer_swap_ppi_channel));
    ERROR_CHECK(nrf_drv_ppi_channel_assign(saadc_buffer_swap_ppi_channel,
                                           (uint32_t)&amp;amp;NRF_SAADC-&amp;gt;EVENTS_END,
                                           (uint32_t)&amp;amp;NRF_SAADC-&amp;gt;TASKS_START));
    ERROR_CHECK(nrf_drv_ppi_channel_enable(saadc_buffer_swap_ppi_channel));

    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, &amp;quot;Starting initial SAADC calibration\n&amp;quot;);
    while(nrf_drv_saadc_calibrate_offset() != NRF_SUCCESS); //trigger calibration task
    saadc_calibrate = false;
}

static void saadc_sampling_event_init(void) {
    //ERROR_CHECK(nrf_drv_ppi_init());

    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
    ERROR_CHECK(nrf_drv_timer_init(&amp;amp;m_saadc_timer, &amp;amp;timer_cfg, saadc_timer_handler));

    // setup m_saadc_timer for compare event every 1000ms
    uint32_t ticks = nrf_drv_timer_ms_to_ticks(&amp;amp;m_saadc_timer, 1000);
    nrf_drv_timer_extended_compare(&amp;amp;m_saadc_timer,
                                   NRF_TIMER_CC_CHANNEL0,
                                   ticks,
                                   NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                   false);
    nrf_drv_timer_enable(&amp;amp;m_saadc_timer);

    uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&amp;amp;m_saadc_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
    ERROR_CHECK(nrf_drv_ppi_channel_alloc(&amp;amp;m_saadc_ppi_channel));
    ERROR_CHECK(nrf_drv_ppi_channel_assign(m_saadc_ppi_channel,
                                           timer_compare_event_addr,
                                           saadc_sample_task_addr));
}

static void saadc_sampling_event_enable(void) {
    ERROR_CHECK(nrf_drv_ppi_channel_enable(m_saadc_ppi_channel));
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Also, when does&amp;nbsp;saadc_timer_handler() get called. In the example it was empty and I see that it never gets called.&lt;/p&gt;
&lt;p&gt;Thanks.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/264365?ContentTypeID=1</link><pubDate>Thu, 13 Aug 2020 07:24:10 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d6a428d1-f293-4157-ba3f-a1f3bc05d344</guid><dc:creator>Karl Ylvisaker</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
[quote user="ftjandra"]NRFX_SAADC_CONFIG_IRQ_PRIORITY&amp;nbsp;is set to 6 in sdk_config.h[/quote]
&lt;p&gt;With your current solution - using CPU to trigger sampling - I would suggest &lt;a href="https://infocenter.nordicsemi.com/topic/sds_s140/SDS/s1xx/processor_avail_interrupt_latency/exception_mgmt_sd.html"&gt;increasing the priority&lt;/a&gt; of the SAADC, to see if this may prevent it from being interrupted by some other peripheral.&lt;/p&gt;
[quote user="ftjandra"]I could set it up through PPI if you&amp;nbsp;show me how. I haven&amp;#39;t used PPI.[/quote]
&lt;p&gt;I would highly recommend making use of the &lt;a href="https://infocenter.nordicsemi.com/index.jsp?topic=%2Fps_nrf52840%2Fppi.html"&gt;PPI peripheral&lt;/a&gt;. The PPI and &lt;a href="https://infocenter.nordicsemi.com/index.jsp?topic=%2Fps_nrf52840%2Fsaadc.html&amp;amp;anchor=saadc_easydma"&gt;easyDMA&lt;/a&gt; is two very powerful features that drastically reduce the necessary CPU intervention to perform sampling.&lt;br /&gt;In essence, what the PPI does is create a hardware connection between two peripherals. In your case, that would be to connect the timer interrupt directly to the SAADC sample task, so that there is no need for the CPU to do anything between processing of the buffers.&lt;br /&gt;&lt;br /&gt;A clean example of how you may use the PPI to connect a timer to your SAADC is demonstrated in the &lt;a href="https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.0.0/nrf_dev_saadc_example.html"&gt;SAADC peripheral example&lt;/a&gt;. Please have a look at this example, and let me know if anything should be unclear, or if you have any questions!&lt;/p&gt;
[quote user="ftjandra"]So far it has only messed up immediately after it calibrates. If I never re-calibrate after the initial calibration it has been fine (24 hours). But, if there is a risk from using the app_timer, I want to fix that.[/quote]
&lt;p&gt;Using the app_timer is fine. You might switch to using the app_timer v2 if you are not already, but none of them should be causing the SAADC buffer troubles, they are very well behaved.&lt;br /&gt;&lt;br /&gt;Looking forward to resolving this issue together!&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Karl&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/264328?ContentTypeID=1</link><pubDate>Wed, 12 Aug 2020 15:56:45 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:386d8dbd-e79f-407c-b3b2-8167c31d0086</guid><dc:creator>ftjandra</dc:creator><description>&lt;p&gt;&lt;span&gt;NRFX_SAADC_CONFIG_IRQ_PRIORITY&amp;nbsp;is set to 6 in sdk_config.h&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I could set it up through PPI if you&amp;nbsp;show me how. I haven&amp;#39;t used PPI.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;So far it has only messed up immediately after it calibrates. If I never re-calibrate after the initial calibration it has been fine (24 hours). But, if there is a risk from using the app_timer, I want to fix that.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Thanks.&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/264320?ContentTypeID=1</link><pubDate>Wed, 12 Aug 2020 15:27:14 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:eaf746a0-970c-47a9-a4ab-c28ec02d55f8</guid><dc:creator>Karl Ylvisaker</dc:creator><description>&lt;p&gt;Hello again,&lt;br /&gt;&lt;br /&gt;Thank you for providing the additional information.&lt;/p&gt;
[quote user="ftjandra"]I think all the relevant code should be in my first post[/quote]
&lt;p&gt;Reading the code and hearing your intentions are both useful.&lt;br /&gt;&lt;br /&gt;I see that you are using an app_timer to call the nrf_drv_saadc_sample function.&lt;br /&gt;The nrf_drv_saadc_sample is a call that is handled by the CPU. I suspect that a higher priority task could interrupt the SAADC sample handling at an inopportune time, potentially causing the shift in the buffered samples. &lt;br /&gt;Is there a particular reason for why you are having the CPU start each sampling, or could you instead set up the timer to trigger the sample task through PPI?&lt;br /&gt;This would greatly reduce the CPU time necessary to perform each sample.&lt;br /&gt;&lt;br /&gt;Additionally, what is your&amp;nbsp;NRFX_SAADC_CONFIG_IRQ_PRIORITY defined as?&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Karl&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/264136?ContentTypeID=1</link><pubDate>Tue, 11 Aug 2020 23:33:27 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:a2d68e70-fd08-4276-8ad1-ad138bc06484</guid><dc:creator>ftjandra</dc:creator><description>&lt;p&gt;I think all the relevant code should be in my first post (plus the modification to saadc_init().&lt;/p&gt;
&lt;p&gt;1. saadc_init(). Does initial calibration.&lt;/p&gt;
&lt;p&gt;2. On&amp;nbsp;NRF_DRV_SAADC_EVT_CALIBRATEDONE set up double-buffer.&lt;/p&gt;
&lt;p&gt;3. App timer: Every second call&amp;nbsp;nrf_drv_saadc_sample() if calibrate flag is not set. If calibrate flag is set call&amp;nbsp;nrf_drv_saadc_calibrate_offset()&lt;/p&gt;
&lt;p&gt;4. On&amp;nbsp;NRF_DRV_SAADC_EVT_DONE, copy out readings and either:&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; set up next buffer,&amp;nbsp;nrf_drv_saadc_buffer_convert(p_event-&amp;gt;data.done.p_buffer, SAADC_SAMPLES_IN_BUFFER)&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; - or -&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; every 4096 samples do a calibration by nrf_drv_saadc_abort() and setting calibrate flag.&lt;/p&gt;
&lt;p&gt;Thanks.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/263946?ContentTypeID=1</link><pubDate>Tue, 11 Aug 2020 08:08:11 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e79443ac-2a18-4814-bd4d-f8cf0cb064f1</guid><dc:creator>Karl Ylvisaker</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
[quote user="ftjandra"]Line 294 or nrfx_saadc.c that you mentioned doesn&amp;#39;t seem to affect me, it&amp;#39;s not asserting with that line as-is.[/quote]
&lt;p&gt;Strange, I would expect it to assert when you combine scan mode with oversampling.&lt;/p&gt;
[quote user="ftjandra"]It&amp;#39;s fine after the initial calibration that I do, but after I trigger another one,&amp;nbsp;the buffer is still out of sync.[/quote]
&lt;p&gt;I see. Could you elaborate on how and when you perform calibrations?&lt;br /&gt;If you could share the code snippets of the calibration that would be beneficial as well.&lt;/p&gt;
[quote user="ftjandra"]Are you saying that even if I don&amp;#39;t do periodic calibrations that the buffer will eventually mess up?[/quote]
&lt;p&gt;No, absolutely not. The buffer-swap issue was an older issue, which is resolved by the modification you added to your saadc_init - the buffer swaps you are seeing now is therefore likely caused by something else, perhaps an incorrectly aborted conversion or similar. Lets look further into how you perform the calibrations, and what else is going on in the application.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Looking forward to resolving this issue together!&lt;br /&gt;&lt;br /&gt;Best regards,&lt;br /&gt;Karl&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: SAADC scan + burst?</title><link>https://devzone.nordicsemi.com/thread/263901?ContentTypeID=1</link><pubDate>Mon, 10 Aug 2020 17:25:15 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:658be68a-2dbf-47b1-9097-cfdbc9a99147</guid><dc:creator>ftjandra</dc:creator><description>&lt;p&gt;Ok, so I added&amp;nbsp;&lt;span&gt;J&amp;oslash;rgen&amp;#39;s changes to the end of saadc_init():&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static void saadc_init(void) {
    nrf_drv_saadc_config_t saadc_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
    saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;
    saadc_config.oversample = (nrf_saadc_oversample_t)NRF_SAADC_OVERSAMPLE_256X;
    saadc_config.interrupt_priority = NRFX_SAADC_CONFIG_IRQ_PRIORITY;
    saadc_config.low_power_mode = NRFX_SAADC_CONFIG_LP_MODE;

    nrf_saadc_channel_config_t channel_0_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
    channel_0_config.gain = NRF_SAADC_GAIN1_6;
    channel_0_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
    channel_0_config.burst = NRF_SAADC_BURST_ENABLED;
    //nrf_saadc_burst_set(0, NRF_SAADC_BURST_ENABLED);

    nrf_saadc_channel_config_t channel_1_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);
    channel_1_config.gain = NRF_SAADC_GAIN1_6;
    channel_1_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
    channel_1_config.burst = NRF_SAADC_BURST_ENABLED;
    //nrf_saadc_burst_set(1, NRF_SAADC_BURST_ENABLED);

    nrf_saadc_channel_config_t channel_2_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN5);
    channel_2_config.gain = NRF_SAADC_GAIN1_6;
    channel_2_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
    channel_2_config.burst = NRF_SAADC_BURST_ENABLED;
    //nrf_saadc_burst_set(2, NRF_SAADC_BURST_ENABLED);

    nrf_saadc_channel_config_t channel_3_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN4);
    channel_3_config.gain = NRF_SAADC_GAIN1_6;
    channel_3_config.reference = NRF_SAADC_REFERENCE_INTERNAL;
    channel_3_config.burst = NRF_SAADC_BURST_ENABLED;
    //nrf_saadc_burst_set(3, NRF_SAADC_BURST_ENABLED);

    ERROR_CHECK(nrf_drv_saadc_init(&amp;amp;saadc_config, saadc_event_handler));

    ERROR_CHECK(nrf_drv_saadc_channel_init(0, &amp;amp;channel_0_config));
    ERROR_CHECK(nrf_drv_saadc_channel_init(1, &amp;amp;channel_1_config));
    ERROR_CHECK(nrf_drv_saadc_channel_init(2, &amp;amp;channel_2_config));
    ERROR_CHECK(nrf_drv_saadc_channel_init(3, &amp;amp;channel_3_config));

    //https://devzone.nordicsemi.com/f/nordic-q-a/63074/buffer-order-swap-of-saadc-used-with-nrf-mesh
    nrf_ppi_channel_t saadc_buffer_swap_ppi_channel;
    nrf_drv_ppi_channel_alloc(&amp;amp;saadc_buffer_swap_ppi_channel);
    nrf_drv_ppi_channel_assign(saadc_buffer_swap_ppi_channel,
                               (uint32_t)&amp;amp;NRF_SAADC-&amp;gt;EVENTS_END,
                               (uint32_t)&amp;amp;NRF_SAADC-&amp;gt;TASKS_START);
    nrf_drv_ppi_channel_enable(saadc_buffer_swap_ppi_channel);

    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, &amp;quot;Starting initial SAADC calibration\n&amp;quot;);
    while(nrf_drv_saadc_calibrate_offset() != NRF_SUCCESS); //trigger calibration task
    saadc_calibrate = false;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;I commented out the NRF_SAADC_TASK_START on line 128 of nrfx_saadc.c&lt;/p&gt;
&lt;p&gt;Line 294 or nrfx_saadc.c that you mentioned doesn&amp;#39;t seem to affect me, it&amp;#39;s not asserting with that line as-is.&lt;/p&gt;
&lt;p&gt;It&amp;#39;s fine after the initial calibration that I do, but after I trigger another one,&amp;nbsp;the buffer is still out of sync.&lt;/p&gt;
&lt;p&gt;Before these modifications, I ran it for a whole day without having it do any periodic calibration and everything was fine. Are you saying that even if I don&amp;#39;t do periodic calibrations that the buffer will eventually mess up?&lt;/p&gt;
&lt;p&gt;Thanks.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>