Measuring Vibration using BNO055 accelerometer.

Hello! I've been working on a project to measure the vibration (Hz) using a BNO055 accelerometer. So far, I was able to measure the acceleration in x, y, and z. I'm also able to plot the vibration in the "Serial Plotter". The last step is to find the frequency of vibration. I've been trying at it for two days now, but I'm still not able to find the right set of codes to obtain it. I've come to the conclusion that there are three possible ways to find it. However, I didn't know how to implement any of them. The three methods are:

Using Fast Fourier Transformation (FFT).
Finding all the local maximum then finding the average period between two peaks. (doesn't seem
practical)
Finally, using some of the Frequency libraries Arduino offers such as FreqCount... etc.

I would truly appreciate the help.
Please find code below.

Thank you!

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>

Adafruit_BNO055 bno = Adafruit_BNO055();

void setup(void)
{
Serial.begin(115200);
Serial.println("Orientation Sensor Raw Data Test"); Serial.println("");

/* Initialise the sensor /
if (!bno.begin())
{
/
There was a problem detecting the BNO055 ... check your connections */
Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
while (1);
}

delay(1000);
Serial.println("Calibration status values: 0=uncalibrated, 3=fully calibrated");
}

void loop(void)
{
/* Display calibration status for each sensor. */
uint8_t system, gyro, accel, mag = 0;
bno.getCalibration(&system, &gyro, &accel, &mag);
Serial.print("CALIBRATION: Sys=");
Serial.print(system, DEC);
Serial.print(" Gyro=");
Serial.print(gyro, DEC);
Serial.print(" Accel=");
Serial.print(accel, DEC);
Serial.print(" Mag=");
Serial.println(mag, DEC);

imu::Vector<3> euler = bno.getVector(Adafruit_BNO055::VECTOR_LINEARACCEL);
/* Display the floating point data */
Serial.print("X: ");
Serial.print(euler.x());
Serial.print(" Y: ");
Serial.print(euler.y());
Serial.print(" Z: ");
Serial.print(euler.z());
Serial.print("\t\t");
}

fsalloum:
Hello! I've been working on a project to measure the vibration (Hz) using a BNO055 accelerometer. So far, I was able to measure the acceleration in x, y, and z. I'm also able to plot the vibration in the "Serial Plotter". The last step is to find the frequency of vibration. I've been trying at it for two days now, but I'm still not able to find the right set of codes to obtain it. I've come to the conclusion that there are three possible ways to find it. However, I didn't know how to implement any of them. The three methods are:

Using Fast Fourier Transformation (FFT).
Finding all the local maximum then finding the average period between two peaks. (doesn't seem
practical)
Finally, using some of the Frequency libraries Arduino offers such as FreqCount... etc.

I would truly appreciate the help.
Please find code below.

Thank you!

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>

Adafruit_BNO055 bno = Adafruit_BNO055();

void setup(void)
{
Serial.begin(115200);
Serial.println("Orientation Sensor Raw Data Test"); Serial.println("");

/* Initialise the sensor /
if (!bno.begin())
{
/
There was a problem detecting the BNO055 ... check your connections */
Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
while (1);
}

delay(1000);
Serial.println("Calibration status values: 0=uncalibrated, 3=fully calibrated");
}

void loop(void)
{
/* Display calibration status for each sensor. */
uint8_t system, gyro, accel, mag = 0;
bno.getCalibration(&system, &gyro, &accel, &mag);
Serial.print("CALIBRATION: Sys=");
Serial.print(system, DEC);
Serial.print(" Gyro=");
Serial.print(gyro, DEC);
Serial.print(" Accel=");
Serial.print(accel, DEC);
Serial.print(" Mag=");
Serial.println(mag, DEC);

imu::Vector<3> euler = bno.getVector(Adafruit_BNO055::VECTOR_LINEARACCEL);
/* Display the floating point data */
Serial.print("X: ");
Serial.print(euler.x());
Serial.print(" Y: ");
Serial.print(euler.y());
Serial.print(" Z: ");
Serial.print(euler.z());
Serial.print("\t\t");
}

If I understand your project, you want to find a frequency, but you have given no time stamp to the values you are printing. So, there is no way to find a frequency.

In addition, you need to determine if there is "A" frequency of vibration, or "many" frequencies of vibration.

Paul

Oh I apologize, I was deleting unnecessary lines at the end of the code before I posted it and accidentally deleted delay(100). I've tried working the code by finding the time from each peak to the other. It doesn't work very well, but I think it's written in an understandable way. I'll attach it anyways. I would truly appreciate your opinion.

