# Understanding how to use an accelerometer to detect vehicle collisions

Objective: To use an accelerometer to detect where on a vehicle a crash occurred (e.g. impact occurred on the passenger side.).

Parts: Arduino Uno and LSM3030DLHC accelerometer

Background: I've been using the code provided in the reference 1 below and I'm having trouble interfacing with the accelerometer component. At rest, the accelerometer is measuring acceleration along all the axis as close to 0g 0g 1g as possible. By doing some background reading in [2] I've come to the conclusion that I can use the force vector to determine the angle where the impact occurred. I'm not sure if I'm testing the impact incorrectly or what is happening but if I hit the breadboard to the right of the accelerometer, inside the well, it sometimes produced different values on the various axis (see sample output). From the reading in [2] I determined that if I use the magnitude variable and the changes in acceleration along the x and y axis I should be able to determine the angle where an impact occurred but this impact is always around the same value regardless if I hit it at the right of the accelerometer or to the left.

Questions:

1) Is the angle being measured using the magnitude R = sqrt(x^2 + y^2 + z^2) not relative to the x-y axis? So I would like to be able to say that if there is an impact on the right side in the picture then that is a collision on the right passenger side.

2) Why does the accelerometer produce different values along all the axis even though the breadboard would be hit in roughly the same spot? Note, I don't mean that the values are slightly off but rather that they would be negative sometimes and positive at others.

Code Walkthrough: The program begins and the accelerometer is initialized. The impact routine is called every 2ms and it gets the acceleration axis readings and then another axis reading and compares them. If the magnitude exceeds some sensitivity value then there is a successful hit and more data is logged. Otherwise if it doesn't exceed this sensitivity we go back to searching.

#include <Wire.h>
#include <math.h>

byte updateflag;

sensors_event_t event;
sensors_event_t magEvent;

int xaxis = 0, yaxis = 0, zaxis = 0;
int deltx = 0, delty = 0, deltz = 0;
int vibration = 0, magnitude = 0, sensitivity = 0, devibrate = 0;
double angle;
unsigned long time1; //Time when the program started. Used to run impact routine every 2mS.
unsigned long time2;
float impactDirection; //Direction car was traveling prior to impact.

void setup()
{
Wire.begin();
sensitivity=15;
devibrate=75;

Serial.begin(9600);

//Initialize component;
if(!accel.begin())
{

Serial.println("Ooops, no LSM303 detected ... Check your wiring!");
while(1);
}
if(!mag.begin())
{
Serial.println("Ooops, no LSM303 detected ... Check your wiring!");
while(1);
}

time1 = micros();
//Serial.print("time1 = "); Serial.println(time1);
}

void loop()
{
accel.getEvent(&event);
mag.getEvent(&magEvent);

if (micros() - time1 > 1999) Impact();  // call impact routine every 2mS

if(updateflag > 0)
{
updateflag=0;
Serial.print("Impact detected!!\tMagnitude:"); Serial.print(magnitude);
Serial.print("\t Angle:"); Serial.print(angle, 2);
Serial.print("\t Car Direction: "); Serial.print(impactDirection);
Serial.print(" ("); Serial.print(compassDirection(impactDirection)); Serial.println(")");
Serial.println();
}

}

void Impact()
{

/*
//Calibration testing. Accelerometer is calibrated correctly x ~0 y ~0 z ~9.8
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 ");
*/

time1 = micros(); // resets time value

int oldx = xaxis; // local variables store previous axis readings for comparison
int oldy = yaxis;
int oldz = zaxis;

//Serial.print("current time = "); Serial.print(micros()); Serial.print("\toldx = "); Serial.print(oldx); Serial.print("\toldy = "); Serial.print(oldy); Serial.print("\toldz = "); Serial.println(oldz);

vibration--; // loop counter prevents false triggering. Vibration resets if there is an impact. Don't detect new changes until that "time" has passed.
//Serial.print("Vibration = "); Serial.println(vibration);
if(vibration < 0) vibration = 0;
//Serial.println("Vibration Reset!");
//Serial.println("****************************");

xaxis = event.acceleration.x;
yaxis = event.acceleration.y;
zaxis = event.acceleration.z;

//Serial.print("current time = "); Serial.print(micros()); Serial.print("\txaxis = "); Serial.print(xaxis); Serial.print("\tyaxis = "); Serial.print(yaxis); Serial.print("\tzaxis = "); Serial.println(zaxis);
//Serial.println("****************************");

if(vibration > 0) return;

deltx = xaxis - oldx;
delty = yaxis - oldy;
deltz = zaxis - oldz;

magnitude = sqrt(sq(deltx) + sq(delty) + sq(deltz)); //Magnitude to calculate force of impact.

if (magnitude >= sensitivity) //impact detected
{

//Values that caused the impact
Serial.print("Impact Time = "); Serial.print(micros()); Serial.print("\t\tCar Direction = "); Serial.print(getHeading(magEvent)); Serial.print(" "); Serial.println(compassDirection(getHeading(magEvent)));
Serial.print("oldx = "); Serial.print(oldx); Serial.print("\toldy = "); Serial.print(oldy); Serial.print("\toldz = "); Serial.println(oldz);
Serial.print("xaxis = "); Serial.print(xaxis); Serial.print("\tyaxis = "); Serial.print(yaxis); Serial.print("\tzaxis = "); Serial.println(zaxis);
Serial.print("Mag = "); Serial.print(magnitude);
Serial.print("\tdeltx = "); Serial.print(deltx);
Serial.print("\tdelty = "); Serial.print(delty);
Serial.print("\tdeltz = "); Serial.println(deltz);

updateflag=1;

//double X = xaxis - 512; // adjust xaxis reading to +/- 512
//double Y = yaxis - 512; // adjust yaxis reading to +/- 512

double X = acos((double) deltx / magnitude);
double Y = acos((double) delty / magnitude);

Serial.print("X = "); Serial.print(X); Serial.print("Y = "); Serial.println(Y);

Serial.println("****************************");

angle = (atan2(Y,X) * 180)/PI; // use atan2 to calculate angle and convert radians to degrees
angle += 180;

vibration = devibrate;                                      // reset anti-vibration counter
time2 = millis();
}
else
{
//if (magnitude > 15)
//Serial.println(magnitude);
magnitude=0;                                              // reset magnitude of impact to 0
}
}

