# Accelerometer data smoothing filtering pothole detection

I wanted to start a separate thread concentrating on smoothing filtering and detecting bumps and potholes with an Arduino and my Accelerometer. I'm using an Analog Accelerometer set to 50HZ bandwidth sampling at 100HZ. I'm plotting data with MegunoLink (GREAT tool BTW). My delemma is that the accelerometer readings are noisy as hell, especially in a car with the engine running and road noise. What would be the best way to filter out the noise? I'm sampling at 100HZ I'm not sure how to implement at filter that wont affect the sampling rate... Also, I'm not sure if 100HZ is enough to sample at, it seems to catch the bump events pretty well though (graphs posted).

Accelerometer is a KXPS5-3157

I converted the accelerometer output to Gforce, should I be using Gforce, or should I use raw voltage or it doesn't matter for potholes application

Here is my code so far:

    #include <GraphSeries.h>

GraphSeries g_aGraphs[] = {"Z"}; //Z acceleration graph label for Meguno

// GLOBALS

long previousMillis = 0;
long interval = 10; // interval in milliseconds (10ms => 100Hz)
int data = 0;

//CALIBRATION DATA FOR ACCELEROMETER
float one_G = 647.0; // OFFSET OF 1G Z axis
float neg_G = 372.0; // OFFSET OF -1G Z axis
// Our ZERO G Reference should be in the middle of these two readings
float mZ = (one_G + neg_G) / 2.0; // ZERO_G REFERENCE FOR Z AXIS
// Estimate Z axis specific sensitivity difference of 2G between readings
float senZ = (one_G - neg_G) / 2.0;
float sensitivity = 440.0; // FROM DATASHEET TYPICAL SENSIVITIY 440mV/G

void setup()
{
// The data is sent via the serial port. Initialize it.
Serial.begin(115200);
analogReference(EXTERNAL); // ACCELEROMETER IS 3.3VOLT
}

void loop()
{

}

{
unsigned long currentMillis = millis();
if((currentMillis - previousMillis) > interval) {
previousMillis = currentMillis;

// Read values from the ADC converter and send them out the serial port.

//float GForceG = ((float)data - mZ) / senZ; // Convert ADC value to G force with gravity
float GForce = ((float)data - (one_G)) / senZ; // ZERO BASE WITHOUT GRAVITY

g_aGraphs[0].SendData(GForce); // SEND Z AXIS G FORCE
}
}


I have two graphs at approximately 25 MPH the pothole event is obvious, then there was a subtle bump afterwards The other graph is the same data, but zoomed in slightly

I'm not sure how to detect the actual pothole event, if I could use FFT, standard Deviation threshold, running average?

Any advice, suggestions, input, wisdom is greatly appreciated!

EDIT

I adjusted the sampling rate and lowered the LPF on the accelerometer to 15HZ. I have obtained better data, I see the negative and postive peaks in a pothole, it seems to oscillate and dampen with time making a "beat" type pattern. I wonder how the pattern could be programmatic ally found?

I know the derivative of acceleration would be "jerk" I'm wondering if the pothole data could be recognized by a series of decrementing jerks? The pattern is also negative though too, there has to be a signature to search for to find the pothole and count it. The only time there will be negative G's in the Z axis of a car is if the tire goes into a hole, or the car is airborne for a brief moment and hits the ground, so a negative "jerk" would be a good signature right?

Here is the RAW DATA for 1 SECOND window of hitting a pothole

Seems maybe my Z axis is upside down O.o? lol

DATA was collected using only the 25HZ RC LPF on the end of the accelerometer Z-axis output no software filtering

RAW DATA FOR PICTURE BELOW:

    ZACCEL,TIME,GFORCE

