Analizar las características de los datos del acelerómetro y diseñar un filtro

13

Tengo alrededor de 32 segundos de datos de acelerómetro de un escenario de manejo básico de 25 MPH en carreteras normales, junto con cerca de 7 baches y una zona irregular de carreteras. El acelerómetro está montado en el tablero de instrumentos de mi auto con cinta de doble cara.

Problema: tengo todos los datos que son ruidosos del acelerómetro, y necesito hacer una manera simple de detectar que ha ocurrido un evento de bache. A continuación se muestran varios gráficos de datos en el dominio del tiempo y FFT. El acelerómetro está midiendo en GForce

Básicamente, quiero que mi arduino sepa que un bache ha ocurrido con bastante gran precisión y que no utiliza técnicas y matemáticas de nivel de posgrado.

El acelerómetro muestreado a 100 hz tiene un filtro de 50 Hz RC LOW PASS simple en el eje Z

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

enlace

ACTUALIZACIÓN: Este es el ancho de banda RAW completo del acelerómetro 1000 HZ muestreado a la frecuencia de muestreo más alta que pude obtener en Arduino. Descarga directa de archivos CSV: aproximadamente 112 segundos de datos

enlace

La traza negra es datos del acelerómetro sin filtrar RAW: La traza azul se filtra mediante un filtro de paro de banda basado en las frecuencias extremas encontradas en FFT, Dominate 2HZ y 12HZ.

Eleventodebacheseveasíeneldominiodetiempo:

no estoy seguro de cuál es el componente de 10 a 15 HZ en la FFT, ¿es ese bache real, o es el salto de la rueda de las ruedas contra la carretera, o es la frecuencia de resonancia del automóvil?

FFT:

parecequesonloseventosdebachesreales,aquíhayunHPF@13HZLascaracterísticasdominantesdelosbachesparecenmejoradas

Quiero poder detectar y contar los baches en tiempo real

Parece ser contraintuitivo, la suspensión debería moverse mucho más lento que un 10 a 13 HZ que podría causar enfermedad de movimiento, creo

ACTUALIZACIÓN:

Según las sugerencias de AngryEE, usé el ancho de banda completo del acelerómetro 1000 HZ y la velocidad de muestreo máxima que pude obtener en el arduino.

FFT:

Aquíhayunamuestradedatosdeleventobacheyalgunosbachesyruidodelacarreteraasualrededor:

Agregado el circuito detector de envolvente de diodo, la salida se ve igual ... El acelerómetro siempre genera una salida de 0 a 3.3 Volts no negativo ...

ACTUALIZACIÓN:

Demuchaspruebasencarretera,nuncaexcedíde1.6Ghasta45MPHenmiautomóvilenelejeZ,usérand()paragenerarlaaceleracióndeGforcepseudoaleatoria.

Miideaesquesipuedoverventanasdedatosde1a3segundos,puedocalculareldesplazamientodelejeZ,peromepreocupabaladerivadelacelerómetroyloserroresenlaintegración.Nonecesitotenerunaprecisióndel90%aquí,>el70%estaríabien,perosiobservoeldesplazamientodeunoatressegundoscadavez,¿seríaposiblehacerloentiemporeal?Deestamanerapuedoversieldesplazamientoesmayorquecomo1pulgada,2pulgadas,5pulgadas.Cuantomayoreseldesplazamiento,másásperaeslaprotuberanciaobache:

¿Puedeverificarsiestoyhaciendoestocorrectamente?Básicamente,loinstaléenmiescritorio,utilizandorand()paragenerarunaaceleraciónaleatoriade-1.6a1.6G,capturando3segundosdedatosconunafrecuenciademuestreosimuladade50Hz

Si,aligualqueejecutas*nix,estoyusandoSleep()deWindows.hparahacerelretardode20ms,lafrecuenciademuestreode50Hz

Soloqueríaversielcódigoteparececorrecto,nohiceelbúferciculartodavía,estoyunpococonfundidosobrecómoimplementarlo:elcódigocomentadoesdelaclaseenlaqueestoytrabajandoporeso,peronoloentiendoal100%todavía.Unbúfercircularpermitiríamoverdeformacontigualasventanasdedatos,¿no?

