锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

使用Arduino 连接旋转编码器

时间:2022-09-29 09:30:00 传感头连接用连接器

文章目录

    • 1. 所需的材料
    • 2. 连接导线旋转编码器是如何工作的?
    • 3. 旋转编码器的类型
    • 4. KY-040旋转编码器引脚和说明
    • 5. Arduino连接到旋转编码器的电路图
    • 6. 为旋转编码器编写的编写Arduino程序
      • 7.3 完整代码
    • 8. 补充其他网民的代码

参考资料:https://www.arduino.cn/thread-2423-1-1.html

1. 所需的材料

2. 如何连接导线旋转编码器?

旋转编码器是一种机电换能器,这意味着它将机械运动转化为电子脉冲。它由旋钮组成。旋转时,旋钮将逐渐移动并产生一系列脉冲序列,每个步骤都有预定的宽度。编码器有很多种,每个编码器都有自己的工作机制。稍后我们将了解这些类型,但现在我们只关注它们KY由于我们在我们的教程中使用了040增量编码器。

编码器的内部机械结构如下所示。它基本上由圆盘(灰色)和放置在圆盘顶部的导电垫(铜色)组成。这些导电焊盘放置在相同的距离,如下所示。输出引脚固定在圆盘顶部,当旋钮旋转时,导电垫与输出引脚接触。有两个输出引脚,输出A和输出B,如下图所示。
在这里插入图片描述

输出引脚A和输出B产生的输出波分别显示为蓝色和绿色。当导电焊盘直接位于引脚下时,它会变得更高,导致导电时间。当导电焊盘移动时,引脚会变低,导致上述波形的关闭时间。现在,如果我们计算脉冲数,我们将能够确定编码器移动了多少步。

当脉冲信号足以计算旋转旋钮时,为什么我们需要两个脉冲信号?这是因为我们需要确定旋钮的旋转方向。如果你看看这两个脉冲,你会注意到它们都是90°异相。因此,当顺时针旋转旋钮时,输出A将首先变高,当旋钮逆时针旋转时,输出B将首先变高。

3. 旋转编码器的类型

市场上有许多类型的旋转编码器,设计工程师可以根据自己的应用程序选择一个。最常见的类型如下所示

  • 增量编码器
  • 绝对值编码器
  • 磁编码器
  • 光学编码器
  • 激光编码器

这些编码器是基于输出信号和传感技术,增量编码器和绝对值编码器是基于输出信号,磁性、光和激光编码器是基于传感技术。这里使用的编码器是增量编码器。

4. KY-040旋转编码器的引脚和说明

KY-如下所示

前两个引脚(接地和Vcc)通常用于为编码器供电 5V电源。编码器除了顺时针和逆时针旋转旋钮外,还有一个
开关(低电平有效),可以按下内部旋钮。通过引脚3(Switch)获得。最后,它有两个输出引脚,产生上述波形。现在让我们学习如何与我们一起学习Arduino进行连接。

5. Arduino连接到旋转编码器的电路图

旋转编码器和Arduino如下图所示

旋转编码器有5个引脚,如上图
标签所示。前两个引脚是接地和Vcc,它连接到Arduino的地和 5V引脚。编码器的开关连接到数字引脚D8,并通过1k电阻拉高。两个输出引脚分别连接到D9和D8。

通过旋转显示Rotary我们需要一个显示模块来增加或减少编码器的变量值。这里常用的字符图形点阵液晶1602。我们将连接的显示屏设置为4位工作模式,并使用它Arduino的 5V引脚供电。电位计用于调整LCD显示屏的对比度。面包板上可以搭建完整的电路,一旦完成所有连接,效果看起来像下图。

由于单片机内部电阻大,使用单片机内部的上拉输入可能会带来更大的功耗,arduino已知每圈脉冲数为2500的基本原理是,当计数大道2500时,计数一圈,如果是stm三十二是溢出中断。A、B判断相的高低电平关系AB相的先后关系,进而判断转向。
通常有三个部分可以区分正反转和检测零点:A相,B相和Z相,A与B相差1/4周期(相位差90度),可用于区分正转或反转;Z与单圈脉冲相比,码盘可以作为编码器的参考部分,如下图所示:

6. 为旋转编码器编写的编写Arduino程序

如果您了解旋转编码器的工作原理,编程Arduino开发板很容易连接到旋转编码器。我们只需要读取脉冲数来确定编码器的旋转数,并首先检查哪个脉冲高,以找到编码器旋转的方向。在本文中,我们将在LCD第一行显示增减数字,第二行显示编码器方向。