Z,0.01,-0.01
Z,0.02,0.02
Z,0.03,0.06
Z,0.04,0.02
Z,0.05,0.04
Z,0.06,0.09
Z,0.07,0.07
Z,0.08,0.00
Z,0.09,-0.10
Z,0.10,-0.04
Z,0.11,-0.03
Z,0.12,-0.05
Z,0.13,-0.13
Z,0.14,-0.12
Z,0.15,-0.19
Z,0.16,-0.16
Z,0.17,-0.09
Z,0.18,-0.17
Z,0.19,-0.18
Z,0.20,0.04
Z,0.21,0.20
Z,0.22,0.04
Z,0.23,-0.12
Z,0.24,-0.25
Z,0.25,-0.15
Z,0.26,-0.17
Z,0.27,0.03
Z,0.28,0.08
Z,0.29,-0.09
Z,0.30,-0.26
Z,0.31,-0.30
Z,0.32,-0.04
Z,0.33,0.20
Z,0.34,0.36
Z,0.35,0.04
Z,0.36,-0.20
Z,0.37,-0.38
Z,0.38,-0.40
Z,0.39,-0.25
Z,0.40,-0.17
Z,0.41,0.40
Z,0.42,0.93
Z,0.43,0.69
Z,0.44,0.01
Z,0.45,-0.17
Z,0.46,-0.42
Z,0.47,-0.54
Z,0.48,-0.21
Z,0.49,0.22
Z,0.50,0.83
Z,0.51,0.65
Z,0.52,0.18
Z,0.53,-0.15
Z,0.54,-0.12
Z,0.55,-0.25
Z,0.56,-0.49
Z,0.57,0.01
Z,0.58,-0.04
Z,0.59,0.37
Z,0.60,0.36
Z,0.61,-0.29
Z,0.62,-0.27
Z,0.63,0.04
Z,0.64,0.06
Z,0.65,-0.09
Z,0.66,-0.04
Z,0.67,0.01
Z,0.68,0.01
Z,0.69,0.28
Z,0.70,-0.08
Z,0.71,-0.18
Z,0.72,-0.11
Z,0.73,-0.10
Z,0.74,0.11
Z,0.75,0.15
Z,0.76,0.01
Z,0.77,-0.11
Z,0.78,-0.33
Z,0.79,-0.14
Z,0.80,0.12
Z,0.81,0.04
Z,0.82,0.01
Z,0.83,0.17
Z,0.84,0.09
Z,0.85,-0.02
Z,0.86,-0.07
Z,0.87,-0.04
Z,0.88,0.04
Z,0.89,0.04
Z,0.90,0.02
Z,0.91,0.09
Z,0.92,0.05
Z,0.93,-0.01
Z,0.94,0.01
Z,0.95,0.01
Z,0.96,-0.07
Z,0.97,0.07
Z,0.98,0.08
Z,0.99,0.12
Z,1.00,0.01


RAW PICTURE:

EXCEL version:

FFT on this seems to peak energy @ 12.5HZ, Would this be a good frequency to filter for?:

HERE IS RAW DATA FOR driving at constant speed, hitting about 6 to 9 potholes and some rough patches in the road:

