Saya memiliki data akselerometer sekitar 32 detik dari skenario normal mengemudi 25MPH jalan bersama dengan memukul sekitar 7 lubang dan jalan yang kasar. Accelerometer dipasang di papan dasbor mobil saya dengan selotip dua sisi.
Masalah: Saya memiliki semua data yang berisik dari accelerometer, dan saya perlu membuat cara sederhana untuk mendeteksi bahwa peristiwa lubang telah terjadi. Di bawah ini adalah beberapa grafik data dalam domain waktu dan FFT. Accelerometer mengukur di GForce
Pada dasarnya saya ingin Arduino saya tahu lubang telah terjadi dengan akurasi yang cukup besar dan tidak menggunakan matematika tingkat sarjana dan teknik.
Accelerometer yang diambil sampel pada 100Hz memiliki 50HZ RC LOW PASS FILTER sederhana PADA Z AXIS
Here is the CSV data for the 32 seconds of accelerometer readings TIME, GFORCE format:
http://hamiltoncomputer.us/50HZLPFDATA.CSV
UPDATE: Ini adalah bandwidth penuh RAW accelerometer 1000HZ yang diambil sampelnya pada tingkat sampling tertinggi yang bisa saya dapatkan di Arduino. Unduh file CSV langsung: Sekitar 112 detik data
http://hamiltoncomputer.us/RAWUNFILTEREDFULLBANDWIDTH500HZ.csv
Jejak hitam adalah data Accelerometer tanpa filter RAW: Jejak biru difilter oleh filter bandstop berdasarkan frekuensi ekstrim yang ditemukan di FFT, Dominate 2HZ, dan 12HZ.
Acara lubang terlihat seperti ini dalam domain waktu:
tidak yakin apa komponen 10 hingga 15HZ dalam FFT, apakah itu lubang yang sebenarnya, atau apakah itu lompatan roda dari roda ke jalan, atau apakah itu frekuensi resonansi mobil?
FFT:
sepertinya itu adalah peristiwa lubang yang sebenarnya, di sini adalah HPF @ 13HZ Fitur dominan lubang tampak ditingkatkan
Saya ingin dapat mendeteksi dan menghitung lubang secara real time
Tampaknya kontra-intuitif suspensi harus bergerak jauh lebih lambat daripada 10 hingga 13 HZ yang akan menyebabkan mabuk-mabuk saya percaya
MEMPERBARUI:
Sesuai saran AngryEE, saya menggunakan bandwidth penuh accelerometer 1000HZ dan laju pengambilan sampel maksimum yang bisa saya dapatkan di Arduino.
FFT:
berikut adalah contoh sepotong data dari peristiwa lubang dan beberapa gundukan dan kebisingan jalan di sekitarnya:
Menambahkan rangkaian detektor amplop Diode, output terlihat sama ... Accelerometer selalu menampilkan 0 hingga 3.3Volts bukan negatif ...
MEMPERBARUI:
Dari banyak tes jalan, saya tidak pernah melebihi 1,6G hingga 45 MPH di mobil saya pada sumbu Z, saya menggunakan rand () untuk menghasilkan akselerasi Gforce pseudorandom.
Gagasan saya adalah jika saya dapat melihat data jendela 1 hingga 3 detik, saya dapat menghitung perpindahan sumbu Z, tetapi saya khawatir dengan pergeseran akselerometer, dan kesalahan dalam integrasi. Saya tidak perlu bahkan 90% akurat di sini,> 70% akan menyenangkan, tetapi jika saya melihat perpindahan pada satu hingga tiga detik sekaligus apakah itu mungkin dilakukan secara real time? Dengan cara ini saya bisa melihat apakah perpindahan lebih besar dari seperti 1 inci, 2 inci, 5 inci. Semakin besar perpindahan, semakin besar tonjolan atau lubangnya:
Dapatkah Anda memeriksa apakah saya melakukan ini dengan benar, pada dasarnya saya mengatur di desktop saya, menggunakan rand () untuk menghasilkan akselerasi acak dari -1,6 ke 1,6 G, menangkap 3 detik data @ laju sampling 50HZ yang disimulasikan
Jika seperti Anda menjalankan * nix, saya menggunakan Sleep () dari Windows.h untuk membuat penundaan 20mS, sampling rate 50 HZ
Saya hanya ingin melihat apakah kodenya cocok untuk Anda, saya belum melakukan buffer cicular, saya agak bingung tentang cara mengimplementasikannya: kode yang dikomentari, berasal dari kelas yang saya kerjakan untuk itu , tapi saya belum mengerti 100%. Buffer bundar akan memungkinkan untuk memindahkan jendela data secara bersamaan, bukan?
#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;
}
Contoh dijalankan:
GFORCE FT/SEC Inch Displacement Z axis
-0.882 -0.565 -0.136
0.199 -0.437 -0.24
-1.32 -1.29 -0.549
0.928 -0.691 -0.715
0.6 -0.307 -0.788
1.47 0.635 -0.636
0.849 1.18 -0.353
-0.247 1.02 -0.108
1.29 1.85 0.335
0.298 2.04 0.824
-1.04 1.37 1.15
1.1 2.08 1.65
1.52 3.05 2.38
0.078 3.1 3.12
-0.0125 3.09 3.87
1.24 3.88 4.8
0.845 4.42 5.86
0.25 4.58 6.96
0.0463 4.61 8.06
1.37 5.49 9.38
-0.15 5.39 10.7
0.947 6 12.1
1.18 6.75 13.7
-0.791 6.25 15.2
-1.43 5.33 16.5
-1.58 4.32 17.5
1.52 5.29 18.8
-0.208 5.16 20.1
1.36 6.03 21.5
-0.294 5.84 22.9
1.22 6.62 24.5
1.14 7.35 26.3
1.01 8 28.2
0.284 8.18 30.1
1.18 8.93 32.3
-1.43 8.02 34.2
-0.167 7.91 36.1
1.14 8.64 38.2
-1.4 7.74 40
-1.49 6.79 41.7
-0.926 6.2 43.2
-0.575 5.83 44.6
0.978 6.46 46.1
-0.909 5.87 47.5
1.46 6.81 49.2
0.353 7.04 50.8
-1.12 6.32 52.4
-1.12 5.6 53.7
-0.141 5.51 55
0.463 5.8 56.4
-1.1 5.1 57.6
0.591 5.48 59
0.0912 5.54 60.3
-0.47 5.23 61.5
-0.437 4.96 62.7
0.734 5.42 64
-0.343 5.21 65.3
0.836 5.74 66.7
-1.11 5.03 67.9
-0.771 4.54 69
-0.783 4.04 69.9
-0.501 3.72 70.8
-0.569 3.35 71.6
0.765 3.84 72.5
0.568 4.21 73.5
-1.45 3.28 74.3
0.391 3.53 75.2
0.339 3.75 76.1
0.797 4.26 77.1
1.3 5.09 78.3
0.237 5.24 79.6
1.52 6.21 81.1
0.314 6.41 82.6
0.369 6.65 84.2
-0.598 6.26 85.7
-0.905 5.68 87.1
-0.732 5.22 88.3
-1.47 4.27 89.4
0.828 4.8 90.5
0.261 4.97 91.7
0.0473 5 92.9
1.53 5.98 94.3
1.24 6.77 96
-0.0228 6.76 97.6
-0.0453 6.73 99.2
-1.07 6.04 101
-0.345 5.82 102
0.652 6.24 104
1.37 7.12 105
1.15 7.85 107
0.0238 7.87 109
1.43 8.79 111
1.08 9.48 113
1.53 10.5 116
-0.709 10 118
-0.811 9.48 121
-1.06 8.8 123
-1.22 8.02 125
-1.4 7.13 126
0.129 7.21 128
0.199 7.34 130
-0.182 7.22 132
0.135 7.31 133
0.885 7.87 135
0.678 8.31 137
0.922 8.9 139
-1.54 7.91 141
-1.16 7.16 143
-0.632 6.76 145
1.3 7.59 146
-0.67 7.16 148
0.124 7.24 150
-1.19 6.48 151
-0.728 6.01 153
1.22 6.79 154
-1.33 5.94 156
-0.402 5.69 157
-0.532 5.35 159
1.27 6.16 160
0.323 6.37 162
0.428 6.64 163
0.414 6.91 165
-0.614 6.51 166
1.37 7.39 168
0.449 7.68 170
0.55 8.03 172
1.33 8.88 174
-1.2 8.11 176
-0.641 7.7 178
-1.59 6.69 179
1.02 7.34 181
-0.86 6.79 183
-1.55 5.79 184
-0.515 5.46 186
0.352 5.69 187
0.824 6.22 188
1.14 6.94 190
-1.03 6.29 192
-1.13 5.56 193
0.139 5.65 194
0.293 5.84 196
1.08 6.53 197
-1.23 5.75 199
-1.1 5.04 200
-1.17 4.29 201
-0.8 3.78 202
-0.905 3.2 203
-0.0769 3.15 203
-0.323 2.95 204
-0.0186 2.93 205
Press any key to continue . . .
Jawaban:
Ini sepertinya bisa diselesaikan dengan pemfilteran yang cukup lurus ke depan. Ini data asli Anda:
Itu terlalu banyak untuk melihat apa yang terjadi dalam suatu peristiwa individu pada tingkat detail yang sesuai untuk di sini. Berikut ini data dari 26 hingga 28:
Saya awalnya berpikir untuk low pass filter ini, tetapi itu tidak berhasil karena tidak ada sinyal frekuensi rendah di sana. Amplitudo sinyal frekuensi tinggi naik sebagai gantinya. Ini adalah low pass yang ditumpangkan ke aslinya:
Perhatikan ini mengikuti "rata-rata" dari sinyal yang cukup baik tidak selama peristiwa lubang. Jika kita mengurangi rata-rata ini dari sinyal asli, kita dibiarkan dengan kunjungan jauh lebih tinggi dari rata-rata ini selama acara daripada yang lain. Dengan kata lain, yang kita inginkan adalah filter pass tinggi. Kami akan melakukannya dengan mengurangi low pass dari yang semula karena itulah yang kami dapatkan di sini, tetapi dalam sistem produksi Anda akan melakukan ini dengan penyaringan pass tinggi secara eksplisit. Bagaimanapun, ini adalah high pass yang difilter asli:
Ini sekarang menunjukkan pendekatan yang jelas untuk mendeteksi peristiwa tersebut. Ada lebih banyak amplitudo sinyal selama acara daripada yang lain. Kami dapat mendeteksi ini dengan menghitung RMS dan menerapkan beberapa penyaringan low pass:
Memperbesar kembali seluruh data, kita melihat:
Ini dengan jelas mengidentifikasi lima peristiwa dalam data, meskipun saya tidak tahu apakah itu yang seharusnya ditampilkan oleh data ini. Melihat peristiwa lebih dekat, Anda perhatikan bahwa masing-masing dari mereka memiliki penurunan rendah sekitar 1 detik sebelum dan setelah puncak. Ini berarti lebih banyak yang dapat dilakukan jika hanya dengan mengirik sinyal RMS seperti sekarang tidak cukup baik. Sebagai contoh, sebuah algoritma sederhana yang mencari ketinggian suatu titik relatif ke titik terendah dalam 1 detik bagaimanapun juga harus mengurangi kebisingan latar belakang. Cara lain untuk mengatakan tentang hal yang sama adalah untuk membedakan sinyal ini mencari kenaikan selama periode 1 detik. Peristiwa lubang akan dideteksi oleh doublet, yang berarti puncak tinggi diikuti oleh puncak rendah.
Cara lain untuk melihat ini adalah dengan melewati sinyal RMS. Ini sudah disaring low pass, tetapi karena Anda mencari kejadian mendadak dengan kemiringan yang kuat, memotong beberapa frekuensi rendah harus bekerja untuk mengurangi kebisingan latar belakang juga.
Ada banyak cara untuk memperbaiki sinyal dari sini, tapi mudah-mudahan saya telah menunjukkan cara mendapatkan setidaknya hasil pertama yang bermanfaat.
Ditambahkan:
Saya ingin tahu seberapa baik mencari dips di kedua sisi puncak akan bekerja, jadi saya mencobanya. Saya menggunakan filter non-linear yang dimulai dengan RMS dari plot sebelumnya. Nilai setiap titik adalah minimum dari berapa banyak itu di atas titik terendah di detik sebelumnya dan titik terendah di detik berikutnya. Hasilnya terlihat cukup baik:
Paling rendah dari 5 puncak lebih dari 3 kali lebih tinggi dari kebisingan latar belakang tertinggi. Ini tentu saja dengan asumsi 5 benjolan ini mewakili peristiwa yang ingin Anda deteksi dan sisanya tidak.
Ditambahkan dalam menanggapi komentar:
Saya melakukan filter dalam domain waktu, jadi saya tidak tahu respons frekuensi secara langsung. Untuk low pass filter saya menggabungkan sinyal input dengan kernel filter COS ^ 2. Jika saya ingat benar, jari-jari (jarak dari pusat ke tepi) dari kernel sebagai beberapa 100 ms. Saya bereksperimen dengan nilai sampai plot terlihat bagus. Untuk low pass filter RMS, saya menggunakan kernel filter yang sama tetapi kali ini dengan radius sekitar satu detik. Saya tidak ingat persisnya. Eksperimen sampai Anda mendapatkan hasil yang baik.
Filter non-linear tidak mendeteksi doublet. Seperti yang saya katakan, saya menemukan perbedaan antara titik saat ini dan yang terendah dari semua poin dalam 1 detik sebelumnya, dan juga perbedaan antara titik saat ini dan yang terendah dari semua poin dalam 1 detik setelahnya. Lalu saya mengambil min dari keduanya.
Perangkat lunak yang saya gunakan adalah program yang saya retas untuk tujuan ini. Saya sudah memiliki berbagai rutinitas untuk membaca dan menulis file CSV, jadi yang harus saya tulis hanyalah kode filter, yang sangat sederhana. Sisanya dilakukan dengan program yang sudah ada sebelumnya yang saya miliki untuk memanipulasi dan merencanakan file CSV.
sumber
Lubang pendeteksi tepi mungkin meminta masalah. Amplop getaran mobil adalah tempat jawabannya, karena getaran aktual yang dilihat oleh sensor berada pada frekuensi yang jauh lebih tinggi. Aku akan pergi dengan RMS ke DC yang merespon sekitar 15Hz atau lebih tinggi dan lulus hal itu.
sumber
Alih-alih mencari filter domain frekuensi atau ambang batas, saya sarankan mencoba untuk membuat kernel untuk lubang "khas", dan melakukan korelasi berjalan dengannya. Ini akan dianggap sebagai teknik pencocokan templat, dan tampaknya akan meminjamkan dirinya ke platform mikrokontroler.
Lihat http://scribblethink.org/Work/nvisionInterface/vi95_lewis.pdf untuk ulasan singkat, dan mungkin DOBBS, STEVEN E., NEIL M. SCHMITT, dan HALUK S. OZEMEK. "Deteksi QRS oleh pencocokan templat menggunakan korelasi waktu-nyata pada komputer mikro." Jurnal teknik klinis 9.3 (1984): 197-212.
Jika Anda menggunakan platform yang lebih besar, saya sarankan untuk memberikan wavelet.
sumber
Pendekatan lain adalah menghitung varian bergerak dari sinyal Anda untuk melihat apakah lubang benar-benar menonjol. Berikut adalah fungsi matlab untuk filter varians bergerak, N poin lebar - pintar (jika saya harus mengatakannya sendiri) menggunakan konvolusi untuk perhitungan
sumber
Pikiran awal saya adalah bahwa filter low-pass mungkin tipe filter yang salah untuk digunakan. Lubang pada dasarnya adalah peristiwa frekuensi tinggi - seperti fungsi langkah atau gelombang persegi. Hanya dengan melihat data yang difilter 50Hz membuat saya berpikir bahwa Anda kehilangan informasi tentang lubang - semuanya terlihat seperti coretan yang sama tanpa perbedaan yang signifikan untuk peristiwa lubang. Pertama saya akan menggunakan filter high-pass, kemudian filter low-pass dengan frekuensi yang jauh lebih tinggi. Anda mungkin menghindari filter low-pass sama sekali jika accelerometer Anda sudah difilter low-pass.
Setelah Anda memiliki data yang disaring high-pass saya pikir bahwa pembanding sederhana dengan ambang batas yang sesuai akan memilih puncak dalam data percepatan yang disebabkan oleh lubang dan memungkinkan Anda untuk menghitungnya.
sumber