编码器芯片为什么会算错角度?因为它以为看到的是圆,实际看到的是椭圆

首发于公众号「如是有为」 · 查看原文

编码器芯片为什么会算错角度?因为它以为看到的是圆,实际看到的是椭圆

我越来越不相信“省掉一个除法器就赢了”这种胜利。

先不讲芯片,讲一个更容易想象的画面:

编码器芯片为什么会算错角度?因为它以为看到的是圆,实际看到的是椭圆

一个点本来应该绕着中心转圈,像钟表指针的端点一样。如果横向和纵向的比例完全一致,它走出来的轨迹就是圆;你只要看这个点在圆上的位置,就能判断角度。但如果横向被压扁一点,或者纵向被拉长一点,甚至中心还偏了一点,那么你记录到的轨迹就不再是圆,而是一条椭圆。这时候你还按“圆”的规则去算角度,结果一定会在某些位置稳定出错。

正余弦编码器里的 sin/cos 信号,本质上就有点像这个点的横坐标和纵坐标。理想情况下,两路信号合在一起,点云应该绕成一个圆。点在圆上走一圈,角度也就走了一圈。但现实里,它经常不是圆,而是椭圆。

我在工程里见过最贵的坑,往往不是“角度解算器不会算”,而是:你以为自己在圆上算角度,实际输入早就变成了椭圆。这时候你省掉一个除法器,可能只是省了芯片面积;但幅值失配、中心偏移、正交误差这些账,迟早会从角度误差曲线里找你要回来。

1)我换了半天角度算法,最后发现问题不在算法

有一次我在工位上看角度误差曲线,越看越不对劲。它不像噪声。噪声是乱的,今天高一点,明天低一点,至少还有点随机性。但那条误差曲线很稳定:某几个角度段永远特别丑,换一套滤波还是丑,换一套参数还是丑,换一套解算器结构,整体噪声小了一些,但那几个地方依然难看。

这就很像一张固定的脸。我后来把这种曲线叫“误差脸谱”。

当时最自然的反应是:是不是角度解算器不够强?于是大家开始盯算法:要不要换 atan2,要不要加除法器,要不要换成 CORDIC,要不要用跟踪环,要不要把 LUT 分得更细?这些问题都合理。但那次真正让我停下来的是一个很土的动作:不看角度,先把原始 sin/cos 点画出来。

结果一下子明白了。我们一直假设输入信号在圆上跑,但实际点云是一条椭圆。也就是说,后面的解算器再聪明,也是在拿“圆的规则”处理“椭圆的数据”。你在椭圆上认真算角度,当然会在某些角度段稳定犯错。

2)为什么编码器要看“圆”?

正余弦编码器为什么会有 sin/cos?可以简单理解成:芯片不是直接“看见角度”,而是先看到两路信号。一路像横坐标 x,一路像纵坐标 y。如果一切理想,这两个信号组合起来,就像一个点沿着圆周转。点转到右边,是 0 度附近;转到上边,是 90 度附近;转到左边,是 180 度附近;转到底下,是 270 度附近。所以只要知道这个点在圆上的位置,就能反推出角度。

写成公式,就是:

x = A cosθ

y = A sinθ

这两个式子不用害怕。它们说的只是:横坐标按余弦变化,纵坐标按正弦变化,而且两路幅值一样。幅值一样,中心不偏,相位刚好差 90 度,点云就是圆。

但现实里,这三个条件经常同时被破坏:两路信号一个大、一个小,叫幅值失配,圆会被拉成椭圆;两路信号中心不在零点,叫offset,圆心会偏;两路信号不是刚好差 90 度,叫正交误差,椭圆会歪。于是你以为自己看到的是圆,实际看到的是一个中心偏了、长短轴不一样、甚至还歪着的椭圆。

这时候角度误差就不是随机冒出来的。它会变成一张固定的脸。因为椭圆的几何形状是固定的,所以错误也会跟着角度位置固定出现。

3)为什么幅值失配会让误差长成“脸谱”?

