存档
This commit is contained in:
@ -4,7 +4,7 @@
|
||||
#include "os/os_api.h"
|
||||
#include "../xtell.h"
|
||||
|
||||
// #define ENABLE_XLOG 1
|
||||
#define ENABLE_XLOG 1
|
||||
#ifdef xlog
|
||||
#undef xlog
|
||||
#endif
|
||||
@ -270,7 +270,7 @@ void SL_SC7U22_RawData_Read(signed short * acc_data_buf,signed short * gyr_data_
|
||||
gyr_data_buf[1] =(signed short)((((unsigned char)raw_data[8])* 256) + ((unsigned char)raw_data[9]));//GYRY-16位
|
||||
gyr_data_buf[2] =(signed short)((((unsigned char)raw_data[10])* 256) + ((unsigned char)raw_data[11]));//GYRZ-16位
|
||||
|
||||
xlog("RawData:AX=%d,AY=%d,AZ=%d,GX=%d,GY=%d,GZ=%d\r\n",acc_data_buf[0],acc_data_buf[1],acc_data_buf[2],gyr_data_buf[0],gyr_data_buf[1],gyr_data_buf[2]);
|
||||
// xlog("RawData:AX=%d,AY=%d,AZ=%d,GX=%d,GY=%d,GZ=%d\r\n",acc_data_buf[0],acc_data_buf[1],acc_data_buf[2],gyr_data_buf[0],gyr_data_buf[1],gyr_data_buf[2]);
|
||||
|
||||
}
|
||||
#else
|
||||
@ -666,7 +666,7 @@ float angle0[3] = {0, 0, 0}, angle_dot0[3] = {0, 0, 0}; // 姿态角的估计值
|
||||
// Q_gyro: 过程噪声协方差,表示陀螺仪偏置(bias)的不确定性。
|
||||
// R_angle: 测量噪声协方差,表示通过加速度计计算出的角度测量值的不确定性。值越小,表示越相信加速度计的测量结果。
|
||||
// dt: 采样时间间隔(单位:秒),这里是10ms (0.01s),对应100Hz的采样率。
|
||||
//float Q_angle=0.0003, Q_gyro=0.001, R_angle=0.005, dt=0.005;//5ms ST
|
||||
// float Q_angle=0.0003, Q_gyro=0.001, R_angle=0.005, dt=0.005;//5ms ST
|
||||
//float Q_angle=0.00001, Q_gyro=0.00001, R_angle=0.005, dt=0.0025;//5ms ST
|
||||
float Q_angle = 0.0003, Q_gyro = 0.001, R_angle = 0.005, dt = 0.01; //10ms
|
||||
|
||||
@ -1166,72 +1166,321 @@ unsigned char get_calibration_state(void){
|
||||
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
//-----------------------------------------
|
||||
调用示例-by_lmx:
|
||||
#if 0
|
||||
// --- 新增:定义自动化校准状态 ---
|
||||
typedef enum {
|
||||
CAL_STATE_IDLE, // 0: 空闲,未开始校准
|
||||
CAL_STATE_WAIT_STILL, // 1: 等待设备静止
|
||||
CAL_STATE_COLLECTING, // 2: 正在采集数据
|
||||
CAL_STATE_PAUSE_BETWEEN_FACES, // 3: 面与面之间的暂停
|
||||
CAL_STATE_CALCULATING, // 4: 正在计算最终参数
|
||||
CAL_STATE_FINISHED, // 5: 校准完成,参数有效
|
||||
} SL_AutoCalib_State;
|
||||
|
||||
// --- 新增:定义校准的面 ---
|
||||
typedef enum {
|
||||
CAL_FACE_POS_Z = 0, // Z+
|
||||
CAL_FACE_NEG_Z, // Z-
|
||||
CAL_FACE_POS_Y, // Y+
|
||||
CAL_FACE_NEG_Y, // Y-
|
||||
CAL_FACE_POS_X, // X+
|
||||
CAL_FACE_NEG_X, // X-
|
||||
CAL_FACE_COUNT // 总面数
|
||||
} SL_Calib_Face;
|
||||
|
||||
// --- 校准参数常量 ---
|
||||
#define CAL_STILL_TIME_THRESHOLD 190 // 需要静止的采样周期数 (约1.9s)
|
||||
#define CAL_SAMPLES_TO_COLLECT 50 // 每个面采集的样本数
|
||||
#define CAL_PAUSE_SECONDS 4 // 面间暂停秒数
|
||||
|
||||
// --- 修改/新增 全局变量 ---
|
||||
static SL_AutoCalib_State g_calib_state = CAL_STATE_IDLE;
|
||||
static SL_Calib_Face g_current_calib_face = CAL_FACE_POS_Z;
|
||||
static unsigned short g_still_count = 0;
|
||||
static unsigned char g_samples_collected = 0;
|
||||
static unsigned short g_pause_timer = 0;
|
||||
|
||||
static long g_calib_data_sum[6] = {0};
|
||||
static signed short g_calib_avg_data[CAL_FACE_COUNT][6] = {{0}};
|
||||
|
||||
static float g_acc_offset[3] = {0.0f};
|
||||
static float g_acc_scale[3] = {1.0f, 1.0f, 1.0f};
|
||||
static signed short g_gyro_offset[3] = {0}; // 陀螺仪偏移用整数更符合原始数据类型
|
||||
|
||||
static unsigned char g_calibration_valid = 0;
|
||||
|
||||
|
||||
//1.
|
||||
// 定义用于存放传感器数据的缓冲区
|
||||
static signed short acc_raw_data[3]; // [0]: acc_x, [1]: acc_y, [2]: acc_z
|
||||
static signed short gyr_raw_data[3]; // [0]: gyr_x, [1]: gyr_y, [2]: gyr_z
|
||||
static signed short combined_raw_data[6]; // 用于合并 acc 和 gyr 数据
|
||||
static float final_angle_data[3]; // [0]: Pitch, [1]: Roll, [2]: Yaw
|
||||
|
||||
// 传感器数据处理任务
|
||||
void sensor_processing_task(void *priv)
|
||||
#if (ACC_RANGE == 2)
|
||||
#define G_VALUE (16384.0f)
|
||||
#elif (ACC_RANGE == 4)
|
||||
#define G_VALUE (8192.0f)
|
||||
#elif (ACC_RANGE == 8)
|
||||
#define G_VALUE (4096.0f)
|
||||
#elif (ACC_RANGE == 16)
|
||||
#define G_VALUE (2048.0f)
|
||||
#endif
|
||||
/**
|
||||
* @brief IMU姿态解算函数,增加了六面校准功能。
|
||||
* @param calibration_cmd 校准命令,来自 SL_Calibration_Cmd 枚举。
|
||||
* @param acc_gyro_input 指向6轴原始数据的指针 (AccX,Y,Z, GyroX,Y,Z)。
|
||||
* @param Angle_output 指向3轴姿态角输出的指针 (Pitch, Roll, Yaw)。
|
||||
* @param yaw_rst Yaw轴复位标志。
|
||||
* @return unsigned char 0: 正在校准, 1: 计算成功, 2: 校准未完成,无法计算。
|
||||
*/
|
||||
unsigned char SIX_SL_SC7U22_Angle_Output(unsigned char auto_calib_start, signed short *acc_gyro_input, float *Angle_output, unsigned char yaw_rst)
|
||||
{
|
||||
while (1) {
|
||||
// 4. 周期性调用读取函数,获取原始数据
|
||||
SL_SC7U22_RawData_Read(acc_raw_data, gyr_raw_data);
|
||||
unsigned char sl_i = 0;
|
||||
|
||||
// 5. 合并加速度和角速度数据到一个数组中
|
||||
// SL_SC7U22_Angle_Output 函数需要一个包含6个元素的数组作为输入
|
||||
memcpy(&combined_raw_data[0], acc_raw_data, sizeof(acc_raw_data));
|
||||
memcpy(&combined_raw_data[3], gyr_raw_data, sizeof(gyr_raw_data));
|
||||
// 启动自动化校准流程
|
||||
if (auto_calib_start == 1 && g_calib_state == CAL_STATE_IDLE) {
|
||||
g_calib_state = CAL_STATE_WAIT_STILL;
|
||||
g_current_calib_face = CAL_FACE_POS_Z;
|
||||
g_calibration_valid = 0;
|
||||
xlog("\n\n===== Auto-Calibration Started =====\r\n");
|
||||
xlog("Step 1/%d: Place device with Z-axis pointing UPWARD and keep it still.\r\n", CAL_FACE_COUNT);
|
||||
}
|
||||
|
||||
// 6. 调用姿态解算函数
|
||||
// 参数: (校准使能, 输入的6轴数据, 输出的角度数据, Yaw轴复位标志)
|
||||
// calibration_en = 1: 让函数内部自动管理校准过程
|
||||
// yaw_rst = 0: 不复位Yaw角
|
||||
unsigned char status = SL_SC7U22_Angle_Output(1, combined_raw_data, final_angle_data, 0);
|
||||
|
||||
// 7. 检查函数返回的状态
|
||||
if (status == 1) {
|
||||
// 计算成功,final_angle_data 中的数据有效
|
||||
xlog("Pitch: %.2f, Roll: %.2f, Yaw: %.2f\n", final_angle_data[0], final_angle_data[1], final_angle_data[2]);
|
||||
} else if (status == 0) {
|
||||
// 传感器正在进行静态校准,此时角度数据可能不准确
|
||||
xlog("Sensor is calibrating...\n");
|
||||
} else {
|
||||
// status == 2, 表示校准未完成或发生错误
|
||||
xlog("Angle calculation error or calibration not finished.\n");
|
||||
// =================================================================================
|
||||
// 步骤 1: 自动化校准状态机
|
||||
// ---------------------------------------------------------------------------------
|
||||
if (g_calib_state != CAL_STATE_IDLE && g_calib_state != CAL_STATE_FINISHED) {
|
||||
// --- 静止检测 (通用逻辑) ---
|
||||
unsigned short acc_delta = 0, gyro_delta = 0;
|
||||
for (sl_i = 0; sl_i < 3; sl_i++) {
|
||||
acc_delta += SL_GetAbsShort(acc_gyro_input[sl_i] - Temp_Accgyro[sl_i]);
|
||||
gyro_delta += SL_GetAbsShort(acc_gyro_input[3 + sl_i] - Temp_Accgyro[3 + sl_i]);
|
||||
}
|
||||
for (sl_i = 0; sl_i < 6; sl_i++) Temp_Accgyro[sl_i] = acc_gyro_input[sl_i];
|
||||
|
||||
int is_still = (acc_delta < 160) && (gyro_delta < 40);
|
||||
|
||||
// 延时一段时间,例如10ms (对应100Hz)
|
||||
os_time_dly(1);
|
||||
switch (g_calib_state) {
|
||||
case CAL_STATE_WAIT_STILL:
|
||||
if (is_still) {
|
||||
if (++g_still_count >= CAL_STILL_TIME_THRESHOLD) {
|
||||
g_calib_state = CAL_STATE_COLLECTING;
|
||||
g_samples_collected = 0;
|
||||
g_still_count = 0;
|
||||
for(sl_i = 0; sl_i < 6; sl_i++) g_calib_data_sum[sl_i] = 0;
|
||||
xlog("Device is still. Collecting data...\r\n");
|
||||
}
|
||||
} else {
|
||||
g_still_count = 0; // 如果移动则重置计数
|
||||
}
|
||||
break;
|
||||
|
||||
case CAL_STATE_COLLECTING:
|
||||
if (!is_still) { // 如果在采集中移动了,则重新开始等待静止
|
||||
g_calib_state = CAL_STATE_WAIT_STILL;
|
||||
g_still_count = 0;
|
||||
xlog("Movement detected! Please keep the device still.\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (g_samples_collected < CAL_SAMPLES_TO_COLLECT) {
|
||||
for (sl_i = 0; sl_i < 6; sl_i++) {
|
||||
g_calib_data_sum[sl_i] += acc_gyro_input[sl_i];
|
||||
}
|
||||
g_samples_collected++;
|
||||
} else {
|
||||
// 当前面采集完成
|
||||
for (sl_i = 0; sl_i < 6; sl_i++) {
|
||||
g_calib_avg_data[g_current_calib_face][sl_i] = g_calib_data_sum[sl_i] / CAL_SAMPLES_TO_COLLECT;
|
||||
}
|
||||
xlog("Face %d data collected.\r\n", g_current_calib_face + 1);
|
||||
|
||||
if (g_current_calib_face < CAL_FACE_NEG_X) {
|
||||
g_calib_state = CAL_STATE_PAUSE_BETWEEN_FACES;
|
||||
g_pause_timer = 0;
|
||||
xlog("Pausing for %d seconds. Please prepare for the next orientation.\r\n", CAL_PAUSE_SECONDS);
|
||||
} else {
|
||||
// 所有面都已完成
|
||||
g_calib_state = CAL_STATE_CALCULATING;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CAL_STATE_PAUSE_BETWEEN_FACES:
|
||||
if (++g_pause_timer >= (CAL_PAUSE_SECONDS * 1000 / dt)) {
|
||||
g_current_calib_face++;
|
||||
g_calib_state = CAL_STATE_WAIT_STILL;
|
||||
g_still_count = 0;
|
||||
switch(g_current_calib_face) {
|
||||
case CAL_FACE_NEG_Z: xlog("Step 2/%d: Place device with Z-axis pointing DOWNWARD and keep it still.\r\n", CAL_FACE_COUNT); break;
|
||||
case CAL_FACE_POS_Y: xlog("Step 3/%d: Place device with Y-axis pointing UPWARD and keep it still.\r\n", CAL_FACE_COUNT); break;
|
||||
case CAL_FACE_NEG_Y: xlog("Step 4/%d: Place device with Y-axis pointing DOWNWARD and keep it still.\r\n", CAL_FACE_COUNT); break;
|
||||
case CAL_FACE_POS_X: xlog("Step 5/%d: Place device with X-axis pointing UPWARD and keep it still.\r\n", CAL_FACE_COUNT); break;
|
||||
case CAL_FACE_NEG_X: xlog("Step 6/%d: Place device with X-axis pointing DOWNWARD and keep it still.\r\n", CAL_FACE_COUNT); break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CAL_STATE_CALCULATING:
|
||||
xlog("All data collected. Calculating calibration parameters...\r\n");
|
||||
// 计算陀螺仪偏移
|
||||
long gyro_sum[3] = {0};
|
||||
for (sl_i = 0; sl_i < CAL_FACE_COUNT; sl_i++) {
|
||||
gyro_sum[0] += g_calib_avg_data[sl_i][3]; // Gx
|
||||
gyro_sum[1] += g_calib_avg_data[sl_i][4]; // Gy
|
||||
gyro_sum[2] += g_calib_avg_data[sl_i][5]; // Gz
|
||||
}
|
||||
g_gyro_offset[0] = gyro_sum[0] / CAL_FACE_COUNT;
|
||||
g_gyro_offset[1] = gyro_sum[1] / CAL_FACE_COUNT;
|
||||
g_gyro_offset[2] = gyro_sum[2] / CAL_FACE_COUNT;
|
||||
|
||||
// 计算加速度计偏移和增益
|
||||
g_acc_offset[0] = (g_calib_avg_data[CAL_FACE_POS_X][0] + g_calib_avg_data[CAL_FACE_NEG_X][0]) / 2.0f;
|
||||
g_acc_scale[0] = (2.0f * G_VALUE) / (g_calib_avg_data[CAL_FACE_POS_X][0] - g_calib_avg_data[CAL_FACE_NEG_X][0]);
|
||||
g_acc_offset[1] = (g_calib_avg_data[CAL_FACE_POS_Y][1] + g_calib_avg_data[CAL_FACE_NEG_Y][1]) / 2.0f;
|
||||
g_acc_scale[1] = (2.0f * G_VALUE) / (g_calib_avg_data[CAL_FACE_POS_Y][1] - g_calib_avg_data[CAL_FACE_NEG_Y][1]);
|
||||
g_acc_offset[2] = (g_calib_avg_data[CAL_FACE_POS_Z][2] + g_calib_avg_data[CAL_FACE_NEG_Z][2]) / 2.0f;
|
||||
g_acc_scale[2] = (2.0f * G_VALUE) / (g_calib_avg_data[CAL_FACE_POS_Z][2] - g_calib_avg_data[CAL_FACE_NEG_Z][2]);
|
||||
|
||||
g_calibration_valid = 1;
|
||||
g_calib_state = CAL_STATE_FINISHED;
|
||||
xlog("===== Calibration Finished! =====\r\n");
|
||||
xlog("Acc Offset: %.2f, %.2f, %.2f\r\n", g_acc_offset[0], g_acc_offset[1], g_acc_offset[2]);
|
||||
xlog("Acc Scale: %.4f, %.4f, %.4f\r\n", g_acc_scale[0], g_acc_scale[1], g_acc_scale[2]);
|
||||
xlog("Gyro Offset: %d, %d, %d\r\n", g_gyro_offset[0], g_gyro_offset[1], g_gyro_offset[2]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0; // 只要还在校准流程中,就返回0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 应用程序主入口或初始化函数
|
||||
void app_main()
|
||||
{
|
||||
// ... 其他初始化代码 ...
|
||||
|
||||
// 2. 调用初始化函数来配置SCU722传感器
|
||||
unsigned char init_success = SL_SC7U22_Config();
|
||||
|
||||
if (init_success) {
|
||||
xlog("SCU722 初始化成功!\n");
|
||||
// 3. 创建一个任务来周期性地读取和处理数据
|
||||
task_create(sensor_processing_task, NULL, "sensor_task");
|
||||
} else {
|
||||
xlog("SCU722 初始化失败!\n");
|
||||
// =================================================================================
|
||||
// 步骤 2: 姿态解算
|
||||
// ---------------------------------------------------------------------------------
|
||||
if (g_calibration_valid == 0) {
|
||||
return 2; // 校准未完成,无法进行姿态解算
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
float angle_acc[3] = {0};
|
||||
float gyro_val[3] = {0};
|
||||
float calibrated_acc[3] = {0};
|
||||
|
||||
//-----------------------------------------
|
||||
*/
|
||||
// --- 2.1 数据预处理 (应用新的校准参数) ---
|
||||
// 应用偏移和增益校准加速度计
|
||||
calibrated_acc[0] = ((float)acc_gyro_input[0] - g_acc_offset[0]) * g_acc_scale[0];
|
||||
calibrated_acc[1] = ((float)acc_gyro_input[1] - g_acc_offset[1]) * g_acc_scale[1];
|
||||
calibrated_acc[2] = ((float)acc_gyro_input[2] - g_acc_offset[2]) * g_acc_scale[2];
|
||||
|
||||
// 应用偏移校准陀螺仪
|
||||
gyro_val[0] = ((float)acc_gyro_input[4] - g_gyro_offset[1]) * 0.061; // GYR-Y -> Pitch
|
||||
gyro_val[1] = ((float)acc_gyro_input[3] - g_gyro_offset[0]) * 0.061; // GYR-X -> Roll
|
||||
gyro_val[2] = ((float)acc_gyro_input[5] - g_gyro_offset[2]) * 0.061; // GYR-Z -> Yaw
|
||||
|
||||
// --- 2.2 使用校准后的加速度计计算姿态角 ---
|
||||
// 将校准后的加速度值转换为归一化的重力分量
|
||||
angle_acc[0] = calibrated_acc[0] / G_VALUE; // ax
|
||||
angle_acc[1] = calibrated_acc[1] / G_VALUE; // ay
|
||||
angle_acc[2] = calibrated_acc[2] / G_VALUE; // az
|
||||
|
||||
// 限制范围,防止asinf/atanf计算错误
|
||||
if (angle_acc[0] > 1.0f) angle_acc[0] = 1.0f;
|
||||
if (angle_acc[0] < -1.0f) angle_acc[0] = -1.0f;
|
||||
// ... (对 angle_acc[1] 和 angle_acc[2] 也做同样处理)
|
||||
|
||||
angle_acc[0] = asinf(angle_acc[0]) * 57.29578f; // Pitch
|
||||
angle_acc[1] = atan2f(angle_acc[1], angle_acc[2]) * 57.29578f; // Roll (使用atan2更稳健)
|
||||
|
||||
// =================================================================================
|
||||
// 步骤 2.4: 卡尔曼滤波
|
||||
// 对Pitch和Roll分别进行滤波
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
/************** Pitch 轴滤波 **************/
|
||||
// --- 预测步骤 ---
|
||||
// 1. 预测状态:根据上一时刻的角度和当前角速度,预测当前角度
|
||||
angle0[0] += (gyro_val[0] - q_bias0[0]) * dt;
|
||||
// 2. 预测协方差:更新P矩阵,表示预测状态的不确定性
|
||||
Pdot0[0] = Q_angle - P0[0][1] - P0[1][0] + P0[1][1] * dt;
|
||||
Pdot0[1] = -P0[1][1];
|
||||
Pdot0[2] = -P0[1][1];
|
||||
Pdot0[3] = Q_gyro;
|
||||
P0[0][0] += Pdot0[0] * dt;
|
||||
P0[0][1] += Pdot0[1] * dt;
|
||||
P0[1][0] += Pdot0[2] * dt;
|
||||
P0[1][1] += Pdot0[3] * dt;
|
||||
|
||||
// --- 更新步骤 ---
|
||||
// 1. 计算卡尔曼增益 K
|
||||
PCt0_0[0] = C_0 * P0[0][0];
|
||||
PCt0_1[0] = C_0 * P0[1][0];
|
||||
E0[0] = R_angle + C_0 * PCt0_0[0];
|
||||
if (E0[0] == 0) { E0[0] = 0.0001; } // 防止除零
|
||||
K0_0[0] = PCt0_0[0] / E0[0];
|
||||
K0_1[0] = PCt0_1[0] / E0[0];
|
||||
|
||||
// 2. 计算测量余差(innovation)
|
||||
angle_err0[0] = angle_acc[0] - angle0[0];
|
||||
// 3. 更新状态估计:结合预测值和测量值,得到最优估计
|
||||
angle0[0] += K0_0[0] * angle_err0[0];
|
||||
// 4. 更新陀螺仪偏置估计
|
||||
q_bias0[0] += K0_1[0] * angle_err0[0];
|
||||
angle_dot0[0] = gyro_val[0] - q_bias0[0];
|
||||
|
||||
// 5. 更新协方差矩阵 P
|
||||
t0_0[0] = PCt0_0[0];
|
||||
t0_1[0] = C_0 * P0[0][1];
|
||||
P0[0][0] -= K0_0[0] * t0_0[0];
|
||||
P0[0][1] -= K0_0[0] * t0_1[0];
|
||||
P0[1][0] -= K0_1[0] * t0_0[0];
|
||||
P0[1][1] -= K0_1[0] * t0_1[0];
|
||||
|
||||
// 输出最终的Pitch角
|
||||
Angle_output[0] = angle0[0];
|
||||
|
||||
/************** Roll 轴滤波 (过程同Pitch) **************/
|
||||
// --- 预测步骤 ---
|
||||
angle0[1] += (gyro_val[1] - q_bias0[1]) * dt;
|
||||
Pdot1[0] = Q_angle - P1[0][1] - P1[1][0] + P1[1][1] * dt;
|
||||
Pdot1[1] = -P1[1][1];
|
||||
Pdot1[2] = -P1[1][1];
|
||||
Pdot1[3] = Q_gyro;
|
||||
P1[0][0] += Pdot1[0] * dt;
|
||||
P1[0][1] += Pdot1[1] * dt;
|
||||
P1[1][0] += Pdot1[2] * dt;
|
||||
P1[1][1] += Pdot1[3] * dt;
|
||||
|
||||
// --- 更新步骤 ---
|
||||
PCt0_0[1] = C_1 * P1[0][0];
|
||||
PCt0_1[1] = C_1 * P1[1][0];
|
||||
E0[1] = R_angle + C_1 * PCt0_0[1];
|
||||
if (E0[1] == 0) { E0[1] = 0.0001; }
|
||||
K0_0[1] = PCt0_0[1] / E0[1];
|
||||
K0_1[1] = PCt0_1[1] / E0[1];
|
||||
angle_err0[1] = angle_acc[1] - angle0[1];
|
||||
angle0[1] += K0_0[1] * angle_err0[1];
|
||||
q_bias0[1] += K0_1[1] * angle_err0[1];
|
||||
angle_dot0[1] = gyro_val[1] - q_bias0[1];
|
||||
t0_0[1] = PCt0_0[1];
|
||||
t0_1[1] = C_1 * P1[0][1];
|
||||
P1[0][0] -= K0_0[1] * t0_0[1];
|
||||
P1[0][1] -= K0_0[1] * t0_1[1];
|
||||
P1[1][0] -= K0_1[1] * t0_0[1];
|
||||
P1[1][1] -= K0_1[1] * t0_1[1];
|
||||
|
||||
// 输出最终的Roll角
|
||||
Angle_output[1] = angle0[1];
|
||||
|
||||
/************** Yaw 轴计算 **************/
|
||||
// Yaw角无法通过加速度计(重力)来校正,因此这里只使用陀螺仪进行简单积分。
|
||||
// 这种方法会因为陀螺仪的漂移而导致误差随时间累积。
|
||||
if (yaw_rst == 1) {
|
||||
Angle_output[2] = 0; // 如果有复位信号,则清零
|
||||
}
|
||||
|
||||
// 增加一个简单的阈值,当角速度较小时,认为没有转动,以减少漂移
|
||||
if (SL_GetAbsShort(Temp_Accgyro[5]) > 8) {
|
||||
Angle_output[2] += gyro_val[2] * dt;
|
||||
}
|
||||
|
||||
return 1; // 返回1,表示计算成功
|
||||
}
|
||||
#endif
|
||||
@ -131,7 +131,7 @@ unsigned char SL_SC7U22_Angle_Output(unsigned char calibration_en,signed short *
|
||||
/**input yaw_rst: reset yaw value***************************/
|
||||
|
||||
unsigned char Original_SL_SC7U22_Angle_Output(unsigned char calibration_en, signed short *acc_gyro_input, float *Angle_output, unsigned char yaw_rst);
|
||||
|
||||
unsigned char SIX_SL_SC7U22_Angle_Output(unsigned char auto_calib_start, signed short *acc_gyro_input, float *Angle_output, unsigned char yaw_rst);
|
||||
unsigned char get_calibration_state(void);
|
||||
/**寄存器宏定义*******************************/
|
||||
#define SC7U22_WHO_AM_I 0x01
|
||||
|
||||
@ -925,72 +925,3 @@ unsigned char SL_SC7U22_Angle_Output(unsigned char calibration_en, signed short
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
//-----------------------------------------
|
||||
调用示例-by_lmx:
|
||||
|
||||
|
||||
//1.
|
||||
// 定义用于存放传感器数据的缓冲区
|
||||
static signed short acc_raw_data[3]; // [0]: acc_x, [1]: acc_y, [2]: acc_z
|
||||
static signed short gyr_raw_data[3]; // [0]: gyr_x, [1]: gyr_y, [2]: gyr_z
|
||||
static signed short combined_raw_data[6]; // 用于合并 acc 和 gyr 数据
|
||||
static float final_angle_data[3]; // [0]: Pitch, [1]: Roll, [2]: Yaw
|
||||
|
||||
// 传感器数据处理任务
|
||||
void sensor_processing_task(void *priv)
|
||||
{
|
||||
while (1) {
|
||||
// 4. 周期性调用读取函数,获取原始数据
|
||||
SL_SC7U22_RawData_Read(acc_raw_data, gyr_raw_data);
|
||||
|
||||
// 5. 合并加速度和角速度数据到一个数组中
|
||||
// SL_SC7U22_Angle_Output 函数需要一个包含6个元素的数组作为输入
|
||||
memcpy(&combined_raw_data[0], acc_raw_data, sizeof(acc_raw_data));
|
||||
memcpy(&combined_raw_data[3], gyr_raw_data, sizeof(gyr_raw_data));
|
||||
|
||||
// 6. 调用姿态解算函数
|
||||
// 参数: (校准使能, 输入的6轴数据, 输出的角度数据, Yaw轴复位标志)
|
||||
// calibration_en = 1: 让函数内部自动管理校准过程
|
||||
// yaw_rst = 0: 不复位Yaw角
|
||||
unsigned char status = SL_SC7U22_Angle_Output(1, combined_raw_data, final_angle_data, 0);
|
||||
|
||||
// 7. 检查函数返回的状态
|
||||
if (status == 1) {
|
||||
// 计算成功,final_angle_data 中的数据有效
|
||||
printf("Pitch: %.2f, Roll: %.2f, Yaw: %.2f\n", final_angle_data[0], final_angle_data[1], final_angle_data[2]);
|
||||
} else if (status == 0) {
|
||||
// 传感器正在进行静态校准,此时角度数据可能不准确
|
||||
printf("Sensor is calibrating...\n");
|
||||
} else {
|
||||
// status == 2, 表示校准未完成或发生错误
|
||||
printf("Angle calculation error or calibration not finished.\n");
|
||||
}
|
||||
|
||||
// 延时一段时间,例如10ms (对应100Hz)
|
||||
os_time_dly(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 应用程序主入口或初始化函数
|
||||
void app_main()
|
||||
{
|
||||
// ... 其他初始化代码 ...
|
||||
|
||||
// 2. 调用初始化函数来配置SCU722传感器
|
||||
unsigned char init_success = SL_SC7U22_Config();
|
||||
|
||||
if (init_success) {
|
||||
printf("SCU722 初始化成功!\n");
|
||||
// 3. 创建一个任务来周期性地读取和处理数据
|
||||
task_create(sensor_processing_task, NULL, "sensor_task");
|
||||
} else {
|
||||
printf("SCU722 初始化失败!\n");
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
*/
|
||||
Reference in New Issue
Block a user