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

Two saadc channels get switched if callback takes too long

I'm trying to read two ADC channels asynchronously.

I can setup two channels, and as mentioned on the forums, the data from channel 0 is at buffer[0].

The issue I'm trying to understand is that if there is a delay in the saadc_callback, channel 1 is at buffer[0] and channel 0 is at buffer[1].

I'm using the nRF52 DK with nRF5_SDK_15.3.0_59ac345.

I can demonstrate this in the saadc example code at nRF5_SDK_15.3.0_59ac345/examples/peripheral/saadc

Diff:

diff --git a/examples/peripheral/saadc/main.c b/examples/peripheral/saadc/main.c
index 8c956541..4e6289f5 100644
--- a/examples/peripheral/saadc/main.c
+++ b/examples/peripheral/saadc/main.c
@@ -66,7 +66,7 @@
 #include "nrf_log_ctrl.h"
 #include "nrf_log_default_backends.h"
 
-#define SAMPLES_IN_BUFFER 5
+#define SAMPLES_IN_BUFFER 2
 volatile uint8_t state = 1;
 
 static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(0);
@@ -141,7 +141,9 @@ void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
         {
             NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]);
         }
-        m_adc_evt_counter++;
+        if(m_adc_evt_counter++ == 15) {
+            nrf_delay_ms(1000);
+        }
     }
 }
 
@@ -149,13 +151,18 @@ void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
 void saadc_init(void)
 {
     ret_code_t err_code;
-    nrf_saadc_channel_config_t channel_config =
-        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
+    nrf_saadc_channel_config_t channel_config0 =
+        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN6);
+
+    nrf_saadc_channel_config_t channel_config1 =
+        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN7);
 
     err_code = nrf_drv_saadc_init(NULL, saadc_callback);
     APP_ERROR_CHECK(err_code);
 
-    err_code = nrf_drv_saadc_channel_init(0, &channel_config);
+    err_code = nrf_drv_saadc_channel_init(0, &channel_config0);
+    APP_ERROR_CHECK(err_code);
+    err_code = nrf_drv_saadc_channel_init(1, &channel_config1);
     APP_ERROR_CHECK(err_code);
 
     err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);

As you can see, I'm changing the number of samples to two, adding a second channel, and after 15 reads, delaying once for a second in the saadc_callback.

I put two resistor dividers from VDD to GND made of random resistors to get two different values on the ADC channels.

So as you can see, channel 1 reads higher voltage than channel 0, but in the 17th read, it switches.

<info> app: ADC event number:14
<info> app: 407
<info> app: 630
<info> app: ADC event number: 15
<info> app: 407
<info> app: 629
<info> app: ADC event number: 16
<info> app: 47
<info> app: 628
<info> app: ADC vent number: 17
<info> app: 628
<info> app: 408
<info> app: ADC event numbe: 18
<info> app: 630
<info> app: 408

Channel 0 reading 47 on the 16th read is just an artifact of logging I think, as other places in the log there are missing characters.

If I use RTT as the logging backend I don't see missing characters, this seems unrelated so I'm ignoring.

full modified saadc/main.c: http://ix.io/1Mk6

If I have an app_timer callback that has a delay in it that also causes the channels to switch.

Related