因为我们用了一个LCD所以包含了显示屏Arduino IDE默认存在的液晶库。然后我们将其定义为连接LCD和Arduino引脚。最后,我们将这些引脚初始化LCD显示屏。

#include  //Default Arduino LCD Library is included const int rs = 7, en = 6, d4 = 5, d5 = 4, d6 = 3, d7 = 2; //Mention the pin number for LCD connection
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
lcd.begin(16, 2); //Initialise 16*2 LCD

接下来在setup函数中,我们在LCD屏幕上显示介绍消息,然后等待2秒钟,以便用户可以读完该消息。这是为了确保LCD能够正常工作。

lcd.print(" Rotary Encoder "); //Intro Message line 1
  lcd.setCursor(0, 1);
  lcd.print(" With Arduino "); //Intro Message line 2

  delay(2000);
  lcd.clear();

Rotary编码器有三个输出引脚,对于Arduino来说,它们都是INPUT引脚。这三个引脚分别是开关(Switch)、输出A(Output A)和输出B(Output B)。这些引脚使用pinMode函数声明为Input,如下所示。

//pin Mode declaration
  pinMode (Encoder_OuputA, INPUT);
  pinMode (Encoder_OuputB, INPUT);
  pinMode (Encoder_Switch, INPUT);

在void setup()函数中,我们读取输出A引脚的状态以检查引脚的最后状态。然后,我们将使用此信息与新值进行比较,以检查哪个引脚(输出A或输出B)变高。

Previous_Output = digitalRead(Encoder_OuputA); //Read the inital value of Output A

最后在loop函数内,我们必须将输出A和输出B的值与先前输出进行比较,以检查哪一个先变高。这可以通过简单地将A和B的当前输出值与先前输出进行比较来完成,如下所示。

if (digitalRead(Encoder_OuputA) != Previous_Output)
   { 
        
     if (digitalRead(Encoder_OuputB) != Previous_Output)
     { 
        
       Encoder_Count ++;
       lcd.clear(); 
       lcd.print(Encoder_Count);
       lcd.setCursor(0, 1); 
       lcd.print("Clockwise");
     }

在上面的代码中,如果输出B已从先前的输出改变,则执行第二个if条件。在这种情况下,编码器变量的值递增,LCD显示编码器以顺时针方向旋转。类似地,如果if条件不符合,则在随后的其他条件中,我们递减变量并显示编码器沿逆时针方向旋转。代码如下所示。

  else
     { 
        
       Encoder_Count--;
       lcd.clear(); 
       lcd.print(Encoder_Count);
       lcd.setCursor(0, 1); 
       lcd.print("Anti - Clockwise");
     }
   }

最后,在loop函数结束时,我们必须使用当前输出值更新先前的输出值,以便可以使用相同的逻辑重复循环。

Previous_Output = digitalRead(Encoder_OuputA);

另一个可选方法是检查编码器上的开关是否被按下。这可以通过检查旋转编码器上的开关销来监控。该引脚是低电平有效引脚,意味着按下该按钮时它将变为低电平。如果没有按下引脚保持高电平,我们也使用了一个上拉电阻,以确保在未按下开关时保持高电平,从而避免浮空状态。

if (digitalRead(Encoder_Switch) == 0)
   { 
        
     lcd.clear(); 
     lcd.setCursor(0, 1); 
     lcd.print("Switch pressed");
   }

Arduino控制旋转编码器的工作过程

一旦硬件和代码准备就绪,只需将代码上传到Arduino开发板板,然后向Arduino供电。您可以通过USB电缆为其供电,也可以使用12V适配器。上电时,LCD应显示介绍消息,然后变为空白。现在旋转旋转编码器,您应该看到值根据旋转方向递增或递减。第二行将显示编码器是以顺时针方向还是逆时针方向旋转。下图显示了实际的工作过程:

此外,当按下按钮时,第二行将显示按下按钮。这只是一个旋转编码器与Arduino连接的示例程序,检查它是否按预期工作。现在,您应该可以将编码器用于任何项目并进行相应的编程。

7.3 完整代码

/* Interfacing Rotary Encoder with Arduino Power LCD and Rotary encoder from the +5V pin of Arduino LCD RS -> pin 7 LCD EN -> pin 6 LCD D4 -> pin 5 LCD D5 -> pin 4 LCD D6 -> pin 3 LCD D7 -> pin 2 Encoder Switch -> pin 10 Encoder Output A -> pin 9 Encoder Output B -> pin 8 */

int Encoder_OuputA  = 9;
int Encoder_OuputB  = 8;
int Encoder_Switch = 10;

int Previous_Output;
int Encoder_Count;



#include  //Default Arduino LCD Librarey is included 

