Sampling rate vs sampling frequency

I am trying to find the FFT of my LSM6DS3 from the code below the sampling rate was set to 833Hz. The accelerometer was placed on a shaker at an amplitude of 3Vpp and frequency of 200Hz. The data was collected from the Arduino serial monitor.

I am having difficulties with the FFT of the data.

Please I have attached the accelerometer and MATLAB code.

I would appreciate any input or suggestions.

#include <Arduino.h>
#include "SparkFunLSM6DS3.h"
#include "Wire.h"
//#include "SPI.h"

//LSM6DS3 myIMU( SPI_MODE, 10 );
LSM6DS3 myIMU(I2C_MODE, 0x6B);

void setup( void ) {
  //Over-ride default settings if desired
  myIMU.settings.gyroEnabled = 1;  //Can be 0 or 1
  myIMU.settings.gyroRange = 2000;   //Max deg/s.  Can be: 125, 245, 500, 1000, 2000
  myIMU.settings.gyroSampleRate = 833;   //Hz.  Can be: 13, 26, 52, 104, 208, 416, 833, 1666
  myIMU.settings.gyroBandWidth = 200;  //Hz.  Can be: 50, 100, 200, 400;
  myIMU.settings.gyroFifoEnabled = 1;  //Set to include gyro in FIFO
  myIMU.settings.gyroFifoDecimation = 1;  //set 1 for on /1

  myIMU.settings.accelEnabled = 1;
  myIMU.settings.accelRange = 2;      //Max G force readable.  Can be: 2, 4, 8, 16
  myIMU.settings.accelSampleRate = 833;  //Hz.  Can be: 13, 26, 52, 104, 208, 416, 833, 1666, 3332, 6664, 13330
  myIMU.settings.accelBandWidth = 400;  //Hz.  Can be: 50, 100, 200, 400;
  myIMU.settings.accelFifoEnabled = 1;  //Set to include accelerometer in the FIFO
  myIMU.settings.accelFifoDecimation = 1;  //set 1 for on /1
  myIMU.settings.tempEnabled = 1;
  
    //Non-basic mode settings
  myIMU.settings.commMode = 1;

  //FIFO control settings
  myIMU.settings.fifoThreshold = 100;  //Can be 0 to 4096 (16 bit bytes)
  myIMU.settings.fifoSampleRate = 50;  //Hz.  Can be: 10, 25, 50, 100, 200, 400, 800, 1600, 3300, 6600
  myIMU.settings.fifoModeWord = 6;  //FIFO mode.
  //FIFO mode.  Can be:
  //  0 (Bypass mode, FIFO off)
  //  1 (Stop when full)
  //  3 (Continuous during trigger)
  //  4 (Bypass until trigger)
  //  6 (Continous mode)
  

  Serial.begin(2000000);  // start serial for output
  delay(1000); //relax...
  Serial.println("Processor came out of reset.\n");
  
  //Call .begin() to configure the IMUs
  if( myIMU.begin() != 0 )
  {
    Serial.println("Problem starting the sensor with CS @ Pin 10.");
  }
  else
  {
    Serial.println("Sensor with CS @ Pin 10 started.");
  }
  
  Serial.print("Configuring FIFO with no error checking...");
  myIMU.fifoBegin();
  Serial.print("Done!\n");
  
  Serial.print("Clearing out the FIFO...");
  myIMU.fifoClear();
  Serial.print("Done!\n");
  
}


void loop()
{
  float temp;  //This is to hold read data
  uint16_t tempUnsigned;
  
  while( ( myIMU.fifoGetStatus() & 0x8000 ) == 0 ) {};  //Wait for watermark
 
  //Now loop until FIFO is empty.  NOTE:  As the FIFO is only 8 bits wide,
  //the channels must be synchronized to a known position for the data to align
  //properly.  Emptying the fifo is one way of doing this (this example)
  while( ( myIMU.fifoGetStatus() & 0x1000 ) == 0 ) {


  
  //Get all parameters
  //Serial.print("\nAccelerometer:\n");
  //Serial.print(" X = ");
  Serial.print(myIMU.readFloatAccelX(), 2);
  Serial.print(",");
  Serial.print(myIMU.readFloatAccelY(), 2);
  Serial.print(",");
  Serial.println(myIMU.readFloatAccelZ(), 2);
  
  delay(10); //Wait for the serial buffer to clear (~50 bytes worth of time @ 57600baud)
  
  }



}

Below is the MATLAB code



