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

nRF52832 SAADC two channels at different sampling rate with burst & oversample

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 = APP_IRQ_PRIORITY_LOW
    • low power mode = true
  • Channel 0 - Burst enable, sample period = 250ms
  • Channel 1 - Burst enable, sample period = 3 seconds

According to this post, https://devzone.nordicsemi.com/f/nordic-q-a/15882/sampling-two-analog-signals-using-saadc-at-two-different-rate#post-id-91845, for sampling two analog signals at different sampling rate which can be achieved by initialize and un-nitialize the channel.

Therefore I initialize and un-nitialize the channel 1 at the SAADC callback function. The first sampling result of channel 1 is OK, get the correct value. However when trigger the second sample, after initialize channel 1 and set the buffer with nrfx_saadc_buffer_convert again, the SAADC stop response, I cannot get any callback.

Below is my log and code, could anyone help me to solve this? Any idea why this is happening?

Here is the Log:

 app: ch1 uninit, ch0 cnt: 0, raw: 117
 app: ch1 uninit, ch0 cnt: 1, raw: 120
 app: ch1 uninit, ch0 cnt: 2, raw: 122
 app: ch1 uninit, ch0 cnt: 3, raw: 130
 app: ch1 uninit, ch0 cnt: 4, raw: 130
 app: ch1 uninit, ch0 cnt: 5, raw: 126
 app: ch1 uninit, ch0 cnt: 6, raw: 127
 app: ch1 uninit, ch0 cnt: 7, raw: 125
 app: ch1 uninit, ch0 cnt: 8, raw: 125
 app: ch1 uninit, ch0 cnt: 9, raw: 124
 app: ch1 uninit, ch0 cnt: 10, raw: 133
 app: ch1 init, ch0 cnt: 11, raw: 128                      <--- channel 1 init first time
 app: ch1 set uninit, ch0 cnt: 12, raw: 122                <--- channel 1 unit
 app:  ch1 result, ch1 cnt: 0, raw:3529, value: 4.1365571  <--- channel 1 get correct result
 app: ch1 uninit, ch0 cnt: 13, raw: 189
 app: ch1 uninit, ch0 cnt: 14, raw: 117
 app: ch1 uninit, ch0 cnt: 15, raw: 112
 app: ch1 uninit, ch0 cnt: 16, raw: 113
 app: ch1 uninit, ch0 cnt: 17, raw: 111
 app: ch1 uninit, ch0 cnt: 18, raw: 112
 app: ch1 uninit, ch0 cnt: 19, raw: 110
 app: ch1 uninit, ch0 cnt: 20, raw: 109
 app: ch1 uninit, ch0 cnt: 21, raw: 112
 app: ch1 uninit, ch0 cnt: 22, raw: 112
 app: ch1 init, ch0 cnt: 23, raw: 109                      <--- channel 1 init second time
<--- SAADC Stop response, no more callback

