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

SAADC readings are frequency-dependent?

Hello,

I am using the SAADC of a nRF52832 with a sample-rate of 1ms (1kHz).

The following code shows, how my SAADC is intialized:

#define SAADC_SAMPLE_RATE               1

void saadc_sampling_event_init(void)
{
    ret_code_t err_code;
    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);
    
    nrf_drv_timer_config_t timer_config = NRF_DRV_TIMER_DEFAULT_CONFIG;
    timer_config.frequency = NRF_TIMER_FREQ_31250Hz;                                                                        
    err_code = nrf_drv_timer_init(&m_timer, &timer_config, timer_handler);
    APP_ERROR_CHECK(err_code);

    /* setup m_timer for compare event */
    uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer,SAADC_SAMPLE_RATE);
    nrf_drv_timer_extended_compare(&m_timer, NRF_TIMER_CC_CHANNEL0, ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);
    nrf_drv_timer_enable(&m_timer);

    uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer, NRF_TIMER_CC_CHANNEL0);
    uint32_t saadc_sample_event_addr = nrf_drv_saadc_sample_task_get();

    /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_ppi_channel_assign(m_ppi_channel, timer_compare_event_addr, saadc_sample_event_addr);
    APP_ERROR_CHECK(err_code);
}

void saadc_sampling_event_enable(void)
{
    ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
    APP_ERROR_CHECK(err_code);
}


void saadc_init(void)
{
    ret_code_t err_code;
	
    nrf_drv_saadc_config_t saadc_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
    saadc_config.resolution = NRF_SAADC_RESOLUTION_8BIT;
	
    nrf_saadc_channel_config_t channel_0_config =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN4);
    channel_0_config.gain = NRF_SAADC_GAIN1_4;
    channel_0_config.reference = NRF_SAADC_REFERENCE_VDD4;
    
    err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_saadc_channel_init(0, &channel_0_config);
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0],SAADC_SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);
    
    ...
    
}    

My problem is, that it looks like, that the readings of the SAADC are frequency-dependent.

I applied the following 5Hz sinus-signal to the analog input:

I receive the following readings from my SAADC:

This looks fine.

But if I apply a 50Hz sinus-signal with the same amplitude and offset to the analog input, which is shown in the following picture:

I receive the following saadc readings:

The amplitude of the SAADC readings is significantly lower.

So here are my questions:

1. Why do the SAADC readings values decrease with a higher frequency?

2. Do you know what the problem is?

3. Do you have any suggestions, how to solve this issue?

Thank you very much in advance.

Parents
  • Can you share raw samples of the two signals? We need to know whether the signals are sampled correctly or not. 

    What is your buffer size?

    Are you running the SoftDevice as well?

  • Hello,

    thank you very much for your quick response.

    Can you share raw samples of the two signals?

    50Hz signal (1 periode): [20 values] 42,39,38,36,35,34,34,35,37,39,41,43,45,47,48,48,48,47,46,43

    5Hz signal (1 periode): [200 values]  from 23 to 60

    -> the raw samples, which the SAADC outputs, are equal to the pictures.

    What is your buffer size?

    I set SAADC_SAMPLES_IN_BUFFER to 4. But I do not use this buffer, instead I created my own array for collecting the SAADC readings for further processing. Every time the SAADC callback function gets called, the SAADC reading gets written into this array:

    #define SAADC_SAMPLES_IN_BUFFER         4
    
    static nrf_saadc_value_t       m_buffer_pool[2][SAADC_SAMPLES_IN_BUFFER];
    
    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
            ...
            ret_code_t err_code;
            err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAADC_SAMPLES_IN_BUFFER);
            APP_ERROR_CHECK(err_code);
            ...
            if (counter <= 40){
                ch_values1[counter-1] = p_event->data.done.p_buffer[0];
            }
            if (counter == 40){     
                counter = 0;
                ble_nus_data_send(...,ch_values1,...)
            }
            counter++;
        }
    }

    I read out the raw samples, which i mentioned earlier, from this ch_values1 array.

    Are you running the SoftDevice as well?

    Yes, s132. The SAADC readings were send to the central via NUS every 40ms.

    In conclusion, it looks like that I am receiving wrong values from the SAADC.

    1. Do you have an idea what causes this issue?

    2. Do you have any suggestions how to solve this problem?

    Thank you so much in advance.

Reply
  • Hello,

    thank you very much for your quick response.

    Can you share raw samples of the two signals?

    50Hz signal (1 periode): [20 values] 42,39,38,36,35,34,34,35,37,39,41,43,45,47,48,48,48,47,46,43

    5Hz signal (1 periode): [200 values]  from 23 to 60

    -> the raw samples, which the SAADC outputs, are equal to the pictures.

    What is your buffer size?

    I set SAADC_SAMPLES_IN_BUFFER to 4. But I do not use this buffer, instead I created my own array for collecting the SAADC readings for further processing. Every time the SAADC callback function gets called, the SAADC reading gets written into this array:

    #define SAADC_SAMPLES_IN_BUFFER         4
    
    static nrf_saadc_value_t       m_buffer_pool[2][SAADC_SAMPLES_IN_BUFFER];
    
    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
            ...
            ret_code_t err_code;
            err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAADC_SAMPLES_IN_BUFFER);
            APP_ERROR_CHECK(err_code);
            ...
            if (counter <= 40){
                ch_values1[counter-1] = p_event->data.done.p_buffer[0];
            }
            if (counter == 40){     
                counter = 0;
                ble_nus_data_send(...,ch_values1,...)
            }
            counter++;
        }
    }

    I read out the raw samples, which i mentioned earlier, from this ch_values1 array.

    Are you running the SoftDevice as well?

    Yes, s132. The SAADC readings were send to the central via NUS every 40ms.

    In conclusion, it looks like that I am receiving wrong values from the SAADC.

    1. Do you have an idea what causes this issue?

    2. Do you have any suggestions how to solve this problem?

    Thank you so much in advance.

Children
  • The SoftDevice is most likely blocking/delaying your buffer handling, but you probably also have an issue with your signal source. 

    I suggest you start by increasing the buffer size to a proper size, there's no point in creating multiple arrays from a single buffer if they're going to contain the same samples as if you just used one big one. 

    I also suggest you try out the SAADC v2 driver in nRF5 SDK17, as it has a better buffer handling than the standard one.

    The SAADC is accurate up to 200ksps, 1ksps is not a problem. 


  • Hello,

    thank you for your reply.

    With your advice to take a look to the SAMPLES_IN_BUFFER I was able to figure out the problem.

    SAMPLES_IN_BUFFER was set to 4, which is okey if I use four channels.

    I set SAMPLES_IN_BUFFER to 1 (At the moment I am using only one channel). I receive correct readings from the saadc now.

    I also suggest you try out the SAADC v2 driver in nRF5 SDK17,

    Unfortunaly, I can´t find anything within this link.

    Finally, thank you very much for your support.

  • If you set SAMPLES_IN_BUFFER to 1 then you will have sampling errors when the SoftDevice is running. A SAMPLES_IN_BUFFER of 4 is still critically low. At high buffer sizes the likelihood of sampling error will be reduced, but not eliminated. The v2 driver further reduces this likelihood. 

    See modules\nrfx\drivers\src\nrfx_saadc.c and modules\nrfx\drivers\include\nrfx_saadc_v2.h

Related