资讯详情

资讯详情

AS5047磁编码器实战:从硬件设计到SPI调试与角度优化

1. 从电机控制到绝对角度为什么我选了AS5047做无刷电机FOC控制或者机器人关节模组的人这几年对“磁编码器”这个词应该都不陌生。AS5047作为一款14位分辨率、带SPI接口的磁旋转编码器芯片在云台、机械臂关节、舵机、低成本伺服方案里出镜率非常高。我最早接触这颗芯片是在做某小型四足机器人的关节模组时当时对比过好几款方案最后把AS5047定为主力角度反馈方案原因无外乎三点分辨率足够、接口干净、抗污染能力强。先说分辨率。14位意味着每圈16384个位置步进单步角度约0.0219度。对绝大多数小型伺服应用来说这个精度已经覆盖了“方波/正弦波驱动都能平滑运行”的基本需求。虽然市面上也有16位甚至更高分辨率的芯片但那些芯片通常要么价格更高要么接口和供电灵活性不如AS5047。在“够用就行同时还要考虑成本和采购周期”的背景下AS5047的定位非常清晰。再说接口。AS5047同时提供SPI、ABZ增量输出、PWM输出等多种接口这意味着同一个位置信号既能给MCU的定时器做正交解码又能走SPI直接读取绝对角度还能用PWM单线传输位置。这种多接口设计在日常开发中非常实用调试阶段可以用SPI看精确角度量产阶段如果MCU引脚不够或者软件定时器紧张直接切到ABZ模式连代码都不用大改。抗污染能力则是磁编码器相对光栅编码器的天然优势。光栅怕灰尘、怕油污、怕振动引起的光盘移位而磁编码器只需要一颗小小的径向磁铁在芯片上方旋转整个检测过程不接触、不透明、不怕污渍覆盖。在小型化、封闭结构、多灰尘环境中这种可靠性是实打实的。当然磁编码器不是没有代价——它对磁铁的安装位置、磁铁的磁极均匀度、芯片与磁铁的间距都有要求这些细节我会在后面的硬件设计部分展开。最后补充一句这颗芯片适合谁。如果你正在做无刷电机的FOC控制、云台增稳、机器人关节反馈或者需要用一个低成本方案实现绝对角度测量那这篇内容可以直接参考。对于纯做光电编码器、高精度超大尺寸机床的老哥这颗芯片可能不是你的菜——那种场景下光栅或更高位数的磁编码器更合适。2. 硬件设计PCB布局与磁铁安装的细节决定了你能不能读到稳定角度2.1 芯片供电与去耦别在电源上省事AS5047的工作电压范围在3.0V到3.6V之间典型值3.3V。这里有个比较容易踩的坑如果应用环境是5V系统千万不要直接把5V接到VDD上需要单独配一颗LDO或者DCDC降到3.3V。虽然有些同类芯片能忍受5V但AS5047的数据手册明确标注的最高电压就是3.6V超压轻则读数异常重则烧掉内部LDO——没错这颗芯片内置了一个LDO输入端有VDD5V这个引脚官方设计允许你从5V引脚供电、内部稳压到3.3V再给芯片用。但即便有这个引脚我在实际项目中还是更喜欢外置3.3V直接供电原因是外置LDO能提供更好的电源噪声抑制对角度读数稳定性有帮助。去耦电容方面官方推荐在VDD和VDD5V引脚附近放置100nF和10nF电容并联我实际测试下来再额外加一颗4.7uF的钽电容滤低频纹波会更稳。如果你的板子上有电机驱动强电流换向瞬间会产生很大的电流冲击电源走线一定要先经过电容再进芯片不能让驱动电流的纹波直接串入芯片电源引脚。另一个容易忽略的点是AS5047的模拟部分对地平面有要求。芯片下方的热焊盘EPAD需要可靠接地官方手册标注它既是散热路径也是模拟地参考点。PCB Layout时建议在芯片正下方的地层不要挖空铺实铜打过孔到主地平面。虽然这颗芯片发热量不大但这个接地处理更多是信号完整性的考量。2.2 磁铁的选型与安装位置磁编码器的命门磁编码器的基础原理是芯片内部有两组正交的霍尔阵列感应上方径向磁铁的磁场方向通过反正切计算得到磁铁旋转的绝对角度。关键点在于“径向”——磁铁需要沿径向充磁而不是轴向充磁。如果把一颗轴向充磁的磁铁放在芯片上方你会在读到的角度数据里看到明显的非线性甚至在旋转一圈内出现角度跳跃。磁铁的尺寸也有讲究。以直径6mm、厚度3mm左右的径向充磁圆柱磁铁为例安装时磁铁轴线应该与芯片中心对齐间距控制在1mm到3mm之间。这个距离不是越近越好——太近了磁场强度可能超过芯片内部动态范围的上限AGC自动增益控制会被压缩到极限反而影响精度太远了信号太弱噪声占比上升。AS5047内部有一个AGC电路可以通过读取DIAAGC寄存器的值来监控当前磁场强度是否合适这个我在调试环节会细讲。实际设计中磁铁的安装精度直接决定测量误差。如果磁铁中心与芯片中心偏移过大会产生谐波误差角度读数在每圈内会有非线性的凸起或凹陷。我踩过的坑是用3D打印的电机座固定磁铁打印公差导致磁铁偏心了大概0.3mm结果FFT分析速度数据时发现明显的三次谐波分量。后来换成数控加工的铝合金联轴器固定磁铁谐波立刻压下去了。这不是玄学磁铁和芯片的同心度对最终精度的影响是实打实的。2.3 SPI引脚连接与细节该拉高的拉高该留意的别大意AS5047在SPI模式下的引脚包括CSN片选、SCK时钟、MOSISDI命令输入、MISOSDO数据输出。这四个引脚直接和MCU的SPI外设连接即可。有一个细节MISO引脚在CSN为高电平未选中时是高阻态因此MCU侧如果同一总线上挂了多个SPI从机不需要额外加缓冲器。但要注意这个高阻态是在CSN拉高之后才出现所以MCU的SPI读取时序里片选信号的处理顺序要正确——先拉低CSN再发送命令最后拉高CSN。有些朋友习惯把CSN直接接地、只用3根线做SPI这在AS5047上行不通。AS5047是通过命令帧来切换读写模式的CSN必须由MCU控制否则没法区分命令阶段和数据阶段。SCK的最高频率官方标注是10MHz。很多人一上来就把SPI配置拉满结果发现自己MCU的SPI外设时钟在极限上沿不够陡或者线太长导致信号振铃读取成功率下降。个人建议如果PCB走线超过5cm先按5MHz跑稳定后再尝试提升。数据的准确性远比读取速度重要角度环的更新率瓶颈往往不在SPI速率上而在控制环路的周期上。3. SPI通信时序与寄存器操作读懂这几个寄存器开发就完成了一大半3.1 16位命令帧与读写时序AS5047的SPI通信协议基于16位命令帧加16位数据帧的结构。整体流程是CSN拉低MCU通过MOSI发送一个16位的命令帧同时芯片在MISO上返回上一条命令对应的数据帧CSN拉高。这个“双帧流水线”的机制常常让第一次用的人困惑你发一个读角度命令MISO上回来的其实不是角度而是之前一条命令的结果。我一开始也在这里栽过跟头。解决方法是对每次读取操作连续发两个命令帧第一帧是“命令字任意数据”第二帧是“你真正想读的寄存器命令”然后在第三帧的MISO上取数。更简洁的做法是发一个帧之后立刻再发一个NOP命令0x0000用第二个帧的MISO数据作为实际读回值。不管哪种方法核心思想就是理解流水线的延迟。对于只读操作命令帧的高8位是操作码和数据位数指示。读ANGLE寄存器的操作码是0xFFFF读DIAAGC的操作码是0xFFFC读ZPOS相关的是0xFFF6之类的指令具体对照数据手册寄存器表即可。有一点需要特别注意操作码后面的低8位必须拼上0x00组合成的16位命令才是一个完整的SPI帧。3.2 关键寄存器从原始值到真实角度的转换AS5047的核心数据寄存器是ANGLE14位有效值范围0到16383。读取得到的原始值线性映射到0到360度公式非常直接角度值 raw × 360 / 16384用整数运算实现时可以用查表法或者定点数避免浮点开销。比如在Cortex-M0上我把这个转换优化成先按高9位查一个粗角度表再用低5位做线性插值开销只有几十个周期适合高频读取。还有一个非常实用的寄存器是DIAAGC它包含两方面信息AGC电平磁场强度自动增益值和诊断标志位。AGC值通常在20到60之间具体与磁铁距离、灵敏度有关。如果读到的AGC值经常顶格比如接近127说明磁场太强需要加大磁铁间距或换用小一点磁性的磁铁如果AGC值偏低比如个位数说明磁场太弱角度噪声会明显增加。诊断标志位中最常见的是COFCORDIC溢出、COF协处理器饱和这两个标志若置1代表芯片内部算法处理饱和一般和磁场过强或转速超出内部跟踪带宽有关。调试时可以把DIAAGC每个周期读一次配合串口打印出现异常能第一时间判断是机械还是电气问题。3.3 零位设置如何自己做一个“绝对零度”AS5047出厂时的零位是0x0000对应磁铁径向磁场某一方向。实际上你在装配时大概率不能保证这个方向正好对准电机零位所以需要通过软件或写寄存器来设置零位偏移。AS5047提供ZPOSM和ZPOSL两个寄存器零位坐标16位数据拆成两个8位寄存器存储。写入方法有两种一种是先读当前角度把目标零位角度值算出来再写入另一种是直接用芯片支持的“设置零位”指令在当前位置写入零位。我在批量生产时用了一种更可靠的方式电机上电后先不使能外用治具把电机轴转到机械零位保持该位置通过MCU发送置零命令然后再把ZPOS寄存器读出来存储到Flash。这样即使换一块板子也能在固件启动时从Flash恢复零位不需要每次手动标定。ZPOS写入之后芯片回读的ANGLE值会自动减去零位偏移得到的就是相对机械零位的角度。这里有个细节ZPOS寄存器是OTP一次性可编程和RAM双备份结构。你可以临时写RAM零位也可以烧录到OTP做成永久零位。量产中如果每台设备零位不同用RAM零位加Flash存储才是正解千万别烧OTP——烧完之后改不回来麻烦大了。4. 实操调参从原始读到稳定位置环的全流程4.1 初始化流程与自检启动阶段的初始化其实不需要太多步骤但顺序对了能少很多排错时间。我的标准流程如下给芯片上电等待至少10ms让内部上电复位完成读取DIAAGC确认芯片已响应。读取诊断标志确认COF、AGC等状态正常。写入零位无论是RAM零位还是OTP零位。连续读取多次ANGLE观察数据跳变范围。如果静态数据抖动在±1 LSB说明供电和读写流程都没问题如果抖动达到±3 LSB以上检查去耦电容和SPI线质量。有一个调试小技巧初始化时故意让磁铁旋转到不同位置读取ANGLE确认数据能线性跟随。这样能快速排除内部SPI时序配置错误的问题——曾经有朋友把SPI模式配错导致数据读出来只有部分位翻转让他误以为芯片坏了。4.2 角度数据处理与滤波原始角度数据在静止时看起来很稳但电机运转时ADC采样噪声、磁场涡流效应、机械振动都会带来角度噪声。在位置环里直接用原始值会发现电机在小范围来回抖动在速度环里直接用差分角度噪声会被放大得更厉害。我的经验是在读取原始值之后先通过一个移动平均滤波器或者一阶IIR低通滤波。比如一阶IIR公式filtered filtered × 0.9 raw × 0.1这个系数对应的截止频率和采样率有关。如果以1kHz读一次0.9的系数大概能把几十赫兹以上的噪声压掉同时保留几百赫兹以内的真实角度变化。但要注意IIR滤波器会带来相位延迟位置环增益较高时可能在临界频率处引发震荡。更“稳”的做法是位置环用滤波后的角度速度计算用原始角度差分再加一阶滤波避免相位叠加太深。另一个更进阶的办法是利用AS5047内部DAEC动态角度误差补偿功能。这个功能是芯片根据转速自动补偿由磁铁旋转引起的滞后误差。使用方法是先关闭DAEC让电机恒速旋转记录不同转速下的角度误差曲线再把补偿参数算出来写入寄存器。在高速FOC应用中这个补偿对电流波形质量有明显影响。我实际对比过开启DAEC后3000rpm下的角度滞后从约2.2度降到了0.5度以内。代价是校准过程稍麻烦但绝对值得做。4.3 速度估算别用连续除法用查表加一阶滤波很多项目里的速度环需要角度微分。直接用相邻两次角度差值再除以时间间隔得到的速度信号包含大量高频噪声。我推荐的做法是把差分结果先经过一个截止频率大约100Hz的一阶低通滤波再做速度标定。还有个需要注意的细节角度数据有0到16383的环绕做差分之前必须先处理回绕。正确的处理方式delta (raw_now - raw_prev 8192) % 16384 - 8192这行代码保证delta在-8192到8191之间避免从0度到360度附近出现突然的±16384跳变。这个回绕处理我见过不止一个同事漏掉结果就是电机每转一圈必然出现一次速度尖峰。说白了解决的是“角度绕着0点来回走导致差分为零但实际差360度”的经典问题。5. 实际调试手册常见问题排查与优化建议5.1 角度数据跳变或非线性现象可能原因排查与解决静态角度抖动超过±3 LSB电源纹波、SPI线干扰示波器检查VDD纹波SPI线加串联电阻或降低SCK频率角度在一圈内非线性、有凸起磁铁偏心、径向充磁不标准重新安装磁铁确认同心度换成正规径向磁铁的供应商角度在0点附近来回跳变差分回绕处理错误确认代码中用了模运算回绕处理高速旋转时角度滞后明显DAEC未开启校准DAEC参数或在软件中加转速前馈补偿读到的角度数值像镜像翻转磁铁上下装反翻转磁铁确认磁场极性方向5.2 SPI通信偶发失败我遇到过最奇葩的SPI问题角度数据在某个特定扇区周期性出错最后定位是CSN走线太长在SCK上升沿附近产生了串扰导致片选信号被毛刺拉高又快速拉低芯片误判为一次新的通信起始。解决方法是给CSN走线包地并且加一个10kΩ上拉电阻到3.3V确保片选信号边沿干净。后来我们又统一在SPI线路上串联33Ω电阻实测信号振铃明显减小。关于SCK空闲电平AS5047的SPI协议要求SCK空闲时保持低电平CPOL0数据在上升沿采样CPHA0也就是标准SPI Mode 0。如果MCU的SPI外设复用引脚务必确认引脚没有默认被拉高否则芯片会认为时钟一直处于活跃状态通信完全混乱。5.3 性能优化从“能跑”到“跑得好”如果只是把角度读出来显示那这篇博文到这里就可以收工了。但做控制的都知道真正考验编码器的是动态响应和一致性。以下几个点是我反复验证过的读取周期要稳定。SPI读取的间隔时间如果抖动差分计算的速度信号会产生随机误差。用定时器中断触发读取不要依赖主循环的轮询顺序。角度值换算成弧度后再送给控制环。用float或double都可以但一定要统一单位别在整个工程里混用角度和弧度等你在PI控制器里调Kp时才发现系数差了57.3倍就晚了。调试阶段尽量同时输出原始角度、滤波角度和速度估算值用串口绘图工具对比。只看最终输出的话问题藏得深很难定位。我个人在实际项目中最满意的组合是SPI速率5MHz读取频率2kHz滤波系数0.85DAEC开启后3000rpm下速度环平稳性明显优于未校准状态。当然这个参数组合不是万能的如果你的电机极对数不同、惯量不同滤波系数和DAEC校准曲线都需要重新调。最后再分享一个小技巧如果你需要跨平台复用驱动代码建议把AS5047的底层驱动抽象成三个函数Init、ReadAngle、SetZero把硬件寄存器操作全部封装在底层上层直接拿角度值用。这样从某STM32平台移植到某国产MCU平台只需要改SPI底层接口控制层代码一行不用动。我这边的几个项目都是这样做的节省了大量重复开发时间。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →