SimpleFOC STM32实战04|STM32F103+HAI库进阶,利用AS5600编码器实现电机转速的精准测量与滤波

张开发
2026/4/11 16:11:16 15 分钟阅读

分享文章

SimpleFOC STM32实战04|STM32F103+HAI库进阶,利用AS5600编码器实现电机转速的精准测量与滤波
1. 从角度到转速AS5600编码器的进阶应用上次我们成功用STM32F103和AS5600编码器读取了电机角度数据这次要玩点更实用的——精准测量电机转速。想象一下你用手转动电机时Jscope上显示的转速曲线像过山车一样起伏不定这在实际应用中显然不行。我们需要让数据既准确又稳定。AS5600这个12位磁性编码器本质上是个角度传感器。要计算转速其实就是计算角度随时间的变化率。SimpleFOC库已经帮我们封装好了getVelocity()方法但直接调用得到的原始数据会有明显抖动。我实测发现手动转动电机时原始转速数据的波动幅度可能高达±30%这就像用普通体温计测发烧——数值上蹿下跳让人心里没底。2. 转速计算的核心原理与实现2.1 底层算法解析SimpleFOC的转速计算采用移动窗口差分法。具体来说库函数会记录最近N个角度采样值默认窗口大小为3用最小二乘法拟合出角度-时间曲线的斜率这个斜率就是角速度。在velocity.cpp源码中可以看到这样的关键计算float delta_angle angle_prev - angle_new; if(delta_angle _PI) delta_angle - _2PI; else if(delta_angle -_PI) delta_angle _2PI; velocity delta_angle / delta_t;这种处理考虑了角度值的圆周特性避免从359°跳到0°时出现巨大速度值。但问题在于当采样间隔较短如1ms时微小的角度测量误差会被放大成明显的速度波动。2.2 基础代码实现基于上一章的user_main.cpp我们只需增加几行关键代码#include SimpleFOC.h MagneticSensorI2C sensor MagneticSensorI2C(AS5600_I2C); void setup() { sensor.init(); Serial.begin(115200); } void loop() { sensor.update(); float velocity sensor.getVelocity(); Serial.println(velocity); }实测这段代码当电机匀速转动时输出值会在真实值上下频繁跳动。我在实验室用标准转速源测试发现原始数据的信噪比只有15dB左右这还没考虑机械振动带来的干扰。3. 滤波算法的实战应用3.1 滑动平均滤波最简单的改进方案是增加滑动平均滤波。在loop()函数中加入以下处理#define FILTER_SIZE 5 float velocity_buffer[FILTER_SIZE]; int buffer_index 0; void loop() { sensor.update(); velocity_buffer[buffer_index] sensor.getVelocity(); buffer_index (buffer_index 1) % FILTER_SIZE; float filtered_velocity 0; for(int i0; iFILTER_SIZE; i){ filtered_velocity velocity_buffer[i]; } filtered_velocity / FILTER_SIZE; Serial.println(filtered_velocity); }这种方法的优点是实现简单实测能将波动幅度降低到±10%以内。但缺点也很明显会引入约FILTER_SIZE/2个采样周期的延迟。在我的STM32F103上测试当FILTER_SIZE5时延迟约2.5ms对于3000RPM的电机相当于滞后4.5°机械角度。3.2 一阶低通滤波更专业的做法是采用一阶低通数字滤波器。SimpleFOC库其实内置了这个功能只需要在初始化时配置MagneticSensorI2C sensor MagneticSensorI2C(AS5600_I2C); void setup() { sensor.init(); sensor.velocity_filter LOWPASS_FILTER(0.1); // 截止频率系数 }这个0.1是滤波时间常数值越小滤波效果越强但延迟越大。经过反复测试我发现0.05-0.2之间的值最适合普通直流电机。下图是不同参数下的滤波效果对比滤波系数波动幅度响应延迟无滤波±28%0ms0.3±15%3ms0.1±7%10ms0.05±4%20ms4. 高级优化技巧4.1 动态调整滤波参数在实际项目中我开发了一套自适应滤波算法。当检测到转速变化剧烈时自动减小滤波强度稳定时增强滤波float last_velocity 0; float filter_coeff 0.1; void loop() { sensor.update(); float current_velocity sensor.getVelocity(); // 计算加速度 float acceleration abs(current_velocity - last_velocity); last_velocity current_velocity; // 动态调整滤波系数 if(acceleration 100) filter_coeff 0.3; // 快速变化时弱滤波 else filter_coeff 0.05; // 稳定时强滤波 // 应用滤波 static float filtered_velocity 0; filtered_velocity filtered_velocity*(1-filter_coeff) current_velocity*filter_coeff; }4.2 多传感器数据融合对于高精度应用我推荐结合IMU的陀螺仪数据。通过卡尔曼滤波融合AS5600的角度和陀螺仪的角速度可以得到更稳定的结果。虽然这会增加硬件成本但在机器人关节控制等场景下效果显著。5. 性能验证与调试技巧用Jscope观察波形时建议同时监控原始值和滤波值。我通常这样设置打开两个波形窗口分别显示原始速度(黄色)和滤波速度(蓝色)添加水平参考线标记目标转速使用测量工具统计峰峰值波动调试时常见问题排查如果波形出现周期性毛刺可能是I2C总线受干扰尝试降低时钟频率到100kHz若数据完全不动检查AS5600的磁铁安装距离最佳1-3mm偶尔出现的异常值可能是角度跳变增加角度校验代码项目源码已更新在GitHub包含本章所有优化版本 github.com/q164129345/MCU_Develop/tree/main/simplefoc04_stm32f103_filter

更多文章