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

How to set NRF52840 DK SAADC Sampling at 200 kHZ?

Dear All,

I am using NRF52840 DK with SDK13.0. I am trying to use one SAADC channel (CH 1) to record input signals at 200 kHz to fill a buffer of 2000 points. After the buffer is full (2000 points collected), the data will be trasfered to my PC via NRF Connect. The sampling event will be triggered by Button 1 on the NRF52840 DK.

I would like to just get 2000 points per buttion on/off. Can someone give me some idea about this function? I am using the example from Github here, but still have not figured this out.

https://github.com/NordicPlayground/nRF52-ADC-examples/tree/master/saadc_low_power/pca10056/blank/arm5_no_packs 

Would you please let me know how to set the sampling frequency to be 200 kHz? How to trigger the SAADC once to get 2000 points? And do I have to divide the 2000 points into 100 packages to sent them to the receiver?

Many thanks in advance.

Hai

Parents
  • This is my settings based on the example in Github. https://github.com/NordicPlayground/nRF52-ADC-examples/blob/master/ble_app_uart__saadc_timer_driven__scan_mode/main.c 

    #define SAADC_SAMPLES_IN_BUFFER 2000
    #define SAADC_SAMPLE_RATE 10 /**< SAADC sample rate in us. */

    In the void saadc_sampling_event_init(void) function, I did these changes.

    void saadc_sampling_event_init(void)
    {
         ......

         timer_config.frequency = NRF_TIMER_FREQ_16MHz;//62500Hz;//31250Hz;//NRF_TIMER_FREQ_;
         ......
         uint32_t ticks = nrf_drv_timer_us_to_ticks(&m_timer,SAADC_SAMPLE_RATE);
         ......
    }

    in the void saadc_callback(nrf_drv_saadc_evt_t const * p_event) function, I did the following changes.

    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
    saadc_sampling_event_disable();
    bsp_board_led_invert(1);
    if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {
    ret_code_t err_code;
    uint16_t adc_value;
    uint8_t value[SAADC_SAMPLES_IN_BUFFER*2];
    uint8_t subvalue[20];

    err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAADC_SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);

    for (int i = 0; i < SAADC_SAMPLES_IN_BUFFER; i++)
    {
    adc_value = p_event->data.done.p_buffer[i];
    value[i*2] = adc_value;
    value[(i*2)+1] = adc_value >> 8;
    }

    for (uint16_t indx_j = 0; indx_j <SAADC_SAMPLES_IN_BUFFER*2/20; indx_j++)//SAADC_SAMPLES_IN_BUFFER*2/20
    {
    for (uint16_t ind_m = 0; ind_m < 20; ind_m++)
    {
    subvalue[ind_m] = value[indx_j*20+ind_m];
    }

    err_code = ble_nus_string_send(&m_nus, subvalue, 20);
    if (err_code != NRF_ERROR_INVALID_STATE)
    {
    APP_ERROR_CHECK(err_code);
    }
    }

    m_adc_evt_counter++;
    nrf_delay_ms(500);
    saadc_sampling_event_enable();
    }
    }

    I always get this error "BLE_HCI_CONNECTION_TIMEOUT".

  • In order to achieve 200 kHz sample rate, you need to set acq_time to NRF_SAADC_ACQTIME_3US.

    You can then trigger the sample task through PPI from TIMER or RTC event until you have filled the 2000 samples buffer. There is no mode that will capture 2000 samples for you from a single sample task.

  • Hi Jorgen,

    Yes, I have "channel_0_config.acq_time = NRF_SAADC_ACQTIME_3US" in void saadc_init(void). So I guess I can fill 2000 points in the buffer successfully.

    When I try to divide the 2000 points (12 bits each, 4000 bytes) into 200 packages and send them to a NRF52832 DK receiver connected to my PC and controlled by NRF Connect, I could not recevie the packages, and always get this error "BLE_HCI_CONNECTION_TIMEOUT" from the receiver.

    This is the saadc_callback function I am using.

     

    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        
    	  if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
         {
            saadc_sampling_event_disable();
    	    bsp_board_led_invert(1);
    	    ret_code_t err_code;
            uint16_t adc_value;
            uint8_t value[SAADC_SAMPLES_IN_BUFFER*2];
    		uint8_t subvalue[20];
    
            err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAADC_SAMPLES_IN_BUFFER);
            APP_ERROR_CHECK(err_code);
    
            for (int i = 0; i < SAADC_SAMPLES_IN_BUFFER; i++)
            {
                adc_value = p_event->data.done.p_buffer[i];
                value[i*2] = adc_value;
                value[(i*2)+1] = adc_value >> 8;
            }
    				
    		for (uint16_t indx_j = 0; indx_j < 20; indx_j++)//SAADC_SAMPLES_IN_BUFFER*2/20
    		{
    			for (uint16_t ind_m = 0; ind_m < 20; ind_m++)
    			{
    				subvalue[ind_m] = value[indx_j*20+ind_m];
    			}
    			err_code = ble_nus_string_send(&m_nus, subvalue, 20);
                
                if (err_code != NRF_ERROR_INVALID_STATE) 
                {
                    APP_ERROR_CHECK(err_code);
                }
    		}
            m_adc_evt_counter++;
    		nrf_delay_ms(500);
    		saadc_sampling_event_enable();
        }
    }

    Would you please help me with this issue?

    Many thanks,

    Hai

  • My guess would be that you get another error code than NRF_ERROR_INVALID_STATE when calling ble_nus_string_send() 100 times, and you end up in the error handler. Note that there is a limited number of buffers available for sending notifications, which is what this function does internally. In general, it is also not recommended to spend long time in handlers/interrupt context, as this will block other lower priority event from being handled.

Reply Children
Related