Files
TweinStein/RTOS_SensorBoard/IMU.c

68 lines
2.2 KiB
C
Raw Normal View History

2026-06-12 02:55:04 -07:00
// IMU.c — GY-521 (MPU-6050) driver over I2C1
// Assumes I2C.c driver on PB2 (SCL) / PB3 (SDA) at 400 kHz.
// AD0 tied low for slave address 0x68.
#include <stdint.h>
#include "IMU.h"
#include "../inc/I2C.h"
volatile int16_t IMU_AccelX;
volatile int16_t IMU_AccelY;
volatile int16_t IMU_AccelZ;
volatile int16_t IMU_Temp;
volatile int16_t IMU_GyroX;
volatile int16_t IMU_GyroY;
volatile int16_t IMU_GyroZ;
// Error codes: 0 = OK, 1 = WHO_AM_I send failed, 2 = WHO_AM_I recv failed,
// 3 = WHO_AM_I mismatch, 4 = wake write failed,
// 5 = DLPF config write failed
int IMU_Init(void){
uint8_t who;
I2C_Init();
// WHO_AM_I sanity check (readable even while chip is asleep)
if(I2C_Send1(I2C_ADDRESS, MPU_WHO_AM_I) == 0) return 1;
if(I2C_RecvN(I2C_ADDRESS, &who, 1) == 0) return 2;
if(who != I2C_ADDRESS) return 3;
// Wake chip: clear SLEEP bit in PWR_MGMT_1
if(I2C_Send2(I2C_ADDRESS, MPU_PWR_MGMT_1, 0x00) == 0) return 4;
// Enable digital low-pass filter (reduces gyro/accel noise)
if(I2C_Send2(I2C_ADDRESS, MPU_CONFIG, IMU_DLPF_CFG) == 0) return 5;
return 0;
}
int IMU_Read(void){
uint8_t buf[14];
int32_t sum_ax = 0, sum_ay = 0, sum_az = 0;
int32_t sum_tp = 0;
int32_t sum_gx = 0, sum_gy = 0, sum_gz = 0;
for(int i = 0; i < IMU_AVG_SAMPLES; i++){
if(I2C_Send1(I2C_ADDRESS, MPU_ACCEL_XOUT_H) == 0) return 1;
if(I2C_RecvN(I2C_ADDRESS, buf, 14) == 0) return 2;
sum_ax += (int16_t)((buf[0] << 8) | buf[1]);
sum_ay += (int16_t)((buf[2] << 8) | buf[3]);
sum_az += (int16_t)((buf[4] << 8) | buf[5]);
sum_tp += (int16_t)((buf[6] << 8) | buf[7]);
sum_gx += (int16_t)((buf[8] << 8) | buf[9]);
sum_gy += (int16_t)((buf[10] << 8) | buf[11]);
sum_gz += (int16_t)((buf[12] << 8) | buf[13]);
}
IMU_AccelX = (int16_t)(sum_ax / IMU_AVG_SAMPLES);
IMU_AccelY = (int16_t)(sum_ay / IMU_AVG_SAMPLES);
IMU_AccelZ = (int16_t)(sum_az / IMU_AVG_SAMPLES);
IMU_Temp = (int16_t)(sum_tp / IMU_AVG_SAMPLES);
IMU_GyroX = (int16_t)(sum_gx / IMU_AVG_SAMPLES);
IMU_GyroY = (int16_t)(sum_gy / IMU_AVG_SAMPLES);
IMU_GyroZ = (int16_t)(sum_gz / IMU_AVG_SAMPLES);
return 0;
}