Using ADXL345 with Arduino UNO R3 to Obtain Time Domain Vibration Signals and Convert to Frequency Domain via FFT

Greetings,

I am a mechanical engineer seeking to acquire time domain data for my helical spring. To achieve this, I have mounted an ADXL345 accelerometer at the top plate of the spring and connected it to an Arduino UNO R3. However, I require guidance on how to obtain the output in the time domain and subsequently convert it into a Fast Fourier Transform (FFT) to analyze amplitude versus frequeUse code tags to format code for the forumncy.

Specifications:

Desired Frequency Range: Upto 850HZ.
Thank you.

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>

// Create the ADXL345 object
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);

// Sampling rate in Hz
const int samplingRate = 1000; // Adjust based on the desired frequency range
const int numSamples = 1024; // Number of samples for FFT

// Arrays to store acceleration data
float ax[numSamples];
float ay[numSamples];
float az[numSamples];

void setup() {
  Serial.begin(115200);
  // Initialize the sensor
  if (!accel.begin()) {
    Serial.println("No ADXL345 detected ... Check your wiring!");
    while (1);
  }
  // Set the range to +/- 16g
  accel.setRange(ADXL345_RANGE_16_G);
}

void loop() {
  // Collect samples
  for (int i = 0; i < numSamples; i++) {
    sensors_event_t event;
    accel.getEvent(&event);
    ax[i] = event.acceleration.x;
    ay[i] = event.acceleration.y;
    az[i] = event.acceleration.z;
    delayMicroseconds(1000000 / samplingRate);
  }

  // Send data to Serial for FFT processing on a computer
  for (int i = 0; i < numSamples; i++) {
    Serial.print(ax[i]);
    Serial.print(",");
    Serial.print(ay[i]);
    Serial.print(",");
    Serial.println(az[i]);
  }

  delay(5000); // Delay between captures
}

Your topic has been moved. Please do not post in "Uncategorized"; see the sticky topics in Uncategorized - Arduino Forum.

That's in general not how the forum works. The people here help you to write the code and advise on possible fixes; you will have to do some work first.

If you don't want to do (or can't do) the work, you can ask for paid consultancy in Jobs and Paid Consultancy - Arduino Forum (your topic can be moved there).


No experience with your sensor so can't help further.

Greetings,

I am a mechanical engineer seeking to acquire time domain data for my helical spring. To achieve this, I have mounted an ADXL345 accelerometer at the top plate of the spring and connected it to an Arduino UNO R3. However, I require guidance on how to obtain the output in the time domain and subsequently convert it into a Fast Fourier Transform (FFT) to analyze amplitude versus frequency.

Specifications:

Desired Frequency Range: Up to 850 Hz

Thank you.

#include <Wire.h>
#include <ADXL345.h>
#include <arduinoFFT.h>

#define SAMPLES 128              // Must be a power of 2
#define SAMPLING_FREQUENCY 1000  // Hz, must be less than 10000 due to ADC conversion time

ADXL345 adxl;                     // ADXL345 object
arduinoFFT FFT = arduinoFFT();    // FFT object

unsigned int sampling_period_us;
unsigned long microseconds;

double vReal[SAMPLES];
double vImag[SAMPLES];

void setup() {
  Serial.begin(115200);
  adxl.powerOn();
  adxl.setRangeSetting(2);        // Set accelerometer range to ±2g

  sampling_period_us = round(1000000 * (1.0 / SAMPLING_FREQUENCY));
}

void loop() {
  for (int i = 0; i < SAMPLES; i++) {
    microseconds = micros();

    int x, y, z;
    adxl.readAccel(&x, &y, &z);

    vReal[i] = x;                 // Using x-axis data, can choose y or z
    vImag[i] = 0;

    while (micros() < (microseconds + sampling_period_us)) {
      // Wait to maintain sampling rate
    }
  }

  FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);  // Windowing
  FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);                 // Compute FFT
  FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);                   // Compute magnitudes

  for (int i = 0; i < (SAMPLES / 2); i++) {
    Serial.print((i * 1.0 * SAMPLING_FREQUENCY) / SAMPLES, 1);
    Serial.print(" Hz ");
    Serial.println(vReal[i], 1);
  }

  delay(1000); // Delay before next capture
}

@mechbasit50686

For a bandwidth of 850Hz you need to operate the ADXL345 in SPI mode with an output data rate of 3200Hz. However the Uno RAM can only hold maybe 90ms worth of data

You need to sample at the very least twice that frequency, or 1700 Hz. The ADXL345 sample rate options are either 1600 or 3200.

With 2K RAM and 8 bytes/sample (with that code) the Uno R3 can hold at most around 256 samples. Choosing sample rate 1600 Hz (Fmax = 800 Hz), that is about 160 milliseconds of data. Since the FFT requires the data array to be sized in powers of two, it will be 128 samples, or 80 milliseconds of data.

@mechbasit50686 ,

Your two or more topics on the same or similar subject have been merged.

Please do not duplicate your questions as doing so wastes the time and effort of the volunteers trying to help you as they are then answering the same thing in different places.

Please create one topic only for your question and choose the forum category carefully. If you have multiple questions about the same project then please ask your questions in the one topic as the answers to one question provide useful context for the others, and also you won’t have to keep explaining your project repeatedly.

Repeated duplicate posting could result in a temporary or permanent ban from the forum.

Could you take a few moments to Learn How To Use The Forum

It will help you get the best out of the forum in the future.

Thank you.

Surely, you have tested your device an know what the fundamental frequency of the assembly is. That could be done with a stop watch and eyeballing the action.

Thanks for the reply,,

Now I tried this second code, but unable to find the graph ( time domain and freq domain on SERIAL PLOTTER OF IDE)

#include <Wire.h>

#include <Adafruit_Sensor.h> 

#include <Adafruit_ADXL345_U.h>

Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified();

void setup(void) 

{

   Serial.begin(9600);  

   if(!accel.begin())

   {

      Serial.println("No valid sensor found");

      while(1);

   }

}

void loop(void) 

{

   sensors_event_t event; 

   accel.getEvent(&event);

   Serial.print("X: "); Serial.print(event.acceleration.x); Serial.print("  ");

   Serial.print("Y: "); Serial.print(event.acceleration.y); Serial.print("  ");

   Serial.print("Z: "); Serial.print(event.acceleration.z); Serial.print("  ");

   Serial.println("m/s^2 ");

   delay(500);

}

This explains how to use the serial ploter
https://docs.arduino.cc/software/ide-v2/tutorials/ide-v2-serial-plotter/