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

nrf52 SAADC manually starting/stopping scan mode

Hi, 

I need the SAADC of the nRF52840 to do the following: 

It should sample two channels as fast as possible for a certain time (or for a certain amount of samples). 

The sampling should be started manually (not by an external timer). 

After the sampling (after enough samples are taken or after a certain time has passed), the sampling shall be stopped and low power mode should be entered. 

I managed to get several SAADC examples running, however, all of them work with external timers and the sampling rate is just too slow (because the sampling is triggered by the timer and the triggering time is always a feq ms in all examples...) and i cant start and stop the sampling manually. 

I dont get the documentation, it confuses me and I really don't know how to implement the solution... 

Can you provide me an example for my problem?

Parents Reply Children
  • Hi, 

    Thank you for the reply. 

    I managed to edit the peripheral/saadc example. I simply call the saadc_init() function in the main routine and afterwards I periodically call nrf_drv_saadc_sample() in the while(1) loop. 

    This works fine, the callback function saadc_callback() (which is the same as in the example) is called after n samples (per channel, which is defined by SAMPLES_IN_BUFFER) are stored in the buffer. 

    However, there are still some questions: 

    Question 1: At what sampling rate are the channels sampled during scan mode (assuming aquisition time is known)

    At the moment, SAMPLES_IN_BUFFER is set to 20 and nrf_drv_saadc_sample() is called periodically (every 100ms after an idle wait, just for testing purposes). So I periodically receive 20 samples (first sample from channel 0, second from channel 1, third from channel 0 and so on), as it should be.

    Can you tell me at what sampling rate these readings are sampled by the SAADC?

    I set the aquisition time for both channels to NRF_SAADC_ACQTIME_3US, so I assume the sampling rate should be fs = 1/(3us+2us + 3us+2us) = 100kHz (the 2us is the conversion time tconv).

    Is that correct? Is it legitimate to assume that the sampling rate remains constant and is not dependent on the rest of the code? 

    Question 2: How (or where) are the n samples (defined by SAMPLES_IN_BUFFER ) sampled, when nrfx_saadc_sample()  is called. How does nrf52 know, how many values have to be sampled and stored in the buffer.

    As far as I understand, nrfx_saadc_sample() basically just triggers NRF_SAADC_TASK_SAMPLE task. In the documentation it says :

    NRF_SAADC_TASK_SAMPLE task. = "Take one ADC sample. If scan is enabled, all channels are sampled"

    According to my understanding, this means, that only ONE value per channel is sampled when calling nrfx_saadc_sample() . However this is not the case in my example, I receive the whole buffer (which is SAMPLES_IN_BUFFER samples long), after calling nrfx_saadc_sample(). 

    Don't get me wrong, I want that 20 samples per function call :-D

    Nevertheless, I am trying to understand what is going on and I could not figure out, where in the code the SAADC is told to sample SAMPLES_IN_BUFFER samples. 

    Can you explain the process to me? 

    Question 3: How to turn it off and on again

    I managed to start the sampling process and gather n samples from the saadc. After the sampling process I want to enter some low power mode to save battery power and restart the process after some time. 

    What is the right way to turn off the SAADC and turn it on again? 

    One concern is, that the value from the two channels end up "in the right place" in the buffer after the saadc has been turned on again. 

    Thank you in advance for your answer. 

    Kind Regards

  • Hi again,

    hypn0 said:
    Is that correct? Is it legitimate to assume that the sampling rate remains constant and is not dependent on the rest of the code? 

     Yes, correct.

     

    hypn0 said:
    Question 2: How (or where) are the n samples (defined by SAMPLES_IN_BUFFER ) sampled, when nrfx_saadc_sample()  is called. How does nrf52 know, how many values have to be sampled and stored in the buffer.

     You set the buffer size in nrf_drv_saadc_buffer_convert().

    A call to nrf_drv_saadc_sample will trigge one sample per channel, you will need to call it 10 times to generate 20 results in the buffer if you have 2 channel actives. If you call it in a while loop then the next sample will be trigger as soon as the previous one is done.

     

    hypn0 said:
    Question 3: How to turn it off and on again

     You may need to do an uninit and init to achieve low power. This case may be relevant for you:

    Best regards,
    Marjeris
  • Hi

    Thank you for your answer. 

    A call to nrf_drv_saadc_sample will trigge one sample per channel, you will need to call it 10 times to generate 20 results in the buffer if you have 2 channel actives. If you call it in a while loop then the next sample will be trigger as soon as the previous one is done.

    As mentioned before, I want to collect as many samples as possible within a certain period of time (within two signal triggers), where the time between each sample should be constant for further signal processing.
    I could measure the n samples by simply calling the function nrfx_saadc_sample() n times in a row, e.g:

    void measure_samples(n)
    {
      uint16_t i = 0; 
      for(i=0;i<n;i++)
      {
        nrf_drv_saadc_sample();
      }
    }

    I find it hard to believe that with such a solution the maximum sampling rate (in my case 100kHz) can be reached, since the for-loop needs execution time as well. Even if the execution time is certainly very fast, I have no more control over how fast the individual samples are actually sampled. 

    Another solution would be to call the function nrfx_saadc_sample() via a timer (e.g. with PPI Channel as in the peripheral/saadc example). With this approach the samples would be measured within a well defined time intervall. 

    In the peripheral/saadc/ example, the timing interval is set in the saadc_sampling_event_init() function using the nrf_drv_timer_ms_to_ticks() function. But I want to set a timing interval which is faster than 1ms to get the desired 100kHz sampling rate. Can you tell me, how to achieve a faster timing intervall? 

    Or would you suggest to implement the solution with the for-loop?

    Thanks a lot for your answer. 

    Kind Regards

  • Hi,

    Sorry for the late reply. I wasn't aware that you needed a sample rate of 100kHz. In that case I agree it would be difficult to achieve without the use of TIMER.

     You can use nrf_drv_us_to_ticks() or you can set the ticks manually to have full control. For example 160 ticks will give you 100kHz if the timer runs on 16MHz, or 10 ticks if the timer runs on 1MHz.

    Best regards,

    Marjeris

Related