嵌入式C语言智能手环编程:实现高精度计步算法的低资源优化
手环计步不是“加速度超阈值就+1”。手腕运动复杂,抬手、敲键盘、甩臂都会出尖峰,固定阈值一上就乱计。 低资源MCU里正确做法是:三轴合成→轻量滤波→动态阈值→峰谷配对→步频窗口过滤→连续合法步才计数。算法本身不重,重的是别用浮点堆、别主循环轮询、别每步刷屏。
一、信号合成消除朝向依赖
手环戴法乱、姿态变,单轴不可靠。先合成三轴幅值:
/* 低资源版用绝对值和,省sqrt */
int32_t acc_mag(int16_t x,int16_t y,int16_t z){
return abs(x)+abs(y)+abs(z);
}
有FPU再开方求模长,M0/M3直接用绝对值和,步态峰值一样抓得住。
二、滑动平均压毛刺
MEMS原始数据有热噪和量化毛刺,先4点滑动:
#define FILT_N 4
static int32_t filt_buf[FILT_N];
static uint8_t fi=0;
int32_t acc_filter(int32_t m){
filt_buf[fi]=m; fi=(fi+1)%FILT_N;
int32_t sum=0;
for(int i=0;i<FILT_N;i++) sum+=filt_buf[i];
return sum/FILT_N;
}
窗口别太大,4~8点足够;25Hz采样时延迟可控,不会把慢走步幅平滑掉。
三、动态阈值:跟背景走
固定阈值对手腕松紧、快走慢走都不适配。阈值跟着近期峰谷中值走:
static int32_t bg_level; // 背景幅值慢跟踪
static int32_t dyn_th;
void threshold_update(int32_t m){
bg_level = bg_level*15/16 + m*1/16; // Q点平滑
dyn_th = bg_level + STEP_BIAS; // 偏置按标定来
}
ADI参考设计里每若干采样更新一次Max/Min,取中值当动态阈值,比单次固定阈值稳得多。
四、峰谷状态机防重复计
一个宽波峰不能被记成两步,规则是“上升越过阈值→标记候选→必须回落到阈值下→才算一步”:
typedef enum { BELOW, ABOVE } ped_state_t;
static ped_state_t st = BELOW;
static uint32_t last_step_ms = 0;
static uint8_t valid_chain = 0;
static uint32_t step_cnt = 0;
void ped_process(int32_t m, uint32_t now){
threshold_update(m);
if(st==BELOW && m > dyn_th){
st = ABOVE;
uint32_t gap = now - last_step_ms;
if(gap > MIN_STEP_MS && gap < MAX_STEP_MS){
valid_chain++;
if(valid_chain >= 3){ // 连续3步才认
step_cnt++;
last_step_ms = now;
}
}else{
valid_chain = 0;
}
}else if(st==ABOVE && m < dyn_th){
st = BELOW; // 回落,准备下一步
}
}
MIN_STEP_MS约300ms、MAX_STEP_MS约1500ms,能挡掉抖手毛刺和长时间停顿。
五、低资源优化要点
1. 中断/FIFO取数,不当主循环轮询
ADXL362/367、LIS2DH都带FIFO和watermark中断,MCU睡眠,中断里读一批再处理,平时CPU睡觉。
2. 定点化
bg_level*15/16这种移位平均比float快,M0无FPU别碰sqrtf。
3. 静止降采样
加速度方差低于门限→降到10Hz甚至停采;检测到运动再回25~50Hz。
4. 步数缓存不上屏
步数放全局step_cnt,每30秒或息屏前写一次Flash/NVS,别每步I2C刷OLED。
5. 连续步链防误触
单次峰不算步,连续3~4个合法间隔才提交,公交颠簸基本被滤掉。
六、落坑清单
单轴阈值→朝向一变就漏计
固定阈值0.5g→老人慢走漏、甩手误计
不回落去重→一个波峰记两步
无步频窗口→抖腕狂加步
每步刷屏→OLED耗电+卡
主循环轮询I2C→MCU睡不下去
浮点开根号→M0吃紧
不连续确认→单次震动误判成步
七、标定顺序
25Hz采三轴,绝对值和合成
4点滑动平均
背景幅值慢跟踪出动态阈值
上升越阈+回落状态机
步间隔300~1500ms过滤
连续3步提交计数
静止降采样、中断取FIFO
实戴标定STEP_BIAS
手环计步精度不在“算法多复杂”,在动态阈值跟不跟得住背景、步频窗口能不能挡掉手腕噪声。低资源MCU别上卡尔曼、别每点浮点,合加速度+滑动平均+动态阈值+峰谷状态机四件套,F103级芯片都能跑,误差压到日常±3%问题不大。 真要再稳一点,加陀螺仪判手臂摆动,但纯加速度这套已经是量产手环底线方案。





