共计 1597 个字符,预计需要花费 4 分钟才能阅读完成。
旋转编码器是 Arduino 项目中常用的输入设备,特别是在需要精确控制旋转位置或速度的场景中。今天我们就来聊聊如何正确使用旋转编码器,从硬件连接到软件处理,再到常见问题的解决。

旋转编码器工作原理
旋转编码器分为绝对式和增量式两种,我们常用的增量式编码器通过 A、B 两相信号输出旋转信息。当编码器旋转时,两相会产生相位差 90 度的方波信号:
- 顺时针旋转时,A 相先于 B 相变化
- 逆时针旋转时,B 相先于 A 相变化
这个特性让我们能够判断旋转方向,同时通过计数脉冲数量可以确定旋转角度。
常见问题分析
实际使用中常会遇到以下问题:
- 信号抖动:机械触点式编码器在切换时会产生多次通断
- 误计数:干扰或抖动导致计数器错误增减
- 连接错误:上拉电阻缺失或接线不当导致信号不稳定
硬件连接方案
一个可靠的硬件连接方案应该包括:
- 编码器输出端通过 10kΩ 上拉电阻连接至 VCC
- A、B 相信号分别连接至 Arduino 的数字引脚(建议使用支持中断的引脚)
- 公共端接地
- 必要时在信号线和地之间添加 0.1μF 电容滤波
推荐使用以下引脚连接:
编码器 A 相 -> Arduino D2(支持外部中断 0)编码器 B 相 -> Arduino D3(支持外部中断 1)编码器 GND -> Arduino GND
软件实现方案
下面是经过验证的完整代码实现,包含方向判断、计数和消抖处理:
// 定义编码器连接的引脚
#define ENCODER_A 2
#define ENCODER_B 3
// 计数器变量
volatile long encoderCount = 0;
volatile long lastEncoded = 0;
void setup() {Serial.begin(9600);
// 设置编码器引脚为输入模式,启用内部上拉
pinMode(ENCODER_A, INPUT_PULLUP);
pinMode(ENCODER_B, INPUT_PULLUP);
// 启用中断,监测 A 相信号变化
attachInterrupt(digitalPinToInterrupt(ENCODER_A), updateEncoder, CHANGE);
}
void loop() {
// 主循环中定期输出计数值
Serial.println(encoderCount);
delay(100);
}
// 中断服务函数
void updateEncoder() {
// 读取当前 A、B 相状态
int MSB = digitalRead(ENCODER_A);
int LSB = digitalRead(ENCODER_B);
// 组合成 2 位二进制数表示状态
int encoded = (MSB << 1) | LSB;
// 计算状态变化方向
int sum = (lastEncoded << 2) | encoded;
// 状态机判断方向
if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) {encoderCount++;} else if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) {encoderCount--;}
// 更新上一次状态
lastEncoded = encoded;
}
性能优化建议
- 中断响应时间:尽量保持中断服务函数简短,避免复杂计算
- 去抖动时间:机械编码器建议设置 5 -20ms 的消抖时间
- 状态采样:使用状态机而非简单边沿检测,提高可靠性
避坑指南
- 电源噪声:为编码器提供干净的电源,必要时添加 LC 滤波
- 机械安装:确保编码器轴对中,避免侧向力
- 长线传输:超过 30cm 的连线建议使用屏蔽线
- 接地处理:单点接地避免地环路干扰
扩展思考
如何实现多编码器同时检测?可以考虑以下方案:
- 使用支持更多中断的 Arduino 型号
- 采用轮询方式检测(牺牲响应速度)
- 使用专用编码器接口芯片
通过本文介绍的方法,你应该能够可靠地使用旋转编码器了。实际应用中,记得根据具体型号调整参数,特别是消抖时间。如果遇到问题,先从硬件连接检查起,再逐步调试软件部分。
正文完
