Arduino旋转编码器读取实战:从硬件连接到抗抖动处理

1次阅读
没有评论

共计 1354 个字符,预计需要花费 4 分钟才能阅读完成。

image.webp

旋转编码器基础认知

  1. 增量式 vs 绝对式
  2. 增量式(本文重点):通过 A / B 两相方波相位差判断方向,每转输出固定脉冲数(如 600PPR)
  3. 绝对式:直接输出二进制位置编码,成本较高但断电不丢位置

  4. 常见类型选择

  5. 机械触点式(EC11):价格低但易抖动,需硬件消抖
  6. 光电式(HEDS-5500):无接触磨损,精度高但需专用解码芯片

硬件连接要点

Arduino 旋转编码器读取实战:从硬件连接到抗抖动处理

图示:典型 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 状态校验实现硬件级消抖


避坑指南

  1. 信号抖动问题
  2. 现象:静止时计数器自动变化
  3. 解决:增加 20ms 软件延时或改用硬件滤波电路

  4. 方向判断错误

  5. 现象:顺时针 / 逆时针计数相反
  6. 解决:交换 AB 相接线或修改代码判断逻辑

  7. 高速漏脉冲

  8. 现象:快速旋转时计数减少
  9. 解决:改用中断方式并优化代码执行效率

  10. 电源干扰

  11. 现象:电机启动时数值跳变
  12. 解决:编码器电源与电机电源隔离

进阶思考

  • 多编码器扩展 :采用 PCA9548A 等 I2C 扩展芯片,或选择带 Index 信号的编码器
  • 高速处理方案 :使用 Timer 中断定期采样,或换用支持 Quadrature 模式的专业 IC(如 LS7366R)

实践发现:在 3D 打印机项目中,采用状态机方案 +100nF 电容滤波后,编码器误触发率从 15% 降至 0.3%

正文完
 0
评论(没有评论)