Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Help and advice on filtering accelerometer data from pothole event

Status
Not open for further replies.

windozeuser

Member
I have about 32 seconds worth of accelerometer data of a basic driving scenario 25MPH normal roads along with hitting about 7 potholes and a rough patch of road. The accelerometer is mounted on the dash board of my car with double sided tape.

Problem: I have all the data that is noisy from the accelerometer, and I need to make a simple way to detect that a pothole event has occurred. Below are several graphs of data in time domain and FFT. The accelerometer is measuring in GForce

Basically I want my arduino to know a pothole has occurred with fairly great accuracy and not using graduate level mathematics and techniques.

Accelerometer sampled at 100hz has a simple 50HZ RC LOW PASS FILTER ON THE Z AXIS

Here is the CSV data for the 32 seconds of accelerometer readings TIME, GFORCE format:

https://textuploader.com/?p=6&id=sQlb

Black trace is RAW unfiltered Accelerometer data:
Blue trace is filtered by a bandstop filter based on the extreme frequencies found in FFT, Dominate 2HZ and 12HZ.

**broken link removed**




Pothole event looks like this in time domain:
**broken link removed**

not sure what the 10 to 15HZ component is in the FFT, is that the actual pothole, or is it the wheel hop of the wheels against the road, or is it the resonant frequency of the car?

FFT:

**broken link removed**

seems like it is the actual pothole events, here is a HPF @ 13HZ The dominant features of the potholes seem enhanced

**broken link removed**


I want to be able to detect and count the potholes in real time

It seems to be counter-intuitive the suspension should move a lot slower than a 10 to 13 HZ that would cause motion-sickness I believe

UPDATE:

As per friends suggestions, I used the full bandwidth of the accelerometer 1000HZ and the maximum sampling rate I could get on the arduino.

FFT:

FFT UNFILTERED DATA FULL BANDWIDTH of ACCELEROMETER:

**broken link removed**

here is a sample piece of data of the pothole event and some bumps and road noise around it:

UNFILTERED DATA POTHOLE EVENT
**broken link removed**

Added the Diode envelope detector circuit, output looks the same... The accelerometer always output 0 to 3.3Volts not negative... I based this idea on filtering and holding the amplitude of the signal like in radio, but the sensor doesn't go negative voltage. the output didn't change much at all. I picked the RC time constant to be around 2mS, I'm sampling at 2mS 500 Samples/ second The accelerometer voltage is always between 0 and 3.3V though... never goes negative so the diode wouldn't work?

**broken link removed**


I did not see a HUGE different in increasing the sampling from 100HZ to 500HZ, the signals looks almost the same. Also, the FFT suggests anything over 55HZ or so can be cutoff, the pothole event would be a high frequency event though kinda like a step input? I'm not sure how I can reliably filter and detect the peaks of the pothole event form the surrounding road noise
 
Last edited:
The pot hole is an impact that's going to excite resonances in the SYSTEM. It may well be the suspension, but it could also be the dash & structure the accelerometer is mounted on.
 
Given that the designers of the cars suspension did their best to isolate the body of the car from rough old roads, if you are trying to detect potholes then maybe the best place for the accelerometer is on the wheel hub.
Then the only isolation from the pothole is the flexing of the tyre.

JimB
 
I would low pass filter in hardware to take out the bulk of that 12Hz resonance from the car suspension springs.

It's amazing that people will start with the dirtiest possible data then try to decode that noisy mess in software. Fiddle with an input filter to get the ADC input signal as close as possible to a "pothole detector", then the software part will be easy.
 
Yes, right now there is a lot of "stuff" between the sensor and the pothole. Get it as close as possible to what you want to measure.
 
Could you provide the raw data as a .wav file?
 
I should have a low pass filter @ 12HZ cutoff? I was using 50HZ then 25HZ cutoffs, I really don't want to attach it to the a-arm since one wheel hits the pothole that maybe the accelerometer wont be on, and also I want this to be able to just attach someone inside the car.

@ Mike not sure how to convert it to a .wav?
 
@ Mike not sure how to convert it to a .wav?

