rm_balance/User/task/atti_esit.c
2026-02-04 04:10:37 +08:00

184 lines
6.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
atti_esit Task
*/
/* Includes ----------------------------------------------------------------- */
#include "task/user_task.h"
/* USER INCLUDE BEGIN */
#include "bsp/gpio.h"
#include "bsp/mm.h"
#include "bsp/pwm.h"
#include "component/ahrs.h"
#include "component/QuaternionEKF.h"
#include "component/pid.h"
#include "device/bmi088.h"
#include "device/mrobot.h"
#include "module/balance_chassis.h"
#include "task/user_task.h"
#include <stdlib.h>
/* USER INCLUDE END */
/* Private typedef ---------------------------------------------------------- */
/* Private define ----------------------------------------------------------- */
/* Private macro ------------------------------------------------------------ */
/* Private variables -------------------------------------------------------- */
/* USER STRUCT BEGIN */
BMI088_t bmi088;
#ifndef USE_QEKF
AHRS_t gimbal_ahrs;
AHRS_Magn_t magn;
#endif
AHRS_Eulr_t eulr_to_send;
Chassis_IMU_t imu_for_chassis;
KPID_t imu_temp_ctrl_pid;
/* 用于 MRobot 显示的 IMU 数据结构 */
typedef struct {
BMI088_t *bmi088;
AHRS_Eulr_t *euler;
} IMU_Display_Data_t;
static IMU_Display_Data_t imu_display_data = {
.bmi088 = &bmi088,
.euler = &eulr_to_send,
};
/*默认校准参数*/
BMI088_Cali_t cali_bmi088 = {
.gyro_offset = {-0.00147764047f, -0.00273479894f, 0.00154074503f},
};
static const KPID_Params_t imu_temp_ctrl_pid_param = {
.k = 0.1f,
.p = 0.15f,
.i = 0.01f,
.d = 0.02f,
.i_limit = 1.0f,
.out_limit = 1.0f,
};
/* USER STRUCT END */
/* Private function --------------------------------------------------------- */
/* BMI088 设备信息打印回调 */
static void bmi088_print_callback(void *device_data, char *buffer, uint16_t buffer_size) {
IMU_Display_Data_t *data = (IMU_Display_Data_t *)device_data;
/* 将浮点数转换为整数和小数部分,避免 printf 浮点数支持问题 */
int accl_x_int = (int)(data->bmi088->accl.x);
int accl_x_frac = (int)((data->bmi088->accl.x - accl_x_int) * 1000);
int accl_y_int = (int)(data->bmi088->accl.y);
int accl_y_frac = (int)((data->bmi088->accl.y - accl_y_int) * 1000);
int accl_z_int = (int)(data->bmi088->accl.z);
int accl_z_frac = (int)((data->bmi088->accl.z - accl_z_int) * 1000);
int gyro_x_int = (int)(data->bmi088->gyro.x);
int gyro_x_frac = (int)((data->bmi088->gyro.x - gyro_x_int) * 1000);
int gyro_y_int = (int)(data->bmi088->gyro.y);
int gyro_y_frac = (int)((data->bmi088->gyro.y - gyro_y_int) * 1000);
int gyro_z_int = (int)(data->bmi088->gyro.z);
int gyro_z_frac = (int)((data->bmi088->gyro.z - gyro_z_int) * 1000);
int temp_int = (int)(data->bmi088->temp);
int temp_frac = (int)((data->bmi088->temp - temp_int) * 100);
float roll_deg = data->euler->rol * 57.2958f;
float pitch_deg = data->euler->pit * 57.2958f;
float yaw_deg = data->euler->yaw * 57.2958f;
int roll_int = (int)roll_deg;
int roll_frac = (int)((roll_deg - roll_int) * 100);
int pitch_int = (int)pitch_deg;
int pitch_frac = (int)((pitch_deg - pitch_int) * 100);
int yaw_int = (int)yaw_deg;
int yaw_frac = (int)((yaw_deg - yaw_int) * 100);
snprintf(buffer, buffer_size,
"加速度计: X=%d.%03d Y=%d.%03d Z=%d.%03d m/s²\r\n"
"陀螺仪: X=%d.%03d Y=%d.%03d Z=%d.%03d rad/s\r\n"
"温度: %d.%02d °C\r\n"
"欧拉角: Roll=%d.%02d Pitch=%d.%02d Yaw=%d.%02d °\r\n",
accl_x_int, abs(accl_x_frac), accl_y_int, abs(accl_y_frac), accl_z_int, abs(accl_z_frac),
gyro_x_int, abs(gyro_x_frac), gyro_y_int, abs(gyro_y_frac), gyro_z_int, abs(gyro_z_frac),
temp_int, abs(temp_frac),
roll_int, abs(roll_frac), pitch_int, abs(pitch_frac), yaw_int, abs(yaw_frac));
}
/* Exported functions ------------------------------------------------------- */
void Task_atti_esit(void *argument) {
(void)argument; /* 未使用argument消除警告 */
osDelay(ATTI_ESIT_INIT_DELAY); /* 延时一段时间再开启任务 */
/* USER CODE INIT BEGIN */
BMI088_Init(&bmi088, &cali_bmi088);
#ifdef USE_QEKF
QEKF_Init(10.0f, 0.001f, 1000000.0f, 0.9996f, 0.0f);
#else
AHRS_Init(&gimbal_ahrs, &magn, BMI088_GetUpdateFreq(&bmi088));
#endif
PID_Init(&imu_temp_ctrl_pid, KPID_MODE_NO_D,
1.0f / BMI088_GetUpdateFreq(&bmi088), &imu_temp_ctrl_pid_param);
BSP_PWM_Start(BSP_PWM_IMU_HEAT);
/* 注册 BMI088 设备到 MRobot */
MRobot_RegisterDevice("bmi088", MROBOT_DEVICE_TYPE_IMU, &imu_display_data, bmi088_print_callback);
/* USER CODE INIT END */
while (1) {
/* USER CODE BEGIN */
BMI088_WaitNew();
BMI088_AcclStartDmaRecv();
BMI088_AcclWaitDmaCplt();
BMI088_GyroStartDmaRecv();
BMI088_GyroWaitDmaCplt();
/* 锁住RTOS内核防止数据解析过程中断造成错误 */
osKernelLock();
/* 接收完所有数据后,把数据从原始字节加工成方便计算的数据 */
BMI088_ParseAccl(&bmi088);
BMI088_ParseGyro(&bmi088);
// IST8310_Parse(&ist8310);
/* 根据设备接收到的数据进行姿态解析 */
#ifdef USE_QEKF
QEKF_Update(bmi088.gyro.x, bmi088.gyro.y, bmi088.gyro.z,
bmi088.accl.x, bmi088.accl.y, bmi088.accl.z,
1.0f / BMI088_GetUpdateFreq(&bmi088));
/* 从EKF获取欧拉角 */
eulr_to_send.rol = QEKF_INS.roll;
eulr_to_send.pit = QEKF_INS.pitch;
eulr_to_send.yaw = QEKF_INS.yaw;
#else
AHRS_Update(&gimbal_ahrs, &bmi088.accl, &bmi088.gyro, &magn);
/* 根据解析出来的四元数计算欧拉角 */
AHRS_GetEulr(&eulr_to_send, &gimbal_ahrs);
#endif
/* 加速度计数据绕z轴旋转270度: (x,y,z) -> (y,-x,z) */
imu_for_chassis.accl.x = bmi088.accl.y;
imu_for_chassis.accl.y = -bmi088.accl.x;
imu_for_chassis.accl.z = bmi088.accl.z;
/* 陀螺仪数据绕z轴旋转270度: (x,y,z) -> (y,-x,z) */
imu_for_chassis.gyro.x = bmi088.gyro.y;
imu_for_chassis.gyro.y = -bmi088.gyro.x;
imu_for_chassis.gyro.z = bmi088.gyro.z;
/* 欧拉角绕z轴旋转270度 */
imu_for_chassis.euler.rol = eulr_to_send.pit;
imu_for_chassis.euler.pit = -eulr_to_send.rol;
imu_for_chassis.euler.yaw = eulr_to_send.yaw - 1.57079632679f; // -90度
osMessageQueueReset(
task_runtime.msgq.chassis.imu); // 重置消息队列,防止阻塞
osMessageQueuePut(task_runtime.msgq.chassis.imu, &imu_for_chassis, 0,
0); // 非阻塞发送底盘IMU数据
BSP_PWM_SetComp(BSP_PWM_IMU_HEAT, PID_Calc(&imu_temp_ctrl_pid, 40.5f,
bmi088.temp, 0.0f, 0.0f));
osKernelUnlock();
/* USER CODE END */
}
}