Arduino旋转编码器读取:从硬件原理到精准解码实践

1次阅读
没有评论

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

image.webp

背景痛点

旋转编码器在 Arduino 项目中常被用于精确的位置检测,但实际应用中经常会遇到以下问题:

Arduino 旋转编码器读取:从硬件原理到精准解码实践

  • 信号抖动:机械接触式编码器在旋转时会产生瞬态抖动,导致误计数。
  • 方向误判:A/ B 相信号的相位差解析不准确,导致旋转方向识别错误。
  • 计数丢失:轮询方式读取时,高速旋转可能导致信号跳变被遗漏。

这些问题直接影响编码器的精度和可靠性,尤其在工业控制或机器人应用中更为明显。

硬件原理

增量式旋转编码器通常输出两路正交信号(A 相和 B 相),其波形关系如下:

  • 顺时针旋转:A 相领先 B 相 90 度。
  • 逆时针旋转:B 相领先 A 相 90 度。

通过检测 A / B 相的边沿变化和相位差,可以准确判断旋转方向和步数。

技术方案

轮询法 vs 中断法

  • 轮询法:简单易实现,但效率低,可能丢失高速信号。
  • 中断法:响应速度快,适合实时性要求高的场景,但需要合理设计中断服务程序。

状态机解码算法

  1. 使用 PORT 寄存器直接读取 :避免digitalRead 函数的开销,提升读取速度。
  2. 4 倍频计数:在 A / B 相的上升沿和下降沿均触发计数,实现更高分辨率。
  3. 时间窗口消抖:设置合理的时间阈值(如 5ms),忽略短时间内多次触发。

代码实现

以下是基于 PlatformIO 的 Arduino 代码示例:

#include <Arduino.h>

// 定义编码器引脚
#define ENC_A 2
#define ENC_B 3

volatile int32_t count = 0;
volatile uint8_t state = 0;

void setup() {
  // 配置引脚为输入,启用内部上拉
  pinMode(ENC_A, INPUT_PULLUP);
  pinMode(ENC_B, INPUT_PULLUP);

  // 配置中断,在 A 相边沿触发
  attachInterrupt(digitalPinToInterrupt(ENC_A), encoderISR, CHANGE);
}

void encoderISR() {
  static uint32_t lastTime = 0;
  uint32_t currentTime = millis();

  // 消抖处理
  if (currentTime - lastTime < 5) return;
  lastTime = currentTime;

  // 读取当前 A / B 相状态
  uint8_t a = digitalRead(ENC_A);
  uint8_t b = digitalRead(ENC_B);

  // 更新状态机
  uint8_t newState = (a << 1) | b;
  if (state == 0x00 && newState == 0x02) count++;
  if (state == 0x02 && newState == 0x03) count++;
  if (state == 0x03 && newState == 0x01) count++;
  if (state == 0x01 && newState == 0x00) count++;
  state = newState;
}

void loop() {
  // 主循环中可以安全使用 count 变量
  Serial.println(count);
  delay(100);
}

避坑指南

  • 上拉电阻选择:10kΩ 是常见选择,但高速应用可能需要更低阻值(如 4.7kΩ)。
  • 中断优先级:多编码器系统中,需确保高优先级编码器的中断能及时响应。
  • 机械安装:编码器轴与旋转部件需严格同轴,避免信号不同步。

性能验证

使用示波器观察 A / B 相信号,确保:

  1. 信号边沿清晰,无过多抖动。
  2. 旋转方向变化时,相位差正确。
  3. 计数结果与实际旋转步数一致。

扩展应用

将编码器计数用于 PID 控制时,位置差计算公式为:

error = target_position - current_position;

通过 PID 算法调整输出,实现精准的位置控制。

动手实验

尝试修改代码,实现以下功能:

  1. 将 4 倍频计数改为 2 倍频或单边沿计数,观察分辨率变化。
  2. 添加方向输出,实时显示旋转方向。
  3. 测试不同消抖时间阈值(如 2ms、10ms)对计数稳定性的影响。

通过以上实践,可以更深入理解旋转编码器的工作原理和优化方法。

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