
简介这份PDF文档面向参加飞思卡尔杯大学生电子设计大赛的选手以及从事运动机械控制与传感器选型的电子工程学习者聚焦绝对式编码器在断电、电子噪声干扰等工况下的位置检测与控制优势。压缩包内仅含1个PDF文件约273KB篇幅紧凑适合快速通读与备赛查阅。目前已有57人学习。文中从光学编码器的“调音轮”起源、码盘与光敏元件的光电转换原理讲起对比增量式编码器断电丢失位置、噪声误差累积的局限重点说明绝对式编码器唯一码值、断电后即时定位、高噪声下纠错等特性并延伸至单圈与多圈结构、格雷码编码、分辨率与齿轮比等知识点可为竞赛选题、课程设计及工程选型提供参考。1. 为什么绝对式编码器断电后依然知道自己在哪做运动机械控制的同行大概都遇到过这个场景一台小车在赛道上跑到一半被人拔了电源重新上电后它居然还能报出当前转向角连一次回零动作都不用做。这个反直觉的表现正是绝对式编码器在飞思卡尔杯大学生电子设计竞赛里被反复选用的理由。它和增量式编码器最大的差别不在分辨率高低而在于每个机械位置对应一个唯一数字码值任何两个位置的码值都不重复所以一上电就是一个确定的位置而不是一个“我转过多少格”的相对量。增量式编码器的思路是数脉冲。A、B 两路方波相差 90 度比较相位先后就能判方向再加一个 Z 相零位信号做参考。问题在于断电时这个累加值就清零了重新上电必须转到 Z 相才能重新找到一个已知位置而这期间噪声引起的误差会被一路累积下去越跑越偏。绝对式编码器直接把这个累加过程从硬件里取消位置由码盘当前刻线决定跟历史无关电子噪声最多影响当前这一帧读数下一帧换了码值就能自我纠正。这两类器件各自的适用边界很清楚短周期、重复性好的场合增量式成本低、接口简单断电无法重新初始化、运动缓慢、可靠性要求高、读取间隔长的场合绝对式才是明智选择。后面的内容就沿着码盘、码制、参数换算、接口时序这条线把这块器件拆开讲透。2. 格雷码与码盘绝对式编码器的信号链从哪里来2.1 码盘、光敏元件与信号调理链路光学绝对式编码器的机械结构简单得不像话一根转轴、一片和转轴同轴固定的码盘、一套准直聚焦光路、一排光敏元件加一个接口保护盖。一束光经过准直、聚焦后穿过码盘码盘上刻着透明与不透明相间的图形把光束调制后投射到光敏元件上光敏元件把光信号转成电信号再经过施密特整形、差分驱动送到控制器。决定精度的不是这套结构本身有多玄妙而是码盘刻线的均匀度、光路对准的一致性、光敏元件阈值的一致性和温漂。制造环节要求很高精度因为任何一条刻线的偏心或宽度误差都会直接变成最低有效位的跳动。常见做法是码盘采用玻璃或金属基底玻璃用于高分辨率、环境相对洁净的场合金属抗冲击和污染能力更好代价是分辨率上限低一些。整条链路上最容易被忽视的是码盘与转轴的机械连接。编码器轴如果装得不正偏心会直接体现为读数周期性摆动而且会显著缩短轴承寿命。一般工程上会用柔性耦合机构连接被测轴而不是刚性联轴器硬顶上去需要减速或增程时也可以用齿轮、同步带配合。2.2 格雷码为什么能消掉多位跳变误读绝对式编码器最常被提到的码制是格雷码它是一种循环二进制码相邻两个数之间只有一位发生变化。这一点不是玄学——如果用普通自然二进制码从 7 变到 8 时会有几乎所有的位同时翻转而机械响应和电子响应总有微小的时间差多位不会严格同时切换中间那一瞬间读出来的就是一段谁也不是的模糊值控制器可能据此算出很大的偏差。格雷码把相邻数之间的跳变压缩到一位采样瞬时要么是旧码要么是新码不会出现中间态。控制器拿到码值后做一次异或前缀运算就能还原成二进制def gray_to_bin(g): 把格雷码还原成自然二进制码 b g shift 1 while (g shift) 0: b ^ (g shift) # 逐级异或等价于异或前缀和 shift 1 return b for code in [0b000, 0b001, 0b011, 0b010, 0b110, 0b111]: print(bin(code), -, gray_to_bin(code))循环里的每一步都是把原始格雷码右移若干位后继续异或位移量从 1 逐步翻倍递增的写法也可以但逐位移更直观。参数上要注意函数的输入必须是完整帧里的有效数据位不要把起始位、错误位或校验位混进去否则还原出来的位置会整体偏移。提示如果编码器内部已经做了格雷码到二进制的译码接口上给出的就是二进制原始值这时候再手工转一次会把数据彻底搞乱。选型时先确认输出码制别凭直觉套公式。2.3 单圈与多圈齿轮比如何决定量程绝对式编码器分单圈和多圈两类。单圈编码器的分辨率只在绕输入轴的一整圈内有效多圈编码器则在整个量程范围内都给出唯一码值。多圈实现方式通常是两个编码器组装在一个壳体内一个精编码器直接连输入轴提供高分辨率的角度信息另一个粗编码器也叫圈数计数编码器通过精密齿轮和精编码器相连精编码器每转过整圈粗编码器的码值就加一位。整个量程内的圈数上限由精、粗编码器之间的齿轮比决定。齿轮齿数比通常取 2 的整数次幂比如 1:8、1:16、1:32这样粗编码器的输出可以直接当二进制高位拼接到精编码器数据前面不需要再做乘除换算。类型单圈分辨率圈数整体分辨率典型场景单圈409612 位14096短程、重复性动作多圈819213 位40968192×4096 ≈ 3355 万长行程、升降机构多圈409612 位256约 105 万转台、云台选型时的判断依据很直接机构的实际最大转圈数只要超过 1 圈就要考虑多圈超过 1 圈但读数只在整圈内用的例如只关心输出轴相位单圈也够用。多圈编码器本质上仍然是绝对式的它的粗编码器同样有断电保持能力靠的往往是内部齿轮组加磁编码或额外的光电码盘而不是外接电池。3. 分辨率、精度、重复性选型参数怎么算才不踩坑3.1 位数与分辨率怎么换算一个编码器的分辨率由位数决定或者由包含在一整圈中的码字数决定。译码之后一个数代表 2 的指数分之一圈。12 位编码器的分辨率是 2 的 12 次方即 4096 个码一个码代表 360°/4096 ≈ 0.0879°13 位是 8192 个码精度直接翻倍。实际工程里更常用的是从被测物理量反推位数。假设要测量的行程是 100 mm要求的测量精度是 0.01 mm那么需要的码数是 100 / 0.01 10000向上取到 2 的整数次幂就是 16384对应 14 位。如果测的是一个圆周内的角度要求分辨率 0.01°需要的码数是 360 / 0.01 36000向上取整到 65536即 16 位。位数每圈码数每码对应角度每码对应 100mm 行程1010240.352°0.098 mm1240960.088°0.024 mm1381920.044°0.012 mm16655360.0055°0.0015 mm195242880.00069°0.00019 mm工业现场普遍使用到 19 位以下的分辨率再往上通常出现在航天和科研场景制造难度和成本都是非线性上升的。经验上码值每增加一位分辨率翻倍但制造难度大致要提高一倍以上所以不要无脑堆位数。3.2 精度不等于分辨率重复性也不等于精度这三个概念经常被混着用但它们描述的是不同的事。分辨率是“能分辨出多小的变化”精度是“最低位的位置准不准”重复性是“每次回到同一位置时读数是否一致”。用一把以英寸为单位的尺子做类比尺子上最小刻度就是它的分辨率但它的精度还没被定义如果这把尺子本身比标准尺长了 1%那它能量出很细的刻度却每次都偏。在编码器里精度一般表达为最低有效位的倍数比如 ±1 LSB 或者 ±0.5 LSB重复性通常是绝对精度的五分之一甚至更好因为重复性只要求读数稳定不要求读数与真实角度严格对应。def check_repeatability(readings, nominal): readings: 多次回到同一位置时的读数列表(单位:度) nominal: 该位置的理论角度(单位:度) lsb 360.0 / 4096 # 12 位单圈的分辨率 errors [r - nominal for r in readings] peak_to_peak max(errors) - min(errors) print(f分辨率 LSB {lsb:.4f}°) print(f单次最大偏差 {max(abs(e) for e in errors):.4f}° f {max(abs(e) for e in errors)/lsb:.2f} LSB) print(f重复性(峰峰值) {peak_to_peak:.4f}° f {peak_to_peak/lsb:.2f} LSB) return peak_to_peak # 正反转各测 5 次回到理论位置 90° data [90.02, 89.99, 90.01, 89.98, 90.00, 90.03, 89.97, 90.00, 90.01, 89.99] check_repeatability(data, 90.0)这段脚本把偏差统一折算成 LSB 倍数方便和厂家手册里的指标直接对照。参数上nominal最好由外部基准例如自准直仪或高一级的标准转台给出而不是由编码器自己反向标定否则测出来只是自洽性不是重复性。注意如果一个编码器给了很高的分辨率和一般的精度用在位置闭环里通常够用因为闭环会持续修正但用在开环的位置测量或标定环节精度才是决定性的。3.3 环境、机械接口与电气接口的选型顺序选定一个满足精度和分辨率要求的编码器之后第一个要过的坎其实是机械和电气接口。机械上大多数绝对式编码器通过柔性耦合机构和系统相连也可以选齿轮、滑轮或其它连接方式。轴装调不合适会引起很大偏差并显著缩短寿命所以装完最好先手动盘一圈看读数是否平滑、有无跳变点。环境因素同样重要。密封连接器、密封轴、加固外壳是用来保护内部精密元件防振动、防冲击、防污染和防误操作的。选择时让编码器的防护等级匹配现场环境比事后加防护罩更可靠。电气接口由连接它的控制器决定重点是输出电平和输入电平的匹配。外部因素里来自电机、接触器和变频器的电气噪声、电缆长度、数据采样率都必须一并考虑。制造厂家通常能提供多种输出形式兼容输出最普遍也可以要求具备一定驱动能力的输出、开路集电极输出、线性差分输出部分型号甚至提供串行数据输出。还有一点最容易被忽略——供给编码器的电源。电缆太长或太细会导致到达编码器端的电压达不到要求一个精密的编码器会因此工作不正常表现为偶发数据错、周期抖动甚至完全无响应。接口形式线数抗干扰能力传输距离适用场景并行多位数电源一般短早期系统、短距离开路集电极少较弱短低速、简单场合线性差分RS-422少强较长工业现场主流串行 SSI4~6强长多圈、高位数BiSS-C / EnDat4~6强长需要参数读写、高实时性4. 电接口与协议从 SSI 到 BiSS-C 的读取流程4.1 串行协议怎么选并行输出把每一位单独引出来控制器一个端口读一次就有完整位置延迟极低但线缆数量随位数线性增长19 位就是 19 根数据线加电源和地现场布线很痛苦长距离下串扰也严重。串行接口把位数压缩到几根线上用时钟同步移位是目前主流的做法。SSI 是最简单的一种主机发时钟编码器在每个时钟沿输出一位一般是一帧起始位加数据位数据以最高位在前的方式移位输出帧间需要留一段空闲时间让编码器准备下一帧这个空闲时间通常要求大于某个最小周期。BiSS-C 在 SSI 的基础上加入了 CRC 校验和双向寄存器读写可以读序列号、分辨率、故障状态等信息实时性和可靠性都更好EnDat 则是另一套带参数通道的协议功能更丰富但实现也更重。选型判断只读绝对位置、线缆不长SSI 够用需要在线诊断、参数在线修改或对数据完整性要求高选 BiSS-C 或 EnDat。飞思卡尔杯这类竞赛项目的控制周期通常在毫秒级接口延迟远小于控制周期SSI 一般不会成为瓶颈。4.2 用软件 SPI 读取一帧 SSI 数据很多 MCU 的硬件 SPI 支持 SSI 时序但 SSI 的帧长、极性和空闲时间不一定匹配用 GPIO 模拟时序反而更可控。下面是一段 25 位帧的读取示例1 位起始位 12 位多圈 12 位单圈具体位段以手册为准#define CLK_HIGH() (GPIOB-BSRR GPIO_PIN_13) #define CLK_LOW() (GPIOB-BRR GPIO_PIN_13) #define DATA_READ() ((GPIOB-IDR GPIO_PIN_14) ? 1u : 0u) uint32_t ssi_read_frame(void) { uint32_t frame 0; /* 帧间空闲拉高时钟至少 t_idle给编码器准备时间 */ CLK_HIGH(); delay_us(20); for (int i 0; i 25; i) { CLK_LOW(); delay_us(1); /* 半周期必须小于编码器允许的最大时钟频率 */ frame 1; if (DATA_READ()) { /* 下降沿后数据有效 */ frame | 1u; } CLK_HIGH(); delay_us(1); } return frame; /* 返回原始帧含起始位 */ } void parse_position(uint32_t frame, uint32_t *multi, uint32_t *single) { *multi (frame 12) 0x0FFF; /* 低 12 位为多圈 */ *single frame 0x0FFF; /* 中间 12 位为单圈 */ }逻辑上时钟由主机全程控制每个下降沿之后数据线更新主机在下降沿后采样即可。参数上有三个必须核对时钟半周期不能小于编码器允许的最小时钟周期帧与帧之间的空闲时间不能小于手册给的 t_idle以及位段的切分必须和手册一致。上面parse_position里的掩码是按示例帧结构写的如果换成 13 位单圈 12 位多圈掩码和移位量都要跟着改。提示第一次调试时先不要做解析把ssi_read_frame()的返回值直接打到串口或示波器上慢慢手动转动编码器观察数值是否单调递增、有无异常跳变这比一上来就写闭环快得多。4.3 采样节拍与滤波SSI 帧读取本身耗时很短通常几十微秒但这不意味着可以随便提高采样率。编码器的更新率、电缆的建立时间、主机中断的抖动都会影响结果。常见做法是固定一个采样周期例如和电流环同频或降频运行读三帧取中值或者对连续两帧做一致性判断不一致就丢弃并使用上一帧。对于位置环直接对编码器原始值做低通滤波要谨慎因为滤波会引入相位滞后降低闭环带宽。更好的方式是把滤波放在速度估计环节用位置差分求速度再对速度做滑动平均或一阶滤波。如果必须在位置环上加滤波也应该只滤掉明显超出机构物理运动能力的跳变例如超过机械最大速度对应值的变化量。5. 竞赛与工程现场的调试技巧5.1 上电、断电与位置校验的完整流程绝对式编码器最核心的价值就是断电后位置不丢但前提是断电期间机构没有被外力移动过或者移动后新的位置仍然能被正确读出。多圈编码器内部齿轮组在没有外部电池的情况下也能保持圈数所以上电后的流程很短读取帧、解析出多圈和单圈、拼接成完整位置、和一个已知的软限位区间比对越界就报错。一个常见的坑是把“上电后不用回零”理解成“上电后不用做任何校验”。正确的做法是保留一次安全校验把上电读到的位置和上次断电前存到非易失存储里的位置对比差值超过阈值就说明机构在断电期间被外力动过需要提示或进入安全状态。阈值一般取几倍 LSB太小会被温漂误触发太大则失去保护意义。5.2 电子噪声下的纠错手段绝对式编码器在高电子噪声场合的优势在于它能纠正在下一个变化位置上的误差并产生一个新的、不同的输出码。落到工程上能主动做的有几件事用双绞屏蔽电缆屏蔽层在控制器侧单点接地数据线走差分时钟和数据尽量远离电机相线和继电器线圈编码器电源和控制器电源之间加磁珠或 LC 滤波。在协议层面如果用的是 BiSS-C 或带 CRC 的帧格式一定要启用校验并把校验失败计数出来。数据错不是罕见事件关键是错的时候要能发现。SSI 帧本身没有校验时可以自己做一致性判定连续两帧的差值不应超过机构在该采样周期内的最大可能变化量超过就丢弃。这个方法比任何滤波器都简单有效。5.3 用最小固件验证一台上电不正常的编码器现场遇到编码器读数异常时最快的定位方式不是翻整机代码而是烧一段最小验证固件只做三件事按固定周期读帧、把原始帧和解析后的位置一起打印、统计连续两次读数的差值。下面这段打印逻辑可以直接塞进主循环uint32_t last 0; uint32_t err_cnt 0; while (1) { uint32_t frame ssi_read_frame(); uint32_t multi, single; parse_position(frame, multi, single); uint32_t pos (multi 12) | single; int32_t delta (int32_t)(pos - last); /* 正常静止或匀速时 delta 应远小于阈值超阈值计入异常 */ if (delta 64 || delta -64) { err_cnt; printf(JUMP frame0x%07lX pos%lu delta%ld cnt%lu\r\n, (unsigned long)frame, (unsigned long)pos, (long)delta, (unsigned long)err_cnt); } last pos; delay_ms(10); }阈值 64 对应约 1.4°12 位单圈按实际机构的最大转速换算后再调整。如果打印出来的JUMP集中在某个角度区间很可能是码盘某段刻线受污染或光路局部遮挡如果JUMP随机分布且伴随固定频率优先怀疑电源纹波和地环路如果上电第一帧就异常检查帧间空闲时间是否足够、电缆是否存在断线或接触不良。把原始frame一并打印而不是只打印解析结果是为了区分是时序错位还是数据位错位——时序错位会让整个帧错位数据位错位则只影响某个位段。本文还有配套的精品资源点击获取