Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

SAADC Multiple channel acquisition

I came across this old thread, which asks the same question, but was abandoned by the OP () without follow-up:

https://devzone.nordicsemi.com/f/nordic-q-a/26699/52832-saadc-multi-channel-acquisition

Modifying the SDK 15.3.0 SAADC example as shown there does, indeed, sample multiple channels.

But it only samples 1 channel on each timer event:

  1. wait for timer 
  2. sample 1st channel
  3. wait for timer 
  4. sample 2nd channel
  5. wait for timer 
  6. sample 3rd channel
  7. wait for timer 
  8. sample 1st channel
  9. wait for timer 
  10. sample 2nd channel
  11. wait for timer 
  12. sample 3rd channel
  13. etc ...

Is there a way to have it sample all the channels "together" (or nearly so) on each timer event:

  1. wait for timer 
  2. sample 1st, 2nd, and 3rd channels
  3. wait for timer 
  4. sample 1st, 2nd, and 3rd channels
  5. wait for timer 
  6. sample 1st, 2nd, and 3rd channels
  7. wait for timer 
  8. sample 1st, 2nd, and 3rd channels
  9. wait for timer 
  10. sample 1st, 2nd, and 3rd channels
  11. wait for timer 
  12. sample 1st, 2nd, and 3rd channels
  13. etc ...

nRF52832 DK

Parents
  • Hello,

    This should work, meaning that it should sample multiple channels when starting conversion. This is also shown in this thread:
    https://devzone.nordicsemi.com/f/nordic-q-a/43191/nrf52832-saadc-two-channels-at-different-sampling-rate-with-burst-oversample 

    The only thing you should be careful about is the issue discussed in the linked case: "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), but instead of oversampling you may consider increase resolution.

    Best regards,
    Kenneth

  • Sorry, I don't see how that answers the question.

    What I want to do is for the SAADC to take a single sample from each of the enabled channels at the "same" time.

    ie, a "simultaneous" sample of all enabled channels:

    1. wait for timer 
    2. sample 1st, 2nd, and 3rd channels all at once
    3. wait for timer 
    4. sample 1st, 2nd, and 3rd channels all at once
    5. wait for timer 
    6. sample 1st, 2nd, and 3rd channels all at once
    7. etc ...

    (it doesn't have to be literally simultaneous - but as close as possible)

    I don't find the documentation at all clear

  • So, for "Scan mode", the nRF52832 Product Spec v1.4 says:

    "If more than one channel, CH[n], is enabled, the ADC enters scan mode."

    I have 3 channels enables, so I should be in Scan mode.

    "In scan mode, one SAMPLE task will trigger one conversion per enabled channel ..."

    Suggests that n samples will be taken - where n is the number of enabled channels.

    But then it says

    "A DONE event signals that one (sic?) sample has been taken"

    Does that really mean one sample - or one sample per enabled channel?

    The behaviour of the example, as stated in the OP, is just one sample of one channel.

    So what I want is:

    1. the DONE event of the 1st channel immediately starts a conversion on the 2nd channel;
    2. the DONE event of the 2nd channel immediately starts a conversion on the 3rd channel;
    3. the DONE event of the 3rd channel is the end of the sequence.

  • Hi,

    Conceptually something like the below should show how this can be done. Just make sure you have not enabled oversampling on any channel, since that won't work with scan mode.

    int main(void)
    {
        static int16_t buffer[10];
        
        NRF_SAADC->ENABLE = 1;  
        NRF_SAADC->OVERSAMPLE = 0;
        NRF_SAADC->RESULT.PTR = (uint32_t) buffer;      
            
        NRF_SAADC->CH[0].PSELN = 0x0;
        NRF_SAADC->CH[0].CONFIG = 0x00020000; // 10us.
        NRF_SAADC->CH[0].LIMIT = 0x7FFF8000;
        NRF_SAADC->CH[0].PSELP = 0x1; 
        
        NRF_SAADC->CH[1].PSELN = 0x0;
        NRF_SAADC->CH[1].CONFIG = 0x00020000; // 10us.
        NRF_SAADC->CH[1].LIMIT = 0x7FFF8000;
        NRF_SAADC->CH[1].PSELP = 0x2;
        
        NRF_SAADC->RESULT.MAXCNT = 2;    
        NRF_SAADC->EVENTS_END = 0;
        NRF_SAADC->TASKS_START = 1;
        NRF_SAADC->TASKS_SAMPLE = 1;
        while(NRF_SAADC->EVENTS_END == 0) // Waiting for both channels to be sampled.
            ;
        NRF_SAADC->EVENTS_END = 0;
    
        while(1)
            ;
    }

    Best regards,
    Kenneth

Reply
  • Hi,

    Conceptually something like the below should show how this can be done. Just make sure you have not enabled oversampling on any channel, since that won't work with scan mode.

    int main(void)
    {
        static int16_t buffer[10];
        
        NRF_SAADC->ENABLE = 1;  
        NRF_SAADC->OVERSAMPLE = 0;
        NRF_SAADC->RESULT.PTR = (uint32_t) buffer;      
            
        NRF_SAADC->CH[0].PSELN = 0x0;
        NRF_SAADC->CH[0].CONFIG = 0x00020000; // 10us.
        NRF_SAADC->CH[0].LIMIT = 0x7FFF8000;
        NRF_SAADC->CH[0].PSELP = 0x1; 
        
        NRF_SAADC->CH[1].PSELN = 0x0;
        NRF_SAADC->CH[1].CONFIG = 0x00020000; // 10us.
        NRF_SAADC->CH[1].LIMIT = 0x7FFF8000;
        NRF_SAADC->CH[1].PSELP = 0x2;
        
        NRF_SAADC->RESULT.MAXCNT = 2;    
        NRF_SAADC->EVENTS_END = 0;
        NRF_SAADC->TASKS_START = 1;
        NRF_SAADC->TASKS_SAMPLE = 1;
        while(NRF_SAADC->EVENTS_END == 0) // Waiting for both channels to be sampled.
            ;
        NRF_SAADC->EVENTS_END = 0;
    
        while(1)
            ;
    }

    Best regards,
    Kenneth

Children
Related