共计 1354 个字符,预计需要花费 4 分钟才能阅读完成。
旋转编码器基础认知
- 增量式 vs 绝对式
- 增量式(本文重点):通过 A / B 两相方波相位差判断方向,每转输出固定脉冲数(如 600PPR)
-
绝对式:直接输出二进制位置编码,成本较高但断电不丢位置
-
常见类型选择
- 机械触点式(EC11):价格低但易抖动,需硬件消抖
- 光电式(HEDS-5500):无接触磨损,精度高但需专用解码芯片
硬件连接要点

图示:典型 5 引脚编码器连接方式(VCC/GND+AB 相)
- 必须组件
- 10kΩ 上拉电阻(若编码器无内置)
-
0.1μF 电容并联 AB 相(机械编码器必选)
-
GPIO 选择原则
- 中断版本:优先选择 D2/D3(UNO 的 INT0/INT1)
- 轮询版本:任意数字引脚均可
软件实现方案
方案一:基础轮询法
// 引脚定义
const int pinA = 2, pinB = 3;
int counter = 0, lastState = 0;
void setup() {pinMode(pinA, INPUT_PULLUP);
pinMode(pinB, INPUT_PULLUP);
lastState = digitalRead(pinA);
}
void loop() {int currentState = digitalRead(pinA);
if (currentState != lastState) {if (digitalRead(pinB) != currentState) {counter++;} else {counter--;}
lastState = currentState;
}
}
缺陷:高速旋转时可能丢失脉冲
方案二:中断 + 状态机(推荐)
volatile int counter = 0;
int lastEncoded = 0;
void updateEncoder() {int MSB = digitalRead(2); // A 相
int LSB = digitalRead(3); // B 相
int encoded = (MSB << 1) | LSB;
int sum = (lastEncoded << 2) | encoded;
if(sum == 0b1101 || sum == 0b0100 ||
sum == 0b0010 || sum == 0b1011) counter++;
if(sum == 0b1110 || sum == 0b0111 ||
sum == 0b0001 || sum == 0b1000) counter--;
lastEncoded = encoded;
}
void setup() {attachInterrupt(0, updateEncoder, CHANGE);
attachInterrupt(1, updateEncoder, CHANGE);
}
优势:通过 4 状态校验实现硬件级消抖
避坑指南
- 信号抖动问题
- 现象:静止时计数器自动变化
-
解决:增加 20ms 软件延时或改用硬件滤波电路
-
方向判断错误
- 现象:顺时针 / 逆时针计数相反
-
解决:交换 AB 相接线或修改代码判断逻辑
-
高速漏脉冲
- 现象:快速旋转时计数减少
-
解决:改用中断方式并优化代码执行效率
-
电源干扰
- 现象:电机启动时数值跳变
- 解决:编码器电源与电机电源隔离
进阶思考
- 多编码器扩展 :采用 PCA9548A 等 I2C 扩展芯片,或选择带 Index 信号的编码器
- 高速处理方案 :使用 Timer 中断定期采样,或换用支持 Quadrature 模式的专业 IC(如 LS7366R)
实践发现:在 3D 打印机项目中,采用状态机方案 +100nF 电容滤波后,编码器误触发率从 15% 降至 0.3%
正文完