If we could convert your .csv to .wav, I was going to pass your data thru a LTSpice simulated filter, like the one below. You will have to actually build one :(
 

Attachments

  • filt.jpg
    filt.jpg
    215.6 KB · Views: 274
I've been using SciDavis an open source Matlab type analysis tool, you can use FFT, and it has low pass, high pass, bandpass, bandstop filters you can apply to the signal. Is 12.5HZ a good cutoff to try like a 5th order butterworth?
 
Maybe the point is not looking for a specific frequency, butfor the "shrarpness" of the bump? I imagine that if you could measure the slew rate between the opposite peaks of the wave, you could get better results.
 
Maybe the point is not looking for a specific frequency, butfor the "shrarpness" of the bump? I imagine that if you could measure the slew rate between the opposite peaks of the wave, you could get better results.
Differentiating (high-pass filter) a noisy signal makes it even more noisy. I vote for integration (area under the curve, low-pass filter).
 
@Kubeek thats a great insight too!

UPDATE: This is the RAW full bandwidth of accelerometer 1000HZ sampled at highest sampling rate I could get on Arduino. Direct CSV file download: About 112 Seconds of data

**broken link removed**

From many road tests, I never exceeded 1.6G's up to 45 MPH in my car on the Z axis, I used rand() to generate pseudorandom Gforce acceleration.

My idea is if I can look at 1 to 3 second windows of data, I can calculate displacement of the Z axis, but I was worried about the accelerometer drift, and errors in the integration. I don't need to be even 90% accurate here, >70% would be nice, but if I'm looking at displacement at one to three seconds at a time would that be possible to do in real time? This way I can see if the displacement is greater than like 1 inch, 2 inches, 5 inches. The bigger the displacement the rougher the bump or pothole was:

Can you check if I'm doing this right, I basically set up on my desktop, using rand() to generate random acceleration from -1.6 to 1.6 G's, capturing 3 seconds of data @ a simulated 50HZ sampling rate

If like you run *nix, I'm using Sleep() from Windows.h to make the 20mS delay, 50HZ sampling rate

I just wanted to see if the code looks right to you, I didn't do the cicular buffer yet, I'm kinda confused on how to implement it: the commented out code, is from the class I'm working on for it, but I don't understand it 100% yet

Code:
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <ctime> // USED BY RAND
#include <windows.h> // Used for delay


using namespace std;



#define SAMPLE_RATE   0.020 // Sample rate in Milliseconds
#define GRAVITYFT_SEC 32 // Gravity velocity 32 feet/sec
#define INCH_FOOT     12 // 12 inches in foot, from velocity to inch displacement calculation










int main(int argc, char *argv[])
{
    srand((unsigned)time(0)); // SEED RAND() for simulation of Geforce Readings
    
    // SIMULATING ACCELERATION READINGS INTO A CIRCULAR BUFFER
    
   // circular_buffer Acceleration; // Create a new Circular buffer for Acceleration
    
   // cb_init(&Acceleration, 150, 4); // Sampling @ 50HZ, 3 seconds of data = 150, size is float data of 4 bytes
    
    //Simulate a sample run of Acceleration data using Rand()
    
    // WE WILL BE SIMULATING "RANDOM" GEFORCE RATINGS using the rand() function constraining to -1.6 to 1.6 GFORCE 
    // These ratings are consistent with our road tests of apparently random vibration and Geforce readings not exceeding about 1.6 G's
    
    float Gforce[150]; // Random Geforce for 3 second window of data
    float velocity[150]; // Hold velocity information
    float displacement[150]; // Hold Displacement information
    
    
    float LO = -1.6; // Low GForce limit recorded from 6 road tests at different speeds
    float HI = 1.6; // High GForce limit recorded from 6 road tests at different speeds
    
    for(int i = 0; i < 150; i++) // 3 Second iwndow of random acceleration data
    {  
            Gforce[i] = LO + (float)rand()/((float)RAND_MAX/(HI-LO)); // Borrowed from Stackexchange : http://stackoverflow.com/questions/686353/c-random-float
            if( i == 0) // Initial values @ first Acceleration
            {
                velocity[i] = Gforce[i] * SAMPLE_RATE * GRAVITYFT_SEC; // Initial velocity
                displacement[i] = velocity[i] * SAMPLE_RATE * INCH_FOOT; // Initial Displacement
            }
            else
            {
                velocity[i] = velocity[i-1] + (Gforce[i] * SAMPLE_RATE * GRAVITYFT_SEC); // Calculate running velocity into buffer
                displacement[i] = displacement[i-1] +(velocity[i] * SAMPLE_RATE * INCH_FOOT); // Calculate running displacement into buffer
            }
            //cout << endl << Gforce[i]; // Debugging
            //cb_push_back(&Acceleration, &Gforce[i]);                   // Push the GeForce into the circular buffer
            
            
            Sleep(SAMPLE_RATE*1000); // 20mS delay simulates 50HZ sampling rate Sleep() expects number in mS already so * 1000
            
    }
    // PRINT RESULTS
    for (int j = 0; j < 150; j++)
            {
                cout << setprecision (3) << Gforce[j] << "\t\t" << velocity[j] << "\t\t" << displacement[j] << endl;
            }
    
    // READ THE BUFFER
    
    
    
    
    
    //cb_free(&Acceleration); // Pervent Memory leaks

    system("PAUSE");
    return EXIT_SUCCESS;
}

Sample run:

Code:
GFORCE          FT/SEC          Inch Displacement Z axis

-0.93           -0.595          -0.143
-0.377          -0.836          -0.344
0.343           -0.375          -0.233
1.16            0.148           -0.107
-0.559          -0.953          -0.371
0.601           -0.211          -0.193
0.124           -0.516          -0.267
-1.27           -1.41           -0.48
0.809           -0.0775         -0.161
-1.06           -1.27           -0.448
-1.16           -1.34           -0.463
-1.1            -1.3            -0.455
-1.33           -1.44           -0.489
0.256           -0.431          -0.246
-1.44           -1.52           -0.507
1.26            0.211           -0.0923
0.932           0.0015          -0.142
0.789           -0.0903         -0.164
0.318           -0.392          -0.237
-0.355          -0.822          -0.34
1.49            0.357           -0.057
1.38            0.289           -0.0733
1.13            0.131           -0.111
-0.342          -0.814          -0.338
-1.52           -1.57           -0.519
-0.406          -0.855          -0.348
-1.22           -1.37           -0.473
-0.182          -0.712          -0.314
0.0257          -0.579          -0.282
0.112           -0.523          -0.268
-0.624          -0.994          -0.381
-0.35           -0.819          -0.339
0.323           -0.388          -0.236
-1.26           -1.4            -0.479
-1.4            -1.49           -0.501
0.409           -0.333          -0.223
0.328           -0.385          -0.235
-0.713          -1.05           -0.395
-1.33           -1.45           -0.49
0.926           -0.00219                -0.143
1.39            0.293           -0.0725
-0.613          -0.987          -0.38
0.0183          -0.583          -0.283
-0.909          -1.18           -0.425
1.19            0.17            -0.102
1.47            0.345           -0.0601
0.844           -0.0549         -0.156
1.46            0.342           -0.0607
0.555           -0.24           -0.2
0.851           -0.0502         -0.155
1.19            0.164           -0.103
0.324           -0.387          -0.236
-0.951          -1.2            -0.432
0.75            -0.115          -0.17
-0.0729         -0.642          -0.297
0.641           -0.185          -0.187
0.909           -0.0133         -0.146
-0.149          -0.69           -0.308
0.461           -0.3            -0.215
-1.32           -1.44           -0.488
-0.402          -0.852          -0.347
-1.03           -1.25           -0.443
0.711           -0.14           -0.176
1.14            0.137           -0.11
0.797           -0.0849         -0.163
1.31            0.241           -0.085
-0.795          -1.1            -0.408
-0.658          -1.02           -0.387
1.1             0.107           -0.117
1.54            0.388           -0.0497
-0.688          -1.04           -0.391
0.0859          -0.54           -0.272
1.3             0.234           -0.0865
-0.853          -1.14           -0.417
-1.47           -1.53           -0.511
-0.973          -1.22           -0.435
0.409           -0.333          -0.223
-0.793          -1.1            -0.407
-0.664          -1.02           -0.388
1.31            0.247           -0.0836
1.27            0.22            -0.09
0.733           -0.126          -0.173
-0.324          -0.803          -0.335
0.894           -0.0229         -0.148
-0.528          -0.933          -0.367
-0.0603         -0.634          -0.295
-0.363          -0.828          -0.341
0.928           -0.00119                -0.143
-0.749          -1.07           -0.401
-1.14           -1.32           -0.46
1.55            0.399           -0.0469
-0.544          -0.943          -0.369
-0.644          -1.01           -0.384
-1.32           -1.44           -0.488
-1.52           -1.57           -0.519
0.383           -0.35           -0.227
-1.13           -1.32           -0.46
0.191           -0.473          -0.256
-1.27           -1.41           -0.481
-0.505          -0.918          -0.363
1.13            0.129           -0.112
0.39            -0.345          -0.226
1.32            0.248           -0.0832
-0.787          -1.1            -0.406
-1.27           -1.41           -0.48
1.23            0.191           -0.097
-1.04           -1.26           -0.445
-1.43           -1.51           -0.505
0.726           -0.13           -0.174
0.241           -0.441          -0.249
0.123           -0.516          -0.267
-0.663          -1.02           -0.387
-1.29           -1.42           -0.484
1.57            0.408           -0.0448
-0.408          -0.856          -0.348
0.341           -0.376          -0.233
0.191           -0.473          -0.256
1.05            0.0739          -0.125
1.18            0.16            -0.104
-1.43           -1.51           -0.505
0.157           -0.494          -0.261
-0.109          -0.665          -0.302
-0.511          -0.922          -0.364
1.06            0.0844          -0.123
0.161           -0.492          -0.261
0.659           -0.174          -0.184
-1.17           -1.34           -0.465
-1.06           -1.27           -0.448
0.201           -0.466          -0.255
1.58            0.417           -0.0426
-1.39           -1.48           -0.499
0.509           -0.269          -0.207
-0.881          -1.16           -0.421
0.595           -0.214          -0.194
0.852           -0.0494         -0.155
1.01            0.0509          -0.131
-0.804          -1.11           -0.409
-0.462          -0.891          -0.357
1.18            0.163           -0.104
-1.11           -1.31           -0.456
-0.542          -0.942          -0.369
0.64            -0.185          -0.187
-0.204          -0.725          -0.317
0.155           -0.496          -0.262
-1.01           -1.24           -0.441
-1.41           -1.5            -0.503
0.0378          -0.571          -0.28
-1.04           -1.26           -0.446
1.14            0.136           -0.11
-1.34           -1.45           -0.491
Press any key to continue . . .
 
Last edited:
We use a similar system at work for counting "bangs" and do this as RB mentions using a hardware filter (Sallen low pass) set for around 12.5 Hz I think. The design has been working over 25 years that I know of. We come off an Endevco accelerometer and use an instrumentation amplifier with low pass filtering. The bangs trigger a simple level detector comparator circuit and then a one shot (old 74123 one shot) just to get a nice clean pulse for counting. Everything is done in hardware as when this was designed was long, long ago. The low pass filtering is just to clean up the HF hash and noise we have no interest in, we only want the bang. That method has worked fine. The accelerometer has a 10-32 screw base and uses a magnetic base mount with a strong magnet. Been years since I have had anything to do with that system but as I recall, that is how we go about it.

Ron
 
Are all High pass filters Differentiating?

Yes. Put it another way, high-pass filters put out a voltage determined by the rate-of-change of the input.
Low-Pass filters put out a voltage determined by the integral of the input.
 
We use a similar system at work for counting "bangs" and do this as RB mentions using a hardware filter (Sallen low pass) set for around 12.5 Hz I think. The design has been working over 25 years that I know of. We come off an Endevco accelerometer and use an instrumentation amplifier with low pass filtering. The bangs trigger a simple level detector comparator circuit and then a one shot (old 74123 one shot) just to get a nice clean pulse for counting. Everything is done in hardware as when this was designed was long, long ago. The low pass filtering is just to clean up the HF hash and noise we have no interest in, we only want the bang. That method has worked fine. The accelerometer has a 10-32 screw base and uses a magnetic base mount with a strong magnet. Been years since I have had anything to do with that system but as I recall, that is how we go about it.

Ron

Wow that sounds awesome , is there an advantage of the sallenkey lpf compared to say a 4th order butterworth?


I found this, is the type of topology you uses

http://www.calculatoredge.com/electronics/sk low pass.htm
 
Wow that sounds awesome , is there an advantage of the sallenkey lpf compared to say a 4th order butterworth?


I found this, is the type of topology you uses

http://www.calculatoredge.com/electronics/sk low pass.htm

Tomorrow if time allows I'll try and dig out some of the old drawings. In a quick nutshell we use accelerometers in a few applications, mostly to detect a "bang" or "bump" that is in other noise. In one instance a very large AC motor (a very strange motor) drives a lead screw using a latching mechanism. When power is removed the latches open and the lead screw slams home. During the SCRAM process there is noise followed by a distinct bang. When power is removed we look at the current decay and start a timer actually two timers start at the same time. When the latches (arms) open there is a thud picked up by an accelerometer, that thud tells us the arms open time for the latches to release the lead screw. The screw under spring force of a very large spring that is compressed begins driving home, when it hits the rod bottom there is a bang picked up by another accelerometer, this stops the second timer. The problem is the noise and as the rod drives home a high level of noise. The entire process is also recorded using a paperless chart recorder scheme. To eliminate the higher frequency noise which we really don't care about we have been using a low pass sallen key butterworth filter scheme. This is nothing real fancy as we just want to drop the noise levels of what we have no real interest in.

While some of the circuits get pretty in depth some are real simple. I think in one application we just use a TL084 or two and a few comparators and a few flip flops. Most of this stuff goes back well over the 25 years I have been in the department. Before the paperless chart recording we were using the old Honeywell Visicorders.

If you just want to count potholes and I see you are in Ohio, feel free to come up to Cleveland, we have plenty. Seriously for what you seem to want to do I would think it can be done pretty easily. What accelerometers are you using?

Ron
 
I found a picture of several of the type accelerometers I was talking about. These are old Endevco (Now Endevco Meggit Sensing Systems) I rescued years ago from the shock and vibration labs from an old program.

**broken link removed**

The one in the back is mounted on one of the magnetic bases I mentioned. I would think any accelerometer with enough sensitivity and the right frequency response would work for detecting and counting pot holes. Accelerometers like this use a 10-32 screw base making for easy mounting and I have even mounted them using epoxy. The output is another 10-32 type screw connector. Anyway, the image should help show what I am describing.

Ron
 
wow those beauties looks awesome, I actually moved to south-western PA a year ago :/ We have tons and tons of potholes here hahaah

Basically I'm using this: https://www.electro-tech-online.com/custompdfs/2013/02/3157.pdf

I have it firmly attached to my dashboard with industrial adhesive tape (I'll regret it later), but my car is 19 years old haha

I'm measuring acceleration converted to Gforce, it actually seems to pick up very well, if you log data with it, and get out of the car and push the front of the car up and down on the suspension is logs the entire dampened sine wave perfectly.

People are telling me to design a filter kernel to HPF the data, and RMS value of the signal, but I don't know anything about digital filter design and kernels. The solution you use for the bangs seems a lot more straightforward, the signal has a lot of noise I think because the pothole event is acted upon four dampers, and four springs, along with road, chassis, and noise from everything.

It seems like the pothole event has high frequency compared to the noise.

Also, the pothole event has a lot higher amplitude than the surrounding noise, I'm not sure how to calculate the RMS of the signal in software, I'd love to see the old circuit drawings!
 
Could you provide the raw data as a .wav file?
@ Mike not sure how to convert it to a .wav?
If you're using Matlab or probably any of its clones, you can just load the csv file, interpolate to the desired sample rate, then resave the file:
e.g. for 8kHz, 16 bit (input csv file is sampled at 100Hz)
Code:
x = load('pothole.csv');
wavwrite(interp(x(:,2), 8000 / 100), 8000, 16, 'pothole.wav');
Or if you don't want to resample, don't use the interp function.

Wav files attached for both 100Hz and 8kHz
 

Attachments

  • pothole100Hz.zip
    3.3 KB · Views: 145
  • pothole.zip
    411 KB · Views: 145
Status
Not open for further replies.

Latest threads

Back
Top