Hello, I just made my account here to get some help from you guys.
I'm currently studying about drones, and I was actually trying to make a simple flight code to test my PID controller.
Among sensors, I am using MPU6050 from GY-86 IMU sensor.
I was trying to apply LPF to my accelerometer and HPF to my gyroscope.
My LPF code works fine, but my problem arised from HPF code.
I applied HPF and changed a drone's yaw, the yaw seemed to change, but as soon as I stopped moving the drone, filtered yaw immediately decayed to near zero, like angular velocity does.
I belive that since yaw from gyroscope is the result of angular velocity integration, yaw should not decay but stay at the current angular position.
Below is my related code:
void loop() {
// === Read acceleromter data === //
Wire.beginTransmission(MPU);
Wire.write(0x3B); // Start with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
//For a range of +-2g, we need to divide the raw values by 16384, according to the datasheet
AccX = (Wire.read() << 8 | Wire.read()) / 16384.0; // X-axis value
AccY = (Wire.read() << 8 | Wire.read()) / 16384.0; // Y-axis value
AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0; // Z-axis value
// Calculating Roll and Pitch from the accelerometer data
accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) - 0.58; // AccErrorX ~(0.58) See the calculate_IMU_error()custom function for more details
accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) + 1.58; // AccErrorY ~(-1.58)
LPFR();
LPFP();
// === Read gyroscope data === //
previousTime = currentTime; // Previous time is stored before the actual time read
currentTime = millis(); // Current time actual time read
elapsedTime = (currentTime - previousTime) / 1000; // Divide by 1000 to get seconds
Wire.beginTransmission(MPU);
Wire.write(0x43); // Gyro data first register address 0x43
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true); // Read 4 registers total, each axis value is stored in 2 registers
GyroX = (Wire.read() << 8 | Wire.read()) / 131.0; // For a 250deg/s range we have to divide first the raw value by 131.0, according to the datasheet
GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;
GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;
// Correct the outputs with the calculated error values
GyroX = GyroX - GyroErrorX; // GyroErrorX ~(-0.56)
GyroY = GyroY - GyroErrorY; // GyroErrorY ~(2)
GyroZ = GyroZ - GyroErrorZ; // GyroErrorZ ~ (-0.8)
// Currently the raw values are in degrees per seconds, deg/s, so we need to multiply by sendonds (s) to get the angle in degrees
gyroAngleX = gyroAngleX + GyroX * elapsedTime; // deg/s * s = deg
gyroAngleY = gyroAngleY + GyroY * elapsedTime;
yaw = yaw + filtered_GyroZ * elapsedTime;
HPFY();
filtered_roll = filtered_accAngleX;
filtered_pitch = filtered_accAngleY;
// Print the values on the serial monitor
Serial.print(filtered_roll);
Serial.print(", ");
Serial.print(filtered_pitch);
Serial.print(", ");
Serial.print(filtered_yaw);
Serial.print(", ");
getAltitudeP();
Serial.println(z_p);
}
void HPFY() {
if (counterYF == 0) {
filtered_yaw = yaw/(1+2*3.14*Ts*f_ch);
counterYF++;
}
else {
filtered_yaw = (yaw - prev_yaw + prev_filtered_yaw)/(2*3.14*Ts*f_ch + 1);
}
prev_filtered_yaw = filtered_yaw;
prev_yaw = yaw;
}
I really appreciate your help!