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

Sampling SAADC channels at different rate

There have been a couple of questions asked that are similar to my question but in the interest of getting more clarity I am asking a new one as others have had accepted answers.

The relevant questions are here and here

Essentially, using the scan mode of SAADC on nRF52, is it possible to sample two inputs at different sampling frequencies? Assume that I want channel0 sampled at 500Hz and channel1 at 2Hz. What is the best way forward without adding to the current consumption?

In the accepted answer of this question, it is said that using PSELP to enable/disable channel and configuring RESULT.MAXCNT is one way. Is it possible to have a code snippet or pseudocode explaining this?

Parents
  • I will see if I can throw together an example. The below preudocode should show the concept and how it can be implemented:

    #define CHANNEL_0_SAMPLE_FREQUENCY 500
    #define CHANNEL_1_SAMPLE_FREQUENCY 2
    
    #define SAMPLES_IN_BUFFER CHANNEL_0_SAMPLE_FREQUENCY + CHANNEL_1_SAMPLE_FREQUENCY
    
    uint32_t sample_count = 0;
    
    void saadc_sample(){
    
        NRF_SAADC->TASKS_START = 1;
        while (NRF_SAADC->EVENTS_STARTED == 0);
        NRF_SAADC->EVENTS_STARTED = 0;
    
        NRF_SAADC->TASKS_SAMPLE = 1;
        while (NRF_SAADC->EVENTS_END == 0);
        NRF_SAADC->EVENTS_END = 0;
    }
    
    rtc0_handler()
    {
    	saadc_sample();
    	
    	if (sample_count == max(CHANNEL_0_SAMPLE_FREQUENCY,CHANNEL_1_SAMPLE_FREQUENCY)/min(CHANNEL_0_SAMPLE_FREQUENCY,CHANNEL_1_SAMPLE_FREQUENCY)-1)
    	{
    		NRF_SAADC->CH[1].PSELP = SAADC_CH_PSELP_PSELP_AnalogInput1 << SAADC_CH_PSELP_PSELP_Pos;
    	}
    	
    	if(sample_count == max(CHANNEL_0_SAMPLE_FREQUENCY,CHANNEL_1_SAMPLE_FREQUENCY)/min(CHANNEL_0_SAMPLE_FREQUENCY,CHANNEL_1_SAMPLE_FREQUENCY))
    	{
    		NRF_SAADC->CH[1].PSELP = SAADC_CH_PSELN_PSELN_NC << SAADC_CH_PSELP_PSELP_Pos;
    		sample_count = 0;
    	}
    	
    	sample_count++;
    }
    
    saadc_init()
    {
    
    	// Configure SAADC channel 0 
    	
    	NRF_SAADC->CH[0].CONFIG = (
    		SAADC_CH_CONFIG_BURST_Enabled << SAADC_CH_CONFIG_BURST_Pos |
    		SAADC_CH_CONFIG_MODE_SE << SAADC_CH_CONFIG_MODE_Pos |
    		SAADC_CH_CONFIG_TACQ_10us << SAADC_CH_CONFIG_TACQ_Pos |
    		SAADC_CH_CONFIG_REFSEL_Internal << SAADC_CH_CONFIG_TACQ_Pos |
    		SAADC_CH_CONFIG_GAIN_Gain1_4 << SAADC_CH_CONFIG_GAIN_Pos |
    		SAADC_CH_CONFIG_RESN_Bypass << SAADC_CH_CONFIG_RESN_Pos |
    		SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESP_Pos );
    
    	NRF_SAADC->CH[0].PSELP = SAADC_CH_PSELP_PSELP_AnalogInput0 << SAADC_CH_PSELP_PSELP_Pos;
    	NRF_SAADC->CH[0].PSELN = SAADC_CH_PSELN_PSELN_NC << SAADC_CH_PSELN_PSELN_Pos;
    	
    	// Configure SAADC channel 1, but leave it not connected
    	
    	NRF_SAADC->CH[1].CONFIG = (
    		SAADC_CH_CONFIG_BURST_Enabled << SAADC_CH_CONFIG_BURST_Pos |
    		SAADC_CH_CONFIG_MODE_SE << SAADC_CH_CONFIG_MODE_Pos |
    		SAADC_CH_CONFIG_TACQ_10us << SAADC_CH_CONFIG_TACQ_Pos |
    		SAADC_CH_CONFIG_REFSEL_Internal << SAADC_CH_CONFIG_TACQ_Pos |
    		SAADC_CH_CONFIG_GAIN_Gain1_4 << SAADC_CH_CONFIG_GAIN_Pos |
    		SAADC_CH_CONFIG_RESN_Bypass << SAADC_CH_CONFIG_RESN_Pos |
    		SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESP_Pos );
    
    	
    	NRF_SAADC->CH[1].PSELP = SAADC_CH_PSELP_PSELP_NC << SAADC_CH_PSELP_PSELP_Pos;
    	NRF_SAADC->CH[1].PSELN = SAADC_CH_PSELN_PSELN_NC << SAADC_CH_PSELN_PSELN_Pos;
    	
    	/* Number of Sample Count*/
        NRF_SAADC->RESULT.MAXCNT = SAMPLES_IN_BUFFER;
    }
    
    rtc_init()
    {
    	// Configure RTC to run at sample rate of fastest SAADC channel 
    }
    
    
    main () 
    {
    	saadc_init();
    	rtc_init();
    	
    	while(1)
    	{
    		// Make sure any pending events are cleared
    		__SEV();
    		__WFE();
    		// Enter System ON sleep mode
    		__WFE();  
    	}
    }
    