只看最简单的一种情况:两路幅值不一样。理想情况是:

x = A cosθ

y = A sinθ

现实可能变成:

x = A cosθ

y = B sinθ

如果 A 和 B 不一样,点云就不是圆,而是椭圆。直观上看也很好理解:假设纵向信号比横向信号大一点,那么点在上半部分、下半部分时,会被“拉高”;在某些角度附近,角度判断就会偏得更明显。

这类误差不会像噪声一样平均散开,而是会跟角度位置绑定。工程上常见的表现,就是角度误差里出现二次谐波特征,近似可以理解成类似:

Δθ ∝ sin(2θ)

这句话翻译成人话就是:幅值失配不会让所有角度都一样差,它会让某些角度段特别差。

所以你在误差曲线上看到的那张“脸谱”,很多时候不是算法突然发疯,而是输入信号已经从圆变成了椭圆。我很怕现场一上来就骂解算器。因为你如果不先看点云,很容易把“输入欠债”误判成“算法不行”。然后你就会开始换算法。换到最后,噪声可能变小了,系统性误差还在。这就像你拿一张变形地图去导航,导航软件再高级,也会被地图坑。

4)“省掉除法器”为什么不是终点?

正余弦到角度的解算,硬件上确实不便宜。传统做法里,atan2、除法器、大 LUT、CORDIC,都可能带来面积、功耗、延迟和时序压力。所以很多论文和架构会追求更轻的实现。

比如International Journal of Circuit Theory and Applications上的A Successive Approximate Angle Track Converter for Sinusoidal Encoders,DOI 为 10.1002/cta.4336。这篇论文工作面向正余弦编码器的角度转换,目标是降低正余弦到角度解调系统的复杂度并提高转换速度;它利用正余弦信号周期性,把 [0, 2π) 划分成八段确定粗角度,再对信号进行重构和后续细角度转换。

这类方向当然有价值。做芯片的人都知道,面积是真钱,功耗是真钱,延迟也是真钱。能少一个大模块,当然值得高兴。但我越来越觉得,不能只看框图里少了什么。很多轻量化结构都有一个隐含前提:输入已经比较干净,至少接近单位圆。

这句话在论文里可能只是一个默认条件。但在工程里,它是一整条链路。你要处理 offset,要处理两路幅值差,要处理正交误差,还要处理温漂、前端增益漂移、磁铁装配偏心、封装应力、噪声和量产离散性。这些东西不会因为你删掉除法器就消失,它们只会换个地方出现。

你不在角度解算器里付账,就要在前端归一化、信号修调、校准流程、测试口径和量产复验里付账。所以,“省掉除法器”本身不是错。错的是有些方案把除法器省掉以后,也顺手把归一化当成了默认前提。

这时候幅值失配就会变得更致命。不是因为失配突然变大了,而是因为你没有足够的前置纠偏能力去吞掉它。换句话说:你省掉的是面积,你欠下的是归一化的账。

5)真正有技术深度的地方:不是算角度,而是先把椭圆修回去

公开专利里,其实已经能看到这个方向。

比如昆泰芯的授权专利CN116358619B《信号误差修调方法、磁性编码器及光学编码器》。这个专利很适合放在这篇文章里,不是因为它“用了某个很炫的角度算法”,而是因为它把问题放在了更前面:角度解算之前,两路分量信号本身可能已经错了。

编码器芯片为什么会算错角度?因为它以为看到的是圆,实际看到的是椭圆

这才是工程味很重的地方。磁性编码器也好,光学编码器也好,两路正交信号理想情况下应该构成一个圆。但现实中,点云可能会因为 offset、幅值差和正交误差变成椭圆,甚至是倾斜椭圆。这时如果后级还直接按理想圆去解角度,本质上是在做一件危险的事:把输入侧的几何畸变,伪装成角度解算误差。

CN116358619B 这类“信号误差修调”的价值,就在于它不是等到角度已经算错了,再去后面补一刀;而是先在 x_in / y_in 这两路输入上做修正。