clear
data=load('green.txt');    %load the data
fs=833; N=length(data);             %sampling rate, number of samples
df=fs/N;                            %frequency spacing of FFT

%% Compute FFT of each channel
data1=data-mean(data);       %subtract mean value from each column
DATA=fft(data1);

%% Plot time domain data
dT=1/fs;        %time interval
t=(0:N-1)*dT;   %vector of times
figure; subplot(211)
plot(t,data(:,1),'-r',t,data(:,2),'-g',t,data(:,3),'-b')
xlabel('Time (s)'); ylabel('Accel.');
title('Acceleration Data'); grid on

%% Plot frequency domain data
f=(0:N/2)*df; %vector of frequencies, for plotting FFT
subplot(212)
plot(f,abs(DATA(1:N/2+1,1)),'-r',f,abs(DATA(1:N/2+1,2)),'-g',f,abs(DATA(1:N/2+1,3)),'-b')
xlabel('Frequency (Hz)'); ylabel('|Accel.|');
legend('ax','ay','az');
title('FFT of Acceleration Data'); grid on

![image|506x223](upload://1Iu1tIFVyXRwqLNKwGTQ6eTB0f1.png)

That line alone limits the output data frequency to 100 Hz, maximum. The actual output data frequency is somewhat lower.

So you can expect severe aliasing in the FFT, if any signals with frequency higher than 50 Hz are present in the sampled data.

This is NOT an Arduino "Installation and Troubleshooting" topic. Use the flag button to ask the moderator to move it elsewhere.

Your topic has been moved to a more suitable location on the forum. Installation and Troubleshooting is not for problems with (nor for advice on) your project :wink: See About the Installation & Troubleshooting category.

Thanks, is it advisable to comment out the line?

With that line, your code cannot possibly produce useful data in the situation described.

The accelerometer was placed on a shaker at an amplitude of 3Vpp and frequency of 200Hz

I have commented out the line.
In the FFT code, what will be the sampling frequency?

It is set by the IMU, because you are checking its FIFO for available data.

from the code the sampling rate was 833Hz, I keyed in that in the MATLAB FFT code.

The output frequency was 294Hz.
That is my worries.

What do you mean, "from the code"? You mean this?

  myIMU.settings.fifoSampleRate = 50;  //Hz.  Can be: 10, 25, 50, 100, 200, 400, 800, 1600, 3300, 6600

This.

how did you determine that?

fft
after running the MATLAB code. I might be wrong, totalling because I am new to this.

The peak frequency output by Matlab is meaningless, because you have ASSUMED a sample rate of 833 Hz.

fs=833; N=length(data);             %sampling rate, number of samples

To determine the actual output frequency of the sampling loop, you can time it, using something like the following (not tested, some junk removed):

void loop()
{
  unsigned long start_time = millis();
  int samples = 0;
  
  while( ( myIMU.fifoGetStatus() & 0x8000 ) == 0 ) {};  //Wait for watermark
 
  //Now loop until FIFO is empty.  NOTE:  As the FIFO is only 8 bits wide,
  //the channels must be synchronized to a known position for the data to align
  //properly.  Emptying the fifo is one way of doing this (this example)

  while( ( myIMU.fifoGetStatus() & 0x1000 ) == 0 ) {

  //Get all parameters
  Serial.print(myIMU.readFloatAccelX(), 2);
  Serial.print(",");
  Serial.print(myIMU.readFloatAccelY(), 2);
  Serial.print(",");
  Serial.println(myIMU.readFloatAccelZ(), 2);
  samples++; // count this measurement
  }
  Serial.print ("rate ");
  Serial.println( (millis()-start_time)/samples);  //average time to output measurement in milliseconds
}

The IMU control variables are numerous - perhaps one or more of them are set incorrectly, or incompatibly with each other.

Yes, and another issue is the use of the FIFO, which means the actual time at which each sample is taken is not known.

The FFT calculation assumes a fixed sample rate, which is violated by the FIFO approach, with possibly severe reduction of accuracy.

Turn off the gyro and the FIFO, then set a fixed sample rate for the accelerometer.

To sample a 200hz signal, you must sample at a minimum of 400hz. Personally I would want a higher sample rate.

I use SDFat's LowLatencyLogger to record my data to an SD card. This gets post process with Discrete Fourier Transform (thanks jremington) to convert to frequency domain. But with most Arduino compatible microcontrollers LLL can only sample at 250Hz. To get a higher sample rate, you will need to use a Tennsy microcontroller. (So says Bill Greiman author of SDFat library)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.