Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Please, correct error in anti-aliasing filter for gyro #10708

Open
and-sh opened this issue Feb 18, 2025 · 6 comments
Open

Please, correct error in anti-aliasing filter for gyro #10708

and-sh opened this issue Feb 18, 2025 · 6 comments

Comments

@and-sh
Copy link

and-sh commented Feb 18, 2025

Current Behavior

The 250 Hz pt1 filter used as anti-aliasing filter for gyro. It have attenuation about 1/5 at 1kHz, that is very insufficient.

Steps to Reproduce

model pt1 filter 250Hz, sampling rate 4kHz and measure attenuation at 1kHz.

Image

Expected behavior

attenuation, at fS/2 should more than the signal-to-noise ratio (SNR) of the sampling system.

https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ApplicationNotes/ApplicationNotes/00699b.pdf
https://electronics.stackexchange.com/questions/274696/anti-aliasing-filter-design

For 16bit representation this is about 90dB.

Suggested solution(s)

Use much effective filters.

Additional context

All versions of Inav have this problem.

@DzikuVx
Copy link
Member

DzikuVx commented Feb 18, 2025

Part of the issue is that for flight control case, we are interested not only in attenuation but also introduced group delay.
I've run some numbers and current PT1 used indroduces 0.5ms of group delay.
Doubling attenuation would double group delay as well (BiQuad). Increasing filter order would increase delay even more

@and-sh
Copy link
Author

and-sh commented Feb 18, 2025

Yes, but ignoring Dr. Nyquist will result in high frequency noise being pushed into the low frequency region. And filtering out low frequency noise will result in more delay. There is usually a lot of high frequency noise in a gyroscope.

@DzikuVx
Copy link
Member

DzikuVx commented Feb 18, 2025

Maybe not ignoring Dr. Nyquist. Rather compromising. Anyway, I quickly added #10710 but not really tested it yet

@and-sh
Copy link
Author

and-sh commented Feb 18, 2025

You are fast. I make two avereging. tested on bench. Next week will try to fly.

    const bool ack = busReadBuf(gyro->busDev, ICM45600_RA_ACCEL_DATA_X1, data, 12);
    if (!ack) {
        return;
    }
//(rand()%10000-5000);

    GYRO_A[0]-= (int32_t) GYRO_V[0][IMU_ptr];
    GYRO_V[0][IMU_ptr] = (int16_t)(rand()%10000-5000);//int16_val_little_endian(data, 3);
    GYRO_A[0]+= (int32_t) GYRO_V[0][IMU_ptr];

        GYRO_A1[0]-= GYRO_V1[0][IMU_ptr1];
        GYRO_V1[0][IMU_ptr1] = GYRO_A[0];
        GYRO_A1[0]+= GYRO_V1[0][IMU_ptr1];

    GYRO_A[1]-= (int32_t) GYRO_V[1][IMU_ptr];
    GYRO_V[1][IMU_ptr] = int16_val_little_endian(data, 4);
    GYRO_A[1]+= (int32_t) GYRO_V[1][IMU_ptr];

        GYRO_A1[1]-= GYRO_V1[1][IMU_ptr1];
        GYRO_V1[1][IMU_ptr1] = GYRO_A[1];
        GYRO_A1[1]+= GYRO_V1[1][IMU_ptr1];

    GYRO_A[2]-= (int32_t) GYRO_V[2][IMU_ptr];
    GYRO_V[2][IMU_ptr] = int16_val_little_endian(data, 5);
    GYRO_A[2]+= (int32_t) GYRO_V[2][IMU_ptr];

        GYRO_A1[2]-= GYRO_V1[2][IMU_ptr1];
        GYRO_V1[2][IMU_ptr1] = GYRO_A[2];
        GYRO_A1[2]+= GYRO_V1[2][IMU_ptr1];


    ACC_A[0]-= (int32_t) ACC_V[0][IMU_ptr];
    ACC_V[0][IMU_ptr] = int16_val_little_endian(data, 0);
    ACC_A[0]+= (int32_t) ACC_V[0][IMU_ptr];

        ACC_A1[0]-= ACC_V1[0][IMU_ptr1];
        ACC_V1[0][IMU_ptr1] = ACC_A[0];
        ACC_A1[0]+= ACC_V1[0][IMU_ptr1];

    ACC_A[1]-= (int32_t) ACC_V[1][IMU_ptr];
    ACC_V[1][IMU_ptr] = int16_val_little_endian(data, 1);
    ACC_A[1]+= (int32_t) ACC_V[1][IMU_ptr];

        ACC_A1[1]-= ACC_V1[1][IMU_ptr1];
        ACC_V1[1][IMU_ptr1] = ACC_A[1];
        ACC_A1[1]+= ACC_V1[1][IMU_ptr1];

    ACC_A[2]-= (int32_t) ACC_V[2][IMU_ptr];
    ACC_V[2][IMU_ptr] = int16_val_little_endian(data, 2);
    ACC_A[2]+= (int32_t) ACC_V[2][IMU_ptr];

        ACC_A1[2]-= ACC_V1[2][IMU_ptr1];
        ACC_V1[2][IMU_ptr1] = ACC_A[2];
        ACC_A1[2]+= ACC_V1[2][IMU_ptr1];

    IMU_ptr++;
    if(IMU_ptr>=n)
    {
        IMU_ptr=0;
    } 
 
    IMU_ptr1++;
    if(IMU_ptr1>=n1)
    {
        IMU_ptr1=0;
    } 

@and-sh
Copy link
Author

and-sh commented Feb 18, 2025

Spectrum and step response 1 and 2 averaging 20 and 14 points in comparison to pt1 250Hz.

Image

@and-sh
Copy link
Author

and-sh commented Feb 25, 2025

Tested
Flies no worse than with standard filters. There is a little less noise.

  1. Standard filters. All by default.

Image

  1. All standard filters off, except Kalman

Image

It is interesting that despite the delay of about 6 ms, there is practically no prop wash. I even lowered the idle to 5 percent.
https://youtu.be/yxB54G2ou74

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants