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

Doubt about the sampling rate

I am using 3 axis LIS2D12H accelerometer interfaced with NRF51832 with SPI interface. The sensor has sampling rate from 1 HZ to 5.376 KHz which is happening at sensor only. I am taking sensor data at 400 Hz by setting register values in sensor. I am implementing FFT algorithm in microcontroller over a raw sensor data received by 3 axis for vibration analysis. I can have resolution of FFT from 64 to 2048. My confusion is how should I sample it at microcontroller for FFT, there are FFT function in ARM cortex which I am using. Shall I take raw samples in buffer and sample them or shall I take each reading from sensor and sample them individually. If that is the case how shall I select sampling frequency at microcontroller level and/or at what rate microcontroller shall read data

  • Hi 

    Shall I take raw samples in buffer and sample them or shall I take each reading from sensor and sample them individually.

    I am not quite sure I understand this question, but I would expect that each sensor read is passed to the FFT after applying some simple processing of the data (at a minimum I would expect some unit conversion and scaling to be required). 

    Also, assuming you are just using one dimensional FFT, how do you plan to convert the three dimensional sensor data to one dimension for the FFT?

    If that is the case how shall I select sampling frequency at microcontroller level and/or at what rate microcontroller shall read data

    You mentioned the sensor is set to 400Hz, then the microcontroller should follow this I would assume?

    Normally you would run the sensor and the internal processing in sync, and set the frequency depending on the frequency range of the data signal that you are trying to analyze. 

    Best regards
    Torbjørn

  • Hi

     "I am not quite sure I understand this question, but I would expect that each sensor read is passed to the FFT after applying some simple processing of the data (at a minimum I would expect some unit conversion and scaling to be required). "

    Actually raw data is being captured from sensor, when I apply FFT for buffer of samples like 32,64..., what happens is I am geting frequency of maximum amplitude always zero. So I am still confused shall it need to be sampled at microcontroller separately in order to take FFT

    "Also, assuming you are just using one dimensional FFT, how do you plan to convert the three dimensional sensor data to one dimension for the FFT?"

    Currenlty we are taking individual FFT for each axis and I want to send the output fft samples over serial.

  • Hi

    Yashodhan said:
    what happens is I am geting frequency of maximum amplitude always zero.

    I assume you mean the amplitude of the maximum frequency is always zero?

    Could you show me the code you use to run the FFT?

    Best regards
    Torbjørn

  • I assume you mean the amplitude of the maximum frequency is always zero?

    no at maximum amplitude of fft the frequency is always zero

    static void draw_fft_data(float32_t * p_input_data, uint16_t data_size)
    {
    
        float32_t max_value;
        uint32_t  max_val_index;
        float32_t freq; 
        // Search FFT max value in input array.
        arm_max_f32(p_input_data, data_size, &max_value, &max_val_index);
        freq = max_val_index*bin_resolution;
    
        
        // NRF_LOG_INFO("Maximum value index %lu\r\n",max_val_index);
        //NRF_LOG_INFO("Max FFT Value: " NRF_LOG_FLOAT_MARKER "\r\n", NRF_LOG_FLOAT(max_value));
    
       //NRF_LOG_INFO("Frequency of max: " NRF_LOG_FLOAT_MARKER "\r\n", NRF_LOG_FLOAT(freq));
             sprintf((char*)datafft,"Maximum value index = %lu,Max FFT Value = %.2f,Frequency of max = %.2f",max_val_index,(float32_t) max_value,(float32_t) freq);
              (void) nrf_serial_write(&serial_uart,
                               & (datafft),strlen((char*)datafft),
                               NULL,
                               NRF_SERIAL_MAX_TIMEOUT);
                               
             (void) nrf_serial_write(&serial_uart,
                               "\n\r",
                               strlen("\n\r"),
                               NULL,
                               NRF_SERIAL_MAX_TIMEOUT);
                (void)nrf_serial_flush(&serial_uart, 0);
                nrf_delay_ms(5);
       
        /* NRF_LOG_RAW_INFO("Maximum value index %lu\r\n",max_val_index);
        NRF_LOG_RAW_INFO("Max FFT Value: " NRF_LOG_FLOAT_MARKER "\r\n", NRF_LOG_FLOAT(max_value));
    
       NRF_LOG_RAW_INFO("Frequency of max: " NRF_LOG_FLOAT_MARKER "\r\n", NRF_LOG_FLOAT(freq));*/
       
       }
    
    void compute_fft(float32_t inputbuf[],float32_t outbuf[],float32_t axis,char a)
    {
             // uint8_t uartchar[10] ;
             // NRF_LOG_RAW_INFO("Axis Data %c\r\n",a);
             sprintf((char*)uartchar,"Axis Data = %c",a);
              (void) nrf_serial_write(&serial_uart,
                               &(uartchar),strlen((char*)uartchar),
                               NULL,
                               NRF_SERIAL_MAX_TIMEOUT);
                               
             (void) nrf_serial_write(&serial_uart,
                               "\n\r",
                               strlen("\n\r"),
                               NULL,
                               NRF_SERIAL_MAX_TIMEOUT);
                               (void)nrf_serial_flush(&serial_uart, 0);
                               nrf_delay_ms(5);
              fft_generate_samples(inputbuf,
                                 FFT_TEST_COMP_SAMPLES_LEN,
                                 FFT_TEST_SAMPLE_FREQ_HZ,
                                 axis);
                        
              fft_process(inputbuf,
                        &arm_cfft_sR_f32_len32,
                        outbuf,
                        FFT_TEST_OUT_SAMPLES_LEN); 
               draw_fft_data(outbuf, FFT_TEST_OUT_SAMPLES_LEN);         
    
    
    }
    
    
    #ifdef FPU_INTERRUPT_MODE
        // Enable FPU interrupt
        NVIC_SetPriority(FPU_IRQn, APP_IRQ_PRIORITY_LOWEST);
        NVIC_ClearPendingIRQ(FPU_IRQn);
        NVIC_EnableIRQ(FPU_IRQn);
    #endif
    
     
        //for (;;)
        while(true)
        
        {
          //GetLis2dhData();
           
           for(volatile uint16_t j = 0; j<numsamples; j++)
           {
               GetLis2dhData();
           
               accdata[j] =gattdata.buff[0] ;
              sqrx+=  pow((float32_t)accdata[j],2);
             
               x_freq = (((uint32_t)accdata[j]) % ((uint32_t)(SINE_WAVE_FREQ_MAX * SIGNALS_RESOLUTION))) / SIGNALS_RESOLUTION;
              compute_fft(m_fft_input_f32_x,m_fft_output_f32_x,x_freq,'X');
             
             
                     
           
           }
        
           (void) nrf_serial_write(&serial_uart,
                               &(outfft),
                               strlen((char*)outfft),
                               NULL,
                               NRF_SERIAL_MAX_TIMEOUT);
                               
                               
                               
             (void) nrf_serial_write(&serial_uart,
                               "\n\r",
                               strlen("\n\r"),
                               NULL,
                               NRF_SERIAL_MAX_TIMEOUT);
           

  • Hi 

    There seems to be some problems with your implementation. 

    First off, the fft_generate_samples(..) function is only used in the example to generate some dummy data for the FFT to process. Since you have some actual data to process from your accelerometer you don't have to generate the data through this function (you can still look at the implementation of this function to see how the input array should be set up). 

    Instead you should buffer a series of samples from your accelerometer, and run the fft_process function once you have buffered the required 64 samples in your buffer. 

    As you can see in fft_generate_samples(..) every even index in the input buffer contains the real value (your accelerometer reading), while every odd index contains the imaginary value, which you can just set to 0. 

    Best regards
    Torbjørn

Related