hi,2年后我又回到了这里

作者毕业后成为通信工程师,因感到迷茫和缺乏激情而决定转行。27岁那年,他选择从头开始学习Python,希望在IT行业找到自己的位置。

今天是2017年3月5日。想不到我又回到了这里

看到以前写的两篇心情,那种感觉仿佛还在昨天

毕业已经两年多了,做了两年多的通信工程师,说实话我好像不清楚我做了什么,可能天色已晚脑袋也混沌了吧

但是我又回到了这里

因为就在前天,我做了一个决定,我要改行

为什么改行?

因为迷茫

我想对的工作不应该整天被这两个字困扰

当然还有别的,不稳定,看不到未来,没有安全感,没有激情,不充实,

也许还有:不适合

我想我的性格还是适合做一个技术人员,我对管理不感兴趣,我不爱管别人

也许还有:不感兴趣

真的很少能提得起激情,完全是敬业和责任在支撑

可是自己对什么感兴趣呢?我想了很久,并不知道答案,但对现在做的事情不感兴趣,好像从入职就预见了,但很新鲜+自己不坚定+不确信

我确信过什么呢

迷茫,是最近一年的状态,迷茫到痛苦。

可是最近突然跨出了一步,决定了,我要改行,

我今年27

打算重头开始,从事IT

在51CTO报了Python

崭新的开始,加油咯

今天就这样吧,没文化写不出啥东西,哈哈。脑子转不动了,洗洗睡。