const int rs = 7, en = 6, d4 = 5, d5 = 4, d6 = 3, d7 = 2; //Mention the pin number for LCD connection
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() { 
        
  lcd.begin(16, 2); //Initialise 16*2 LCD

  lcd.print(" Rotary Encoder "); //Intro Message line 1
  lcd.setCursor(0, 1);
  lcd.print(" With Arduino "); //Intro Message line 2

  delay(2000);
  lcd.clear();

  //pin Mode declaration
  pinMode (Encoder_OuputA, INPUT);
  pinMode (Encoder_OuputB, INPUT);
  pinMode (Encoder_Switch, INPUT);

  Previous_Output = digitalRead(Encoder_OuputA); //Read the inital value of Output A
}

void loop() { 
        
  //aVal = digitalRead(pinA);

  if (digitalRead(Encoder_OuputA) != Previous_Output)
  { 
        
    if (digitalRead(Encoder_OuputB) != Previous_Output)
    { 
        
      Encoder_Count ++;
      lcd.clear();
      lcd.print(Encoder_Count);
      lcd.setCursor(0, 1);
      lcd.print("Clockwise");
    }
    else
    { 
        
      Encoder_Count--;
      lcd.clear();
      lcd.print(Encoder_Count);
      lcd.setCursor(0, 1);
      lcd.print("Anti - Clockwise");
    }
  }

  Previous_Output = digitalRead(Encoder_OuputA);

  if (digitalRead(Encoder_Switch) == 0)
  { 
        
    lcd.clear();
    lcd.setCursor(0, 1);
    lcd.print("Switch pressed");
  }
}

8. 补充其他的网友的代码

#define PinA 2 //外部中断0
#define PinZ 3 //外部中断1
#define PinB 8 //编码器的OUT_B信号连接到数字端口8

//变量初始化
unsigned long time1 = 0; // 时间标记
float time_cw;
float time_ccw;
long count = 0;
const float d = 75.7 / 1000; //轮子的直径
const float pi = 3.141592654;//圆周率
int num = 0;//圈数
double t;//一圈的运动时间
float velocity;
double time3;//外部中断1产生时的时间,即捕捉到Z相的置零信号时,用于在loop循环内进行一圈时间长短的计算

void setup()
{ 
        
  pinMode(PinA, INPUT_PULLUP);//因为编码器信号为欧姆龙E6B2-CWZ6C,为开漏输出,因此需要上拉电阻,此处采用arduino的内部上拉输入模式,置高
  pinMode(PinB, INPUT_PULLUP);//同上
  pinMode(PinZ, INPUT_PULLUP);//同上
  attachInterrupt(0, Encode, FALLING);//脉冲中断函数:捕捉A相信号,并判断A、B相先后顺序
  attachInterrupt(1, Set_state , FALLING);//用于在捕捉到Z的零信号时,进行状态置零

  Serial.begin (9600);
}

void loop()
{ 
        
  double distance;
  //正转
  if (count == 2500)
  { 
        
    // Serial.println("ok");//调试用
    num = num + 1;
    time_cw = millis();
    t = time_cw - time3;
    t = t / 1000;
    distance = num * d * pi;
    velocity = d * pi / t;
    Serial.print("The wheel has run ");
    Serial.print(distance);
    Serial.println("m.");
    Serial.print("The cw_speed is ");
    Serial.print(velocity);
    Serial.println("m/s.");
    Serial.print("The time is ");
    Serial.print(t);
    Serial.println("s.");
  }
  //反转
  if (count == -2500)
  { 
        
    // Serial.println("ok");//调试用
    num = num + 1;
    time_ccw = millis();
    t = time_ccw - time3;
    t = t / 1000;
    distance = num * d * pi;
    velocity = d * pi / t;
    Serial.print("The wheel has run ");
    Serial.print(distance);
    Serial.println("m.");
    Serial.print("The ccw_speed is ");
    Serial.print(velocity);
    Serial.println("m/s.");
    Serial.print("The time is ");
    Serial.print(t);
    Serial.println("s.");
  }
}

// 编码器计数中断子程序

void Encode()
{ 
        
  //为了不计入噪音干扰脉冲,
  //当2次中断之间的时间大于5ms时,计一次有效计数
  if ((millis() - time1) > 5)
  { 
        
    //当编码器码盘的OUTA脉冲信号下跳沿每中断一次,
    if ((digitalRead(PinA) == LOW) && (digitalRead(PinB) == HIGH))
    { 
        
      count--;
    }
    else
    { 
        
      count++;
    }
  }
  time1 == millis();
}
void Set_state() { 
        
  count = 0;
  time3 = millis();//发生中断时的时间
}
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章