Загрузка данных
#include <Wire.h>
#define DEV_ADDR 0x68
int16_t ax_raw, ay_raw, az_raw;
int16_t temp_raw;
int16_t gx_raw, gy_raw, gz_raw;
// Исходный базис датчика S
float ax, ay, az;
float wx, wy, wz;
// Новый базис B
float aBx, aBy, aBz;
float p, q, r;
// Углы
float roll = 0;
float pitch = 0;
float yaw = 0;
float beta_z = 0;
const float alpha = 0.02;
unsigned long lastTime;
void readMPU() {
Wire.beginTransmission(DEV_ADDR);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(DEV_ADDR, 14, true);
ax_raw = (Wire.read() << 8) | Wire.read();
ay_raw = (Wire.read() << 8) | Wire.read();
az_raw = (Wire.read() << 8) | Wire.read();
temp_raw = (Wire.read() << 8) | Wire.read();
gx_raw = (Wire.read() << 8) | Wire.read();
gy_raw = (Wire.read() << 8) | Wire.read();
gz_raw = (Wire.read() << 8) | Wire.read();
// Ускорение в м/с^2
ax = ax_raw / 16384.0 * 9.81;
ay = ay_raw / 16384.0 * 9.81;
az = az_raw / 16384.0 * 9.81;
// Гироскоп в рад/с
wx = gx_raw / 131.0 * PI / 180.0;
wy = gy_raw / 131.0 * PI / 180.0;
wz = gz_raw / 131.0 * PI / 180.0;
// Переход в новый базис
aBx = -ay;
aBy = ax;
aBz = az;
p = -wy;
q = wx;
r = wz;
}
void setup() {
Serial.begin(115200);
Wire.begin();
// Разбудить MPU6050
Wire.beginTransmission(DEV_ADDR);
Wire.write(0x6B);
Wire.write(0);
Wire.endTransmission(true);
delay(100);
// Калибровка гироскопа по Z
// Датчик не двигать
float sum = 0;
for (int i = 0; i < 500; i++) {
readMPU();
sum += r;
delay(3);
}
beta_z = sum / 500.0;
// Начальные углы
readMPU();
roll = atan2(aBy, aBz);
pitch = atan2(
-aBx,
sqrt(aBy * aBy + aBz * aBz)
);
yaw = 0;
lastTime = micros();
}
void loop() {
readMPU();
unsigned long now = micros();
float dt = (now - lastTime) / 1000000.0;
lastTime = now;
// =====================================
// ИСХОДНЫЕ ДАННЫЕ
// =====================================
Serial.println("===== SOURCE MPU6050 =====");
Serial.print("ax = ");
Serial.print(ax);
Serial.print(" ay = ");
Serial.print(ay);
Serial.print(" az = ");
Serial.print(az);
Serial.println(" m/s^2");
Serial.print("wx = ");
Serial.print(wx);
Serial.print(" wy = ");
Serial.print(wy);
Serial.print(" wz = ");
Serial.print(wz);
Serial.println(" rad/s");
// =====================================
// ЗАДАНИЕ 1
// ПЕРЕХОД В НОВЫЙ БАЗИС
// =====================================
Serial.println("===== TASK 1 =====");
Serial.print("aBx = ");
Serial.print(aBx);
Serial.print(" aBy = ");
Serial.print(aBy);
Serial.print(" aBz = ");
Serial.print(aBz);
Serial.println(" m/s^2");
Serial.print("p = ");
Serial.print(p);
Serial.print(" q = ");
Serial.print(q);
Serial.print(" r = ");
Serial.print(r);
Serial.println(" rad/s");
// =====================================
// ЗАДАНИЕ 2
// ROLL, PITCH, YAW
// =====================================
float roll_acc = atan2(aBy, aBz);
float pitch_acc = atan2(
-aBx,
sqrt(aBy * aBy + aBz * aBz)
);
roll =
(1.0 - alpha) *
(
roll +
dt *
(
p +
q * sin(roll) * tan(pitch) +
r * cos(roll) * tan(pitch)
)
)
+
alpha * roll_acc;
pitch =
(1.0 - alpha) *
(
pitch +
dt *
(
q * cos(roll) -
r * sin(roll)
)
)
+
alpha * pitch_acc;
yaw = yaw + dt * (r - beta_z);
// Перевод в градусы
float roll_deg = roll * 180.0 / PI;
float pitch_deg = pitch * 180.0 / PI;
float yaw_deg = yaw * 180.0 / PI;
Serial.println("===== TASK 2 =====");
Serial.print("Roll = ");
Serial.print(roll_deg);
Serial.print(" deg ");
Serial.print("Pitch = ");
Serial.print(pitch_deg);
Serial.print(" deg ");
Serial.print("Yaw = ");
Serial.print(yaw_deg);
Serial.println(" deg");
Serial.println("==============================");
delay(100);
}