• You've said what features you'd like to filter out of your data. Equally important, what are the features you want to keep? What will you do with the data after you remove the road noise and pothole aritfacts? – The Photon Jan 27 '13 at 5:37
• @The Photon I want to be able to detect pothole and bump events from the noise while the system is continuously running. Rough road events from smooth road noise basically I'm making a pothole detector that will get potholes, bumps, etc and grade how severe they are on a map GPS road map for example that you are traveling on. I guess how "Severe" they are would be on a subjected scale of somesort to the driver/passenger – zacharoni16 Jan 27 '13 at 5:40
• OK. Then another question: What are other features in the data that you don't want to detect as potholes? For example, turning into a driveway and going over a curb? Stopping abruptly at a stoplight? Railroad tracks? Going over the crown of a cross-street? How do these events appear in your data and how are they different from potholes? I'm not going to be able to give you an answer to your question, but I hope these questions will help you get to an answer. – The Photon Jan 27 '13 at 5:53
• If you want to retrieve 50Hz worth of signal, you really would need more than 100Hz sampling rate (as I've already explained in your other question). Also, the ADC itself is usually noisy in the last one or two bits depending on how good the supply and pcb are. Shorting the adc input to ground and plotting it will tell how many bits are fluctuating. It is worthwhile to either discard these bits or oversample and average to reduce the conversion noise. Also, a low pass filter at 1KHz or so at the ADC input can help discard higher frequency noise. That's often called an anti aliasing fiter. – Chintalagiri Shashank Jan 27 '13 at 7:27
• Also, what do the other axes look like around the pothole event? Is there a noticeable bump in the Y axis corresponding with hitting an object head on and slowing acceleration for a brief moment? I think you're concentrating too hard on trying to make your Z axis graph look like the physical representation of what happens to a car when it hits a pothole (wheel goes down and up with a fast rise time).. but ignoring other useful data that could be correlated with it for a more complete answer. – Toby Lawrence Jan 27 '13 at 14:16

You are not going to be able to distinguish potholes clearly from other short peak events apart from being able to distinguish between a rising bump in the road and a hole (the intial direction will be opposite) but you can certainly capture them quite easily.
Determine an initial direction (e.g. negative/positive XYZ depending on how your device is mounted), a threshold level, and a maximum time the reading should be over this level (determined by width of pothole) Then time the peak height/width and see if it fits your pothole characteristic.
The device already contains an internal 1kHz LPF, so you could add a HPF of say 50-200Hz for the potholes, since they will have a fast risetime. I'm not an expert on car vibration frequencies, but you will probably get some noise from vibration however you filter. However that's not an issue as long as the pot hole event is large in comparison with the noise - it looks like the data is okay as it is, I would just sample a bit faster to prevent aliasing (e.g. >2kHz) or add a LPF to the existing internal one as described in the datasheet. Since you are trying to capture fast risetime events, I'd go with the former (faster sampling, possibly with HPF)

To compensate for a change in inclination, you can have a running average value which can be used to zero the axis out (one for each axis). Also, note that a HPF will ignore the DC level, so (as long as it doesn't go off the end of the scale) a slow gradient will make no difference.

According to the datasheet (bottom of page 7 in the link above), the formula for the external capacitance is:

$C2 = C3 = C4 = \dfrac{4.97 \times 10^{-6}}{f_{BW}}$

$\dfrac{4.97 \times 10^{-6}}{10Hz} = 497nF$ is correct.

• I set the sample rate to 2KHZ now, I added 0.1uF capacitor on the Z input to obtain 50HZ on the accelerometer according to the datasheet, is that bandwidth or changing the rolloff of the internal LPF to 50HZ? if the internal LPF is 1000HZ it will refect frequencies over 1000HZ right? I don't get how to add the 50-200Hz HPF filter would I have to design one and feed the Z axis into it before it goes to the microcontroller kanga.gerbilator.org/Sensors/Accelerometers/… about sensor bandwidth, should I be using 500HZ or the 50HZ I been usi – zacharoni16 Jan 27 '13 at 16:45
• Adding the external cap will reduce the roll off of the LPF to 50Hz, so that's your bandwidth. Remove this if you want to see signals >50Hz. If you leave the cap out, signals above 1kHz will be attenuated/rejected, yes. – Oli Glaser Jan 27 '13 at 16:52
• So to change the roll off to 10HZ as Olin suggested, would I leave the capacitor in and then design a filter with 10HZ rolloff with the Z axis output feeding into it then into the Arduino? – zacharoni16 Jan 27 '13 at 16:55
• I think @Olin is suggesting the opposite, to LPF down to 10Hz, so in this case you would use the capacitor or do it digitally. I would forget the cap and filter digitally. My suggestion is to look for the large/fast intial risetime of a pothole event, Olin's seems to be to look for the entire event, which does have the benefit of getting rid of most of the noise, although may make it harder to distinguish potholes from e.g. a sharp turn or dip in the road. If you filter digitally, it would be easy to try both ways and see which works for you best. – Oli Glaser Jan 27 '13 at 17:01
• ah thank you In my set up, gravity is always working on the accelerometer and I subtracted its value with an offset to "zero" the accelerometer, however I just discovered if you're driving on slopes and hilly terrain gravity will be split between two axises.... Is there a way to compensate for the uneven terrain to correct the G offset of driving up a hill? – zacharoni16 Jan 27 '13 at 17:21

It looks like all you need is some low pass filtering to give you a better signal to noise ratio. I would sample as fast as I could otherwise get away with in the micro. 100 Hz (every 10 ms) sounds pretty slow, but even so, you seem to be getting useful data.

The raw data has a lot of sample to sample noise. However, you know that going over a pothole is a much lower frequency event. Apply a 2-3 poles of low pass filtering wih a rolloff of maybe 10 Hz and see what that looks like. Unfortunately you are only sampling 5x faster than the minimum to support 10 Hz, so again, I'd make that faster. I'd probably start out sampling every ms, then apply the low pass filtering. That gives a lot more dynamic range for the 10 Hz filter to work with, about 50x.

For the best data, I'd probably do this in a low end DSP like a dsPIC and apply a convolution. A 256-point kernel at 1 kHz sample rate should do nicely. A dsPIC 33F can run at 40 MIPS, which is 40000 instructions/ms. A 256 point convolution every 40000 instructions will only take a small fraction of the processor time.

I wouldn't get too fancy with the filter. There is no need for a sync, for example, and that would have undesirable effects anyway. Something like a gaussian or cosine squared should be good. This should yield a little better result than a few poles of simple single-pole LPFs, since the convolution is symmetric. Put another way, for each output point, the convolution takes into account input points both before and after in time symmetrically, which the single pole IIR filters don't do.

It might be useful to capture maybe 5 seconds of data surrounding a pothole event and post the numbers in a CSV file or something. Actually, the raw data for you top trace would be a good start.

## protected by W5VO♦Jan 28 '13 at 22:11

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).