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

Data from sensor can not be sampled at 1000 Hz.

Hi,

I am using nRF_SDK_15.0.0_a53641 and writing a program with keil.

I am receiving data from the sensor with TWI communication and writing it to the sensor by SPI communication.

So I sampled the data with reference to the apptimer example,

timer_ms = 1;
time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_TWI, time_ms);

As I tried to write data every 1 ms (1000 Hz), it runs at sampling frequency much lower than 1000 Hz.

Is it due to some other configuration?

The frequency setting for TWI communication with the sensor and SPI communication with the SD card is the default.

I will attach a part of the program below.

/**
 * @brief Handler for timer events.
 */
void timer_twi_event_handler(nrf_timer_event_t event_type, void* p_context)
{

    switch (event_type)
    {
        case NRF_TIMER_EVENT_COMPARE1:
					
        
			flag = 1;
					
            break;

            default:
            //Do nothing.
            break;
    }
}

int main(void)
{
	float time = 0.000;
	float g = 9.81;
	float t = 0.001;
	uint32_t time_ms = 1; //Time(in miliseconds) between consecutive compare events.
	uint32_t time_ticks;
    uint32_t err_code = NRF_SUCCESS;

	//SPI start condition
	SPI_start();
	
		
    bsp_board_init(BSP_INIT_LEDS);
	
	
    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("FATFS example started.");
	
	//Configure TIMER_LED for generating simple light effect - leds on board will invert his state one after the other.
    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    err_code = nrf_drv_timer_init(&TIMER_TWI, &timer_cfg, timer_twi_event_handler);
    APP_ERROR_CHECK(err_code);

    time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_TWI, time_ms);

    nrf_drv_timer_extended_compare(
         &TIMER_TWI, NRF_TIMER_CC_CHANNEL1, time_ticks, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, true);

    nrf_drv_timer_enable(&TIMER_TWI);

	TWI_start();//ST
	nrf_delay_us(5);
    twi_init();
	nrf_delay_us(5);
    LM75B_set_mode();//SAD+W,SUB(SUB[7] set to 1)
   	nrf_delay_us(100);
   	
    while (true)
    {

		if(flag){
			time += t;
   	        TWI_start();//SR
		    nrf_delay_us(600);//600-500
		    read_sensor_data();//SAD+R
		    nrf_delay_us(4);
	        TWI_stop();//SP
		    nrf_delay_us(5);
	
	        //uint8 to short(16bit)
	        x = (short)(m_sample[1] << 8 | m_sample[0]);
	        y = (short)(m_sample[3] << 8 | m_sample[2]);
		    z = (short)(m_sample[5] << 8 | m_sample[4]);

    
            x_g = (((float)x*2*2)/(float)65536);
		    y_g = (((float)y*2*2)/(float)65536);
		    z_g = (((float)z*2*2)/(float)65536);
		
		    x_g = x_g * g;
		    y_g = y_g * g;
		    z_g = z_g * g;

		    sprintf(time_b,"%lf",time);
	        sprintf(buf0,"%lf",x_g);
	        sprintf(buf1,"%lf",y_g);
	        sprintf(buf2,"%lf",z_g);
		

            fatfs_example(time_b,buf0,buf1,buf2);
		
		    flag = 0;
			
			
		}
		__WFI();
    }
}

Thank you.

Parents
  • You should move everything except TWI read and SPI write outside the loop, there is no need to initialize the TWI/SPI interface more than once. Ideally you should also perform the SPI write while reading the next TWI value. The peripherals can operate concurrently in non-blocking mode. I have attached a code snippet that show how you can implement this in your application:

    bool spi_write_done = true;
    bool twi_read_done = false;
    
    twi_handler()
    {
    	twi_read_done = true;
    }
    
    spi_handler()
    {
    	spi_write_done = true;
    }
    
    main()
    {
    	twi_init(twi_handler);
    	spi_init(spi_handler);
    	
    	while(1)
    	{
    		twi_read_done = false;
    		twi_read(twi_buffer);										// Read sensor data into twi_buffer
    		
    		while((twi_read_done == false) || (spi_write_done == false));	// Wait for TWI read and previous SPI transfer to finish before starting SPI write
    		spi_buffer = twi_buffer;									// Copy sensor data from twi_buffer to spi_buffer. This will allow you to start a new twi_read operation immediately after starting SPI write operation.
    		
    		spi_write_done = false;
    		spi_write(spi_buffer);
    	}
    }

    (Note that this is not a complete, working code. It is only meant for illustrating a possible implementation.) 

Reply
  • You should move everything except TWI read and SPI write outside the loop, there is no need to initialize the TWI/SPI interface more than once. Ideally you should also perform the SPI write while reading the next TWI value. The peripherals can operate concurrently in non-blocking mode. I have attached a code snippet that show how you can implement this in your application:

    bool spi_write_done = true;
    bool twi_read_done = false;
    
    twi_handler()
    {
    	twi_read_done = true;
    }
    
    spi_handler()
    {
    	spi_write_done = true;
    }
    
    main()
    {
    	twi_init(twi_handler);
    	spi_init(spi_handler);
    	
    	while(1)
    	{
    		twi_read_done = false;
    		twi_read(twi_buffer);										// Read sensor data into twi_buffer
    		
    		while((twi_read_done == false) || (spi_write_done == false));	// Wait for TWI read and previous SPI transfer to finish before starting SPI write
    		spi_buffer = twi_buffer;									// Copy sensor data from twi_buffer to spi_buffer. This will allow you to start a new twi_read operation immediately after starting SPI write operation.
    		
    		spi_write_done = false;
    		spi_write(spi_buffer);
    	}
    }

    (Note that this is not a complete, working code. It is only meant for illustrating a possible implementation.) 

Children
  • Thank you for the idea to solve!

    It is done with a while loop without using "apptimer example"!

    I currently use a common buffer for read and write of the array m_sample [6].

    Is it a recognition that this m_sample is used as another for read and write?

    Even with this method, is it okay for sprintf to end up in a while loop?

    I am inside the read_sensor_data () function

    static void read_sensor_data()
    {
    	m_xfer_done = false;
    
    
    	/* Read 1 byte from the specified address - skip 3 bits dedicated for fractional part of temperature. */
    	ret_code_t err_code = nrf_drv_twi_rx(&m_twi, LSM_ADDR, m_sample, sizeof(m_sample));
    	APP_ERROR_CHECK(err_code);
    	nrf_gpio_cfg_output(LSM303DLHC_SDA_PIN);	
    	nrf_gpio_pin_clear(LSM303DLHC_SDA_PIN);
      	while(m_xfer_done == false);
    }

    In this case it is the last line
    while (m_xfer_done == false);
    Should I put out?

  • You will need two separate buffers if you want to read/write at the same time. You should copy the content from TWI buffer to SPI buffer as illustrated in my code snippet. If you need sprintf, you should put it in the loop, but I still think that function is too slow to get the sample frequency you want.

Related