{
float heading = (atan2(event.magnetic.y,event.magnetic.x) * 180) / PI;

}

{
int val = (int) ((heading / 22.5) + .5);
String arr [] = {"N","NNE","NE","ENE","E","ESE", "SE", "SSE","S","SSW","SW","WSW","W","WNW","NW","NNW"};

return arr[(val % 16)];
}


Output:

Impact Time = 1988808 Car Direction = 55.69 NE oldx = 0 oldy = 0 oldz = 9 xaxis = -2 yaxis = 13 zaxis = -20 Mag = 31 deltx = -2 delty = 13 deltz = -29 X = 1.64Y = 1.14 **************************** Impact detected!! Magnitude:31 Angle:214.83 Car Direction: 55.69 (NE)

Impact Time = 5076556 Car Direction = 56.86 ENE oldx = 0 oldy = 0 oldz = 9 xaxis = 13 yaxis = 0 zaxis = -13 Mag = 25 deltx = 13 delty = 0 deltz = -22 X = 1.02Y = 1.57 **************************** Impact detected!! Magnitude:25 Angle:236.90 Car Direction: 56.86 (ENE)

Impact Time = 8273600 Car Direction = 57.63 ENE oldx = 0 oldy = 0 oldz = 9 xaxis = -1 yaxis = 11 zaxis = -20 Mag = 31 deltx = -1 delty = 11 deltz = -29 X = 1.60Y = 1.21 **************************** Impact detected!! Magnitude:31 Angle:217.00 Car Direction: 57.63 (ENE)

Impact Time = 12727924 Car Direction = 57.27 ENE oldx = 0 oldy = 0 oldz = 9 xaxis = -3 yaxis = 10 zaxis = -17 Mag = 28 deltx = -3 delty = 10 deltz = -26 X = 1.68Y = 1.21 **************************** Impact detected!! Magnitude:28 Angle:215.69 Car Direction: 57.27 (ENE)

Impact Time = 14347336 Car Direction = 57.15 ENE oldx = 0 oldy = 0 oldz = 9 xaxis = 16 yaxis = 2 zaxis = -19 Mag = 32 deltx = 16 delty = 2 deltz = -28 X = 1.05Y = 1.51 **************************** Impact detected!! Magnitude:32 Angle:235.23 Car Direction: 57.15 (ENE)

Impact Time = 15695684 Car Direction = 57.20 ENE oldx = 0 oldy = 0 oldz = 9 xaxis = 1 yaxis = 4 zaxis = -8 Mag = 17 deltx = 1 delty = 4 deltz = -17 X = 1.51Y = 1.33 **************************** Impact detected!! Magnitude:17 Angle:221.41 Car Direction: 57.20 (ENE)

Impact Time = 17879680 Car Direction = 57.27 ENE oldx = 0 oldy = 0 oldz = 9 xaxis = 14 yaxis = 7 zaxis = -18 Mag = 31 deltx = 14 delty = 7 deltz = -27 X = 1.10Y = 1.34 **************************** Impact detected!! Magnitude:31 Angle:230.62 Car Direction: 57.27 (ENE)

Impact Time = 19149812 Car Direction = 57.08 ENE oldx = 12 oldy = 1 oldz = -10 xaxis = 2 yaxis = -3 zaxis = 5 Mag = 18 deltx = -10 delty = -4 deltz = 15 X = 2.16Y = 1.79 **************************** Impact detected!! Magnitude:18 Angle:219.73 Car Direction: 57.08 (ENE)

Impact Time = 23040448 Car Direction = 56.63 ENE oldx = 0 oldy = 0 oldz = 9 xaxis = 2 yaxis = 10 zaxis = -14 Mag = 25 deltx = 2 delty = 10 deltz = -23 X = 1.49Y = 1.16 **************************** Impact detected!! Magnitude:25 Angle:217.87 Car Direction: 56.63 (ENE)

Impact Time = 25968304 Car Direction = 57.11 ENE oldx = 0 oldy = 0 oldz = 9 xaxis = 0 yaxis = 5 zaxis = -7 Mag = 16 deltx = 0 delty = 5 deltz = -16 X = 1.57Y = 1.25 **************************** Impact detected!! Magnitude:16 Angle:218.58 Car Direction: 57.11 (ENE)