首页 > 解决方案 > 如何读取旋转编码器输入

问题描述

我有一个关于如何读取旋转编码器输入的简单问题。如果我正确理解了这张图片,那么每转一圈都会触发引脚 A 的上升。然后,您必须检查引脚 B,如果编码器顺时针转动,则该引脚为高电平,如果编码器逆时针转动,则引脚 B 为低电平。 图表

我尝试编写自己的代码而不使用任何库,因为我认为这会非常简单,但事实证明并非如此。

这是我写的代码:

#define rotary_A 2
#define rotary_B 3

void setup() 
{
  pinMode(rotary_A, INPUT);
  pinMode(rotary_B,  INPUT);

  attachInterrupt(digitalPinToInterrupt(rotary_A), rotary_spin, RISING);

  Serial.begin(9600);
}

void rotary_spin()
{
  if (digitalRead(rotary_B) == HIGH)
    Serial.println("+");
  else
    Serial.println("-");
}

+当我顺时针转动它和逆时针转动它时,我期望得到-。但是,我每回合都会得到几个输出,就像快速连续触发了几个中断一样。例如,当我顺时针转动编码器时:

-
-
+
+

和逆时针:

+
+
-
-
-
-

每次输出都不同,但最后一个字符总是正确的。
我怎么了?是不是很简单,还是有不同类型的编码器?

标签: carduinoembeddedinterrupt

解决方案


这个问题意味着每转应该只有一个中断。但编码器通常每转产生一个以上的周期——有些是数千个。这可能就是中断似乎比预期发生得更快的原因。

在零延迟中断环境中,代码应该可以工作。但是如果在A相管脚变高后,B相管脚采样时间过长,就会失效。Serial.println如果在前一个中断中仍在执行时出现下一个阶段 A 上升沿,则可能会发生这种情况。

一个简单的测试,看看是否是这种情况,就是非常非常缓慢地转动编码器。如果这导致正确的数据,则问题可能是中断延迟。Serial.println然后可以用更快的东西代替,比如点亮 LED,看看这是否能解决延迟问题。

对于实际使用,您需要确保 A 相变高和 B 相被采样之间的最坏情况延迟足以满足编码器旋转的最大速率。

最后说明:代码应该能够充分检测方向,但不能用于增加/减少计数器以跟踪位置。这需要每个周期不止一个中断。


推荐阅读