解决单向旋转偶发反向:旋转电位器(rotary-potentiometer)严格消抖算法深度解析
【免费下载链接】CupCode_EC11旋转编码器模块此扩展适配于采用EC11的旋转编码器,不支持按键。项目地址: https://gitcode.com/yuanshixiong/rotary-potentiometer
旋转旋钮只往一个方向转,数值却偶尔"跳回去"——这是EC11旋转编码器使用中最典型的接触抖动问题。本文以源师兄扩展的旋转电位器项目(rotary-potentiometer / EC11旋转编码器模块)为例,深度解析其核心 ec11.py 中的严格消抖算法:从"为什么会偶发反向"讲起,拆解"下降沿捕捉 + 5次采样表决 + 连续3次确认"的三层抗抖动机制,并演示如何用积木块快速接线、初始化与验证旋转方向,帮新手一次读懂旋转编码器消抖的原理与用法。
一、为什么单向旋转会"偶发反向"?
要解决反向,先要理解它的来源。EC11 编码器靠CLK(A相)与 DT(B相)两路数字信号通信,两路脉冲之间有约 90° 的相位差,芯片正是靠"谁先变"来判断方向:
- A 先变化 → 一个方向
- B 先变化 → 另一个方向
⚠️ 机械触点在切换瞬间会产生毫秒级的抖动(弹跳、干扰),A/B 两路电平会短暂"乱跳"。如果程序对每次电平变化都立刻响应,一次正常的旋转就可能被误判成几次"正、反、正",这就是偶发反向的根源。
结论:任何可靠的编码器驱动都必须"消抖",区别只在于消抖有多严格。
二、严格消抖算法:三层防线怎么工作
核心逻辑全部位于驱动文件 ec11.py,其设计目标是文件开头注释所写的——"解决单向旋转时偶发反向的问题"。
1. 只在 CLK 下降沿采样,且先等 200 微秒
程序并不追踪 A、B 两路的所有变化,而是只盯着 CLK 的下降沿(高电平→低电平)这一个"节拍点"。捕捉到下降沿后,先故意等待 200 微秒,等触点抖动趋于稳定,再去读取 DT 的状态。
💡 一句话:把"乱糟糟的抖动窗口"整体跳过,只在一个相对稳定的时刻采样。
2. 5 次采样取多数:一次读数不够,就数 5 次
单次采样仍可能被干扰"骗到"。于是驱动在 L96-L101 连续对 DT 采样 5 次(每次间隔 50 微秒),然后做多数表决:
dt_value = 1 if sum(dt_samples) > 2 else 0 # 5 次中超过 2 次为高,判定为高电平5 次采样里最多允许 2 次"错票",结果依然正确——这就是"取多数"的抗噪能力。表决结果直接给出本次的原始方向:DT 为高 = 顺时针,DT 为低 = 逆时针。
3. 连续 3 次同向才确认方向
最后一道防线在 L108-L114:即使单次的表决结果正确,驱动也不立即计数,而是检查本次原始方向与上一次是否一致——
- 方向一致 → 计数器加 1
- 方向变了 → 计数清零、重新累计
- 连续 3 次同向,方向才被"确认",驱动才真正更新数值和方向
这一步专治"偶发":偶发的一次反向脉冲撑不起连续 3 次,会被直接丢弃;而真实的反向旋转会持续产生同向脉冲,第 3 次即被确认。偶发反向因此从机制上被消除。
三层防线的效果可以这样概括:
| 防线 | 针对的问题 | 代价 |
|---|---|---|
| 下降沿 + 200µs 延时 | 触点抖动窗口 | 几乎无 |
| 5 次采样多数表决 | 单次采样毛刺 | 约 250µs |
| 连续 3 次同向确认 | 偶发反向脉冲 | 响应略延迟,手感更顺滑 |
三、顺带理解:加速计数与边界保护
消抖确认方向后,L114-L128 还会做两件事:
- 加速计数:两次旋转间隔小于 50ms 时,步进系数逐级增大(最高 10 倍),转得越快数值跑得越快,手感更接近旋钮;停顿后系数自动回落。
- 边界钳位:数值自动限制在初始化设定的最小值与最大值之间(默认 0~255),不会越界。
如果你发现"数值卡在边界不动",就是钳位生效了,调大初始化积木的最大值即可。
四、积木块快速上手:从接线到验证方向
最快配置方法(对应 blocksdef.js 中定义的积木):
- 硬件接线:CLK 接积木"A连接到"所选数字引脚,DT 接"B连接到"所选引脚,VCC 接 3.3V/5V,GND 共地;按键 SW 悬空(本扩展不支持按键)。接线细节见 README.md。
- 放置初始化积木:程序开头先用"EC11旋转编码器 | 初始化",指定 A/B 引脚与最小值、最大值、步长,它会创建编码器对象并启动后台计数线程。
- 用获取方向积木验证:顺时针返回
1,逆时针返回-1,无新旋转返回0。
💡 注意:方向在每次旋转事件后只返回一次即复位,需要持续判断时请每次旋转后立即读取"获取方向"。
五、常见问题速查清单
| 现象 | 原因与解决办法 |
|---|---|
| 旋转方向与预期相反 | A/B 两相接反,交换接线或初始化时把reverse设为True |
| 读数偶发反向 / 抖动 | 驱动已内置严格消抖;若仍异常,检查接线牢固度与供电稳定性(建议 3.3V 共地) |
| 数值卡在边界不动 | 值被钳位在最小/最大值,调大初始化积木的最大值 |
| "获取方向"一直是 0 | 方向只持续一次事件,旋转后立即读取 |
| 按键无效 | 本扩展不支持 EC11 的 SW 按键,请改用其他按键积木 |
六、相关资源导航
- 核心驱动(严格消抖 + 加速计数):ec11.py
- 积木块定义:blocksdef.js
- 设备说明与接线文档:README.md
- 扩展元信息:config.json、category.json
小结:旋转电位器(rotary-potentiometer)解决"单向旋转偶发反向"的关键,不在硬件而在算法——下降沿定点采样、5 次表决、连续 3 次确认,三层防线把接触抖动挡在计数之外。理解这套思路后,你也能把同样的方法用到自己的编码器项目中。
【免费下载链接】CupCode_EC11旋转编码器模块此扩展适配于采用EC11的旋转编码器,不支持按键。项目地址: https://gitcode.com/yuanshixiong/rotary-potentiometer
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考