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

"Right way" to oversample+burst multiple SAADC input pins.

Context: nrf52840DK, s140, SDK 17.0.2

Hi,

I need to oversample a few ADC pins with burst enabled at roughly the same time periodically: e.g. oversampling 4 separate inputs, every 10 seconds.

I've been doing my best to follow the advice on this forum to oversample multiple ADC pins. Currently I am trying to initialise one channel at a time to oversample it. Essentially I am initialising channel 0 with a different channel config for each input pin, converting my buffer, then sampling, and then once the oversampled value has been retrieved the channel is uninitialised.

I've found that I am only able to init the channel immediately after init-ing the ADC, and then the call to uninit is successful, but then when I come back to re-init a channel it fails at the NRFX_ASSERT(channel < NRF_SAADC_CHANNEL_COUNT). Or if I don't init the channel immediately after init-ing the ADC (only init it when I want to take my first sample) it never triggers the callback function.

It seems like I am unable to dynamically init & uninit ADC channels so that I can oversample and use the ADC on more than one input. This was mentioned by Kenneth in response this post from 2 years ago as something nordic was looking into fixing.

I'm assuming that this is a solved issue and that I am just doing something wrong, so would it be possible to get a simple example of this working with an explanation of the correct function call order to achieve oversampling on multiple separate inputs?

I'm not trying to do anything too complicated, I just want to oversample (with burst) a couple of different inputs and then use those values to update some BLE characteristic values.

Thank you in advance for any assistance,

Kalina

Parents
  • Hi,

    If you are using oversampling, then only 1 saadc channel can be configured. So if you need to oversample 4 inputs, then you would to reconfigure saadc channel0 between each (over)sampling.

    There are many ways this can be solved, you can for instance have an app_timer that initiate sampling every 2.5seconds, the timer callback can use a static counter%4 to ensure that you reconfigure channel0 so that every input is sampled.

    Usage of the saadc driver is explained here:
    https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.0.2/hardware_driver_saadc.html#saadc_using

    If you are not using blocking mode, then you need to wait for the saadc callback before the data is ready. In such it may make sense that the SAADC callback have higher interrupt priority than the app_timer callback.

    In any case you typically would need to do the following for each of the 4 inputs:

    saadc_init()
    channel0_init() //this will change depending which pin should be oversampled
    buffer_convert() //prepare buffer
    sample() //execute oversampling on channel0
    //wait data is ready
    channel0_uninit()
    saadc_uninit()

    Kenneth

Reply
  • Hi,

    If you are using oversampling, then only 1 saadc channel can be configured. So if you need to oversample 4 inputs, then you would to reconfigure saadc channel0 between each (over)sampling.

    There are many ways this can be solved, you can for instance have an app_timer that initiate sampling every 2.5seconds, the timer callback can use a static counter%4 to ensure that you reconfigure channel0 so that every input is sampled.

    Usage of the saadc driver is explained here:
    https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.0.2/hardware_driver_saadc.html#saadc_using

    If you are not using blocking mode, then you need to wait for the saadc callback before the data is ready. In such it may make sense that the SAADC callback have higher interrupt priority than the app_timer callback.

    In any case you typically would need to do the following for each of the 4 inputs:

    saadc_init()
    channel0_init() //this will change depending which pin should be oversampled
    buffer_convert() //prepare buffer
    sample() //execute oversampling on channel0
    //wait data is ready
    channel0_uninit()
    saadc_uninit()

    Kenneth

Children
  • Hi Kenneth,

    In such it may make sense that the SAADC callback have higher interrupt priority than the app_timer callback.

    Seeing as I am using the soft device, am I able to increase the priority level of the SAADC to level 5? Or is that reserved and instead do I need to downgrade the priority of the app_timer to 7?

    In any case you typically would need to do the following for each of the 4 inputs:

    saadc_init()
    channel0_init() //this will change depending which pin should be oversampled
    buffer_convert() //prepare buffer
    sample() //execute oversampling on channel0
    //wait data is ready
    channel0_uninit()
    saadc_uninit()

    This is basically what I have been doing, however can I confirm whether I need to also init & uinit the saadc each time I want to init & uninit the channels?

    So far I have been trying to sample in a non-blocking way but I'll attempt it with the blocking way to see if I can get it to work.

  • kalknight said:
    Seeing as I am using the soft device, am I able to increase the priority level of the SAADC to level 5? Or is that reserved and instead do I need to downgrade the priority of the app_timer to 7?

    Here you can find an overview of available interrupts for the application:
    https://infocenter.nordicsemi.com/topic/sds_s140/SDS/s1xx/processor_avail_interrupt_latency/exception_mgmt_sd.html

    You can't do any softdevice api calls from priority 2 and 3, else you can do what you want. 

    kalknight said:
    This is basically what I have been doing, however can I confirm whether I need to also init & uinit the saadc each time I want to init & uninit the channels?

    It should not be required to unint and init every time no, however I do believe you want to unint (when SAADC is not in use) to save power.

    Make sure you are only calling buffer_convert() one time for each sample(). 

Related