风筝
发表于: 2019-1-7 22:06:19 | 显示全部楼层

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


在本篇文章中,我们将了解不同类型的旋转编码器及其工作原理。我们还将它连接到PIC单片机PIC16F877A,并通过旋转编码器控制整数值,然后在LCD液晶屏1602显示其值。在本文结束时,您将熟悉为项目使用旋转编码器。让我们开始吧......


旋转编码器及其类型

旋转编码器通常称为轴编码器。它是一种机电换能器,意味着它将机械运动转换为电子脉冲,或者换句话说,它将角位置或运动或轴位置转换为数字或模拟信号。它由旋钮组成,当旋转时,旋钮将逐步移动并产生一系列脉冲序列,每次步进具有预定义的宽度。


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

●     增量型编码器

●     绝对值编码器

●     磁编码器

●     光学编码器

●     激光编码器

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


绝对值编码器即使在断电后也会存储位置信息,当我们再次为其供电时,位置信息依然可用。


另一种基本类型,增量型编码器在编码器改变其位置时提供数据。它无法存储位置信息。


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

KY-040增量式旋转编码器的引脚分布如下所示。在本文中,我们将该旋转编码器连接到Microchip公司的微控制器PIC16F877A。

KY-040-Rotary-Encoder-Pinout.jpg

前两个引脚(接地和Vcc)用于为编码器供电,通常使用+ 5V。除了以顺时针方向和逆时针方向旋转旋钮外,编码器还有一个开关(低电平有效),按下内部的旋钮可以按下该开关。来自该开关的信号通过引脚3(SW)获得。最后它有两个输出引脚(DT和CLK),它们产生如下所述的波形。我们之前已将此旋转编码器连接到Arduino开发板


旋转编码器的工作原理

输出完全取决于内部的铜焊盘,它提供与GND和VCC与轴的连接。

Rotary-Encoder-Internal-Diagram.png

旋转编码器有两部分。轴轮与轴连接并根据轴的旋转顺时针或逆时针旋转,以及进行电气连接的底座。底座具有连接到DT或CLK的端口或点,使得当轴轮旋转时,它将连接基点并在DT和CLK端口上提供方波。


当轴旋转时,输出将类似于:

Rotary-Encoder-Output-Waveform.png


两个端口提供方波,但时序略有不同。因此,如果我们接受输出为1和0,则只能有四个状态,0 0,1 0,1 1,0 1.二进制输出的序列决定顺时针转动或逆时针转动。例如,如果旋转编码器在空闲状态下提供1 0并在此之后提供1 1,则意味着编码器将其位置向顺时针方向改变一步,但如果在空闲1 0之后提供0 0,则意味着轴一步一步地沿逆时针方向转动其位置。


需要的组件

以下是我们将旋转编码器与PIC微控制器连接起来需要的组件:

●     PIC16F877A单片机

●     4.7k电阻

●     1k电阻

●     10k电位器

●     33pF陶瓷电容

●     20Mhz晶振

●     1602显示屏

●     旋转编码器

●     5V适配器

●     面包板

●     连接导线


PIC16F877A旋转编码器接口电路图

Circuit-Diagram-for-Rotary-Encoder-Interfacing-with-PIC-Microcontroller.png


Circuit-Model-for-Rotary-Encoder-Interfacing-with-PIC-Microcontroller.png

下面是根据电路图连接组件后的最终设置图:

Rotary-Encoder-Interfacing-with-PIC-Microcontroller.jpg

我们使用单个1K电阻来代替LCD的对比度,而不是使用电位计。


代码说明

在本文的末尾处给出了完整的PIC代码,这里我们将解释代码的一些重要部分。


正如我们之前讨论的那样,我们需要检查输出并区分DT和CLK的二进制输出,因此我们为操作创建了一个if-else部分。

  1. if (Encoder_CLK != position){
  2.             if (Encoder_DT != position){
  3.                // lcd_com (0x01);
  4.                 counter++; // Increase the counter which will be printed on the lcd
  5.                 lcd_com (0xC0);
  6.                 lcd_puts("                ");
  7.                 lcd_com (0xC0);
  8.                 lcd_bcd(1,counter);
  9.             }

  10.             else{
  11.               // lcd_com (0x01);
  12.                 lcd_com (0xC0);
  13.                 counter--; // decrease the counter
  14.                 lcd_puts("                ");
  15.                 lcd_com (0xC0);
  16.                 lcd_bcd(1,counter);
  17.                 //lcd_puts("Left");
  18.             }           
  19.         }
复制代码

我们还需要在每一步上存储位置。 为此,我们使用了一个存储当前位置的变量“position”。

  1. position = Encoder_CLK; // It is to store the encoder clock position on the variable. Can be 0 or 1.
复制代码

除此之外,还提供了一个功能,用于在LCD上显示开关按下。

  1. if (Encoder_SW == 0){
  2.             sw_delayms(20); //debounce delay
  3.             if (Encoder_SW == 0){
  4.                 //lcd_com(1);
  5.                 //lcd_com(0xC0);
  6.                 lcd_puts ("switch pressed");
  7. //                itoa(counter, value, 10);
  8. //                lcd_puts(value);
复制代码

system_init()函数用于初始化引脚I / O操作、LCD以及存储旋转编码器位置。

  1. void system_init(){
  2.     TRISB = 0x00; // PORT B as output, This port is used for LCD   
  3.     TRISDbits.TRISD2 = 1;
  4.     TRISDbits.TRISD3 = 1;
  5.     TRISCbits.TRISC4 = 1;
  6.     lcd_init(); // This will Initialize the LCD
  7.     position = Encoder_CLK;// Sotred the CLK position on system init, before the while loop start.
  8. }
复制代码

LCD函数写在lcd.c和lcd.h库中,其中声明了lcd_puts()lcd_cmd()。有关变量声明、配置位和其他代码片段,请在参考下面完整的代码。


代码

以下是本篇文章使用的完整代码: main.rar (1.23 KB, 下载次数: 33)

跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 10 | 回复: 13



手机版|

GMT+8, 2024-4-26 09:37 , Processed in 0.052004 second(s), 6 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

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

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