#include<cstdlib>#include<iostream>#include<iomanip>#include<ctime>//USEDBYRAND#include<windows.h>//Usedfordelayusingnamespacestd;#defineSAMPLE_RATE0.020//SamplerateinMilliseconds#defineGRAVITYFT_SEC32//Gravityvelocity32feet/sec#defineINCH_FOOT12//12inchesinfoot,fromvelocitytoinchdisplacementcalculationintmain(intargc,char*argv[]){srand((unsigned)time(0));//SEEDRAND()forsimulationofGeforceReadings//SIMULATINGACCELERATIONREADINGSINTOACIRCULARBUFFER//circular_bufferAcceleration;//CreateanewCircularbufferforAcceleration//cb_init(&Acceleration,150,4);//Sampling@50HZ,3secondsofdata=150,sizeisfloatdataof4bytes//SimulateasamplerunofAccelerationdatausingRand()//WEWILLBESIMULATING"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;
}

Ejecución de muestra:

    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 . . .
    
pregunta zacharoni16

5 respuestas

12

Esto parece que puede resolverse mediante un filtrado bastante directo. Aquí están tus datos originales:

Esoesdemasiadoparaverloquesucedeenuneventoindividualalniveldedetalleapropiadoparaaquí.Aquíestánlosdatosdelsegundo26al28:

Originalmente pensé en filtrar el filtro de paso bajo, pero eso no funciona porque no hay una señal de baja frecuencia allí. La amplitud de la señal de alta frecuencia aumenta en su lugar. Aquí hay un paso bajo superpuesto al original:

Notequeestosigueel"promedio" de la señal bastante bien, no durante el evento bache. Si restamos este promedio de la señal original, nos quedamos con excursiones mucho más altas de este promedio durante el evento que de otra manera. Dicho de otra manera, lo que realmente queremos es un filtro de paso alto. Lo haremos restando el paso bajo del original, ya que así es como llegamos aquí, pero en un sistema de producción lo haríamos al filtrar explícitamente el paso alto. De todos modos, aquí está el original de alto paso filtrado:

Estoahoraseñalaunenfoqueobvioparadetectarelevento.Haymuchamásamplituddeseñalduranteeleventoquedeotramanera.PodemosdetectarestocalculandoelRMSyaplicandoalgunosfiltrosdepasobajo:

Volviendo a los datos completos, vemos:

Estoidentificaclaramentecincoeventosenlosdatos,aunquenosésiesoesloqueestosdatosdebenmostrar.Siobservaloseventosmásdecerca,observaráquecadaunodeellostienebajascaídasaproximadamente1segundoantesydespuésdelospicos.EstosignificaquesepuedehacermássisimplementeelumbraldelaseñalRMScomoestáahoranoessuficiente.Porejemplo,unalgoritmosimplequebuscalaalturadeunpuntoenrelaciónconelmásbajodentrode1segundo,deberíareduciraúnmáselruidodefondo.Otraformadedecirlomismoesdiferenciarestaseñalbuscandoelaumentoenunperíodode1segundo.Undobletedetectaríauneventodebache,loquesignificaunpicoaltoseguidoporunpicobajo.

OtraformadeverestoespasarlaseñalRMS.Yaestáfiltradoenpasobajo,perocomoestábuscandoeventosrepentinosconfuertespendientes,recortaralgunasdelasfrecuenciasbajastambiéndeberíafuncionarparareducirelruidodefondo.

Haymuchasmanerasderefinarlaseñaldesdeaquí,peroesperoquehayamostradocómollegaralmenosaunprimerresultadoútil.

Añadido:

Teníacuriosidadporlobienquefuncionaríabuscarinmersionesaambosladosdeunpico,asíquelointenté.UséunfiltronolinealquecomienzaconelRMSdelagráficaanterior.Elvalordecadapuntoeselmínimodecuántoestáporencimadelpuntomásbajoenelsegundoanterioryelpuntomásbajoenelsegundosiguiente.Elresultadosevebastantebien:

El más bajo de los 5 picos es 3 veces más alto que el ruido de fondo más alto. Esto es, por supuesto, asumiendo que estos 5 baches representan eventos que desea detectar y el resto no.

