风筝
发表于: 2018-7-26 22:30:29 | 显示全部楼层

旋转编码器是一种帮助用户与系统交互的输入设备。它看起来更像是一个无线电电位器,但它输出一系列脉冲,这是它应用的​​独特之处。当旋转编码器旋钮时,它以小步进的形式旋转,这使得它非常合适用于步进/伺服电机控制、系列菜单导航和增加/减少数字值等等。


在本篇文章中,我们将介绍不同类型的旋转编码器及其工作原理。我们还将它与Arduino进行连接,并通过旋转编码器控制整数的值,然后LCD液晶屏1602上显示其值。在本教程结束时,您将熟悉为项目使用旋转编码器。让我们开始吧......


所需的材料

●    旋转编码器(KY-040)

●    Arduino UNO开发板

●    字符型图形点阵液晶1602

●    电位器10k

●    面包板

●    连接导线


旋转编码器是如何工作的?

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


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

Output-Waveform-of-Rotary-Encoder.png


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


现在可能会出现这样的问题:当一个脉冲信号足以计算旋转旋钮时所采取的步数时,为什么我们需要两个脉冲信号。这是因为我们需要确定旋钮旋转的方向。如果您看一下这两个脉冲,您会注意到它们都是90°异相。因此,当顺时针旋转旋钮时,输出A将首先变高,当旋钮逆时针旋转时,输出B将首先变高。


旋转编码器的类型

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

●    增量编码器

●    绝对值编码器

●    磁编码器

●    光学编码器

●    激光编码器


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


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

KY-040增量式旋转编码器的引脚分布如下所示

Rotary-Encoder-Pinout.jpg


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


Arduino与旋转编码器的连接电路图

旋转编码器与Arduino连接的完整电路图如下图所示

Circuit-Diagram-for-Interfacing-Rotary-Encoder-with-Arduino.png


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


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

Circuit-Hardware-for-Interfacing-Rotary-Encoder-with-Arduino.jpg

跳转到指定楼层
风筝
发表于: 2018-7-27 09:13:07 | 显示全部楼层

编写用于旋转编码器的Arduino程序

如果您了解旋转编码器的工作原理,那么编程Arduino开发板以便将旋转编码器连接到它是相当容易的。我们只需要读取脉冲数来确定编码器的转动数,以及首先检查哪个脉冲高,以找到编码器旋转的方向。在本篇文章中,我们将在LCD第一行上显示增加或减少的数字以及在第二行上显示编码器的方向。


由于我们使用了一个LCD显示屏,因此包含了Arduino IDE中默认存在的液晶库。然后我们定义用于连接LCD和Arduino的引脚。最后,我们初始化这些引脚上的LCD显示屏。

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

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

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

  4.   delay(2000);
  5.   lcd.clear();
复制代码

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

  1. //pin Mode declaration
  2.   pinMode (Encoder_OuputA, INPUT);
  3.   pinMode (Encoder_OuputB, INPUT);
  4.   pinMode (Encoder_Switch, INPUT);
复制代码

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

  1. Previous_Output = digitalRead(Encoder_OuputA); //Read the inital value of Output A
复制代码

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

  1. if (digitalRead(Encoder_OuputA) != Previous_Output)
  2.    {
  3.      if (digitalRead(Encoder_OuputB) != Previous_Output)
  4.      {
  5.        Encoder_Count ++;
  6.        lcd.clear();
  7.        lcd.print(Encoder_Count);
  8.        lcd.setCursor(0, 1);
  9.        lcd.print("Clockwise");
  10.      }
复制代码

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

  1.   else
  2.      {
  3.        Encoder_Count--;
  4.        lcd.clear();
  5.        lcd.print(Encoder_Count);
  6.        lcd.setCursor(0, 1);
  7.        lcd.print("Anti - Clockwise");
  8.      }
  9.    }
复制代码

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

  1. Previous_Output = digitalRead(Encoder_OuputA);
复制代码

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

  1. if (digitalRead(Encoder_Switch) == 0)
  2.    {
  3.      lcd.clear();
  4.      lcd.setCursor(0, 1);
  5.      lcd.print("Switch pressed");
  6.    }
复制代码

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

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

Interfacing-Rotary-Encoder-with-Arduino.jpg



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


希望你已经理解了本篇文章。如果您有任何问题,请在本贴下面进行回复。


代码

本篇文章的完整代码: main.txt.rar (768 Bytes, 下载次数: 87)

回复

使用道具 举报

绿色的meng
发表于: 2018-10-1 21:54:12 | 显示全部楼层

楼主好,编译有误,Previous_Output = digitalRead(Encoder_OuputA); //Read the inital value of Output A,这句代码有问题
回复

使用道具 举报

风筝
发表于: 2018-10-2 17:00:05 | 显示全部楼层

绿色的meng 发表于 2018-10-1 21:54
楼主好,编译有误,Previous_Output = digitalRead(Encoder_OuputA); //Read the inital value of Output A ...

您好 请问一下有什么问题?我这边编译没问题呢
回复

使用道具 举报

绿色的meng
发表于: 2018-10-4 20:58:49 | 显示全部楼层

找出来了,压缩包代码我说的那条,少了//;但是还是编译不过,你试着编译一下附件的代码看看
回复

使用道具 举报

风筝
发表于: 2018-10-4 21:33:10 | 显示全部楼层

绿色的meng 发表于 2018-10-4 20:58
找出来了,压缩包代码我说的那条,少了//;但是还是编译不过,你试着编译一下附件的代码看看 ...

代码中包含一些注释,。重新更新了一下附件内容,可以试试
回复

使用道具 举报

绿色的meng
发表于: 2018-10-8 16:38:53 | 显示全部楼层

我找出来了,改好了,附件还是有误,3个错误,第一是pinA,正确应该是Encoder_OuputA,第二是//aVal = digitalRead(pinA);多了//,第三是aVal,没定义。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 700 | 回复: 1480



手机版|

GMT+8, 2024-4-25 23:25 , Processed in 0.048319 second(s), 6 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表