4. 多圈角度累积
任务目标
使用AS5048磁编码器实现多圈角度累积。AS5048单圈分辨率为14位(0°~360°),当转子连续旋转超过一圈时,原始角度值会在0°附近发生跳变(如从359.9°跳变到0.1°)。本案例通过检测该跳变方向,累加圈数,输出连续的多圈角度值。
核心原理
设当前读取的原始角度为raw(0~360),上一次角度为prev。定义角度差delta = raw - prev:
- 若
delta < -180°:说明发生了正向过零(从接近360°跳变到接近0°),圈数turns加1; - 若
delta > 180°:说明发生了反向过零(从接近0°跳变到接近360°),圈数turns减1; - 否则,未跨零,圈数不变。
连续角度 angle_continuous = turns * 360 + raw。
硬件与依赖
- STM32F103 开发板(或其他带SPI的MCU),AS5048编码器模块;
- AS5048 SPI读取函数(本案例提供
AS5048_ReadRaw(),返回0~16383的14位原始值); - 角度换算:
raw_deg = raw * 360.0 / 16384.0。
完整代码
#include <stdint.h>
#include <stdio.h>
// 模拟SPI读取AS5048原始值(14位,0~16383)
// 实际使用时替换为硬件SPI读取函数
uint16_t AS5048_ReadRaw(void);
// 多圈累积器结构
typedef struct {
float prev_deg; // 上一次角度(度)
int32_t turns; // 累积圈数
float continuous; // 连续角度输出
uint8_t initialized; // 首次读取标志
} MultiTurn_t;
// 初始化累积器
void MultiTurn_Init(MultiTurn_t *mt) {
mt->prev_deg = 0.0f;
mt->turns = 0;
mt->continuous = 0.0f;
mt->initialized = 0;
}
// 更新累积角度,输入raw为14位原始值
void MultiTurn_Update(MultiTurn_t *mt, uint16_t raw) {
float deg = (float)raw * 360.0f / 16384.0f; // 转换为0~360度
if (!mt->initialized) {
// 首次读取,无历史跳变
mt->prev_deg = deg;
mt->continuous = deg;
mt->initialized = 1;
return;
}
float delta = deg - mt->prev_deg;
// 检测过零跳变
if (delta < -180.0f) {
mt->turns++; // 正向过零(359→0)
} else if (delta > 180.0f) {
mt->turns--; // 反向过零(0→359)
}
mt->prev_deg = deg;
mt->continuous = (float)mt->turns * 360.0f + deg;
}
// 使用示例
int main(void) {
MultiTurn_t mt;
MultiTurn_Init(&mt);
// 模拟输入序列:350°→355°→359°→1°→5°(正向旋转跨零)
uint16_t raw_seq[] = {
(uint16_t)(350.0f / 360.0f * 16384),
(uint16_t)(355.0f / 360.0f * 16384),
(uint16_t)(359.0f / 360.0f * 16384),
(uint16_t)(1.0f / 360.0f * 16384),
(uint16_t)(5.0f / 360.0f * 16384)
};
for (int i = 0; i < 5; i++) {
MultiTurn_Update(&mt, raw_seq[i]);
printf("raw=%4d deg=%7.2f continuous=%9.2f\n",
raw_seq[i],
(float)raw_seq[i] * 360.0f / 16384.0f,
mt.continuous);
}
return 0;
}
运行与验证
- 将上述代码在STM32工程中编译,
AS5048_ReadRaw()替换为实际SPI读取函数(读取14位数据并返回); - 串口输出观察
continuous值; - 手动缓慢正向旋转编码器轴超过一圈,观察输出:
预期输出(模拟序列):
raw=15909 deg=350.00 continuous=350.00
raw=16148 deg=355.00 continuous=355.00
raw=16320 deg=359.00 continuous=359.00
raw=45 deg=1.00 continuous=361.00
raw=227 deg=5.00 continuous=365.00
通过条件:当角度从359°跳变到1°时,continuous从359°变为361°(而非1°),说明圈数已正确累加。反向旋转时,continuous应平滑递减(如从5°→359°时变为-1°)。若连续旋转多圈,continuous应始终单调递增/递减,无跳变。
关键说明
- 跳变阈值设为180°可区分正反向旋转;若电机转速极快导致相邻采样间隔内角度变化超过180°,需提高采样频率;
- AS5048上电时的初始角度作为0圈基准,累积从该点开始;
- 若需掉电保存圈数,需配合外部存储或磁极对计数,本案例仅演示运行中的多圈累积。