Go Down

Topic: 50-250 Hz Vibration measurement with ADXL345 (Read 8771 times) previous topic - next topic

Jabberwox

Dear all,

I m trying to set up a vibration measurement with arduino and an adxl345. I m using I2C for accessing the accelerometer and i have connected a serial data logger do capture whatever is printed through the serial port of the arduino. The code i used is from the code that came with the adafruit library.

Now the frequencies i want to measure are probably between 50-250 Hz and measurement time is up to 1 minute maximum.  The sampling rate on the acceleration can go up to quite high frequencies but it seems that the serial print function slows things down. In fact, the fastest i could print out through serial with this option was around 200 Hz.

So my idea is to buffer 50 samples or so in the SRAM and send out the bunch at once. Do you think this would increase the speed at least to 500 Hz? How would i code this?



Code: [Select]


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

/* Assign a unique ID to this sensor at the same time */
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);

int timestamp = 0;


void setup(void)
{
  Serial.begin(115200);
  Serial.println("Accelerometer Test"); Serial.println("");
 
  /* Initialise the sensor */
  if(!accel.begin())
  {
    /* There was a problem detecting the ADXL345 ... check your connections */
    Serial.println("Ooops, no ADXL345 detected ... Check your wiring!");
    while(1);
  }

  /* Set the range to whatever is appropriate for your project */
  accel.setRange(ADXL345_RANGE_8_G);
  // displaySetRange(ADXL345_RANGE_8_G);
  // displaySetRange(ADXL345_RANGE_4_G);
  // displaySetRange(ADXL345_RANGE_2_G);
 
  accel.setDataRate(ADXL345_DATARATE_800_HZ);

 
  /* Display some basic information on this sensor */
  displaySensorDetails();
 
  /* Display additional settings (outside the scope of sensor_t) */
  displayDataRate();
  displayRange();
  Serial.println("");
}

void loop(void)
{
  /* Get a new sensor event */
  sensors_event_t event;
  accel.getEvent(&event);
  timestamp = timestamp++;

    /* Display the results (acceleration is measured in m/s^2) */
 
    Serial.print("Timestamp:"); Serial.print(timestamp);
    Serial.print(" X: "); Serial.println(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(1);
}

wildbill

Save the data in arrays or a single array of struct. Use one for loop to read it, a second to print it. That'll certainly get you a higher sample rate if serial was slowing you down (quite likely). Whether it's fast enough you can easily find by trying it out  ;) 

Jabberwox

#2
Feb 09, 2015, 04:15 pm Last Edit: Feb 09, 2015, 04:17 pm by Jabberwox
Thanks for the help! So i programmed two for-loops. One is filling an array with the data while another one sends it out through serial.

Still the sample rate on my output is too low (no wonder i guess since both loops run in the same main loop). So do I have to run two loops independently but at the same time? Dont i loose samples if i do that? It seems that i am also struggling with how to send out the data as a bunch and not as multiple serial prints :/ Any suggestions?



Code: [Select]

/* Assign a unique ID to this sensor at the same time */
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);

struct measure
{
    int timestamp;
    float x;  // ACC in x direction
    float y;  //ACC in y direction
    float z;  //ACC in z direction
};

struct measure measurements[49];

int timestamp = 0;

...

void setup(void)
{
  Serial.begin(115200);
...

}

void loop(void)
{
  /* Feeding the array with data*/

  for (int i = 0; i < 50; i++)
  {
   sensors_event_t event;
   accel.getEvent(&event);
   measurements[i].timestamp = timestamp++;
   measurements[i].x  = event.acceleration.x;
   measurements[i].y  = event.acceleration.y;
   measurements[i].z  = event.acceleration.z;
  }

  /* Sending the array with data through serial*/
  for (int i = 0; i < 50; i++)
  {
   Serial.print(measurements[i].timestamp);
   Serial.print(" X: ");
   Serial.print(measurements[i].x);
   Serial.print(" Y: ");
   Serial.print(measurements[i].y);
   Serial.print(" Z: ");
   Serial.println(measurements[i].z);
  }

 delay(1);
}


wildbill

Oops. Serial is killing you and buffering isn't going to help if you want to run this for a minute of sampling - you would need far far more RAM than any arduino has although you might get close with a Due if you could compress the data a bit.

Is the actual sampling fast enough? Print millis before and after your collection loop. If that's too slow any other efforts will be fruitless without better hardware.

You're emitting ~50 characters per set of readings. If you want 500Hz, that's 25K cps. 115200 baud will only give you ~11K.  You can improve matters by getting rid of all the fluff in your output. No need for identifiers, just put a comma between each field.

Some folks have reported getting higher baud rates to work. IIRC, I've seen 300K mentioned. Perhaps between cranking up the speed and reducing the superfluous data going out, you might get closer. Drop the buffering though - it's useless.

Jabberwox

Thanks again :)

So i printed the millis as recommended and it takes on average 90ms to take 50 samples. So roughly a frequency of 550 Hz for the acquisition which is ok for me.

I cranked up the Baudrate to 230400 and used , for delimitation. The sampling frequency with the buffer is now at 290 Hz while, strangely, if i use the original code (meaning Serial.print ing the (event.acceleration.x) directly), i get 230 Hz on average.

Argh i just bugs me that its already so close. I think i will do my measurements with this for testing and eventually switch to a faster platform :) If there is any other recommendation for improving the code more so that i get slightly faster let me know!

wildbill

That delay(1) can't be helping and it makes things worse in the original version.

PabloCardenas

Jabberwox

Hi, you have the connection scheme and final code of this project. I try a similar project for the college and I think that your project would serve me like a guide.


MarkT

Sending just CSV's without the " X: " padding will help a lot, and the ultimate in serial throughput
would be binary, buts that's probably harder to parse.

CSV = comma-separate-values:

23,65,194
-56,123,545

etc
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

iborg

That'll certainly get you a higher sample rate if serial was slowing you down (quite likely). Whether it's fast enough you can easily find by trying it out  ;) 
Thank you wildbill,  your comment here about serial slowing you down solved my problem of pulse counting failing around 50Hz.  I was using serial.print to track where the loop was upto. Taking the prints out made it work.

Philip

Go Up