Here is my code:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "nrf.h"
//#include "nrf_drv_saadc.h"
#include "nrfx_saadc.h"
//#include "boards.h"
#include "app_timer.h"
#include "app_error.h"
#include "app_util_platform.h"
#include "nrf_pwr_mgmt.h"
#include "nrf_drv_power.h"
#include "nrf_drv_clock.h"
//#include "nrf_drv_rtc.h"
#include "nrfx_rtc.h"
#include "nrf_delay.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • I forgot to mention, for enable the oversample for two channels, I comment out Line 293 & 294 at nrfx_saadc_channel_init of nrfx_saadc.c.

    Line 293 & 294

        // Oversampling can be used only with one channel.

        //NRFX_ASSERT((nrf_saadc_oversample_get() == NRF_SAADC_OVERSAMPLE_DISABLED) ||

        //            (m_cb.active_channels == 0));

  • Hi,

    If I understand you correctly you are trying to execute a combination that is not supported in hardware. From the documentation you can find:

    http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52832.ps.v1.1/saadc.html?cp=2_1_0_36_4#saadc_operationmodes 

    "Scan mode and oversampling cannot be combined."

    So if you are using oversampling then only one channel can be enabled at any time (only one CH[n].PSELP is set).

    Best regards,
    Kenneth

  • Hello Kenneth,

    Thank you for your reply.

    However, according to the documentation, oversampling with scan mode is supported, if burst is enabled on all channels.

    "Scan mode can be combined with BURST=1, if burst is enabled on all channels." 

    And also according to this post, https://devzone.nordicsemi.com/f/nordic-q-a/20556/how-does-the-saadc-scan-mode-use-the-burst-1, it also answered that when burst is enabled for all the active channels, scan mode with oversampling will work correctly.

    I did a test with following code for scan mode with oversampling and burst enabled for channel 1 & 2 at the SAME sampling rate (250ms). From the log, the SAADC does appear to work correctly.

    Moreover, for the "oversampling then only one channel can be enabled at any time", according to this post, https://devzone.nordicsemi.com/f/nordic-q-a/26659/saacd-scan-oversample/104878#104878, although the SAADC driver in the SDK is not support the multichannel oversampling yet, it can be quite simple to add this function by following the Jørgen's instructions. To simplify my test, I just comment out the Line 293 & 294 at nrfx_saadc_channel_init of nrfx_saadc.c.

    Therefore my question is: For sampling two analog signals at different sampling rate in scan mode with oversampling and burst enabled, how to initialize and un-nitialize the channel 1 & 2 correctly? Thanks!

    Here is the log for scan mode with oversampling and burst enabled for channel 1 & 2 at the SAME sampling rate:

    <info> app: ch0 result cnt: 0, raw: 100
    <info> app: ch1 result cnt: 0, raw:3522, value: 4.1283521
    <info> app: ch0 result cnt: 1, raw: 164
    <info> app: ch1 result cnt: 1, raw:3517, value: 4.1224913
    <info> app: ch0 result cnt: 2, raw: 163
    <info> app: ch1 result cnt: 2, raw:3517, value: 4.1224913
    <info> app: ch0 result cnt: 3, raw: 167
    <info> app: ch1 result cnt: 3, raw:3516, value: 4.1213188
    <info> app: ch0 result cnt: 4, raw: 177
    <info> app: ch1 result cnt: 4, raw:3530, value: 4.1377291
    <info> app: ch0 result cnt: 5, raw: 179
    <info> app: ch1 result cnt: 5, raw:3567, value: 4.1810994

    Here is my code for testing scan mode with oversampling and burst enabled for channel 1 & 2 at the SAME sampling rate:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <string.h>
    #include "nrf.h"
    //#include "nrf_drv_saadc.h"
    #include "nrfx_saadc.h"
    //#include "boards.h"
    #include "app_timer.h"
    #include "app_error.h"
    #include "app_util_platform.h"
    #include "nrf_pwr_mgmt.h"
    #include "nrf_drv_power.h"
    #include "nrf_drv_clock.h"
    //#include "nrf_drv_rtc.h"
    #include "nrfx_rtc.h"
    #include "nrf_delay.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • My suggestion is that you set a flag in the SAADC callback function, and then you in main initialize and un-initialize 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 nrfx_saadc_irq_handler(), and that occurs before the 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.

  • Hello Kenneth,

    Thank you for your reply.

    I modified my test code to initialize and un-initialize the channel 1 at the main loop. However I get the same error, after re-init the channel 1 and set the buffer with nrfx_saadc_buffer_convert at the 2nd sample, the SAADC stop response and there is no more callback from the SAADC.

    Here is the log:

    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
     app: ch1 init at main                                        <---- 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      <---- ch1 correct result
     app: ch1 uninit at main                                      <---- ch1 un-init at main 1st time
     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                                        <---- ch1 init at main 2nd time                                                    <--- SAADC Stop response, no more callback


    Here is the modified test code to initialize and un-initialize the channel 1 at the main loop.
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <string.h>
    #include "nrf.h"
    //#include "nrf_drv_saadc.h"
    #include "nrfx_saadc.h"
    //#include "boards.h"
    #include "app_timer.h"
    #include "app_error.h"
    #include "app_util_platform.h"
    #include "nrf_pwr_mgmt.h"
    #include "nrf_drv_power.h"
    #include "nrf_drv_clock.h"
    //#include "nrf_drv_rtc.h"
    #include "nrfx_rtc.h"
    #include "nrf_delay.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     

1 2 3