Getting Maximum Acceleration Values from Accelerometer

Hi!

I’m completly new at the Arduino platform and at programing.

I am trying to measure the maximum acceleration of a punching bag using an accelerometer (ADXL 345); but while i can read the raw values of it, I can’t figure out how to get the program to give me the maximum acceleration values of an impact.

I would be really greatfull if anyone could give some insight on the question.

This is the sample code I’m using:

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

int highest_accel = 0;
int current_accel = 0;

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

void displaySensorDetails(void)
{
  sensor_t sensor;
  accel.getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" m/s^2");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" m/s^2");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" m/s^2");  
  Serial.println("------------------------------------");
  Serial.println("");
  delay(500);
}

void displayDataRate(void)
{
  Serial.print  ("Data Rate:    "); 
  
  switch(accel.getDataRate())
  {
    case ADXL345_DATARATE_3200_HZ:
      Serial.print  ("3200 "); 
      break;
    case ADXL345_DATARATE_1600_HZ:
      Serial.print  ("1600 "); 
      break;
    case ADXL345_DATARATE_800_HZ:
      Serial.print  ("800 "); 
      break;
    case ADXL345_DATARATE_400_HZ:
      Serial.print  ("400 "); 
      break;
    case ADXL345_DATARATE_200_HZ:
      Serial.print  ("200 "); 
      break;
    case ADXL345_DATARATE_100_HZ:
      Serial.print  ("100 "); 
      break;
    case ADXL345_DATARATE_50_HZ:
      Serial.print  ("50 "); 
      break;
    case ADXL345_DATARATE_25_HZ:
      Serial.print  ("25 "); 
      break;
    case ADXL345_DATARATE_12_5_HZ:
      Serial.print  ("12.5 "); 
      break;
    case ADXL345_DATARATE_6_25HZ:
      Serial.print  ("6.25 "); 
      break;
    case ADXL345_DATARATE_3_13_HZ:
      Serial.print  ("3.13 "); 
      break;
    case ADXL345_DATARATE_1_56_HZ:
      Serial.print  ("1.56 "); 
      break;
    case ADXL345_DATARATE_0_78_HZ:
      Serial.print  ("0.78 "); 
      break;
    case ADXL345_DATARATE_0_39_HZ:
      Serial.print  ("0.39 "); 
      break;
    case ADXL345_DATARATE_0_20_HZ:
      Serial.print  ("0.20 "); 
      break;
    case ADXL345_DATARATE_0_10_HZ:
      Serial.print  ("0.10 "); 
      break;
    default:
      Serial.print  ("???? "); 
      break;
  }  
  Serial.println(" Hz");  
}

void displayRange(void)
{
  Serial.print  ("Range:         +/- "); 
  
  switch(accel.getRange())
  {
    case ADXL345_RANGE_16_G:
      Serial.print  ("16 "); 
      break;
    case ADXL345_RANGE_8_G:
      Serial.print  ("8 "); 
      break;
    case ADXL345_RANGE_4_G:
      Serial.print  ("4 "); 
      break;
    case ADXL345_RANGE_2_G:
      Serial.print  ("2 "); 
      break;
    default:
      Serial.print  ("?? "); 
      break;
  }  
  Serial.println(" g");  
}

void setup(void) 
{
#ifndef ESP8266
  while (!Serial); // for Leonardo/Micro/Zero
#endif
  Serial.begin(9600);
  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_16_G);
  // displaySetRange(ADXL345_RANGE_8_G);
  // displaySetRange(ADXL345_RANGE_4_G);
  // displaySetRange(ADXL345_RANGE_2_G);
  
  /* 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);
 
  /* Display the results (acceleration is measured in m/s^2) */
  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);
}

If I were to read you a list of numbers, how would you be able to tell me the value of the largest number?

I can't figure out how to get the program to give me the maximum acceleration values of an impact.

Set a variable, lets call it maxAccel to zero. Each time you read an acceleration compare it with maxAccel and if the new value us larger then set maxAccel to the new value. Repeat as many times as you like or for a period then print maxAccel and reset it back to zero.

If the acceleration can be positive or negative then you can either use the abs() value of acceleration or keep max pos and neg values.

Ok!

so, i declared:

int max_accel = 0;
int current_accel = 0;

and then, in the loop:

int x,y,z;
adxl.readXYZ(&x, &y, &z); //read the accelerometer values and store them in variables x,y,z

//Determine max accel
current_accel = (z);
if (current_accel > max_accel)
{
max_accel = current_accel;
}

// Output x,y,z values
Serial.print("Max Accel: ");

Serial.println(max_accel);

It seems to be working.

Thanks guys! :slight_smile:

At some point, you need to determine when to reset max_accel to 0.

Yes!

For that i was thinking of hitting the reset switch :roll_eyes:

But now i'm thinking that would be nice to start the reading at "0" (calibrating the sensor). I don't know if that's possible.

I'm a real noob (only got the arduino yesterday) :sweat_smile:

For that i was thinking of hitting the reset switch

That's a bit extreme and you can do better.
As I said in post #2 there are choices as to how and when you reset the max value.

Would you rather have it reset by a button (NOT reset), after a period of time (how long ?) or after a number of readings have been taken (how many ?). Which would you prefer or would you like a combination perhaps ?

i'm thinking that would be nice to start the reading at "0" (calibrating the sensor)

I am not sure what you mean by this. Can you please expand on your idea ?

Well, the main ideia is to attach the sensor to a punching bag or a Makiwara board, to measure the power of impacts.

So, the display should start at zero, and only give the final impact value.

You're right, calibrating the sensor would be extreme, i will try to implement the "tap trigger" of the sensor to start the reading; and maybe reset the reading after a period of time!

Thanks for the feedback :slight_smile:

So, the display should start at zero, and only give the final impact value.

At the end of a second? At the end of a minute? An hour? A day? A week? Just before the Arduino wears out? WHAT defines that a value is final?

maybe reset the reading after a period of time!

If you do this do not be tempted to use the delay() function to provide the timing as while it is executing nothing else can happen and that includes reading sensors.

Have a look at the BlinkWithoutDelay example and Several things at the same time to see how to use millis() for timing without stopping the program dead in its tracks.

After burning my brains for a few hours, i was able to set the "Activity trigger" from the sensor; so i put the previous statments inside that trigger and, it works preety well :slight_smile:

void loop(){

byte interrupts = adxl.getInterruptSource(); //Habilitar trigger

//Trigger de atividade
if(adxl.triggered(interrupts, ADXL345_ACTIVITY)){

//read the accelerometer values and store them in variables x,y,z
int x,y,z;
adxl.readXYZ(&x, &y, &z);

//Determinar a aceleração máxima no eixo X
current_accel = (x);
if (current_accel > max_accel)
{
max_accel = current_accel;
}

Serial.print("Max Accel: "); //Imprimir titulo

Serial.println(max_accel); //Imprime a aceleração máxima

}

So, each time i hit the sensor, it prints the maximum value of that hit!

Still got to work on the reset function :sweat_smile:

Thanks for the tips, wouldn't have got so far without your help!!