ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

正余弦编码器采样出现8LSB台阶?FPGA状态机少等一拍引发的建立时间问题

正余弦编码器采样出现8LSB台阶?FPGA状态机少等一拍引发的建立时间问题 这个月调一套正余弦编码器细分板卡被一个不大不小的毛病卡了整整两天14位的ADC采回来的Sin波形远看是条正弦拉近了一看全是台阶每个台阶不多不少正好8个LSB。起初以为是量化噪声或者器件体质问题后来用万用表、示波器、逻辑分析仪轮着盘了一遍最后锁定的原因特别朴素——FPGA采样状态机里少等了一拍。这个坑在正余弦采样、带输入MUX的SAR ADC、SPI接口采集这一类场景里非常典型今天把它完整记下来给搞FPGA高速采集、电机编码器细分、伺服位置反馈的同行当个参考。项目本身不复杂一颗14位、8通道、SPI接口的SAR级ADC前端用模拟开关MUX切换Sin和Cos两路正余弦信号FPGA发通道选择和转换脉冲读回码值最后做atan2角度解算。理论上14位、4.096V基准一个LSB也就是0.25mV左右角度细分精度完全可以做到0.05°以内。但实测波形出现固定的8LSB台阶整个细分精度直接被打回原形。这篇文章的内容按工程排障的顺序展开先说现象再说排查思路接着把“8 LSB台阶到底是怎么来的”用公式拆清楚最后给出状态机多看一拍的具体改法和实测收益。1. 项目背景正余弦信号为什么需要14位ADC1.1 正余弦编码器与细分原理正余弦编码器输出的是两路相位差90°的模拟正弦信号通常记作Sin和Cos。角度的计算不需要太多花活核心就是θ atan2(Cos, Sin)。问题在于这两路信号的幅度很小常见的是1Vpp到2Vpp而系统要分辨的角度往往要小于0.1°对应到电压上就是微伏到毫伏级别的变化。举个例子如果正余弦信号幅度A1V在过零附近角度变化1mrad对应约1mV的电压变化。对于14位ADC、4.096V基准来说1mV大约就是4个LSB这还能分辨如果换成12位ADC1mV只相当于1个LSB左右加上噪声基本就废了。所以我一开始选14位ADC而不是12位不是因为“多两位更好看”而是12位的分辨率在正余弦细分场景下确实不够用。1.2 系统对ADC的两个关键要求正余弦采样和普通波形采集最大的区别在于它不只看波形长什么样更看Sin和Cos两路之间的相位关系和幅值精度。有两个要求是硬性的。第一是分辨率要足。14位意味着满量程内共16384个码4.096V基准时1LSB0.25mV。这个量级才能支撑角度细分到0.05°以下不然ADC自己就变成了精度瓶颈。第二是两路信号要尽量同时采样。Sin和Cos如果先采Sin、后采Cos中间隔了哪怕几十微秒在电机转动较快时就会引入一个额外相位差。这个误差在角度解算时表现为一个“椭圆误差”轻则精度下降重则波形看上去像被拧了一圈。这一点后面会再次提到正余弦采样的错误通常是成对出现的要么是时序相位问题要么是建立时间问题。2. 问题现象平滑正弦波上出现了重复的8 LSB台阶2.1 现象的具体描述把信号发生器设置成1kHz、±1.5V的差分正弦输出通过调理电路接到ADC的Sin通道Cos通道接一个相位差90°的同样信号。FPGA以250kSPS的采样率交替采集两路重建出来的波形图上Sin和Cos在过零附近的若干采样点明显不在理想曲线上而是呈阶梯状。台阶的特征非常典型相邻采样点之间的跳变大多是8、0、-8这样的组合偶尔有7或者-9但基本围绕8LSB这个数值波动。台阶每次出现在同一个相位窗口和信号周期严格同步不是随机抖动的噪声。把数据导出来看更直观某个点理论值应该是8194实际采出来是8202下一个点理论上应该缓慢增加结果又跳回8194附近。这种“有规律、幅度固定、位置固定”的异常基本可以排除白噪声和随机干扰。2.2 复现和控制变量的步骤为了确定问题不是个例我把测试流程固定下来信号发生器固定输出FPGA复位后连续采集2000个点上位机做波形重建和差分统计。然后依次做三个控制变量实验。一是只采Sin通道不切换MUX把采样序列里的Cos位置全部用Sin信号填充结果波形完全正常台阶消失。说明ADC本身、SPI读取逻辑、参考电压和模拟前端运放链路都是正常的。二是恢复交替采样但把采样率从250kSPS降到50kSPS台阶幅度肉眼可见地缩小50kSPS时几乎淹没在噪声里。说明问题与时间有关不是纯静态的线性度问题。三是换上模拟开关之前的那一路直接送入ADC的固定通道即使采样率回到250kSPS波形依然干净。到这里矛头已经很清楚了问题出在MUX通道切换之后的时序上而不是ADC芯片本身。3. 排障实录从怀疑器件到锁定采样时序3.1 先排除最容易背锅的量化噪声遇到波形台阶工程师的第一反应往往是“ADC芯片太烂”或者“量化噪声太大”。量化噪声确实是随机的、均匀分布在±0.5LSB范围内的但8LSB的固定台阶显然超出这个范畴。判断依据其实很简单把同一组波形数据做FFT如果是白噪声频谱是一条平底所有频率点上的噪声底均匀抬升如果是这种固定台阶频谱里会出现明显的高次谐波尤其是3次、5次谐波而且谐波幅度和基波幅度比值固定。实测频谱正是后者谐波突兀地立起来说明误差是确定性的、有周期的和信号本身存在固定相位关系。3.2 降采样率实验给出的关键线索降采样率实验是整个排障的分水岭。当时把采样率从250kSPS一路降到50kSPS观察每个采样点相对理想值的偏差。50kSPS时台阶几乎看不见100kSPS时隐约出现2-4LSB的跳变250kSPS时稳定在8LSB左右。这个趋势很容易解释MUX切换后模拟开关的输出到ADC采样保持电容之间需要建立时间建立时间不足采样结果就依赖“上一段历史”。采样率越低两次采样之间留给模拟链路的恢复时间越长误差自然越小。如果问题出在电源纹波或者参考源漂移上这个趋势不会出现。所以基本锁定问题出在“通道切换后立即启动转换”这个操作上。3.3 示波器实测通道选择信号和转换脉冲同时出现锁定方向后用示波器同时抓MUX通道选择信号、ADC的CNV脉冲、BUSY状态和SPI时钟终于看到了决定性证据。FPGA的原始状态机在发出通道选择地址的同一个时钟周期内就拉高了CNV脉冲相当于MUX切换和启动转换是同时发生的。MUX模拟开关的导通切换时间、开关后级RC网络的建立时间、以及SAR ADC采样保持电容完成充电所需的时间全都挤在这一个周期里。数据手册上建议的MUX建立时间在几十纳秒到百纳秒量级而我的系统时钟周期只有100ns等于把裕量全部吃光甚至还不够。所以ADC采样保持电容在CNV上升沿到来时还没有充到目标电压直接被“定格”在了一个偏低的值上。这个现象用一句话概括就是切换通道后少等了一拍就在这一拍里模拟前端还没稳定。而正余弦信号恰恰是斜率最大的信号类型一拍的电压变化直接被放大成8个LSB的台阶。4. 原理拆解8 LSB的台阶是怎么精确算出来的4.1 LSB的物理意义与理想信噪比在展开计算之前先把14位ADC的量化基础捋一遍。基准电压Vref4.096V14位分辨率1LSB计算公式LSB Vref / 2^N 4.096V / 16384 ≈ 0.25mV满量程输入范围是±Vref也就是正负4.096V。理论上ADC的量化噪声引起的理想信噪比SNR为SNR 6.02N 1.76 dB ≈ 86dB这个86dB是理想值实际工程里能做到70dB以上就算不错。但如果出现8LSB的固定台阶换算到SNR大概是20 * log10(满量程 / 误差) 20 * log10(16384 / 8) ≈ 66dB从86dB掉到66dB有效位数ENOB大约掉到11位以下整整损失3位。这正是正余弦细分里绝对不能接受的。4.2 信号斜率、一拍时间与LSB的换算关系台阶是8LSB而不是别的数字这个数值其实完全可以推导出来。正余弦信号过零点附近的斜率最大表达式为dV/dt 2π * f * A * cos(2πft)在过零处cos项等于1所以最大斜率是2πfA。假设测试信号频率f2kHz幅度A1.5V那么2π * 2000 * 1.5 ≈ 18850V/s 18.85mV/ms系统时钟周期T100ns也就是0.1μs。如果采样时刻比理想时刻晚了正好一个时钟周期误差就是ΔV 18850V/s * 0.1us ≈ 1.88mV换算成LSB1.88mV / 0.25mV ≈ 7.5 LSB正好约等于8LSB。这就是“8 LSB台阶”的精确来源。它不是一个神秘的缺陷而是“信号斜率 × 一拍时间”的乘积。频率越高、幅度越大、时钟周期越长台阶就越明显。这也是为什么降低采样率后台阶会缩小——采样周期变大了但信号频率没变但MUX建立时间相对采样周期来说占了更小的比重误差的来源主导因素变了。4.3 建立时间不满足要求的数学本质SAR ADC的采样保持前端可以简化成一阶RC模型采样电容C通过模拟开关的导通电阻R充电。设充电时间常数为τ经过时间t后电容电压Vc(t)和最终目标电压Vs的关系是Vc(t) Vs * (1 - e^(-t/τ))剩余误差为ΔV Vs - Vc(t) Vs * e^(-t/τ)要让误差小于0.5LSB也就是0.125mV要求充电时间满足t ≥ τ * ln(Vs / 0.125mV)如果Vs是2.5V的通道电压差τ是10ns那么需要的建立时间是10ns * ln(20000) ≈ 10ns * 9.9 ≈ 99ns。刚好接近一个系统时钟周期。我原来的状态机只给了大约几十纳秒误差实际落在1.88mV左右于是就是8LSB。这个推导也说明了一个工程原则看ADC数据手册不能只看分辨率还要把tACQ采样建立时间、tCONV转换时间、通道切换后的MUX settling time都加在一起算一遍。SAR ADC的性能上限往往不是芯片决定的而是前端模拟通路和FPGA时序共同决定的。5. 解决方案状态机里多看一拍5.1 原状态机的缺陷原始FPGA状态机是典型的“急性子”写法状态切换极其精简// 错误示例通道切换和启动转换在同一拍完成 IDLE: mux_sel next_channel; cnv_pulse 1b1; // 立刻启动转换 state WAIT_BUSY;问题就在mux_sel和cnv_pulse同时赋值。MUX地址刚切换模拟开关还没完全导通SAR ADC内部的采样保持电容还没来得及对上信号电压CNV脉冲就上来了。这相当于相机快门已经按下但镜头的防抖机构还在调整拍出来的照片自然糊掉。5.2 修改后的状态机增加一拍稳定时间修正方案非常直白就是在MUX通道设置完成后故意多等一拍再拉高CNV。这也是标题里“多看一拍”的由来。// 正确做法通道切换后专门用一个状态等待模拟前端稳定 localparam MUX_SET 3d1; localparam MUX_SETTLE 3d2; // 这拍就是“多看的一拍” MUX_SET: mux_sel next_channel; state MUX_SETTLE; MUX_SETTLE: cnv_pulse 1b1; // 通道稳定后再启动转换 state WAIT_BUSY;这一拍需要根据实际的RC时间常数来定。如果实测一拍不够就改成两拍、三拍直到建立时间余量满足0.5LSB的误差要求。我在这个项目里先加一拍台阶从8LSB降到2LSB左右再加一拍降到1LSB以内。5.3 SPI读取的锁存沿也要多注意台阶问题除了MUX建立之外SPI读取本身也有一个“多看一拍”的细节。SAR ADC通过SPI输出数据时数据在SCK边沿变化FPGA需要在数据稳定后再锁存。常见的错误是SCK最后一个边沿刚过去立刻把移位寄存器的值锁存到输出寄存器结果锁到了不稳定的跳变沿。最稳妥的做法是移位寄存器数满N位之后无条件再等一拍再执行锁存。这样保证数据总线上的电平已经完全稳定边界情况全部消除。// SPI接收完成后的锁存也建议多等一拍 if (shift_cnt 14) begin state LATCH_DELAY; // 看拍 end LATCH_DELAY: sample_data shift_reg; // 数据完全稳定后再锁存 state IDLE;5.4 对模拟前端的额外处理代码层面的“多看一拍”是治本但模拟前端也要配合。我把MUX输出到ADC输入之间的RC低通滤波器的电容从100pF减小到47pF时间常数相应降低建立速度更快。代价是抗混叠能力变弱但对2kHz级别的正余弦信号来说完全够用后面的数字滤波可以再补一刀。这里有个平衡要记住RC滤波器为了抗混叠时间常数不能太小但SAR ADC采样保持为了建立时间时间常数又不能太大。两者是矛盾的。工程上通常保证RC截止频率至少是信号最高频率的5到10倍然后通过时序多看几拍来弥补建立时间。6. 复测结果与量化收益6.1 波形与频谱对比修改之后重建的正余弦波形过零附近不再有明显的8LSB台阶。相邻点差分值从±8下降到±1以内大部分点已经是0到±1的合理量化波动。用FFT看频谱改善更明显。修改前3次谐波幅度约-52dBc修改后降到-72dBc以下大约改善了20dB。整体SNR也从61dB提升到72dB左右有效位数ENOB从大约9.8位提升到11.8位。这个数字已经接近该ADC在这块模拟前端上的实际极限再往上就要靠校准和数字滤波了。指标修改前修改后过零处最大台阶8 LSB1 LSB3次谐波-52 dBc-72 dBcSNR61 dB72 dBENOB9.8 bit11.8 bit6.2 角度解码精度的实际提升对正余弦编码器来说最终看的是角度误差。修改前用CORDIC做atan2解算最大角度误差约±0.35°在伺服控制里这个误差会引起明显的换向抖动。修改后同样的数据角度误差降到±0.04°以内对一般的伺服应用已经非常够用。这个收益也反过来验证了前面的判断8LSB台阶在电压域只占约2mV但在正弦过零附近的电压-角度映射区域2mV直接对应零点几度的误差不可忽视。7. 常见问题排查速查表这个表是我做完这次排障后整理的适合直接抄走现象可能原因快速判断方法处理办法固定LSB台阶随采样率变化MUX切换后建立时间不足单通道正常切通道才出问题状态机多看一拍或几拍台阶随信号频率增大而增大采样时刻与理想时刻存在固定偏移算斜率×一拍的误差和实测对比调整CNV脉冲相对采样窗口的位置Sin和Cos角度误差呈椭圆两路采样不同步采样顺序不是同时启动改用同步触发或者同步采样ADC数据跳变随机无固定规律电源纹波或参考源噪声FFT底噪平抬查LDO、去耦电容、参考源低半字和高半字错位SPI锁存沿选择错误数据呈2^n倍的大跳变检查SCK极性和相位锁存前多等一拍7.1 几条独家避坑经验第一排查ADC台阶问题时不要一上来就怀疑ADC本身。先做“固定通道直流测试”如果直流线性度正常ADC芯片大概率没问题再复现交流问题往往能快速锁定到时序。第二示波器抓时序时一定要把MUX地址线、CNV、BUSY、SCK放在同一帧里看。我最初只看了CS和SCK完全没注意到地址线是跟CNV同拍变化的方向错了半天。第三数据手册上的tACQ数值是按理想信号源算的实际系统里还有MUX导通电阻、滤波器、PCB寄生电容。简单粗暴地把tACQ理解成“绝对够用”是错误的。先用“斜率×一拍时间”估算误差再留出至少50%的时序余量才是不会翻车的做法。最后再留一句经验这套板子现在已经连续跑了两周电机反复正反转、升温之后台阶再没有出现。回看整个排障过程最大的教训不是“ADC坏了”或者“芯片不行”而是FPGA时序里少的那一拍。ADC的数据手册会写满各种电气参数但“建立时间要留够”这种事往往只存在于现场波形里。正余弦信号天生斜率大采样时序每差一拍信号变化量就会原样转成电压误差。这种时候多等一拍往往比换一颗更贵的ADC更管用。
返回列表