暂存:数据发送协议完善中

This commit is contained in:
lmx
2025-11-21 14:54:21 +08:00
parent bdadd5de1e
commit baa5979ee1
8 changed files with 620 additions and 608 deletions

View File

@ -1,11 +1,14 @@
/* /*
使用四元数求角度和去掉重力分量
*/ */
#include "skiing_tracker.h" #include "skiing_tracker.h"
#include "../sensor/SC7U22.h" #include "../sensor/SC7U22.h"
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#define G_ACCELERATION 9.81f
#define DEG_TO_RAD (3.14159265f / 180.0f)
#define ENABLE_XLOG 1 #define ENABLE_XLOG 1
#ifdef xlog #ifdef xlog
#undef xlog #undef xlog
@ -16,13 +19,83 @@
#define xlog(format, ...) ((void)0) #define xlog(format, ...) ((void)0)
#endif #endif
// --- 静止检测 ---
//两个判断是否静止的必要条件:动态零速更新(ZUPT)阈值
// 加速方差阈值,提高阈值,让“刹车”更灵敏,以便在波浪式前进等慢速漂移时也能触发零速更新
#define STOP_ACC_VARIANCE_THRESHOLD 0.2f
// 陀螺仪方差阈值
#define STOP_GYR_VARIANCE_THRESHOLD 5.0f
// 静止时候的陀螺仪模长
#define STOP_GYR_MAG_THRESHOLD 15
// --- --- ---
#define G_ACCELERATION 9.81f // --- 启动滑雪阈值 ---
#define DEG_TO_RAD (3.14159265f / 180.0f) // 加速度模长与重力的差值大于此值,认为开始运动;降低阈值,让“油门”更灵敏,以便能捕捉到真实的慢速启动
#define START_ACC_MAG_THRESHOLD 1.0f //0.5、1
// 陀螺仪方差阈值,以允许启动瞬间的正常抖动,但仍能过滤掉混乱的、非滑雪的晃动。
#define START_GYR_VARIANCE_THRESHOLD 15.0f
// --- --- ---
// --- 滑雪过程 ---
//加速度 模长(不含重力),低于此值视为 在做匀速运动
#define SKIING_ACC_MAG_THRESHOLD 0.5f
//陀螺仪 模长,高于此值视为 摔倒了
#define FALLEN_GRY_MAG_THRESHOLD 2000.0f //未确定
// --- --- ---
// --- 原地旋转抖动 ---
// 加速度 方差 阈值。此值比 静止检测 阈值更宽松,
#define WOBBLE_ACC_VARIANCE_THRESHOLD 0.5f
// 加速度 模长 阈值
#define WOBBLE_ACC_MAG_THRESHOLD 1.0f
// 角速度 总模长 大于此值(度/秒),认为正在进行非滑雪的旋转或摆动
#define ROTATION_GYR_MAG_THRESHOLD 30.0f
// --- --- ---
// --- 滑雪转弯动 ---
// 加速度 方差 阈值,大于此值,滑雪过程可能发生了急转弯
#define WHEEL_ACC_VARIANCE_THRESHOLD 7.0f
// 角速度 总模长 大于此值(度/秒),认为滑雪过程中进行急转弯
#define WHEEL_GYR_MAG_THRESHOLD 500.0f //
// --- --- ---
// --- 跳跃 ---
// 加速度模长低于此值(g),认为进入失重状态(IN_AIR)
#define AIRBORNE_ACC_MAG_LOW_THRESHOLD 0.4f
// 加速度模长高于此值(g),认为发生落地冲击(LANDING)
#define LANDING_ACC_MAG_HIGH_THRESHOLD 3.5f
// 起跳加速度阈值(g)用于进入TAKING_OFF状态
#define TAKEOFF_ACC_MAG_HIGH_THRESHOLD 1.8f
// 进入空中状态确认计数需要连续3个采样点加速度低于阈值才判断为起跳
#define AIRBORNE_CONFIRM_COUNT 3
// 落地状态确认计数加速度恢复到1g附近并持续2个采样点(20ms)则认为已落地
#define GROUNDED_CONFIRM_COUNT 2
// 最大滞空时间(秒),超过此时间强制认为已落地,防止状态锁死
#define MAX_TIME_IN_AIR 12.5f
// --- --- ---
// --- 用于消除积分漂移的滤波器和阈值 ---
// 高通滤波器系数 (alpha)。alpha 越接近1滤除低频(直流偏移)的效果越强,但可能滤掉真实的慢速运动。
// alpha = RC / (RC + dt)参考RC电路而来fc ≈ (1 - alpha) / (2 * π * dt)
#define HPF_ALPHA 0.999f
//0.995f 0.08 Hz 的信号
//0.999f 0.0159 Hz
// --- --- ---
// --- 低通滤波器 ---
// 低通滤波器系数 (alpha)。alpha 越小,滤波效果越强(更平滑),但延迟越大。
// alpha 推荐范围 0.7 ~ 0.95。可以从 0.85 开始尝试。
#define LPF_ALPHA 0.7f
// 加速度死区阈值 (m/s^2)。低于此阈值的加速度被认为是噪声,不参与积分。
// 设得太高会忽略真实的慢速启动,设得太低则无法有效抑制噪声。
//参考0.2f ~ 0.4f
#define ACC_DEAD_ZONE_THRESHOLD 0.05f
// --- 模拟摩擦力,进行速度衰减 ---
#define SPEED_ATTENUATION 1.0f //暂不模拟
BLE_KS_send_data_t KS_data; BLE_KS_send_data_t KS_data;
static float quaternion_data[4]; static float quaternion_data[4];
#ifdef XTELL_TEST #ifdef XTELL_TEST
debug_t debug1; debug_t debug1;
@ -53,7 +126,7 @@ void stop_detection(void){
} }
/** /**
* @brief 初始化 * @brief 初始化滑雪追踪器
* *
* @param tracker * @param tracker
*/ */
@ -67,6 +140,18 @@ void skiing_tracker_init(skiing_tracker_t *tracker)
tracker->state = STATIC; tracker->state = STATIC;
} }
/**
* @brief 当检测到落地时,计算空中的水平飞行距离并累加到总距离
*/
static void calculate_air_distance(skiing_tracker_t *tracker) {
float horizontal_speed_on_takeoff = sqrtf(
tracker->initial_velocity_on_takeoff[0] * tracker->initial_velocity_on_takeoff[0] +
tracker->initial_velocity_on_takeoff[1] * tracker->initial_velocity_on_takeoff[1]
);
float distance_in_air = horizontal_speed_on_takeoff * tracker->time_in_air;
tracker->distance += distance_in_air;
}
/** /**
@ -93,7 +178,7 @@ void q_remove_gravity_with_quaternion(const float *acc_device, const float *q, f
} }
/** /**
* @brief 使用四元数将设备坐标系的线性加速度转换到世界坐标系,并且移除重力分量 * @brief 使用四元数将设备坐标系的线性加速度转换到世界坐标系
* @details 同样,此方法比使用欧拉角更优。 * @details 同样,此方法比使用欧拉角更优。
* @param acc_linear_device 输入:设备坐标系下的线性加速度 [x, y, z] * @param acc_linear_device 输入:设备坐标系下的线性加速度 [x, y, z]
* @param q 输入:表示姿态的四元数 [w, x, y, z] * @param q 输入:表示姿态的四元数 [w, x, y, z]
@ -117,6 +202,208 @@ void q_transform_to_world_with_quaternion(const float *acc_linear_device, const
} }
/**
* @brief 计算缓冲区内三轴数据的方差之和
*
* @param buffer 传进来的三轴数据:陀螺仪/加速度
* @return float 返回方差和
*/
static float calculate_variance(float buffer[VARIANCE_BUFFER_SIZE][3])
{
float mean[3] = {0};
float variance[3] = {0};
// 计算均值
for (int i = 0; i < VARIANCE_BUFFER_SIZE; i++) {
mean[0] += buffer[i][0];
mean[1] += buffer[i][1];
mean[2] += buffer[i][2];
}
mean[0] /= VARIANCE_BUFFER_SIZE;
mean[1] /= VARIANCE_BUFFER_SIZE;
mean[2] /= VARIANCE_BUFFER_SIZE;
// 计算方差
for (int i = 0; i < VARIANCE_BUFFER_SIZE; i++) {
variance[0] += (buffer[i][0] - mean[0]) * (buffer[i][0] - mean[0]);
variance[1] += (buffer[i][1] - mean[1]) * (buffer[i][1] - mean[1]);
variance[2] += (buffer[i][2] - mean[2]) * (buffer[i][2] - mean[2]);
}
variance[0] /= VARIANCE_BUFFER_SIZE;
variance[1] /= VARIANCE_BUFFER_SIZE;
variance[2] /= VARIANCE_BUFFER_SIZE;
// 返回三轴方差之和,作为一个综合的稳定度指标
return variance[0] + variance[1] + variance[2];
}
/**
* @brief 摩擦力模拟,进行速度衰减
*
* @param tracker
*/
void forece_of_friction(skiing_tracker_t *tracker){
// 增加速度衰减,模拟摩擦力
tracker->velocity[0] *= SPEED_ATTENUATION;
tracker->velocity[1] *= SPEED_ATTENUATION;
tracker->velocity[2] = 0; // 垂直速度强制归零
}
/**
* @brief 状态机更新
*
* @param tracker 传入同步修改后传出
* @param acc_device_ms2 三轴加速度m/s^2
* @param gyr_dps 三轴陀螺仪dps
*/
static void update_state_machine(skiing_tracker_t *tracker, const float *acc_device_ms2, const float *gyr_dps)
{
// 缓冲区未填满时,不进行状态判断,默认为静止
if (!tracker->buffer_filled) {
tracker->state = STATIC;
return;
}
// --- 计算关键指标 ---
float acc_variance = calculate_variance(tracker->acc_buffer); // 计算加速度方差
float gyr_variance = calculate_variance(tracker->gyr_buffer); // 计算陀螺仪方差
float gyr_magnitude = sqrtf(gyr_dps[0]*gyr_dps[0] + gyr_dps[1]*gyr_dps[1] + gyr_dps[2]*gyr_dps[2]); //dps
float acc_magnitude = sqrtf(acc_device_ms2[0]*acc_device_ms2[0] + acc_device_ms2[1]*acc_device_ms2[1] + acc_device_ms2[2]*acc_device_ms2[2]); //m/s^s
float acc_magnitude_g = acc_magnitude / G_ACCELERATION; // 转换为g单位用于跳跃判断
#ifdef XTELL_TEST
debug1.acc_variance =acc_variance;
debug1.gyr_variance =gyr_variance;
debug1.gyr_magnitude=gyr_magnitude;
debug1.acc_magnitude=fabsf(acc_magnitude - G_ACCELERATION);
#endif
// --- 状态机逻辑 (核心修改区域) ---
#if 0 //暂时不考虑空中
// 1. 空中/落地状态的后续处理
if (tracker->state == IN_AIR) {
// A. 检测巨大冲击 -> 落地
if (acc_magnitude_g > LANDING_ACC_MAG_HIGH_THRESHOLD) {
tracker->state = LANDING;
// B. 检测超时 -> 强制落地 (安全机制)
} else if (tracker->time_in_air > MAX_TIME_IN_AIR) {
tracker->state = LANDING;
// C. 检测恢复正常重力 (平缓落地)
} else if (acc_magnitude_g > 0.8f && acc_magnitude_g < 1.5f) {
tracker->grounded_entry_counter++;
if (tracker->grounded_entry_counter >= GROUNDED_CONFIRM_COUNT) {
tracker->state = LANDING;
}
} else {
tracker->grounded_entry_counter = 0;
}
return; // 在空中或刚切换到落地,结束本次状态判断
}
// 2. 严格的 "起跳->空中" 状态转换逻辑
// 只有当处于滑行状态时,才去检测起跳意图
if (tracker->state == NO_CONSTANT_SPEED || tracker->state == CONSTANT_SPEED || tracker->state == WHEEL) {
if (acc_magnitude_g > TAKEOFF_ACC_MAG_HIGH_THRESHOLD) {
tracker->state = TAKING_OFF;
tracker->airborne_entry_counter = 0; // 准备检测失重
return;
}
}
// 只有在TAKING_OFF状态下才去检测是否进入失重
if (tracker->state == TAKING_OFF) {
if (acc_magnitude_g < AIRBORNE_ACC_MAG_LOW_THRESHOLD) {
tracker->airborne_entry_counter++;
if (tracker->airborne_entry_counter >= AIRBORNE_CONFIRM_COUNT) {
memcpy(tracker->initial_velocity_on_takeoff, tracker->velocity, sizeof(tracker->velocity));
tracker->time_in_air = 0;
tracker->state = IN_AIR;
tracker->airborne_entry_counter = 0;
tracker->grounded_entry_counter = 0;
return;
}
} else {
// 如果在起跳冲击后一段时间内没有失重,说明只是一个颠簸,恢复滑行
// 可以加一个小的超时计数器,这里为了简单先直接恢复
tracker->state = NO_CONSTANT_SPEED;
}
return; // 无论是否切换,都结束本次判断
}
#endif
// --- 静止判断 ---
if (acc_variance < STOP_ACC_VARIANCE_THRESHOLD && gyr_variance < STOP_GYR_VARIANCE_THRESHOLD && gyr_magnitude < STOP_GYR_MAG_THRESHOLD) {
tracker->state = STATIC;
return;
}
// --- 地面状态切换逻辑 ---
switch (tracker->state) {
case LANDING:
tracker->state = STATIC;
break;
case STATIC:
// 优先判断是否进入 WOBBLE 状态
// 条件:陀螺仪活动剧烈,但整体加速度变化不大(说明是原地转或晃)
if (gyr_magnitude > ROTATION_GYR_MAG_THRESHOLD && fabsf(acc_magnitude - G_ACCELERATION) < WOBBLE_ACC_MAG_THRESHOLD) {
tracker->state = WOBBLE;
}
// 只有在陀螺仪和加速度都满足“前进”特征时,才启动
else if (gyr_variance > START_GYR_VARIANCE_THRESHOLD && fabsf(acc_magnitude - G_ACCELERATION) > START_ACC_MAG_THRESHOLD) {
tracker->state = NO_CONSTANT_SPEED;
}
break;
case WOBBLE:
// 从 WOBBLE 状态启动的条件应该和从 STATIC 启动一样严格
if (gyr_variance < START_GYR_VARIANCE_THRESHOLD * 2 && fabsf(acc_magnitude - G_ACCELERATION) > START_ACC_MAG_THRESHOLD) {
tracker->state = NO_CONSTANT_SPEED;
}
// 如果陀螺仪活动减弱,则可能恢复静止
else if (gyr_magnitude < ROTATION_GYR_MAG_THRESHOLD * 0.8f) { // 增加迟滞,避免抖动
// 不直接跳回STATIC而是依赖下一轮的全局静止判断
}
break;
case NO_CONSTANT_SPEED: //非匀速状态
//暂时不考虑摔倒
// if (gyr_magnitude > FALLEN_GRY_MAG_THRESHOLD) {
// tracker->state = FALLEN; //摔倒
// } else
if (gyr_magnitude > WHEEL_GYR_MAG_THRESHOLD && acc_variance > WHEEL_ACC_VARIANCE_THRESHOLD) {
tracker->state = WHEEL; //转弯
} else if (fabsf(acc_magnitude - G_ACCELERATION) < SKIING_ACC_MAG_THRESHOLD) {
tracker->state = CONSTANT_SPEED; //匀速
}
break;
case CONSTANT_SPEED: //匀速状态
if (fabsf(acc_magnitude - G_ACCELERATION) > START_ACC_MAG_THRESHOLD) {
tracker->state = NO_CONSTANT_SPEED;
}
//TODO可以添加进入转弯或摔倒的判断
break;
case WHEEL:
// 从转弯状态,检查转弯是否结束
// 如果角速度和加速度方差都降下来了,就回到普通滑行状态
if (gyr_magnitude < WHEEL_GYR_MAG_THRESHOLD * 0.8f && acc_variance < WHEEL_ACC_VARIANCE_THRESHOLD * 0.8f) { // 乘以一个滞后系数避免抖动
tracker->state = NO_CONSTANT_SPEED;
}
break;
case FALLEN:
// TODO回到 STATIC
break;
}
}
/** /**
* @brief 主更新函数 * @brief 主更新函数
* *
@ -140,49 +427,139 @@ void skiing_tracker_update(skiing_tracker_t *tracker, float *acc_g, float *gyr_d
acc_device_ms2[1] = acc_g[1] * G_ACCELERATION; acc_device_ms2[1] = acc_g[1] * G_ACCELERATION;
acc_device_ms2[2] = acc_g[2] * G_ACCELERATION; acc_device_ms2[2] = acc_g[2] * G_ACCELERATION;
#if 1 //测试禁止状态下陀螺仪的三轴加速度,去掉重力分量后是否正常 // 将最新数据存入缓冲区
float tmp_device_acc[3]; memcpy(tracker->acc_buffer[tracker->buffer_index], acc_device_ms2, sizeof(acc_device_ms2));
memcpy(tracker->gyr_buffer[tracker->buffer_index], gyr_dps, 3 * sizeof(float));
tracker->buffer_index++;
if (tracker->buffer_index >= VARIANCE_BUFFER_SIZE) {
tracker->buffer_index = 0;
tracker->buffer_filled = 1; // 标记缓冲区已满
}
// --- 更新状态机 ---
update_state_machine(tracker, acc_device_ms2, gyr_dps);
// --- 根据状态执行不同的计算逻辑 ---
switch (tracker->state) {
case TAKING_OFF:
tracker->speed = 0.0f;
break;
case IN_AIR:
// 在空中时,只累加滞空时间
tracker->time_in_air += dt;
break;
case LANDING:
// 刚落地,计算空中距离
calculate_air_distance(tracker);
// 清理速度和滤波器状态,为恢复地面追踪做准备
memset(tracker->velocity, 0, sizeof(tracker->velocity));
tracker->speed = 0;
memset(tracker->acc_world_unfiltered_prev, 0, sizeof(tracker->acc_world_unfiltered_prev));
memset(tracker->acc_world_filtered, 0, sizeof(tracker->acc_world_filtered));
memset(tracker->acc_world_lpf, 0, sizeof(tracker->acc_world_lpf)); // 清理新增的LPF状态
break;
case WHEEL:
case NO_CONSTANT_SPEED:
float linear_acc_device[3];
float linear_acc_world[3];
// 在设备坐标系下,移除重力,得到线性加速度
q_remove_gravity_with_quaternion(acc_device_ms2, quaternion_data, linear_acc_device);
// 将设备坐标系下的线性加速度,旋转到世界坐标系
q_transform_to_world_with_quaternion(linear_acc_device, quaternion_data, linear_acc_world);
// 将最终用于积分的加速度存入 tracker 结构体
memcpy(tracker->acc_no_g, linear_acc_world, sizeof(linear_acc_world));
float acc_world_temp[3]; // 临时变量存储当前周期的加速度
for (int i = 0; i < 2; i++) { // 只处理水平方向的 x 和 y 轴
// --- 核心修改:颠倒滤波器顺序为 HPF -> LPF ---
// 1. 高通滤波 (HPF) 先行: 消除因姿态误差导致的重力泄漏(直流偏置)
// HPF的瞬态响应会产生尖峰这是正常的。
tracker->acc_world_filtered[i] = HPF_ALPHA * (tracker->acc_world_filtered[i] + tracker->acc_no_g[i] - tracker->acc_world_unfiltered_prev[i]);
tracker->acc_world_unfiltered_prev[i] = tracker->acc_no_g[i];
// 2. 低通滤波 (LPF) 殿后: 平滑掉HPF产生的尖峰和传感器自身的高频振动噪声。
// 这里使用 tracker->acc_world_filtered[i] 作为LPF的输入。
tracker->acc_world_lpf[i] = (1.0f - LPF_ALPHA) * tracker->acc_world_filtered[i] + LPF_ALPHA * tracker->acc_world_lpf[i];
// 将最终处理完的加速度值存入临时变量
acc_world_temp[i] = tracker->acc_world_lpf[i];
}
// 计算处理后加速度的水平模长
float acc_horizontal_mag = sqrtf(acc_world_temp[0] * acc_world_temp[0] +
acc_world_temp[1] * acc_world_temp[1]);
#if XTELL_TEST
debug2.acc_magnitude = acc_horizontal_mag;
#endif
// 应用死区,并积分
if (acc_horizontal_mag > ACC_DEAD_ZONE_THRESHOLD) {
tracker->velocity[0] += acc_world_temp[0] * dt;
tracker->velocity[1] += acc_world_temp[1] * dt;
}
// 更新速度和距离
tracker->speed = sqrtf(tracker->velocity[0] * tracker->velocity[0] +
tracker->velocity[1] * tracker->velocity[1]);
tracker->distance += tracker->speed * dt;
break;
case CONSTANT_SPEED:
//保持上次的速度不变。只更新距离
tracker->distance += tracker->speed * dt;
break;
case STATIC:
case WOBBLE:
// 速度清零,抑制漂移
memset(tracker->velocity, 0, sizeof(tracker->velocity));
tracker->speed = 0.0f;
memset(tracker->acc_world_unfiltered_prev, 0, sizeof(tracker->acc_world_unfiltered_prev));
memset(tracker->acc_world_filtered, 0, sizeof(tracker->acc_world_filtered));
memset(tracker->acc_world_lpf, 0, sizeof(tracker->acc_world_lpf)); // 清理新增的LPF状态
#if XTELL_TEST
debug2.acc_magnitude = 0;
#endif
break;
case FALLEN:
// TODO
break;
default:
break;
}
#if 1
float linear_acc_device[3];
float linear_acc_world[3];
float tmp_world_acc[3]; float tmp_world_acc[3];
// remove_gravity_in_device_frame(acc_device_ms2,angle,tmp_device_acc); // 在设备坐标系下,移除重力,得到线性加速度
// transform_acc_to_world_frame(acc_device_ms2,angle,tmp_world_acc); q_remove_gravity_with_quaternion(acc_device_ms2, quaternion_data, linear_acc_device);
q_remove_gravity_with_quaternion(acc_device_ms2,quaternion_data,tmp_device_acc); // 将设备坐标系下的线性加速度,旋转到世界坐标系
q_transform_to_world_with_quaternion(tmp_device_acc,quaternion_data,tmp_world_acc); q_transform_to_world_with_quaternion(linear_acc_device, quaternion_data, tmp_world_acc);
// 计算处理后加速度的水平模长
float all_device_mag = sqrtf(tmp_device_acc[0] * tmp_device_acc[0] +
tmp_device_acc[1] * tmp_device_acc[1] +
tmp_device_acc[2] * tmp_device_acc[2]);
float all_world_mag = sqrtf(tmp_world_acc[0] * tmp_world_acc[0] + float all_world_mag = sqrtf(tmp_world_acc[0] * tmp_world_acc[0] +
tmp_world_acc[1] * tmp_world_acc[1] + tmp_world_acc[1] * tmp_world_acc[1] +
tmp_world_acc[2] * tmp_world_acc[2]); tmp_world_acc[2] * tmp_world_acc[2]);
float gx_proj = 2.0f * (quaternion_data[1] * quaternion_data[3] - quaternion_data[0] * quaternion_data[2]);
float gy_proj = 2.0f * (quaternion_data[0] * quaternion_data[1] + quaternion_data[2] * quaternion_data[3]);
float gz_proj = quaternion_data[0] * quaternion_data[0] - quaternion_data[1] * quaternion_data[1] - quaternion_data[2] * quaternion_data[2] + quaternion_data[3] * quaternion_data[3];
static int count = 0; static int count = 0;
if(count > 100){ if(count > 100){
xlog("===original(g): x %.2f, y %.2f, z %.2f===\n",acc_g[0],acc_g[1],acc_g[2]); xlog("===original(g): x %.2f, y %.2f, z %.2f===\n",acc_g[0],acc_g[1],acc_g[2]);
xlog("===device(m/s^2) no g: x %.2f, y %.2f, z %.2f, all %.2f===\n",tmp_device_acc[0],tmp_device_acc[1],tmp_device_acc[2],all_device_mag); xlog("===world(m/s^2) no g: x %.2f, y %.2f, z %.2f, all %.2f===\n",tmp_world_acc[0],tmp_world_acc[1],tmp_world_acc[2],all_world_mag); //去掉重力加速度
xlog("===world(m/s^2) no g: x %.2f, y %.2f, z %.2f, all %.2f===\n",tmp_world_acc[0],tmp_world_acc[1],tmp_world_acc[2],all_world_mag); xlog("===gyr(dps) : x %.2f, y %.2f, z %.2f===\n",gyr_dps[0],gyr_dps[1],gyr_dps[2]); //angle
xlog("===gyr(dps) : x %.2f, y %.2f, z %.2f, all %.2f===\n",gyr_dps[0],gyr_dps[1],gyr_dps[2]); //angle
xlog("===angle : x %.2f, y %.2f, z %.2f,===\n",angle[0],angle[1],angle[2]); xlog("===angle : x %.2f, y %.2f, z %.2f,===\n",angle[0],angle[1],angle[2]);
xlog("GRAVITY VECTOR in device frame: gx=%.2f, gy=%.2f, gz=%.2f\n", gx_proj, gy_proj, gz_proj);
extern mmc5603nj_cal_data_t cal_data;
xlog("cal_data:X: %.4f, Y: %.4f, Z: %.4f\n", cal_data.offset_x,cal_data.offset_y,cal_data.offset_z);
count = 0; count = 0;
char send_tmp[1];
send_tmp[0] = (char)all_world_mag;
send_data_to_ble_client(&send_tmp,1);
} }
count++; count++;
#endif #endif
} }
@ -193,13 +570,14 @@ void skiing_tracker_update(skiing_tracker_t *tracker, float *acc_g, float *gyr_d
* @param acc_data_buf 传入的三轴加速度数据 * @param acc_data_buf 传入的三轴加速度数据
* @param gyr_data_buf 传入的三轴陀螺仪数据 * @param gyr_data_buf 传入的三轴陀螺仪数据
* @param angle_data 传入的欧若拉角数据 * @param angle_data 传入的欧若拉角数据
* @return BLE_send_data_t 要发送给蓝牙的数据 * @return 速度cm/s
*/ */
BLE_send_data_t sensor_processing_task(signed short* acc_data_buf, signed short* gyr_data_buf, float* angle_data, float* quaternion) { int sensor_processing_task(signed short* acc_data_buf, signed short* gyr_data_buf, float* angle_data, float* quaternion) {
static int initialized = 0; static int initialized = 0;
static float acc_data_g[3]; static float acc_data_g[3];
static float gyr_data_dps[3]; static float gyr_data_dps[3];
if(quaternion != NULL){ if(quaternion != NULL){
memcpy(quaternion_data, quaternion, 4 * sizeof(float)); memcpy(quaternion_data, quaternion, 4 * sizeof(float));
} }
@ -207,7 +585,6 @@ BLE_send_data_t sensor_processing_task(signed short* acc_data_buf, signed short*
// const float delta_time = DELTA_TIME+0.01f; // const float delta_time = DELTA_TIME+0.01f;
// const float delta_time = DELTA_TIME + 0.005f; // const float delta_time = DELTA_TIME + 0.005f;
const float delta_time = DELTA_TIME; const float delta_time = DELTA_TIME;
BLE_send_data_t BLE_send_data;
if (!initialized) { if (!initialized) {
skiing_tracker_init(&my_skiing_tracker); skiing_tracker_init(&my_skiing_tracker);
@ -252,22 +629,7 @@ BLE_send_data_t sensor_processing_task(signed short* acc_data_buf, signed short*
skiing_tracker_update(&my_skiing_tracker, acc_data_g, gyr_data_dps, angle_data, delta_time); skiing_tracker_update(&my_skiing_tracker, acc_data_g, gyr_data_dps, angle_data, delta_time);
// BLE_send_data.skiing_state = my_skiing_tracker.state;
// for (int i = 0; i < 3; i++) {
// #ifdef XTELL_TEST
// BLE_send_data.acc_data[i] = (short)(acc_data_g[i] * 9.8f) * 100; //cm/^s2
// BLE_send_data.gyr_data[i] = (short)gyr_data_dps[i]; //dps
// BLE_send_data.angle_data[i] = angle_data[i];
// #else
// BLE_send_data.acc_data[i] = (short)acc_data_buf[i]; //原始adc数据
// BLE_send_data.gyr_data[i] = (short)gyr_data_buf[i]; //原始adc数据
// BLE_send_data.angle_data[i] = angle_data[i];
// #endif
// }
// BLE_send_data.speed_cms = (int)(my_skiing_tracker.speed * 100);
// BLE_send_data.distance_cm = (int)(my_skiing_tracker.distance * 100);
// // printf("Calculate the time interval =============== end\n");
return BLE_send_data; return (int)(my_skiing_tracker.speed * 100);
} }

View File

@ -30,7 +30,7 @@ typedef struct {
skiing_state_t state; // 当前滑雪状态 skiing_state_t state; // 当前滑雪状态
// 内部计算使用的私有成员 // 内部计算使用的私有成员
float acc_world[3]; // 在世界坐标系下的加速度 float acc_no_g[3]; // 去掉重力分量后的加速度
// 用于空中距离计算 // 用于空中距离计算
float time_in_air; // 滞空时间计时器 float time_in_air; // 滞空时间计时器
@ -84,5 +84,5 @@ typedef struct{
*/ */
void skiing_tracker_init(skiing_tracker_t *tracker); void skiing_tracker_init(skiing_tracker_t *tracker);
BLE_send_data_t sensor_processing_task(signed short* acc_data_buf, signed short* gyr_data_buf, float* angle_data, float* quaternion); int sensor_processing_task(signed short* acc_data_buf, signed short* gyr_data_buf, float* angle_data, float* quaternion);
#endif // SKIING_TRACKER_H #endif // SKIING_TRACKER_H

View File

@ -35,6 +35,9 @@
#else #else
#define xlog(format, ...) ((void)0) #define xlog(format, ...) ((void)0)
#endif #endif
#define SENSOR_DATA_BUFFER_SIZE 500 // 定义缓冲区可以存储XXX个sensor_data_t元素
// //
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
@ -42,6 +45,7 @@
//START -- 函数定义 //START -- 函数定义
void send_data_to_ble_client(const u8* data, u16 length); void send_data_to_ble_client(const u8* data, u16 length);
extern void create_process(u16* pid, const char* name, void *priv, void (*func)(void *priv), u32 msec); extern void create_process(u16* pid, const char* name, void *priv, void (*func)(void *priv), u32 msec);
extern void close_process(u16* pid,char* name);
//END -- 函数定义 //END -- 函数定义
////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////
@ -49,492 +53,109 @@ extern void create_process(u16* pid, const char* name, void *priv, void (*func)(
////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////
//START -- 变量定义 //START -- 变量定义
// --- 任务ID ---
static u16 xtell_i2c_test_id;
static u16 collect_data_id;
static u16 ble_send_data_id;
static u16 sensor_read_data_id;
static u16 calculate_data_id;
// --- 环形缓冲区 --- typedef struct {
#define SENSOR_DATA_BUFFER_SIZE 512 // -- 六轴 --
static u8 sensor_data_buffer[SENSOR_DATA_BUFFER_SIZE]; signed short acc_data[3];
static circle_buffer_t sensor_cb; signed short gyr_data[3];
// -- 磁力计 --
uint8_t mmc5603nj_buffer[9];
// -- 速度 --
int speed_cms;
// -- 气压计 --
//...
} BLE_send_data_t;
static int count = 0; static int count = 0;
//--- test --- // --- 环形缓冲区 ---
// 全局变量 static circle_buffer_t BLE_send_buff; // 环形缓冲区管理结构体
u16 gsensor_id=0;
u16 test_id=0;
//END -- 变量定义 //END -- 变量定义
////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////
#if 0
BLE_send_data_t BLE_send_data;
void test(){
signed short acc_data_buf[3] = {0};
signed short gyr_data_buf[3] = {0};
signed short acc_gyro_input[6] = {0};
float Angle_output[3] = {0};
// xlog("============start\n");
SL_SC7U22_RawData_Read(acc_data_buf,gyr_data_buf);
BLE_send_data = sensor_processing_task(acc_data_buf, gyr_data_buf);
u8 data[50];
data[0] = 0xBB;
data[1] = 0xBE;
data[2] = 0x01;
data[3] = sizeof(BLE_send_data_t); //后续包的数据长度
// send_data_to_ble_client(&data,sizeof(BLE_send_data_t)+4);
memcpy(&data[4], &BLE_send_data, sizeof(BLE_send_data_t));
static int count = 0;
if(count >=10){
count = 0;
char* division = "==========\n";
send_data_to_ble_client(division,strlen(division));
char log_buffer[100]; // 100个字符应该足够了
// 使用 snprintf 进行格式化
int num_chars_written = snprintf(
log_buffer, // 目标缓冲区
sizeof(log_buffer), // 目标缓冲区的最大容量
"s %d, %dcm/s, %dcm\n", // 格式化字符串
BLE_send_data.skiing_state, // 第一个 %d 的参数
BLE_send_data.speed_cms, // 第二个 %d 的参数
BLE_send_data.distance_cm // 第三个 %d 的参数
);
send_data_to_ble_client(&log_buffer,strlen(log_buffer));
extern BLE_KS_send_data_t KS_data;
memset(&log_buffer, 0, 100);
num_chars_written = snprintf(
log_buffer,
sizeof(log_buffer),
"Acc:%d, %d, %d\n",
KS_data.acc_KS[0],KS_data.acc_KS[1],KS_data.acc_KS[2]
); // cm/s^2
send_data_to_ble_client(&log_buffer,strlen(log_buffer));
memset(&log_buffer, 0, 100);
num_chars_written = snprintf(
log_buffer,
sizeof(log_buffer),
"Gyr_dps:%d, %d, %d\n",
KS_data.gyr_KS_dps[0],
KS_data.gyr_KS_dps[1],
KS_data.gyr_KS_dps[2]
);
send_data_to_ble_client(&log_buffer,strlen(log_buffer));
memset(&log_buffer, 0, 100);
num_chars_written = snprintf(
log_buffer,
sizeof(log_buffer),
"angle: %d, %d, %d\n",
KS_data.angle_KS[0],
KS_data.angle_KS[1],
KS_data.angle_KS[2]
);
send_data_to_ble_client(&log_buffer,strlen(log_buffer));
extern debug_t debug1;
extern debug_t debug2;
memset(&log_buffer, 0, 100);
num_chars_written = snprintf(
log_buffer,
sizeof(log_buffer),
"debug:%.2f,%.2f,%.2f(%.2f),%.2f\n",
debug1.acc_variance,
debug1.gyr_variance,
debug1.acc_magnitude,
debug2.acc_magnitude, //滤波后的加速度
debug1.gyr_magnitude
);
send_data_to_ble_client(&log_buffer,strlen(log_buffer));
xlog("Call interval\n");
}
count++;
memset(&BLE_send_data, 0, sizeof(BLE_send_data_t));
memset(&data, 0, 50);
// xlog("end============\n");
}
#endif
#define SENSOR_DATA_BUFFER_SIZE 500 // 定义缓冲区可以存储100个sensor_data_t元素
static circle_buffer_t sensor_read; // 环形缓冲区管理结构体
typedef struct {
signed short acc_data[3];
signed short gyr_data[3];
float angle[3]; //pitch roll yaw
float quaternion_output[4]; //四元数数据
} sensor_data_t;
static sensor_data_t sensor_read_buffer[SENSOR_DATA_BUFFER_SIZE]; // 存放sensor读到的数据
static circle_buffer_t sensor_send; // 环形缓冲区管理结构体
static BLE_send_data_t sensor_send_buffer[SENSOR_DATA_BUFFER_SIZE]; // 存放ble要发送的数据
static u8 mutex1 = 0;
static u8 mutex2 = 0;
static int count_test1 = 0;
static int count_test2 = 0;
/** /**
* @brief //读取传感器的数据放进缓冲区 * @brief 六轴静态校准
* *
*/ */
void sensor_read_data(){ void SC7U22_static_calibration(void){
signed short acc_data_buf[3];
signed short gyr_data_buf[3];
float angle[3];
float quaternion_output[3];
// xlog("=======sensor_read_data START\n");
static signed short combined_raw_data[6]; static signed short combined_raw_data[6];
static int initialized = 0;
static int calibration_done = 0; static int calibration_done = 0;
char status = 0; char status = 0;
if(circle_buffer_is_full(&sensor_read)){ set_SC7U22_Error_Flag(0);
// xlog("sensor_read_data: read buffer full\n"); SL_SC7U22_RawData_Read(acc_data_buf,gyr_data_buf);
return; memcpy(&combined_raw_data[0], acc_data_buf, 3 * sizeof(signed short));
memcpy(&combined_raw_data[3], gyr_data_buf, 3 * sizeof(signed short));
status = Q_SL_SC7U22_Angle_Output(1, combined_raw_data, angle,NULL, 0, quaternion_output);
if(status == 1){ //校准完成
extern u16 SC7U22_calibration_id;
extern u8 SC7U22_init;
SC7U22_init = 1;
close_process(&SC7U22_calibration_id, "SC7U22_calibration");
u8 send2_1[5] = {0xBB,0xBE,0x02,0x00,0x01};
send_data_to_ble_client(&send2_1,strlen(send2_1));
} }
// if(count > 100){
static sensor_data_t tmp; // count = 0;
SL_SC7U22_RawData_Read(tmp.acc_data,tmp.gyr_data); // char log_buffer[100];
// xlog("=======sensor_read_data middle 1\n"); // // snprintf( log_buffer, sizeof(log_buffer),"status:%d\n",status);
memcpy(&combined_raw_data[0], tmp.acc_data, 3 * sizeof(signed short)); // // send_data_to_ble_client(&log_buffer,strlen(log_buffer));
memcpy(&combined_raw_data[3], tmp.gyr_data, 3 * sizeof(signed short)); // xlog("status:%d\n", status);
// xlog("RawData:AX=%d,AY=%d,AZ=%d,GX=%d,GY=%d,GZ=%d\r\n",combined_raw_data[0],combined_raw_data[1],combined_raw_data[2],combined_raw_data[3],combined_raw_data[4],combined_raw_data[5]);
if (!calibration_done) { //第1次启动开启零漂检测
// status = SL_SC7U22_Angle_Output(1, combined_raw_data, tmp.angle, 0);
// status = SIX_SL_SC7U22_Angle_Output(1, combined_raw_data, tmp.angle, 0);
// status = Original_SL_SC7U22_Angle_Output(1, combined_raw_data, tmp.angle, 0);
status = Q_SL_SC7U22_Angle_Output(1, combined_raw_data, tmp.angle,NULL, 0, tmp.quaternion_output);
if(count > 100){
count = 0;
char log_buffer[100]; // 100个字符应该足够了
// snprintf( log_buffer, sizeof(log_buffer),"status:%d\n",status);
// send_data_to_ble_client(&log_buffer,strlen(log_buffer));
xlog("status:%d\n", status);
}
count++;
if (status == 1) {
calibration_done = 1;
printf("Sensor calibration successful! Skiing mode is active.\n");
}
} else {
// printf("Calculate the time interval =============== start\n");
// status = SL_SC7U22_Angle_Output(0, combined_raw_data, tmp.angle, 0);
// status = SIX_SL_SC7U22_Angle_Output(0, combined_raw_data, tmp.angle, 0);
// status = Original_SL_SC7U22_Angle_Output(0, combined_raw_data, tmp.angle, 0);
status = Q_SL_SC7U22_Angle_Output(0, combined_raw_data, tmp.angle,NULL, 0, tmp.quaternion_output);
memcpy(tmp.acc_data, &combined_raw_data[0], 3 * sizeof(signed short));
memcpy(tmp.gyr_data, &combined_raw_data[3], 3 * sizeof(signed short));
if(mutex1 == 0){
mutex1 = 1;
// count_test1++;
// xlog("count_test_1: %d\n",count_test1);
circle_buffer_write(&sensor_read, &tmp);
mutex1 = 0;
}
extern void ano_send_attitude_data(float rol, float pit, float yaw, uint8_t fusion_sta) ;
ano_send_attitude_data(tmp.angle[0],tmp.angle[1],tmp.angle[2], 1);
}
// xlog("=======sensor_read_data END\n");
}
void calculate_data(){
// xlog("=======start\n");
sensor_data_t tmp;
if(circle_buffer_is_empty(&sensor_read)){
// xlog("sensor_read_buffer: read buffer empty\n");
return;
}
if(mutex1 == 0){
mutex1 = 1;
circle_buffer_read(&sensor_read, &tmp);
mutex1 = 0;
}else{
return;
}
BLE_send_data_t data_by_calculate = sensor_processing_task(tmp.acc_data, tmp.gyr_data,tmp.angle,tmp.quaternion_output);
if(circle_buffer_is_full(&sensor_send))
return;
if(mutex2 == 0){
mutex2 = 1;
circle_buffer_write(&sensor_send, &data_by_calculate);
mutex2 = 0;
}
// extern void BLE_send_data();
// BLE_send_data();
// xlog("=======end\n");
}
extern char xt_Check_Flag;
void BLE_send_data(){
// xlog("=======start\n");
if(circle_buffer_is_empty(&sensor_send)){
// xlog("sensor_send_buffer: send buffer empty\n");
return;
}
#ifdef XTELL_TEST
// #if 0
BLE_send_data_t tmp;
if(mutex2 == 0){
mutex2 = 1;
circle_buffer_read(&sensor_send, &tmp);
mutex2 = 0;
}else{
return;
}
if(count >=100){
// extern debug_t debug2;
// xlog("s %d, %dcm/s, %dcm\n",tmp.skiing_state, tmp.speed_cms, tmp.distance_cm);
// xlog("Acc:%d, %d, %d\n",tmp.acc_data[0],tmp.acc_data[1],tmp.acc_data[2]);
// xlog("Gyr:%d, %d, %d\n", tmp.gyr_data[0],tmp.gyr_data[1],tmp.gyr_data[2]);
// xlog("debug2.acc_magnitude:%.2f\n", debug2.acc_magnitude);
int num_chars_written;
count = 0;
char* division = "==========\n";
send_data_to_ble_client(division,strlen(division));
char log_buffer[100]; // 100个字符应该足够了
// extern char iic_read_len;
// extern char iic_write_result;
// num_chars_written = snprintf(log_buffer, sizeof(log_buffer),"SL_SC7U22_Check=0x%d, %d, %d\n", xt_Check_Flag, iic_read_len, iic_write_result);
// send_data_to_ble_client(&log_buffer,strlen(log_buffer));
memset(&log_buffer, 0, 100);
#if 1
// 使用 snprintf 进行格式化
num_chars_written = snprintf(
log_buffer, // 目标缓冲区
sizeof(log_buffer), // 目标缓冲区的最大容量
"s %d, %dcm/s, %dcm\n", // 格式化字符串
tmp.skiing_state, // 第一个 %d 的参数
tmp.speed_cms, // 第二个 %d 的参数
tmp.distance_cm // 第三个 %d 的参数
);
send_data_to_ble_client(&log_buffer, strlen(log_buffer));
memset(&log_buffer, 0, 100);
num_chars_written = snprintf(
log_buffer,
sizeof(log_buffer),
"Acc:%d, %d, %d\n",
tmp.acc_data[0],tmp.acc_data[1],tmp.acc_data[2]
);
send_data_to_ble_client(&log_buffer,strlen(log_buffer));
memset(&log_buffer, 0, 100);
num_chars_written = snprintf(
log_buffer,
sizeof(log_buffer),
"Gyr:%d, %d, %d\n",
tmp.gyr_data[0],tmp.gyr_data[1],tmp.gyr_data[2]
);
send_data_to_ble_client(&log_buffer,strlen(log_buffer));
memset(&log_buffer, 0, 100);
num_chars_written = snprintf(
log_buffer,
sizeof(log_buffer),
"Angle:%.1f, %.1f, %1.f\n",
tmp.angle_data[0],tmp.angle_data[1],tmp.angle_data[2]
);
send_data_to_ble_client(&log_buffer,strlen(log_buffer));
#endif
short acc_mo_cms = sqrtf(tmp.acc_data[0]*tmp.acc_data[0] + tmp.acc_data[1]*tmp.acc_data[1] + tmp.acc_data[2]*tmp.acc_data[2])-900;
memset(&log_buffer, 0, 100);
num_chars_written = snprintf(
log_buffer,
sizeof(log_buffer),
"acc_cm/s^2:%d\n",
acc_mo_cms
);
send_data_to_ble_client(&log_buffer,strlen(log_buffer));
// xlog("s %d, %dcm/s, %dcm\n",tmp.skiing_state, tmp.speed_cms, tmp.distance_cm);
// xlog("Acc:%d, %d, %d\n", tmp.acc_data[0],tmp.acc_data[1],tmp.acc_data[2]);
// xlog("GYR:%d, %d, %d\n", tmp.gyr_data[0],tmp.gyr_data[1],tmp.gyr_data[2]);
}
count++;
// xlog("=======end\n");
#else
#endif
}
//iic测试调用的
#if 0
static u16 xt_iic_test_id;
char log_buffer_1[100];
extern char sen_log_buffer_1[100];
extern char sen_log_buffer_2[100];
extern char sen_log_buffer_3[100];
extern char sen_log_buffer_4[100];
extern char sen_log_buffer_5[100];
extern char w_log_buffer_1[100];
extern char w_log_buffer_2[100];
extern char w_log_buffer_3[100];
extern char w_log_buffer_4[100];
extern char w_log_buffer_5[100];
void xt_iic_test(){
char log_buffer[100];
send_data_to_ble_client(&log_buffer_1,strlen(log_buffer_1));
extern char iic_read_len;
extern char iic_write_result;
int num_chars_written = snprintf(log_buffer, sizeof(log_buffer),"SL_SC7U22_Check=0x%d,%d,%d\n", xt_Check_Flag, iic_read_len, iic_write_result);
extern void send_data_to_ble_client(const u8* data, u16 length);
send_data_to_ble_client(&log_buffer,strlen(log_buffer));
if(sen_log_buffer_1 != NULL)
send_data_to_ble_client(&sen_log_buffer_1,strlen(sen_log_buffer_1));
if(sen_log_buffer_2 != NULL)
send_data_to_ble_client(&sen_log_buffer_2,strlen(sen_log_buffer_2));
if(sen_log_buffer_3 != NULL)
send_data_to_ble_client(&sen_log_buffer_3,strlen(sen_log_buffer_3));
if(sen_log_buffer_4 != NULL)
send_data_to_ble_client(&sen_log_buffer_4,strlen(sen_log_buffer_4));
if(sen_log_buffer_5 != NULL)
send_data_to_ble_client(&sen_log_buffer_5,strlen(sen_log_buffer_5));
if(w_log_buffer_1 != NULL)
send_data_to_ble_client(&w_log_buffer_1,strlen(w_log_buffer_1));
if(w_log_buffer_2 != NULL)
send_data_to_ble_client(&w_log_buffer_2,strlen(w_log_buffer_2));
if(w_log_buffer_3 != NULL)
send_data_to_ble_client(&w_log_buffer_3,strlen(w_log_buffer_3));
if(w_log_buffer_4 != NULL)
send_data_to_ble_client(&w_log_buffer_4,strlen(w_log_buffer_4));
if(w_log_buffer_5 != NULL)
send_data_to_ble_client(&w_log_buffer_5,strlen(w_log_buffer_5));
// SL_SC7U22_Config();
}
#endif
#if 0
u16 xt_iic_test_id;
char hw_iic_init_result;
void xt_hw_iic_test(){
char log_buffer[100];
extern char iic_read_len;
extern char iic_write_result;
int num_chars_written = snprintf(log_buffer, sizeof(log_buffer),"init result:%d, SL_SC7U22_Check=0x%d,%d,%d\n",hw_iic_init_result, xt_Check_Flag, iic_read_len, iic_write_result);
extern void send_data_to_ble_client(const u8* data, u16 length);
send_data_to_ble_client(&log_buffer,strlen(log_buffer));
}
#endif
void sensor_measure(void){
// xlog("=======sensor_read_data START\n");
static signed short combined_raw_data[6];
static int initialized = 0;
static int calibration_done = 0;
char status = 0;
static sensor_data_t tmp;
mmc5603nj_mag_data_t mag_data;
SL_SC7U22_RawData_Read(tmp.acc_data,tmp.gyr_data);
// os_time_dly(1);
mmc5603nj_read_mag_data(&mag_data);
// xlog("=======sensor_read_data middle 1\n");
memcpy(&combined_raw_data[0], tmp.acc_data, 3 * sizeof(signed short));
memcpy(&combined_raw_data[3], tmp.gyr_data, 3 * sizeof(signed short));
if (!calibration_done) { //第1次启动开启零漂检测
// status = SL_SC7U22_Angle_Output(1, combined_raw_data, tmp.angle, 0);
// status = SIX_SL_SC7U22_Angle_Output(1, combined_raw_data, tmp.angle, 0);
// status = Original_SL_SC7U22_Angle_Output(1, combined_raw_data, tmp.angle, 0);
// status = Q_SL_SC7U22_Angle_Output(1, combined_raw_data, tmp.angle,&mag_data, 0, tmp.quaternion_output);
status = Q_SL_SC7U22_Angle_Output(1, combined_raw_data, tmp.angle,NULL, 0, tmp.quaternion_output);
if(count > 100){
count = 0;
char log_buffer[100];
// snprintf( log_buffer, sizeof(log_buffer),"status:%d\n",status);
// send_data_to_ble_client(&log_buffer,strlen(log_buffer));
xlog("status:%d\n", status);
xlog("RawData:AX=%d,AY=%d,AZ=%d,GX=%d,GY=%d,GZ=%d\r\n",combined_raw_data[0],combined_raw_data[1],combined_raw_data[2],combined_raw_data[3],combined_raw_data[4],combined_raw_data[5]);
}
count++;
if (status == 1) {
calibration_done = 1;
printf("Sensor calibration successful! Skiing mode is active.\n");
}
} else {
// printf("Calculate the time interval =============== start\n");
// status = SL_SC7U22_Angle_Output(0, combined_raw_data, tmp.angle, 0);
// status = SIX_SL_SC7U22_Angle_Output(0, combined_raw_data, tmp.angle, 0);
// status = Original_SL_SC7U22_Angle_Output(0, combined_raw_data, tmp.angle, 0);
// status = Q_SL_SC7U22_Angle_Output(0, combined_raw_data, tmp.angle,&mag_data, 0, tmp.quaternion_output);
status = Q_SL_SC7U22_Angle_Output(0, combined_raw_data, tmp.angle,NULL, 0, tmp.quaternion_output);
memcpy(tmp.acc_data, &combined_raw_data[0], 3 * sizeof(signed short));
memcpy(tmp.gyr_data, &combined_raw_data[3], 3 * sizeof(signed short));
BLE_send_data_t data_by_calculate = sensor_processing_task(tmp.acc_data, tmp.gyr_data,tmp.angle, tmp.quaternion_output);
extern void ano_send_attitude_data(float rol, float pit, float yaw, uint8_t fusion_sta) ;
ano_send_attitude_data(tmp.angle[0],tmp.angle[1],tmp.angle[2], 1);
}
// mmc5603nj_mag_data_t mag_data;
// mmc5603nj_read_mag_data(&mag_data);
// float temperature = mmc5603nj_get_temperature();
// count_test1++;
// if(count_test1 >500){
// count_test1 =0;
// xlog("Mag X: %.4f, Y: %.4f, Z: %.4f Gauss\n", mag_data.x, mag_data.y, mag_data.z);
// } // }
// count++;
}
/**
* @brief 开始采集传感器数据和计算速度
*
*/
void start_collect_fuc(void){
// xlog("=======sensor_read_data START\n");
static signed short combined_raw_data[6];
static int initialized = 0;
static int calibration_done = 0;
char status = 0;
BLE_send_data_t BLE_send_data;
uint8_t mmc5603nj_buffer[9];
signed short acc_data_buf[3];
signed short gyr_data_buf[3];
float angle[3];
float quaternion_output[3];
SL_SC7U22_RawData_Read(acc_data_buf,gyr_data_buf);
mmc5603nj_read_origin_data(mmc5603nj_buffer);
memcpy(&combined_raw_data[0], acc_data_buf, 3 * sizeof(signed short));
memcpy(&combined_raw_data[3], gyr_data_buf, 3 * sizeof(signed short));
status = Q_SL_SC7U22_Angle_Output(0, combined_raw_data, angle,NULL, 0, quaternion_output);
memcpy(acc_data_buf, &combined_raw_data[0], 3 * sizeof(signed short));
memcpy(gyr_data_buf, &combined_raw_data[3], 3 * sizeof(signed short));
int speed = sensor_processing_task(acc_data_buf,gyr_data_buf,angle, quaternion_output);
// -- 数据包装进结构体 --
memcpy(BLE_send_data.acc_data, acc_data_buf, 3 * sizeof(signed short));
memcpy(BLE_send_data.gyr_data, gyr_data_buf, 3 * sizeof(signed short));
memcpy(BLE_send_data.mmc5603nj_buffer, mmc5603nj_buffer, 9);
BLE_send_data.speed_cms = speed;
// xlog("=======sensor_read_data END\n");
} }
void xtell_task_create(void){ void xtell_task_create(void){
// int ret = hw_iic_init(0);
// xlog("hw_iic_init result:%d\n",ret);
// //初始化传感器
// SL_SC7U22_Config();
#if TCFG_GSENOR_USER_IIC_TYPE #if TCFG_GSENOR_USER_IIC_TYPE
int ret = hw_iic_init(0); int ret = hw_iic_init(0);
xlog("init iic result:%d\n", ret); //返回0成功 xlog("init iic result:%d\n", ret); //返回0成功
#else #else
@ -543,52 +164,13 @@ void xtell_task_create(void){
#endif #endif
// os_time_dly(10);
// delay_2ms(10);
// if(bmp280_init() != 0){
// xlog("bmp280 init error\n");
// }
// float temp, press;
// bmp280_read_data(&temp, &press);
// xlog("get temp: %d, get press: %d\n",temp, press);
// MPU9250_Mag_Init(); // MPU9250_Mag_Init();
//iic总线设备扫描 //iic总线设备扫描
// extern void i2c_scanner_probe(void); extern void i2c_scanner_probe(void);
// i2c_scanner_probe(); i2c_scanner_probe();
xlog("xtell_task_create\n"); xlog("xtell_task_create\n");
// 初始化环形缓冲区
// circle_buffer_init(&sensor_cb, sensor_data_buffer, SENSOR_DATA_BUFFER_SIZE);
circle_buffer_init(&BLE_send_buff, sensor_read_buffer, SENSOR_DATA_BUFFER_SIZE, sizeof(BLE_send_data_t));
ano_protocol_init(115200);
circle_buffer_init(&sensor_read, sensor_read_buffer, SENSOR_DATA_BUFFER_SIZE, sizeof(sensor_data_t));
circle_buffer_init(&sensor_send, sensor_send_buffer, SENSOR_DATA_BUFFER_SIZE, sizeof(BLE_send_data_t));
// create_process(&sensor_read_data_id, "read",NULL, sensor_read_data, 10);
//
// create_process(&calculate_data_id, "calculate",NULL, calculate_data, 4);
// create_process(&ble_send_data_id, "send",NULL, BLE_send_data, 1);
#if 0
hw_iic_init_result = ret;
create_process(&xt_iic_test_id,"iic_test",NULL,xt_hw_iic_test,1000);
#endif
} }

View File

@ -32,7 +32,7 @@ int mmc5603nj_init(void) {
// ID // ID
if ( mmc5603nj_get_pid() != 0x10) { if ( mmc5603nj_get_pid() != 0x10) {
printf("MMC5603NJ init failed: wrong Product ID (read: 0x%X)\n", mmc5603nj_get_pid()); printf("MMC5603NJ init failed: wrong Product ID (read: 0x%X)\n", mmc5603nj_get_pid());
return -1; return 0;
} }
// 软件复位 // 软件复位
@ -58,7 +58,7 @@ int mmc5603nj_init(void) {
mmc5603nj_enable_continuous_mode(0x04); mmc5603nj_enable_continuous_mode(0x04);
return 0; return 1;
} }
void mmc5603nj_start_calibration(void){ void mmc5603nj_start_calibration(void){
@ -219,3 +219,41 @@ void mmc5603nj_read_mag_data(mmc5603nj_mag_data_t *mag_data) {
mag_data->y -= cal_data.offset_y; mag_data->y -= cal_data.offset_y;
mag_data->z -= cal_data.offset_z; mag_data->z -= cal_data.offset_z;
} }
void mmc5603nj_read_origin_data(uint8_t *buffer) {
if (g_continuous_mode_enabled) {
// 连续模式下,只需检查数据是否就绪
uint8_t status = 0;
mmc5603nj_read_regs(MMC_STATUS1, &status, 1);
if ((status & 0x40) == 0) { // Meas_M_done bit
// 数据未就绪,可以选择返回或等待,这里我们直接返回旧数据
return;
}
} else {
// 单次测量模式
uint8_t status = 0;
uint8_t timeout = 20;
// 触发一次带自动SET/RESET的磁场测量
mmc5603nj_write_reg(MMC_INCTRL0, 0x21); // 0b00100001 (TAKE_MEAS_M=1, AUTO_SR_EN=1)
// 等待测量完成
do {
os_time_dly(10);
mmc5603nj_read_regs(MMC_STATUS1, &status, 1);
timeout--;
} while ((status & 0x40) == 0 && timeout > 0);
if (timeout == 0) {
printf("Error: Magnetic measurement timeout!\n");
return;
}
}
// 读取9个字节的原始数据
mmc5603nj_read_regs(MMC_XOUT0, buffer, 9);
}

View File

@ -36,6 +36,14 @@
#define MMC_ST_Z 0x29 #define MMC_ST_Z 0x29
#define MMC_PID 0x39 #define MMC_PID 0x39
// 定义一个结构体来存放三轴磁场数据(原始数据)
typedef struct {
float x;
float y;
float z;
} mmc5603nj_original_data_t;
// 定义一个结构体来存放三轴磁场数据(单位:高斯 Gauss // 定义一个结构体来存放三轴磁场数据(单位:高斯 Gauss
typedef struct { typedef struct {
float x; float x;

View File

@ -1167,10 +1167,19 @@ unsigned char Original_SL_SC7U22_Angle_Output(unsigned char calibration_en, sign
return 2; // 校准未完成,返回错误状态 return 2; // 校准未完成,返回错误状态
} }
unsigned char get_calibration_state(void){
unsigned char get_SC7U22_Error_Flag(void){
return SL_SC7U22_Error_Flag; return SL_SC7U22_Error_Flag;
} }
/**
* @brief 设置零漂检测标准位
*
* @param flag 0重新进行零漂检测
*/
void set_SC7U22_Error_Flag(char flag){
SL_SC7U22_Error_Flag = flag;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -20,7 +20,7 @@ Copyright (c) 2022 Silan MEMS. All Rights Reserved.
/***使用前请根据实际情况配置以下参数******/ /***使用前请根据实际情况配置以下参数******/
/**SC7U22的SDO 接地: 0****************/ /**SC7U22的SDO 接地: 0****************/
/**SC7U22的SDO 接电源:1****************/ /**SC7U22的SDO 接电源:1****************/
#define SL_SC7U22_SDO_VDD_GND 1 #define SL_SC7U22_SDO_VDD_GND 0
/*****************************************/ /*****************************************/
/***使用前请根据实际IIC地址配置参数***/ /***使用前请根据实际IIC地址配置参数***/
/**SC7U22的IIC 接口地址为 7bits: 0****/ /**SC7U22的IIC 接口地址为 7bits: 0****/
@ -131,6 +131,7 @@ unsigned char SL_SC7U22_Angle_Output(unsigned char calibration_en,signed short *
/**output Angle_output[2]: Yaw*******************************/ /**output Angle_output[2]: Yaw*******************************/
/**input yaw_rst: reset yaw value***************************/ /**input yaw_rst: reset yaw value***************************/
void set_SC7U22_Error_Flag(char flag);
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 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 SIX_SL_SC7U22_Angle_Output(unsigned char auto_calib_start, signed short *acc_gyro_input, float *Angle_output, unsigned char yaw_rst);
unsigned char Q_SL_SC7U22_Angle_Output(unsigned char calibration_en, signed short *acc_gyro_input, float *Angle_output, const mmc5603nj_mag_data_t *mag_data_input, unsigned char yaw_rst, float *quaternion_output); unsigned char Q_SL_SC7U22_Angle_Output(unsigned char calibration_en, signed short *acc_gyro_input, float *Angle_output, const mmc5603nj_mag_data_t *mag_data_input, unsigned char yaw_rst, float *quaternion_output);

View File

@ -85,13 +85,21 @@ unsigned char xtell_bl_state=0; //存放经典蓝牙的连接状态0断开
u8 bt_newname =0; u8 bt_newname =0;
unsigned char xt_ble_new_name[9] = "CM-22222"; unsigned char xt_ble_new_name[9] = "CM-22222";
static u16 play_poweron_ok_timer_id = 0; static u16 play_poweron_ok_timer_id = 0;
// -- 初始化标志位 --
u8 SC7U22_init = 0; //六轴是否初始化
u8 MMC5603nj_init = 0; //地磁是否初始化
// -- 线程id --
u16 SC7U22_calibration_id;
u16 start_collect_fuc_id;
// //
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
extern int bt_hci_event_handler(struct bt_event *bt); extern int bt_hci_event_handler(struct bt_event *bt);
extern void SC7U22_static_calibration(void);
extern void create_process(u16* pid, const char* name, void *priv, void (*func)(void *priv), u32 msec);
extern void close_process(u16* pid,char* name);
extern void start_collect_fuc(void);
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
/* /*
* 模式状态机, 通过start_app()控制状态切换 * 模式状态机, 通过start_app()控制状态切换
@ -204,51 +212,55 @@ void le_user_app_event_handler(struct sys_event* event){
if(event->u.app.buffer[2] == 0x01){ //后面的数据长度 1 if(event->u.app.buffer[2] == 0x01){ //后面的数据长度 1
switch (event->u.app.buffer[3]){ switch (event->u.app.buffer[3]){
case 0x01: case 0x01:
char* send_start = "will start after 5 seconds\n";
send_data_to_ble_client(send_start,strlen(send_start));
if (mmc5603nj_init() != 0) {
xlog("MMC5603NJ initialization failed!\n");
char* send_error = "calibration error\n";
send_data_to_ble_client(send_error,strlen(send_error));
}
xlog("MMC5603NJ PID: 0x%02X\n", mmc5603nj_get_pid());
char* send_tmp = "8th calibration completed\n";
send_data_to_ble_client(send_tmp,strlen(send_tmp));
break;
case 0x02:
extern void create_process(u16* pid,char* name, void *priv, void (*func)(void *priv), u32 msec);
extern void sensor_measure(void);
static int test_id;
SL_SC7U22_Config();
static skiing_tracker_t skiing_data;
skiing_tracker_init(&skiing_data);
create_process(&test_id, "test",NULL, sensor_measure, 10);
send_tmp = "The test has begun.\n";
send_data_to_ble_client(send_tmp,strlen(send_tmp));
break;
case 0x03:
extern void start_detection(void);
start_detection();
send_tmp = "start_detection\n";
send_data_to_ble_client(send_tmp,strlen(send_tmp));
break;
case 0x04:
extern void stop_detection(void);
stop_detection();
send_tmp = "stop_detection\n";
send_data_to_ble_client(send_tmp,strlen(send_tmp));
break;
case 0x05:
extern void clear_speed(void);
clear_speed();
send_tmp = "Reset speed and distances to zero\n";
send_data_to_ble_client(send_tmp,strlen(send_tmp));
break; break;
default: default:
break; break;
}
}else if(event->u.app.buffer[2] == 0x02){ //后面数据长度为2
switch (event->u.app.buffer[3]){ //数据包类型
case 0x00: //数据包类型为:指定传感器初始化
u8 send2_0[5] = {0xBB,0xBE,0x02,0x00,0x00};
if(event->u.app.buffer[4] == 0x01){ //六轴
if (SL_SC7U22_Config() == 0) {
send2_0[4] = 0x00; //初始化失败
SC7U22_init = 0;
send_data_to_ble_client(&send2_0,strlen(send2_0));
break;
}
create_process(&SC7U22_calibration_id,"SC7U22_calibration",NULL,SC7U22_static_calibration,10);
}else if(event->u.app.buffer[4] == 0x02){ //地磁
if(mmc5603nj_init() == 0){
MMC5603nj_init = 0;
break;
}
MMC5603nj_init = 1;
send2_0[4] = 0x03; //地磁初始化失败
send_data_to_ble_client(&send2_0,strlen(send2_0));
}
break;
case 0x01: //数据包类型为:获取指定传感器初始化状态
u8 send2_1[5] = {0xBB,0xBE,0x02,0x01,0x00};
if(event->u.app.buffer[4] == 0x01){ //六轴
send2_1[4] = SC7U22_init;
}else if(event->u.app.buffer[4] == 0x02){ //地磁
send2_1[4] = MMC5603nj_init + 2;
}
send_data_to_ble_client(&send2_1,strlen(send2_1));
break;
case 0x02: //开始/停止滑雪计算
if(event->u.app.buffer[4] == 0x01){ //开始滑雪计算
if(SC7U22_init == 0 || MMC5603nj_init == 0){ //传感器未进行初始化
u8 send2_2[5] = {0xBB,0xBE,0x02,0x01,0x00};
send_data_to_ble_client(&send2_2,strlen(send2_2));
send2_2[4] = 0x02;
send_data_to_ble_client(&send2_2,strlen(send2_2));
return;
}
create_process(&start_collect_fuc_id,"start_collect",NULL,start_collect_fuc,10);
}else if(event->u.app.buffer[4] == 0x02){ //停止滑雪计算
close_process(&start_collect_fuc_id,"start_collect");
}
break;
} }
} }
} }