从工程抽象上看,至少要处理三类参数。第一类是中心偏移,也就是 x_0 / y_0。如果两路信号的中心不在零点,那么点云整体会平移。这个问题不修,后面算出来的角度会带明显的一次谐波误差。第二类是幅值比例,也就是两路 gain 不一致。如果 x 方向半径和 y 方向半径不同,圆会变成椭圆。这个问题不修,典型表现就是二次谐波型角度误差。第三类是正交误差,也就是两路并不是严格 90 度。这个更麻烦,因为它不只是把圆拉长,还会让椭圆轴向倾斜。只做简单的幅值归一化,未必能完全解决正交性带来的交叉项。

所以,真正严肃的 sin/cos 修调,本质上不是简单乘一个系数,而是在做一个从“畸变坐标系”到“理想正交坐标系”的变换。最粗略的修正可以写成:

x’ = Kx · (x_in - x_0)

y’ = Ky · (y_in - y_0)

这一步处理的是中心和幅值。但如果正交误差明显,还要考虑两路之间的耦合关系。更一般地看,可以把它理解成一个二维线性变换:

编码器芯片为什么会算错角度?因为它以为看到的是圆,实际看到的是椭圆

这里的 a、b、c、d,就不只是简单的幅值缩放,而是在同时处理轴向比例和非正交带来的混合。这就是为什么我说,编码器里的校准不是“调几个寄存器”那么简单。它背后真正要解决的是:如何从一个偏心、拉伸、倾斜的椭圆,恢复出一个尽量接近理想单位圆的坐标系。

恢复得越好,后面的角度解算器压力就越小。恢复得不好,你后面再省除法器、再优化 atan2、再调跟踪环,都可能只是在椭圆上做精致计算。

6)为什么“四点修调”这种思路很工程?

专利里提到“信号误差修调”,这类方法在工程上通常离不开一个关键动作:找特征点。因为你要知道这个椭圆到底怎么歪。

一个圆变成椭圆以后,最重要的信息通常藏在几个地方:x 方向的正峰值、x 方向的负峰值、y 方向的正峰值、y 方向的负峰值,以及它们对应的过零、相位和幅值关系。这些点可以帮助你估计 x_p / x_n、y_p / y_n、x_0 / y_0、Kx / Ky,以及正交误差相关的相位偏移或交叉耦合项。

为什么这比直接看角度误差更靠谱?因为角度误差是结果,点云形状才是原因。如果你只看角度误差,你只能看到“错了多少”;但如果你看 x/y 点云和这些修调参数,你能知道“为什么错”:是中心偏了,是 y 路幅值大了,是 x 路增益小了,是正交性塌了,还是噪声和谐波污染了峰值估计。

这就是工程诊断和数学解算的区别。数学解算关心的是:给我两个数,我算出角度。工程诊断关心的是:这两个数本身配不配让我算角度。CN116358619B 这类专利真正值得看的地方,也在这里。它把“输入信号不像圆”这件事,从一句经验判断,变成了可修调的参数体系。这就从“算法假设”变成了“产品能力”。

7)为什么这件事在量产里更值钱?

很多人看芯片架构,喜欢看最性感的部分:有没有不用除法,有没有不用大 LUT,有没有不用 ADC,面积多少,功耗多少,几拍出结果。这些当然重要。但编码器芯片真正到量产,麻烦通常不在宣传图最亮的地方。

麻烦在这些地方:磁铁装得不够居中,气隙有偏差,封装后应力变了,客户的机械结构有偏心,前端两路增益不完全一致,温度一变 offset 漂了,某个批次的点云椭圆度更差。

这时候客户不会关心你论文里省了几个模块。客户只会问:为什么这个角度段误差这么大?为什么换一颗芯片曲线变了?为什么装到我的电机上就不一样?为什么标定前后差这么多?为什么低速还行,高速就变难看?