Añadido en respuesta a los comentarios:

Hice los filtros en el dominio de tiempo, por lo que no conozco la respuesta de frecuencia directamente. Para el filtro de paso bajo, convolucioné la señal de entrada con un núcleo de filtro COS ^ 2. Si recuerdo bien, el radio (la distancia del centro al borde) del núcleo es de unos 100 ms. Experimenté con el valor hasta que la trama se veía bien. Para el filtro de paso bajo del RMS, utilicé el mismo núcleo de filtro, pero esta vez con un radio de aproximadamente un segundo. No recuerdo exactamente. Experimente hasta que obtenga buenos resultados.

El filtro no lineal no detectó dobletes. Como dije, encontré la diferencia entre el punto actual y el más bajo de todos los puntos dentro de 1 segundo antes, y también la diferencia entre el punto actual y el más bajo de todos los puntos dentro de 1 segundo después. Luego tomé el mínimo de esos dos.

El software que utilicé fue un programa que pirateé para este propósito. Ya tenía varias rutinas para leer y escribir archivos CSV, así que todo lo que tenía que escribir era el código de filtrado, que es muy simple. El resto se realizó con los programas preexistentes que tengo para manipular y trazar archivos CSV.

    
respondido por el Olin Lathrop
2

Los baches de detección de bordes pueden estar pidiendo problemas. La envolvente de vibración de los autos es donde se encuentra la respuesta, ya que las vibraciones reales observadas por el sensor tienen frecuencias mucho más altas. Me gustaría ir con RMS a DC, que responde a aproximadamente 15Hz o más, y pasa la cosa.

    
respondido por el Chintalagiri Shashank
2

En lugar de buscar un filtro de dominio de frecuencia o un umbral, recomiendo intentar encontrar un núcleo para un bache "típico" y hacer una correlación de ejecución con él. Se consideraría una técnica de coincidencia de plantillas y parece prestarse a una plataforma de microcontroladores.

Vea enlace para una revisión rápida, y tal vez DOBBS, STEVEN E., NEIL M. SCHMITT, y HALUK S. OZEMEK. "Detección de QRS por coincidencia de plantillas usando correlación en tiempo real en un microordenador". Revista de ingeniería clínica 9.3 (1984): 197-212.

Si estuvieras en una plataforma más robusta, te recomendaría darle una vuelta a las olas.

    
respondido por el Scott Seidman
2

Otro enfoque sería calcular una variación en movimiento de su señal para ver si los baches realmente sobresalen. Aquí hay una función matlab para un filtro de variación en movimiento, N puntos de ancho - inteligentemente (si debo decirlo yo mismo) usando una convolución para el cálculo

function y=movingvar(X,N)
% y=movingvar(X,N)
% Calculates N-point moving variance of  Vector X
% Highly recommend that N be odd (no error checking)
% Note: first and last N/2 points will be unreliable.
% Output will be a column vector.


X=X(:);
XSQR=X.*X;
convsig=ones(1,N);
y=(conv(convsig,XSQR)-(conv(convsig,X).^2)/N)/(N-1);

y=y(ceil(N/2):length(X)+floor(N/2));
    
respondido por el Scott Seidman
1

Mi idea inicial es que un filtro de paso bajo podría ser el tipo incorrecto de filtro que se debe usar. El bache es esencialmente un evento de alta frecuencia, como una función de paso u onda cuadrada. El solo hecho de mirar los datos filtrados a 50Hz me hace pensar que está perdiendo la información sobre el bache: todo se parece a los mismos garabatos sin una distinción significativa para el evento bache. Primero usaría un filtro de paso alto, luego un filtro de paso bajo con una frecuencia mucho más alta. Puede evitar el filtro de paso bajo por completo si su acelerómetro ya está filtrado en paso bajo.

Una vez que tenga los datos filtrados de paso alto, creo que un comparador simple con un conjunto de umbrales adecuadamente seleccionará los picos en los datos de aceleración causados por los baches y le permitirá contarlos.

    
respondido por el AngryEE

Lea otras preguntas en las etiquetas