如何读取旋转编码器输入

时间:2019-09-18 09:02:48

标签: c arduino embedded interrupt

我有一个关于如何读取旋转编码器输入的简单问题。 如果我正确理解this图像,则每转都会触发引脚A的上升。然后,您必须检查引脚B,如果编码器顺时针旋转,则为高;如果编码器逆时针旋转,则为低。 diagram

我试图编写自己的代码而不使用任何库,因为我认为这真的很简单,但事实并非如此。

这是我编写的代码:

#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("-");
}

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

-
-
+
+

和逆时针方向:

+
+
-
-
-
-

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

2 个答案:

答案 0 :(得分:1)

这个问题意味着每转只能有一个中断。但是编码器通常每转产生一个以上的周期-几千个。这可能就是为什么中断发生得比预期更快的原因。

在零延迟中断环境中,代码应该起作用。但是,如果在A相引脚变为高电平后对B相引脚进行采样的时间过长,它将失败。如果Serial.println在上一个中断中仍在执行时,下一个A相上升沿就会发生。

一个简单的测试,看是否是这种情况,就是慢慢转动编码器非常非常。如果这导致正确的数据,则问题可能出在中断延迟上。然后Serial.println可以换成更快的东西,例如发光的LED,以查看是否可以解决延迟问题。

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

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

答案 1 :(得分:0)

在Github上查看我的这个存储库。

https://github.com/KingZuluKing/Rotary-Encoder-Peripheral-System

必须是类似这样的东西,仓库中有更多细节。

  void encode_Rotor_func()
{
    lcd.clear();
    Vol_Knob_stat=digitalRead(Vol_Knob);    
    if(Vol_Knob_stat==0)
    {
      Vol_Dir_stat=digitalRead(Vol_Dir); 
      if(Vol_Dir_stat==0 && deciBells<=9)
      {
        deciBells++;
        lcd.setCursor(0, 0);
        lcd.print("VOLUME=   .");
        lcd.setCursor(7, 0);
        lcd.print(deciBells);
        lcd.setCursor(10, 0);
        lcd.print("dB's");
       }
    else if(Vol_Dir_stat==1 && deciBells >=-79)
    {
      deciBells--;
      lcd.setCursor(0, 0);
      lcd.print("VOLUME=   .");
      lcd.setCursor(7, 0);
      lcd.print(deciBells);
      lcd.setCursor(10, 0);
      lcd.print("dB's");
    }
    else{
          do something else etc.. etc....
   }
   }
}