/* * MPU6000.c * * Created on: Nov 24, 2021 * Author: angoosh */ #include "MPU6000.h" #include "main.h" #include MPU6000_Typedef IMU; uint32_t sysclock = 0; void MPU6000_readGyro(); void MPU6000_readAccel(); int MPU6000_Init(I2C_HandleTypeDef *hi2c, uint32_t timeout); uint8_t MPU6000_readRegister(uint8_t reg); void MPU6000_Calibrate(); void MPU6000_Gyro(); void MPU6000_Raw_Data_Convert(); void MPU6000_readAll(); void MPU6000_Pedometer_Init(); void MPU6000_Pedometer(); void MPU6000_I2C_CallbackFunc(I2C_HandleTypeDef *hi2c); void IMU_Check_State(); madgwick_handle_t madgwick_handle; madgwick_quat_data_t quat_data; /** * @brief Converts raw sensor data to usable format * @retval none */ void MPU6000_Raw_Data_Convert(){ for(int i = 0; i < 6; i++){ IMU.accel_data[i] = IMU.all_data[i]; IMU.gyro_data[i] = IMU.all_data[i+8]; } IMU.g_x = (float)((int16_t)(IMU.gyro_data[0] * 256 + IMU.gyro_data[1]) - IMU.cal_g_x) / IMU.gyro_LSB; IMU.g_y = (float)((int16_t)(IMU.gyro_data[2] * 256 + IMU.gyro_data[3]) - IMU.cal_g_y) / IMU.gyro_LSB; IMU.g_z = (float)((int16_t)(IMU.gyro_data[4] * 256 + IMU.gyro_data[5]) - IMU.cal_g_z) / IMU.gyro_LSB; IMU.a_x = (float)((int16_t)(IMU.accel_data[0] * 256 + IMU.accel_data[1]) - IMU.cal_a_x) / IMU.accel_LSB; IMU.a_y = (float)((int16_t)(IMU.accel_data[2] * 256 + IMU.accel_data[3]) - IMU.cal_a_y) / IMU.accel_LSB; IMU.a_z = (float)((int16_t)(IMU.accel_data[4] * 256 + IMU.accel_data[5]) - IMU.cal_a_z) / IMU.accel_LSB; } /** * @brief Read all data on the sensor * @retval none */ void MPU6000_readAll(){ HAL_I2C_Mem_Read_IT(IMU.peripheral,(MPU6000_ADDRESS << 1),ACCEL_XOUT_H,1,IMU.all_data,14); } /** * @brief Read only gyroscope * @retval none */ void MPU6000_readGyro(){ switch(GYRO_RANGE){ case 0: IMU.gyro_LSB = 131; case 1: IMU.gyro_LSB = 65.5; case 2: IMU.gyro_LSB = 32.8; case 3: IMU.gyro_LSB = 16.4; default: IMU.gyro_LSB = 16.4; } HAL_I2C_Mem_Read_IT(IMU.peripheral,(MPU6000_ADDRESS << 1),GYRO_XOUT_H,1,IMU.gyro_data,6); } /** * @brief Read only accelerometer * @retval none */ void MPU6000_readAccel(){ switch(GYRO_RANGE){ case 0: IMU.accel_LSB = 16384; case 1: IMU.accel_LSB = 8192; case 2: IMU.accel_LSB = 4096; case 3: IMU.accel_LSB = 2048; default: IMU.accel_LSB = 2048; } HAL_I2C_Mem_Read_IT(IMU.peripheral,(MPU6000_ADDRESS << 1),ACCEL_XOUT_H,1,IMU.accel_data,6); } /** * @brief Converts accelerometer data to roll pitch and yaw * @retval none */ void MPU6000_Gyro(){ IMU.roll = atan2(IMU.a_y, IMU.a_z) * 180.0 / M_PI; IMU.pitch = atan2(IMU.a_x, IMU.a_z) * 180.0 / M_PI; IMU.yaw = atan2(IMU.a_x, IMU.a_y) * 180.0 / M_PI; } /** * @brief Initialization function of MPU6000 library * @param i2c peripheral to be used * @param i2c timeout * @retval none */ int MPU6000_Init(I2C_HandleTypeDef *hi2c, uint32_t timeout){ uint8_t data; IMU.accel_LSB = 16384; IMU.gyro_LSB = 131; IMU.peripheral = hi2c; IMU.timeout = timeout; IMU.dataReady = 0; madgwick_cfg_t madgwick_cfg; madgwick_cfg.beta = MADGWICK_BETA; madgwick_cfg.sample_freq = MADGWICK_SAMPLE_RATE; madgwick_handle = madgwick_init(&madgwick_cfg); if(HAL_I2C_IsDeviceReady(hi2c, (uint16_t)(MPU6000_ADDRESS << 1), 3, IMU.timeout) != 0){ return 1; } data = 0x00; HAL_I2C_Mem_Write(IMU.peripheral,(MPU6000_ADDRESS << 1),PWR_MGMT_1,1,&data,1,IMU.timeout); HAL_Delay(200); data = 0x07; HAL_I2C_Mem_Write(IMU.peripheral,(MPU6000_ADDRESS << 1),SMPLRT_DIV,1,&data,1,IMU.timeout); HAL_Delay(50); data = 0x00; HAL_I2C_Mem_Write(IMU.peripheral,(MPU6000_ADDRESS << 1),ACCEL_CONFIG,1,&data,1,IMU.timeout); HAL_Delay(50); data = 0x00; HAL_I2C_Mem_Write(IMU.peripheral,(MPU6000_ADDRESS << 1),GYRO_CONFIG,1,&data,1,IMU.timeout); HAL_Delay(50); // data = 0; // HAL_I2C_Mem_Write(IMU.peripheral,(MPU6000_ADDRESS << 1),PWR_MGMT_1,1,&data,1,IMU.timeout); // HAL_Delay(50); // data = 0x08;//0x28 pro lowpower rezim s frekvenci 1.25Hz // HAL_I2C_Mem_Write(IMU.peripheral,(MPU6000_ADDRESS << 1),PWR_MGMT_1,1,&data,1,IMU.timeout); // HAL_Delay(50); data = 0x00; HAL_I2C_Mem_Write(IMU.peripheral,(MPU6000_ADDRESS << 1),PWR_MGMT_2,1,&data,1,IMU.timeout); HAL_Delay(50); MPU6000_readAll(); return 0; } /** * @brief Read certain register of sensor * @param register address * @retval value of register */ uint8_t MPU6000_readRegister(uint8_t reg){ uint8_t reg_data[1]; HAL_I2C_Mem_Read(IMU.peripheral,(MPU6000_ADDRESS << 1),reg,1,reg_data,1,IMU.timeout); HAL_Delay(50); return reg_data[0]; } /** * @brief Calibrate the sensor * @retval none */ void MPU6000_Calibrate(){ uint8_t data[1] = {GYRO_XOUT_H}; uint8_t data_out[6]; HAL_I2C_Master_Transmit(IMU.peripheral, (MPU6000_ADDRESS << 1), data, 1, IMU.timeout); HAL_I2C_Master_Receive(IMU.peripheral, (MPU6000_ADDRESS << 1), data_out, 6, IMU.timeout); IMU.cal_g_x = data_out[0] * 256 + data_out[1]; IMU.cal_g_y = data_out[2] * 256 + data_out[3]; IMU.cal_g_z = data_out[4] * 256 + data_out[5]; data[0] = ACCEL_XOUT_H; HAL_I2C_Master_Transmit(IMU.peripheral, (MPU6000_ADDRESS << 1), data, 1, IMU.timeout); HAL_I2C_Master_Receive(IMU.peripheral, (MPU6000_ADDRESS << 1), data_out, 6, IMU.timeout); IMU.cal_a_x = data_out[0] * 256 + data_out[1]; IMU.cal_a_y = data_out[2] * 256 + data_out[3]; IMU.cal_a_z = data_out[4] * 256 + data_out[5]; } /** * @brief Initialize pedometer * @retval none */ void MPU6000_Pedometer_Init(){ IMU.pedo_index = 1; IMU.pedo_steps = 0; IMU.pedo_vector[0] = 0; IMU.pedo_flag = 0; IMU.pedo_threshold = 2000; IMU.pedo_vector_max = 0; IMU.pedo_vector_avg = 0; IMU.pedo_vector_samples = 0; sysclock = HAL_RCC_GetSysClockFreq(); } /** * @brief Pedometer calculations * @retval none */ void MPU6000_Pedometer(){ IMU.pedo_a_x[IMU.pedo_index] = IMU.a_x * IMU.accel_LSB; IMU.pedo_a_y[IMU.pedo_index] = IMU.a_y * IMU.accel_LSB; IMU.pedo_a_z[IMU.pedo_index] = IMU.a_z * IMU.accel_LSB; IMU.pedo_work_vector[IMU.pedo_index] = sqrt(((IMU.pedo_a_x[IMU.pedo_index] - IMU.pedo_avg_a_x) * (IMU.pedo_a_x[IMU.pedo_index] - IMU.pedo_avg_a_x)) + ((IMU.pedo_a_y[IMU.pedo_index] - IMU.pedo_avg_a_y) * (IMU.pedo_a_y[IMU.pedo_index] - IMU.pedo_avg_a_y)) + ((IMU.pedo_a_z[IMU.pedo_index] - IMU.pedo_avg_a_z) * (IMU.pedo_a_z[IMU.pedo_index] - IMU.pedo_avg_a_z))); IMU.pedo_vector[0] = (IMU.pedo_work_vector[IMU.pedo_index] + IMU.pedo_work_vector[IMU.pedo_index - 1]) / 2 ; if(IMU.pedo_vector[0] > IMU.pedo_threshold && IMU.pedo_flag == 0){ IMU.pedo_steps = IMU.pedo_steps + 1; IMU.pedo_last_step_timestamp = HAL_GetTick(); IMU.pedo_flag = 1; } else if (IMU.pedo_vector[0] > IMU.pedo_threshold && IMU.pedo_flag == 1){ // Don't Count } if (IMU.pedo_vector[0] < IMU.pedo_threshold && IMU.pedo_flag == 1){ IMU.pedo_flag = 0; } if (IMU.pedo_steps < 0) { IMU.pedo_steps = 0; } IMU.pedo_index++; if(IMU.pedo_work_vector[IMU.pedo_index] > IMU.pedo_vector_max){ IMU.pedo_vector_max = IMU.pedo_work_vector[IMU.pedo_index]; } IMU.pedo_vector_avg = IMU.pedo_vector_avg + (IMU.pedo_vector[0] - IMU.pedo_vector_avg) / ((float)IMU.pedo_vector_samples + 1); IMU.pedo_vector_samples ++; if(IMU.pedo_index >= 100){ IMU.pedo_index = 1; IMU.pedo_vector[0] = 0; float sum[3] = {0}; for(int i = 0; i < 100; i++){ sum[0] = IMU.pedo_a_x[i] + sum[0]; sum[1] = IMU.pedo_a_y[i] + sum[1]; sum[2] = IMU.pedo_a_z[i] + sum[2]; } IMU.pedo_avg_a_x = sum[0] / 100.0; IMU.pedo_avg_a_y = sum[1] / 100.0; IMU.pedo_avg_a_z = sum[2] / 100.0; } } /** * @brief Function to be put into i2c callback function * @retval none */ void MPU6000_I2C_CallbackFunc(I2C_HandleTypeDef *hi2c){ if(hi2c -> Instance == IMU.peripheral->Instance){ IMU.peripheral->Instance->CR1 &= ~(1 << 1); IMU.dataReady = 1; // MPU6000_Raw_Data_Convert(); // madgwick_update_6dof(madgwick_handle, IMU.g_x * DEG2RAD, IMU.g_y * DEG2RAD, IMU.g_z * DEG2RAD, IMU.a_x, IMU.a_y, IMU.a_z); // madgwick_get_quaternion(madgwick_handle, &quat_data); // IMU.roll = 180.0 / 3.14 * atan2(2 * (quat_data.q0 * quat_data.q1 + quat_data.q2 * quat_data.q3), 1 - 2 * (quat_data.q1 * quat_data.q1 + quat_data.q2 * quat_data.q2)); // IMU.pitch = 180.0 / 3.14 * asin(2 * (quat_data.q0 * quat_data.q2 - quat_data.q3 * quat_data.q1)); // IMU.yaw = 180.0 / 3.14 * atan2f(quat_data.q0 * quat_data.q3 + quat_data.q1 * quat_data.q2, 0.5f - quat_data.q2 * quat_data.q2 - quat_data.q3 * quat_data.q3); // // IMU.dataReady = 0; // MPU6000_readAll(); } } void IMU_Check_State(){ if(IMU.dataReady){ MPU6000_Raw_Data_Convert(); madgwick_update_6dof(madgwick_handle, IMU.g_x * DEG2RAD, IMU.g_y * DEG2RAD, IMU.g_z * DEG2RAD, IMU.a_x, IMU.a_y, IMU.a_z); madgwick_get_quaternion(madgwick_handle, &quat_data); IMU.roll = 180.0 / 3.14 * atan2(2 * (quat_data.q0 * quat_data.q1 + quat_data.q2 * quat_data.q3), 1 - 2 * (quat_data.q1 * quat_data.q1 + quat_data.q2 * quat_data.q2)); IMU.pitch = 180.0 / 3.14 * asin(2 * (quat_data.q0 * quat_data.q2 - quat_data.q3 * quat_data.q1)); IMU.yaw = 180.0 / 3.14 * atan2f(quat_data.q0 * quat_data.q3 + quat_data.q1 * quat_data.q2, 0.5f - quat_data.q2 * quat_data.q2 - quat_data.q3 * quat_data.q3); IMU.dataReady = 0; MPU6000_readAll(); } }