#include <Wire.h>
float RateRoll, RatePitch, RateYaw;
float RateCalibrationRoll, RateCalibrationPitch, RateCalibrationYaw;
int RateCalibrationNumber;
float AccX, AccY, AccZ;
float AngleRoll, AnglePitch;
uint32_t LoopTimer;
float KalmanAngleRoll=0, KalmanUncertaintyAngleRoll=2*2;
float KalmanAnglePitch=0, KalmanUncertaintyAnglePitch=2*2;
float Kalman1DOutput[]={0,0}; // angle prediction, uncertainity in prediction
void kalman_1d(float KalmanState, float KalmanUncertainty, float KalmanInput, float KalmanMeasurement) {
KalmanState=KalmanState+0.004*KalmanInput; // <--------------------------------- State vector declaration ; prediction
KalmanUncertainty=KalmanUncertainty + 0.004 * 0.004 * 4 * 4; // < ------------------ uncertainity prediction
float KalmanGain=KalmanUncertainty * 1/(1*KalmanUncertainty + 3 * 3); // <-------- kalman gain statement from uncertainity on prediction and measurement.
KalmanState=KalmanState+KalmanGain * (KalmanMeasurement-KalmanState); // <--------- update of state vector by measurement through kalman gain ; update of prediction.
KalmanUncertainty=(1-KalmanGain) * KalmanUncertainty; // <------------------------- uncertainity update
Kalman1DOutput[0]=KalmanState;
Kalman1DOutput[1]=KalmanUncertainty;
// Kalman input - roation rate
// kalman measurement - accelerometer angle
// kalman state - angle calculated with kalman filter
}
void gyro_signals(void) {
Wire.beginTransmission(0x68);
Wire.write(0x1A);
Wire.write(0x05);
Wire.endTransmission();
Wire.beginTransmission(0x68);
Wire.write(0x1C);
Wire.write(0x10);
Wire.endTransmission();
Wire.beginTransmission(0x68);
Wire.write(0x3B);
Wire.endTransmission();
Wire.requestFrom(0x68,6);
int16_t AccXLSB = Wire.read() << 8 | Wire.read();
int16_t AccYLSB = Wire.read() << 8 | Wire.read();
int16_t AccZLSB = Wire.read() << 8 | Wire.read();
Wire.beginTransmission(0x68);
Wire.write(0x1B);
Wire.write(0x8);
Wire.endTransmission();
Wire.beginTransmission(0x68);
Wire.write(0x43);
Wire.endTransmission();
Wire.requestFrom(0x68,6);
int16_t GyroX=Wire.read()<<8 | Wire.read();
int16_t GyroY=Wire.read()<<8 | Wire.read();
int16_t GyroZ=Wire.read()<<8 | Wire.read();
RateRoll=(float)GyroX/65.5;
RatePitch=(float)GyroY/65.5;
RateYaw=(float)GyroZ/65.5;
AccX=(float)AccXLSB/4096; // add/subtract respective calibration values for accelerometer
AccY=(float)AccYLSB/4096; // add/subtract respective calibration values for accelerometer
AccZ=(float)AccZLSB/4096; // add/subtract respective calibration values for accelerometer
AngleRoll=atan(AccY/sqrt(AccX*AccX+AccZ*AccZ))*1/(3.142/180);
AnglePitch=-atan(AccX/sqrt(AccY*AccY+AccZ*AccZ))*1/(3.142/180);
}
void setup() {
Serial.begin(57600);
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
Wire.setClock(400000);
Wire.begin();
delay(250);
Wire.beginTransmission(0x68);
Wire.write(0x6B);
Wire.write(0x00);
Wire.endTransmission();
for (RateCalibrationNumber=0; RateCalibrationNumber<2000; RateCalibrationNumber ++) {
gyro_signals();
RateCalibrationRoll+=RateRoll;
RateCalibrationPitch+=RatePitch;
RateCalibrationYaw+=RateYaw;
delay(1);
}
RateCalibrationRoll/=2000;
RateCalibrationPitch/=2000;
RateCalibrationYaw/=2000;
LoopTimer=micros();
}
void loop() {
gyro_signals();
RateRoll-=RateCalibrationRoll;
RatePitch-=RateCalibrationPitch;
RateYaw-=RateCalibrationYaw;
// roll kalman:
kalman_1d(KalmanAngleRoll, KalmanUncertaintyAngleRoll, RateRoll, AngleRoll);
KalmanAngleRoll=Kalman1DOutput[0];
KalmanUncertaintyAngleRoll=Kalman1DOutput[1];
// pitch kalman:
kalman_1d(KalmanAnglePitch, KalmanUncertaintyAnglePitch, RatePitch, AnglePitch);
KalmanAnglePitch=Kalman1DOutput[0];
KalmanUncertaintyAnglePitch=Kalman1DOutput[1];
Serial.print("Roll Angle [°]:");
Serial.print(KalmanAngleRoll);
Serial.print("Pitch Angle [°]:");
Serial.println(KalmanAnglePitch);
while (micros() - LoopTimer < 4000);
LoopTimer=micros();
}