这就是“信号修调”比看上去更值钱的原因。它解决的不是一个漂亮公式,而是一个产品问题:当现实世界把理想圆搞成椭圆以后,芯片有没有能力把它拉回来。如果有,那轻量化解算器才站得住。如果没有,那你省掉的面积,可能会在客户现场的误差曲线里加倍还回来。

8)验收口径要改:先验“圆不圆”,再验“角度准不准”

很多验收流程有一个毛病:一上来就看角度误差。角度误差当然要看,最终客户也确实看角度误差。但如果你只看角度误差,很容易看错根因。

我更建议把验收拆成三步。

第一步,采原始 sin/cos,画点云。不要先上复杂算法,先肉眼看一眼:它像圆吗?中心偏了吗?长短轴差多少?椭圆有没有倾斜?有没有局部畸变?有没有高频毛刺?这一步很土,但非常有效。

第二步,把点云变成可对账指标。至少输出幅值比、offset、正交误差、椭圆倾角,必要时再看谐波、噪声和温漂。这一步的价值是把“感觉不圆”变成数字。不要在会议室里只说“角度误差有点大”,这句话没有工程价值。更有价值的说法是:“y 路幅值比 x 路大 3%,中心偏了 12 LSB,正交误差约 1.5 度,修调前点云椭圆度超限。”

第三步,输入质量达标后,再看角度解算器。否则你永远分不清:到底是解算器不行,还是输入本来就歪?很多现场问题最浪费时间的地方就在这里。你以为自己在调算法,其实你在替前端信号质量还债。

9)我最喜欢的一个现场动作:故意把幅值失配放大

如果你要快速判断一个角度解算结构对幅值失配是否敏感,我建议做一个很粗暴但有效的动作:在不改解算器的前提下,故意让一路信号变大或变小。

可以调前端增益,也可以在离线数据里对一路 sin/cos 做缩放。然后看两件事:角度误差脸谱有没有明显变形,最差角度段是不是跟着变化。如果幅值失配一变大,误差脸谱就明显“长得更丑”,那就说明你的结构把“输入已经归一化”当成了默认前提。

这时候你就不能再把归一化写成设计笔记里的一句话。你必须把它变成产品交付物:怎么采点,怎么估 offset,怎么估幅值比,怎么估正交误差,怎么生成修调参数,怎么存参数,怎么复验,怎么定义量产限值,怎么在客户现场复现。

当然,这个动作也有副作用。你故意放大一路信号时,可能也会改变噪声表现。所以它必须和点云分析一起看,不能把噪声误判成非线性。但作为现场排查手段,它很有用,因为它能快速回答一个问题:你的角度解算器到底是在稳健地算角度,还是在假装输入永远完美?

结尾:轻量化不是不要成本,是把成本从算术转移到校准

我不反对更轻的角度解算器。恰恰相反,在编码器芯片里,轻量化非常重要。面积要省,功耗要控,延迟要低,时序要好收,客户还希望价格别太难看,这些都是真实约束。

但轻量化不是魔法。你从算术单元里省下来的成本,往往会转移到别的地方:输入归一化、信号修调、校准流程、寄存器配置、量产复验、客户现场调试。

所以我现在看一个 sin/cos → angle 的方案,不会只问:有没有省掉除法器,LUT 多大,几拍收敛,延迟多少,面积省了多少。我还会问:点云怎么验,椭圆怎么修,offset 怎么估,幅值失配怎么处理,正交误差怎么补,修调参数存在哪里,量产怎么复验,客户现场出问题怎么对账。

这些问题听起来不如“架构创新”漂亮,但它们决定了一个方案到底能不能交付。

编码器芯片为什么会算错角度?很多时候,不是因为它不会算,而是因为它以为自己看到的是圆,实际看到的是椭圆。

你真的想把“省掉除法器”变成可交付优势,就必须把椭圆度验收 + 输入归一化 + 信号误差修调 + 失配敏感性测试写成一套能复现的流程。

否则你省下来的面积,迟早会在量产的误差曲线里加倍还回去。

应作如是观
公众号「如是有为」二维码

关注公众号「如是有为」

微信扫一扫,新文章先在公众号发出。