Reply
  • I will see if I can throw together an example. The below preudocode should show the concept and how it can be implemented:

    #define CHANNEL_0_SAMPLE_FREQUENCY 500
    #define CHANNEL_1_SAMPLE_FREQUENCY 2
    
    #define SAMPLES_IN_BUFFER CHANNEL_0_SAMPLE_FREQUENCY + CHANNEL_1_SAMPLE_FREQUENCY
    
    uint32_t sample_count = 0;
    
    void saadc_sample(){
    
        NRF_SAADC->TASKS_START = 1;
        while (NRF_SAADC->EVENTS_STARTED == 0);
        NRF_SAADC->EVENTS_STARTED = 0;
    
        NRF_SAADC->TASKS_SAMPLE = 1;
        while (NRF_SAADC->EVENTS_END == 0);
        NRF_SAADC->EVENTS_END = 0;
    }
    
    rtc0_handler()
    {
    	saadc_sample();
    	
    	if (sample_count == max(CHANNEL_0_SAMPLE_FREQUENCY,CHANNEL_1_SAMPLE_FREQUENCY)/min(CHANNEL_0_SAMPLE_FREQUENCY,CHANNEL_1_SAMPLE_FREQUENCY)-1)
    	{
    		NRF_SAADC->CH[1].PSELP = SAADC_CH_PSELP_PSELP_AnalogInput1 << SAADC_CH_PSELP_PSELP_Pos;
    	}
    	
    	if(sample_count == max(CHANNEL_0_SAMPLE_FREQUENCY,CHANNEL_1_SAMPLE_FREQUENCY)/min(CHANNEL_0_SAMPLE_FREQUENCY,CHANNEL_1_SAMPLE_FREQUENCY))
    	{
    		NRF_SAADC->CH[1].PSELP = SAADC_CH_PSELN_PSELN_NC << SAADC_CH_PSELP_PSELP_Pos;
    		sample_count = 0;
    	}
    	
    	sample_count++;
    }
    
    saadc_init()
    {
    
    	// Configure SAADC channel 0 
    	
    	NRF_SAADC->CH[0].CONFIG = (
    		SAADC_CH_CONFIG_BURST_Enabled << SAADC_CH_CONFIG_BURST_Pos |
    		SAADC_CH_CONFIG_MODE_SE << SAADC_CH_CONFIG_MODE_Pos |
    		SAADC_CH_CONFIG_TACQ_10us << SAADC_CH_CONFIG_TACQ_Pos |
    		SAADC_CH_CONFIG_REFSEL_Internal << SAADC_CH_CONFIG_TACQ_Pos |
    		SAADC_CH_CONFIG_GAIN_Gain1_4 << SAADC_CH_CONFIG_GAIN_Pos |
    		SAADC_CH_CONFIG_RESN_Bypass << SAADC_CH_CONFIG_RESN_Pos |
    		SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESP_Pos );
    
    	NRF_SAADC->CH[0].PSELP = SAADC_CH_PSELP_PSELP_AnalogInput0 << SAADC_CH_PSELP_PSELP_Pos;
    	NRF_SAADC->CH[0].PSELN = SAADC_CH_PSELN_PSELN_NC << SAADC_CH_PSELN_PSELN_Pos;
    	
    	// Configure SAADC channel 1, but leave it not connected
    	
    	NRF_SAADC->CH[1].CONFIG = (
    		SAADC_CH_CONFIG_BURST_Enabled << SAADC_CH_CONFIG_BURST_Pos |
    		SAADC_CH_CONFIG_MODE_SE << SAADC_CH_CONFIG_MODE_Pos |
    		SAADC_CH_CONFIG_TACQ_10us << SAADC_CH_CONFIG_TACQ_Pos |
    		SAADC_CH_CONFIG_REFSEL_Internal << SAADC_CH_CONFIG_TACQ_Pos |
    		SAADC_CH_CONFIG_GAIN_Gain1_4 << SAADC_CH_CONFIG_GAIN_Pos |
    		SAADC_CH_CONFIG_RESN_Bypass << SAADC_CH_CONFIG_RESN_Pos |
    		SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESP_Pos );
    
    	
    	NRF_SAADC->CH[1].PSELP = SAADC_CH_PSELP_PSELP_NC << SAADC_CH_PSELP_PSELP_Pos;
    	NRF_SAADC->CH[1].PSELN = SAADC_CH_PSELN_PSELN_NC << SAADC_CH_PSELN_PSELN_Pos;
    	
    	/* Number of Sample Count*/
        NRF_SAADC->RESULT.MAXCNT = SAMPLES_IN_BUFFER;
    }
    
    rtc_init()
    {
    	// Configure RTC to run at sample rate of fastest SAADC channel 
    }
    
    
    main () 
    {
    	saadc_init();
    	rtc_init();
    	
    	while(1)
    	{
    		// Make sure any pending events are cleared
    		__SEV();
    		__WFE();
    		// Enter System ON sleep mode
    		__WFE();  
    	}
    }
    
Children
No Data
Related