Also do you think FFT would work better? The thing is, I read about it a lot but didn't understand how to implement it to a set of data. I truly appreciate your reply.

Thank you!

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>

#define BUFFER_SIZE 10
#define DELAY 100
#define THRESH 5

Adafruit_BNO055 bno = Adafruit_BNO055();

double ys[BUFFER_SIZE];
int index = 0;
bool cycled = false;

double avgFreq(double ys[])
{
int prev_crest = -1;
int curr_crest = -1;
// i1,i2,i3 are the index of the unique value
int i1 = -1;
int i2 = -1;
int i3 = -1;
// y1,y2,y3 are the previous 3 unique values
double y1 = 0;
double y2 = 0;
double y3 = 0;

// accumulater for average
double sum = 0;
int count = 0;

for (int i = 0; i < BUFFER_SIZE; i++) {
// if current (ys) is a crest,
if (i1 == -1 || ys != y3) {

  • // found a unique value, update set of unique values (y1, y2, y3)*
  • y1 = y2;*
  • y2 = y3;*
    _ y3 = ys*;_
    _
    i1 = i2;_
    _
    i2 = i3;_
    _
    i3 = i;_
    _
    }_
    _
    // if y2 is a crest*_
    * if (i1 != -1 && y2 > y1 && y2 > y3) {*
    * prev_crest = curr_crest;
    curr_crest = i2; // i is the crest, as an index on ys array (100ms delay between them)
    _
    }_
    _
    // if crests are valid, add to accumulater*_
    * if (prev_crest != -1) {
    double dt = (curr_crest - prev_crest) * DELAY;
    _
    sum = sum + dt;_
    _
    count++;_
    _
    }_
    _
    }_
    _
    double avgPeriod = (sum / count);_
    _
    double avgFreq = 1.0/avgPeriod;_
    _
    return avgFreq;_
    _
    }_
    void setup(void)
    _
    {_
    _
    Serial.begin(115200);_
    _
    Serial.println("Orientation Sensor Raw Data Test"); Serial.println("");_
    _ / Initialise the sensor /_
    _
    if (!bno.begin())_
    _
    {_
    _ / There was a problem detecting the BNO055 ... check your connections /_
    _
    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");_
    _
    while (1);_
    _
    }_
    _
    delay(100);_
    _
    // Serial.println("Calibration status values: 0=uncalibrated, 3=fully calibrated");_
    _
    }_
    void loop(void)
    _
    {_
    _ / Display calibration status for each sensor. /_
    uint8_t system, gyro, accel, mag = 0;
    _
    bno.getCalibration(&system, &gyro, &accel, &mag);_
    _
    // Serial.print("CALIBRATION: Sys=");_
    _
    // Serial.print(system, DEC);_
    _
    // Serial.print(" Gyro=");_
    _
    // Serial.print(gyro, DEC);_
    _
    // Serial.print(" Accel=");_
    _
    // Serial.print(accel, DEC);_
    _
    // Serial.print(" Mag=");_
    _
    // Serial.println(mag, DEC);_
    _
    // Possible vector values can be:_
    // - VECTOR_ACCELEROMETER - m/s^2*

    * // - VECTOR_MAGNETOMETER - uT*
    * // - VECTOR_GYROSCOPE - rad/s*
    * // - VECTOR_EULER - degrees*
    * // - VECTOR_LINEARACCEL - m/s^2*
    * // - VECTOR_GRAVITY - m/s^2*
    * imu::Vector<3> euler = bno.getVector(Adafruit_BNO055::VECTOR_LINEARACCEL);
    _ / Display the floating point data /_
    _
    // Serial.print("X: ");_
    _
    // Serial.print(euler.x());_
    _
    // Serial.print(" Z: ");_
    _
    // Serial.print(euler.z());_
    _
    // Serial.print(" Y: ");_
    _
    // Serial.print(euler.y());_
    _
    // Serial.print("\t\t");_
    _
    ys[index] = euler.y();_
    _
    index++;_
    if (index >= BUFFER_SIZE) {
    _
    // wrap around round-robin manner*_
    * index = 0;*
    * cycled = true;*
    * }*
    * double sumYs = 0;*
    * for (int i = 0; i < BUFFER_SIZE; i++) {
    _ sumYs = sumYs + abs(ys);
    }
    if (cycled && sumYs > THRESH) {
    Serial.print(" Average Frequency = ");
    Serial.print(avgFreq(ys));
    Serial.println("\t\t");
    }
    delay(DELAY);
    }*_

I looked at Arduino FFT example and that should work for you. You will need to do a lot more work on your program logic to implement it.

Paul