/*更新时间2024年9/17中秋节于重庆理工大学*/ /* * ===== Yaw角自加问题根本原因 ===== * 陀螺仪Z轴静止时不是完全的0,而是存在一个小偏置(零漂) * 这个偏置值虽然很小,但持续累加会导致Yaw角不断增加 * * ===== 解决方案 ===== * 1. 开机时对陀螺仪进行标定,获取Z轴的零漂偏置值 * 2. 每次读取陀螺仪数据时都减去这个偏置值 * 3. 这样就能彻底解决Yaw角自加的问题 */ #include "mpu6050.h" #include "math.h" //定义6个int16_t的数据,一会用于对于接收的数据拼接 //int16_t是有负数的,uint16_t是没负数的 int16_t Accel_X_RAW = 0; int16_t Accel_Y_RAW = 0; int16_t Accel_Z_RAW = 0; int16_t Gyro_X_RAW = 0; int16_t Gyro_Y_RAW = 0; int16_t Gyro_Z_RAW = 0; //这6个是把拼接好的数据经过计算得到结果 float Ax, Ay, Az, Gx, Gy, Gz; //使用加速度计算《加速度欧拉角》,先定义几个变量。_a的意思就是用的加速度 float roll_a, pitch_a; //使用角速度计算《角速度欧拉角》,先定义几个变量。_g的意思就是用的角速度 float roll_g, pitch_g, yaw_g; //欧拉角 float roll, pitch, yaw; //========== Yaw角零漂补偿 ========== //陀螺仪Z轴零漂标定值(单位:度/秒) - 需要通过标定函数获取 float Gz_offset = 0.0f; //标定陀螺仪Z轴零漂的函数 //方法:将陀螺仪放在平稳不动的地方,调用此函数收集100个样本计算平均值 void MPU6050_Calibrate_Yaw(void) { float Gz_sum = 0.0f; uint16_t samples = 100; for(uint16_t i = 0; i < samples; i++) { uint8_t Rec_Data_G[6]; HAL_I2C_Mem_Read(&hi2c3, MPU6050_ADDR, GYRO_XOUT_H_REG, 1, Rec_Data_G, 6, 1000); Gyro_Z_RAW = (int16_t)(Rec_Data_G[4] << 8 | Rec_Data_G[5]); Gz_sum += Gyro_Z_RAW / 16.384; // 转换为度/秒 HAL_Delay(10); // 延迟10ms再读下一个 } Gz_offset = Gz_sum / samples; // 计算平均零漂值 } void MPU6050_Init(void)//初始化 { uint8_t check; uint8_t Data; HAL_I2C_Mem_Read(&hi2c3, MPU6050_ADDR, WHO_AM_I_REG, 1, &check, 1, 1000); //注意。我的板子I2C1给显示屏了,所以给陀螺仪的是I2C2,故用&hi2c3 if (check == 0x68)//寄存器文档最后一页写了WHO_AM_I_REG就是0x68 { //电源管理1 Data = 0x01; HAL_I2C_Mem_Write(&hi2c3, MPU6050_ADDR, PWR_MGMT_1_REG, 1, &Data, 1, 1000); //电源管理2 Data = 0x00; HAL_I2C_Mem_Write(&hi2c3, MPU6050_ADDR, PWR_MGMT_2_REG, 1, &Data, 1, 1000); //滤波 - 设置为0x06(5Hz带宽)以提高稳定性 Data = 0x06; HAL_I2C_Mem_Write(&hi2c3, MPU6050_ADDR, CONFIG, 1, &Data, 1, 1000); //采样频率分频器寄存器 - 设置为0x04(200Hz采样率)以获得更多数据点 Data = 0x04; HAL_I2C_Mem_Write(&hi2c3, MPU6050_ADDR, SMPLRT_DIV_REG, 1, &Data, 1, 1000); //加速度计配置 // Data = 0x18; Data = 0x00; HAL_I2C_Mem_Write(&hi2c3, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &Data, 1, 1000); //陀螺仪配置 Data = 0x18; HAL_I2C_Mem_Write(&hi2c3, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &Data, 1, 1000); //初始化后需要调用标定函数 //MPU6050_Calibrate_Yaw(); // 在main中调用,或其他初始化位置 } } void MPU6050_Read_Accel(void)//读取加速度 { uint8_t Rec_Data[6]; HAL_I2C_Mem_Read(&hi2c3, MPU6050_ADDR, ACCEL_XOUT_H_REG, 1, Rec_Data, 6, 1000); Accel_X_RAW = (int16_t)(Rec_Data[0] << 8 | Rec_Data[1]); Accel_Y_RAW = (int16_t)(Rec_Data[2] << 8 | Rec_Data[3]); Accel_Z_RAW = (int16_t)(Rec_Data[4] << 8 | Rec_Data[5]); Ax = Accel_X_RAW / 2048.0; Ay = Accel_Y_RAW / 2048.0; Az = Accel_Z_RAW / 2048.0 - 0.5;//此处多减0.5是我的硬件问题,如果你硬件是好的,就不用减 } //此处请特别注意!!!!!!我硬件有问题减了0.5!!!!你们用的时候可以先不减 void MPU6050_Read_Gyro(void)//读取角速度 { uint8_t Rec_Data[6]; HAL_I2C_Mem_Read(&hi2c3, MPU6050_ADDR, GYRO_XOUT_H_REG, 1, Rec_Data, 6, 1000); Gyro_X_RAW = (int16_t)(Rec_Data[0] << 8 | Rec_Data[1]); Gyro_Y_RAW = (int16_t)(Rec_Data[2] << 8 | Rec_Data[3]); Gyro_Z_RAW = (int16_t)(Rec_Data[4] << 8 | Rec_Data[5]); Gx = Gyro_X_RAW / 16.384; Gy = Gyro_Y_RAW / 16.384; Gz = Gyro_Z_RAW / 16.384; } //此函数是读取结果,当然这个结果是互补滤波法计算的 //如果你想读取yaw roll pitch 仅需调用此函数 void MPU6050_Read_Result(void){ //上面函数MPU6050_Read_Accel()中的,改了下变量名,让大家更易懂,你也可以直接调用函数 uint8_t Rec_Data_A[6]; HAL_I2C_Mem_Read(&hi2c3, MPU6050_ADDR, ACCEL_XOUT_H_REG, 1, Rec_Data_A, 6, 1000); Accel_X_RAW = (int16_t)(Rec_Data_A[0] << 8 | Rec_Data_A[1]); Accel_Y_RAW = (int16_t)(Rec_Data_A[2] << 8 | Rec_Data_A[3]); Accel_Z_RAW = (int16_t)(Rec_Data_A[4] << 8 | Rec_Data_A[5]); Ax = Accel_X_RAW / 2048.0; Ay = Accel_Y_RAW / 2048.0; // Az = Accel_Z_RAW / 2048.0 - 0.5; ← 先注释掉这行 Az = Accel_Z_RAW / 16384.0; // ← 改成这样(不减0.5,用16384) //上面函数MPU6050_Read_Gyro()中的,改了下变量名,让大家更易懂,你也可以直接调用函数 uint8_t Rec_Data_G[6]; HAL_I2C_Mem_Read(&hi2c3, MPU6050_ADDR, GYRO_XOUT_H_REG, 1, Rec_Data_G, 6, 1000); Gyro_X_RAW = (int16_t)(Rec_Data_G[0] << 8 | Rec_Data_G[1]); Gyro_Y_RAW = (int16_t)(Rec_Data_G[2] << 8 | Rec_Data_G[3]); Gyro_Z_RAW = (int16_t)(Rec_Data_G[4] << 8 | Rec_Data_G[5]); Gx = Gyro_X_RAW / 16.384; Gy = Gyro_Y_RAW / 16.384; Gz = Gyro_Z_RAW / 16.384; //使用加速度计算欧拉角,如果用3.1415926,计算结果会慢,C8T6算小数太慢 roll_a = atan2(Ay, Az) /3.14f * 180; pitch_a = - atan2(Ax, Az) /3.14f * 180; //使用角速度计算欧拉角 //★★★ 关键修改:从陀螺仪读数中减去零漂偏置值,彻底解决Yaw角自加 ★★★ yaw_g = yaw + (Gz - Gz_offset) * 0.005; // 减去零漂,消除自加 roll_g = roll + Gx * 0.005; pitch_g = pitch + Gy * 0.005; //进行互补融合 - 修正融合公式以提高稳定性 const float alpha = 0.95;//这个0.98可以改,0-1之间的数,一般在0.95往上,一次增加0.01调试一下 //正确的互补滤波: 加速度权重较小用于长期纠正,陀螺仪权重较大用于实时响应 roll = alpha * roll_g + (1.0f - alpha) * roll_a; pitch = alpha * pitch_g + (1.0f - alpha) * pitch_a; //Yaw角: 由于加速度计无法检测Yaw旋转,Yaw仅依赖陀螺仪 //但已经通过零漂补偿消除了静止时的自加问题 yaw = yaw_g; } #ifndef __MPU6050_H__ #define __MPU6050_H__ //这是引用的头文件 #include "main.h" #include "i2c.h" #include"math.h" //这一堆都是地址,可以看寄存器的文件 #define MPU6050_ADDR 0xD0//从机地址 #define SMPLRT_DIV_REG 0x19//采样率 #define CONFIG 0x1A #define GYRO_CONFIG_REG 0x1B//陀螺仪 #define ACCEL_CONFIG_REG 0x1C//加速度 #define ACCEL_XOUT_H_REG 0x3B #define TEMP_OUT_H_REG 0x41 #define GYRO_XOUT_H_REG 0x43 #define PWR_MGMT_1_REG 0x6B #define PWR_MGMT_2_REG 0x6C #define WHO_AM_I_REG 0x75 //这是咱们的函数,初始化,读A,读G void MPU6050_Init(void); void MPU6050_Read_Accel(void); void MPU6050_Read_Gyro(void); void MPU6050_Read_Result(void);//读roll, pitch, yaw //补偿函数 void MPU6050_Calibrate_Yaw(void); //导出,导出后数据才能被其他程序应用 extern float Ax, Ay, Az, Gx, Gy, Gz,roll, pitch, yaw;//A代表加速度,G代表角速度 #endif 请基于我的陀螺仪库帮我实现一个7步法的计步函数,简单实现即可
12-02
要基于你现有的 MPU6050 陀螺仪库实现一个**简单的7步法计步算法**,我们不需要使用角速度(Gyro)来计步,而是依赖加速度数据(Ax, Ay, Az),因为**计步的本质是检测身体在行走时产生的周期性加速度变化**。 虽然你的代码中包含了姿态解算(roll/pitch/yaw),但计步主要用的是 **三轴加速度原始值**。下面是一个“**简化版的7步法计步器**”实现思路和代码: --- ### ✅ 实现原理:7步法简述(简化为峰值检测+状态机) 1. 计算合加速度:`acc_total = sqrt(Ax&sup2; + Ay&sup2; + Az&sup2;)` 2. 滑动窗口滤波或简单低通滤波 3. 设定动态阈值 4. 检测上升沿(过零点/上升穿越阈值) 5. 判断是否为有效峰值(幅值、时间间隔) 6. 状态机防抖(避免连步误判) 7. 步数累加 > 注:真正的“7步法”可能涉及更复杂的信号处理,这里取其思想精髓——**通过加速度总值的波动检测步伐**,适合单片机快速部署。 --- ### ✅ 添加到你的工程中的代码(可直接复制) ```c // ===== 计步相关变量 ===== #define STEP_THRESHOLD_MIN 1.4f // 最小有效加速度峰值 (g) #define STEP_THRESHOLD_MAX 3.0f // 防止噪声干扰的最大值 #define STEP_INTERVAL_MS 300 // 两步步长最小间隔(ms),防止抖动误判 #define FILTER_ALPHA 0.6f // 一阶低通滤波系数 static float acc_filtered = 0.0f; // 滤波后的合加速度 static uint32_t last_peak_time = 0; // 上一次检测到步伐的时间 static uint8_t step_state = 0; // 状态机:0=等待上升,1=已过峰 uint32_t step_count = 0; // 总步数(可被外部访问) // ===== 计步函数:建议每 20~50ms 调用一次(如 HAL_Delay(20) 循环中)===== void Pedometer_Update(void) { // 1. 获取当前时间 uint32_t current_time = HAL_GetTick(); // 2. 计算合加速度(单位:g) float acc_total = sqrtf(Ax*Ax + Ay*Ay + Az*Az); // 3. 一阶低通滤波,平滑数据 acc_filtered = FILTER_ALPHA * acc_filtered + (1 - FILTER_ALPHA) * acc_total; // 4. 获取与上次峰值的时间差 uint32_t time_diff = current_time - last_peak_time; // 5. 状态机检测峰值 if (step_state == 0) { // 当前处于“等待上升”状态 if (acc_filtered > STEP_THRESHOLD_MIN && acc_filtered < STEP_THRESHOLD_MAX) { step_state = 1; // 进入“已触发”状态 } } else { // step_state == 1,正在等待回落再重新触发 if (acc_filtered < STEP_THRESHOLD_MIN) { // 已经回落,允许下一次检测 if (time_diff >= STEP_INTERVAL_MS) { step_count++; // ✅ 成功检测一步! last_peak_time = current_time; step_state = 0; // 回到初始状态 } } // 如果长时间没回落,强制重置(防卡死) if (time_diff > 1500) { step_state = 0; } } } // ===== 可选:重置步数 ===== void Pedometer_Reset(void) { step_count = 0; last_peak_time = 0; step_state = 0; acc_filtered = 1.0f; // 初始约为重力1g } ``` --- ### ✅ 使用方法(在 main.c 中调用示例) ```c // 主循环中定期调用 while (1) { MPU6050_Read_Accel(); // 必须先更新 Ax/Ay/Az Pedometer_Update(); // 更新计步器(建议每20ms一次) printf("Steps: %lu, Acc: %.2f g\r\n", step_count, sqrtf(Ax*Ax+Ay*Ay+Az*Az)); HAL_Delay(20); // 推荐频率 ~50Hz } ``` --- ### ✅ 注意事项 - **MPU6050_Init() 后确保加速度计配置正确**(你已经设为 ±2g 量程,对应 16384 LSB/g,所以 `/16384.0` 才对) - 若你在 `MPU6050_Read_Result()` 中修改了 `Az = Accel_Z_RAW / 16384.0;`,请确认所有轴都用了正确的缩放。 - 建议将 `MPU6050_Read_Accel()` 改为统一使用 `/16384.0` 而非 `/2048.0`(除非你设置了 ±8g 模式) --- ### ✅ 改进建议(后续优化方向) | 功能 | 描述 | |------|------| | 动态阈值 | 根据静止时均值自动调整 `STEP_THRESHOLD_MIN` | | 加入 Z-score 归一化 | 提高不同人走路适应性 | | 使用 FIFO 缓冲 | 更精准采样定时 | | 结合倾斜补偿 | 在非竖直佩戴时仍能准确计步 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值