成为订阅者(免费)

加入29,000名其他订阅者以获得用户销售折扣和 其他免费资源。
:
:
大学教师'担心 - 您的邮件地址完全是 安全的。我保证使用它 只要 to send you MicroZine.

旋转编码器:如何使用键KY-040 arduino上的编码器

旋转编码器是输入设备 您可以连续地在任一方向上旋转。当您打开设备时 生成数字脉冲以使用两个相位显示旋转方向 输出信号。这两个输出也表示单个位置运动,所以 您可以在控制面板中使用它们以增加或减少参数。

笔记: 旋转编码器产生极其嘈杂的输出 由于开关反弹引起的振荡以及此页面上的信息给您 两种消除噪音的技术。第一个是一个简单的 过滤方法和第二种方法使用表解码来获得非常好的 从低质量设备输出。

下面用于演示的编码器类型也称为一个 增量旋转编码器,因为它产生了指示单步的脉冲 变化。其他类型生成绝对输出等I.。相同的输出编号(4 根据所需的精度或更多位的比特是针对特定的 编码器的位置,您将在机器人应用中使用这些。

本教程的目的是为ARDuino提供一个例子 简单的旋转编码器实现。

旋转编码器允许您通过单个容易地增加或减少参数 value.

以及生成方向信息和步骤改变脉冲 设备有一个物理反馈机制,让您感受到何时移动 一个位置到下一个位置。这些点被称为棘爪和范围从12 在360°旋转内24个位置。对于这里使用的设备有20 detents.

与电位器不同的旋转编码器 没有结局停止,这样你就可以使用一个来不断增加或减少一个 参数(由微控制器解码一旦解码),无需设置 控制位置回到起点(没有)。

它们通常也有一个压制按钮开关,内置在轴上 适用于菜单选择等。

您可以将它们用于许多应用范围:

  • 音量控制
  • 照明水平控制
  • 参数控制e.g.对于一个过程。速度,高度,温度 etc.
  • 菜单选择(按钮在此处有用)。

由于输出是数字信号,您可以使用a处理它们 微控制器并以任何方式使用结果,以便更改值 表示系统参数的变量。

事实上,旋转编码器看起来很简单,但有很多事情正在发生 在这些小型器件内(〜11mm x〜13mm)。

这里's what is going on:

  • 提供正交编码信号的两个输出。
  • 物理位置反馈和凹凸停止(称为棘爪) - 为此 设备有20个棘爪。
  • 主轴按钮(推动制作开关)。

当你转动控制旋钮,你可以感受到每个人'detent' position 停止,所以您知道何时通过恰好拨打设备。 这提供了细粒度的物理反馈,允许精确参数更改。 这与使用电位器设定音量等非常不同。 没有物理反馈的地方。

正交相移 Encoding

这是一个非常简单的技术声音编码方法。全部 这意味着两个信号被彼此偏移了四分之一 期间(或阶段偏移90?)。它也在洗涤中脱落 生成的信号是灰色编码,这只是意味着没有两个信号边缘 对齐即,I.信号输出不会同时更改状态。

灰度编码对于机电装置可产生信号 这是明确的。例如,如果输出是二进制编码的那么在 转换点(由于信号路径的小延迟),您可能会解码a 完全错误的价值I.E.在过渡时,任何代码都可能是 generated.

这可能是一个问题,特别是如果只使用组合逻辑 解码器。灰色代码停止发生(虽然它不会停止 switch bounce).

下图显示了引脚A和旋转编码器波形输出 B(CLK)和(DT)分别。

旋转编码器正交信号A和B.

[源PEC11L数据表]

笔记: 图中的D在上图显示了棘爪的地方 位置位于。事实上,这是输出没有连接的地方 因此,它们被突破的10K电阻拉高 board.

在旋转编码器内

下图显示了旋转编码器的内部工作。每个 在三个连接8a,8b和8c中由推动的弹簧臂形成 在基板上。

有三个信号,一个信号连接到金属基板(接地)和 另外两个移动交替的基板图案。所以输出是 随着器件旋转,然后留下浮动而短路 (未连接)当接触处于基板间隙时。

注意弹簧臂触点如何偏离四分之一 期间(由物理基质定义) - 图中的触点8b和8c 下面 - 这就是如何生成正交编码的输出。

内部旋转编码器操作

资料来源:过期专利(现在在公众中 domain).

笔记: 触点8a,8b,8c是弹跳的弹簧和 关闭接触基板,导致输出信号在高位之间反弹 低i.e.开关弹跳。

旋转编码器的类型

联系增量 Rotary Encoders

这是本页上演示中使用的设备类型。在每一个 产生两个正交信号的棘爪位置指示单个 位置变化并显示旋转方向。

该特定装置具有相当高的旋转寿命 - 100K旋转 (见数据表) - 但由于存在物理接触,设备将 最终磨损。在博尔斯 目录 其他物理设备的范围从15K到200k maximum rotations.

光学编码器

PEC11LHA最大RPM为60RPM,而光学编码器 目录,拥有1000万革命生活,可以在3000rpm运行 - 这些 是您可以在高速机械中测量的类型,但看到 下面的磁编码器具有更高的寿命,并且当然是更高的 cost!

磁编码器

对于甚至更高的旋转寿命,磁编码器提供了最佳选择 (由于设备内没有物理接触)唯一的部分 磨损是轴承。这些提供了1亿的转动寿命 revolutions!

这些设备有4种不同的口味:

  1. 增量正交(与此处使用的PEC11L相同)。
  2. 方向/步骤编码器 - 提供更好的分辨率(每次最多512个脉冲) revolution).
  3. 绝对编码器 - 允许编码器的绝对位置检测 (1024个代码定义位置)。
  4. PWM编码器 - 从1US到1024US宽度生成PWM输出 - 声称的优点是噪声免疫和更快的数据采集。

测量:使用旋转增量 Encoders

以下示例涵盖以下测量值:

  • 速度
  • 对数变革

速度

您可能希望测量用于代码中的参数的速度,例如: 如果你更快地转动车轮,然后执行不同的动作。改变 参数以不同的速率。

对数

这是一个参数调整,测量旋转速度,如果找到 保持恒定的定期增加参数。这非常有用 具有大范围控制的设备。 DDS(直接数字 合成)可以输出频率形式1至10MHz。你真的不't want to 坐在那里用1Hz时期转动旋钮到达10MHz!

解码方法

有方法可以解码旋转编码器输出:

  • 轮询
  • 中断

在KY-040上,有两个标记为DT和CLK的信号,意味着时钟和 数据。如果您查看这些信号的时序图,它似乎是显而易见的 使用时钟作为时钟并读取上升沿的数据输入 钟。然而,这忽略了信号反弹的事实 place.

如果您使用CLK信号作为中断,您将陷入困境 输入的随机弹跳将触发所有时间的中断(而不是 在你想读取数据信号的时候,所以你会得到不正确的 data.

有轮询方法使用状态解码灰色编码信号 机器,使弹跳信号被忽略即错误状态被忽略。 这些都很复杂,有时会失去同步。

我使用这些设备的方式是少量平滑的组合 电容器和简单的数字旋转开关去抖算法。 (见下面的代码)。 这提供了易于理解的代码(也小代码大小)并工作 准确地获得单独的制动位置信息并准确 方向旋转信息。

但有时,你可能有一个非常差的编码器和那个 需要更多努力解码,在这种情况下,您需要查看 更复杂的强大解码器代码 这里.

设备解码技术

您可以使用许多巧妙的方法来解码涉及复杂状态的输出 机器和灰色解码算法。一些使用中断和大多数使用 轮询。将输出连接到中断引脚的问题是 您无法控制您可能会遇到的反弹和处理器 可能会被打断太多,无法做任何有用的工作(并且甚至可以挂起)和 无论如何都会从数据输入中获取错误的值。

警告: 由于开关,旋转编码器非常嘈杂 由于设备的内部结构而被弹跳(使用物理接触 弹出基板连接的弹簧)。这使它成为极大的 难以准确地解码设备输出。

但是看到我的新技术 - 最后一个代码示例代码 above.

当触点是弹跳的弹簧时,开关弹跳 基板触点 - 即使是数据表也表示您可以获得的开关反弹 对于每次回合,高达10ms(Bourns PEC11L)。

旋转编码器正交信号A和B.

[源PEC11L数据表]

您可以看到标记为A和B的信号可以更改为CLK(时钟) 和dt(数据),时钟信号(a)上的上升沿将提供一个逻辑 如果顺时针转动,则在DT(b)上,并且逆时针转动逻辑高电平 (当沿相反方向转动时,下降沿变成了上升 edge!).

电容平滑

添加巨大的平滑电容(以及电阻见下文和 用470nf替换0.01uf作为一个例子"too big" capacitor" - which 有些人建议的)停止反弹将停止反弹但也是 将输入信号电平降低到它将通过的点 未定义的逻辑输入电平(下面的顶部阈值V下方IH. 和 above 较低的阈值VIL.)微控制器。在这个输入中 该输入的区域噪声可以(并且通常是!)触发输入到高或 低导致振荡i.e.制作更多的反弹信号而不是解决 problem at all.

您可以使用施密特触发器设备来解决此问题,例如74HC14 要创建正确的快边信号,但您可能会更改太多时间 获得有用的输出信号。

RC对和数字过滤器

我发现的一种方式是使用小型平滑电容器电阻对 以及数字去抖过滤器。这允许个体制动位置 准确识别(控制轴的慢速转动准确 解码)。在更快的革命代码中错过了,但实际点 旋转编码器是允许准确的个体制动(和方向) detection. You don'需要了解快速转动的确切棘爪停止 - 所有 您需要知道用户想要更快地增加参数。

数字去抖过滤器

数字滤波器由单个16位整数变量组成 转换输入引脚的当前状态:

国家=(州<<1)| DigitalRead(CLK_PIN)| 0xe000;

这是一个非常紧凑的过滤器 - 每次循环都是新位 向左移动(在位0)。这"or"0xe000的操作定义了数量 迭代I.E.前3位被阻止离开休息作为有用 输入。这个想法是您测试状态0xF000,只能发生 有一系列1 0000 0000 0000输入,这意味着信号具有 在循环周围的12个迭代是稳定的,即不要弹跳。

arduino.旋转编码器 Datasheet

KY-040中使用的旋转编码器看起来像Bourns PEC11L设备 - 您可以从下面的链接下载该旋转编码器数据表。这一切 突破板确实是添加两个10K上拉电阻(R2和R3),而 交换机上拉的空间已留空。

下载 PEC11L Datasheet..

arduino.旋转编码器 Software Setup:

IDE版本使用:1.6.4
二手董事会:Arduino Uno R3

旋转编码器硬件设置

使用的设备:KY-040(突破板)

其他组件10K电阻和10NF电容器 - 仅适用于时钟 信号,连接如下所示:

旋转编码器连接

[源PEC11L数据表]

注意:10K和10N是突破板(A和B有10K的额外 板上的上拉)。仅将它们添加到时钟信号(a)。

示例旋转编码器代码:

这是一个 arduino. KY-040旋转编码器示例 that 向您展示如何通过卸下开关反弹来解码20个旋转编码器。用一个 数字滤波技术。讨论了该数字滤波器的操作 这里.

笔记: 编码器的质量会影响输出信号 (我的跳过代码之一,而更高质量的摘要没有!)。

#define CLK_PIN  2
#define DATA_PIN 7
#define YLED A1

////////////////////////////////////////////////////
void setup() {
   pinMode(CLK_PIN,INPUT);
   pinMode(DATA_PIN,INPUT);
   pinMode(YLED,OUTPUT);

   Serial.begin(9600);
   Serial.println("Rotary Encoder KY-040");
}

////////////////////////////////////////////////////
void loop() {
static uint16_t state=0,counter=0;

    delayMicroseconds(100); // Simulate doing somehing else as well.

    state=(state<<1) | digitalRead(CLK_PIN) | 0xe000;

    if (state==0xf000){
       state=0x0000;
       if(digitalRead(DATA_PIN))
         counter++;
       else
         counter--;
       Serial.println(counter);
    }
}


驯服嘈杂的旋转编码器

由于开关弹跳,keyes-040编码器可以非常嘈杂,您可以 需要使用更强大的解码方式 - 我有一个相当的 表现良好,一个非常嘈杂的人。

以下示例使用需要更多代码的表解码方法 比前一个例子更容易读取旋转编码器而没有 根本需要任何去抖电容器。 (但是检查这是否有效 你自己的硬件来确保这个)。

它的工作方式是将解码器的输出作为二进制数进行编码。 为此,您可以将CLK定义为LSB二进制数字和数据作为MSB binary digit.

然后观察输出可以占据的有效状态即。 通过虚线如下图所示。

因为输出处于正交状态,因为这导致灰色 代码输出没有输出更改状态与另一个不同的状态。这是什么 意思是,只有两个输出中的一个将在任何情况下弹跳 过渡边缘。这意味着弹跳信号可以很容易地忽略,因为 弹跳主要会产生无效的编码器状态。

旋转编码器表分配

如果您查看上面的图表,您可以看到有四个州(11, 10,00,01)。除此之外,只有8种方法可以从中移动 一个州到下一个状态,包括向后(反顺时针)。

有关顺时针运动,您只能执行以下操作:

(11.> 10), (10 > 00), (00 > 01) and (01 >11)

类似地,只有以下编码器输出转换是有效的 逆时针旋转:

(01.> 00), (00 > 10), (10 > 11), and (11 > 01)

您可以找到其他旋转解码方法(包括此) 这里.

表格方法背后的想法是您存储以前的状态和 当前状态并将其设置为二进制代码。通过这种方式直接表现 编码有效输出的转换 - 技术背后的主要目的 是由开关反弹引起的无效丢弃。

有效代码输出

因此,在上面的顺时针方向,有四个有效的输出(其中 2 MSBits是前一个状态,2个LSBits是当前状态):

1110

1000

0001

0111

只有这些是有效状态。理论上,只有这些应该被输出 旋转编码器,但在实践中,开关弹跳产生其他代码。

对于相反的方向(反顺时针)以下代码是 valid:

0100

0010

1011

1101

允许微控制器检查有效的代码并忽略无效 需要表格(具有4位PSNS - 以前的州下一个状态 - 代码 as the input):


PSNS(上一个国家,下一个州) 有效代码 方向
0000 X X
0001 有效的 CW.
0010 有效的 CCW.
0011 X X
0100 有效的 CCW.
0101 X X
0110 X X
0111 有效的 CW.
1000 有效的 CW.
1001 X X
1010 X X
1011 有效的 CCW.
1100 X X
1101 有效的 CCW.
1110 有效的 CW.
1111 X X

将其编译到C表中并用1和CCW用-1替换CW和CW 无效的0结果如下:

rot_enc_table [] = {0,1,-1,0,-1,0,0,1,1,0,0,-1,0,-1,1,0};

您可以在Web上找到使用此方法的代码(我可能有 交换-1为1 - 并不重要只是交换sig a和sig b)但是 方法将任何CW或CCW有效输出作为真正的转换,因此 "detent" to "detent"返回运动四个CWS或四个CCW状态(该 制动位置如下图所示)。问题是蹦蹦跳跳 可能导致状态向后更换,直到交换机沉降并进行 forwards again.

旋转编码器正交信号A和B.

改进的表解码方法

通过使用以下代码,您可以看到每个代码之间生成的输出 棘爪。当它找到7或0xB时,代码只需生成换行符。 这些是在执行棘爪时产生的最后一个代码 rotation.

旋转编码器质量测试 Program

使用以下程序来查看您的编码器是多么好(观察 下面的典型结果)。

#define CLK 2
#define DATA 7
#define BUTTON A5
#define YLED A2

void setup() {
  pinMode(CLK, INPUT);
  pinMode(CLK, INPUT_PULLUP);
  pinMode(DATA, INPUT);
  pinMode(DATA, INPUT_PULLUP);
  pinMode(BUTTON, INPUT);
  pinMode(BUTTON, INPUT_PULLUP);
  pinMode(YLED,OUTPUT);

  Serial.begin (115200);
  Serial.println("KY-040 Quality test:");
}

static uint8_t prevNextCode = 0;

void loop() {
uint32_t pwas=0;

   if( read_rotary() ) {

      Serial.print(prevNextCode&0xf,HEX);Serial.print(" ");

      if ( (prevNextCode&0x0f)==0x0b) Serial.println("eleven ");
      if ( (prevNextCode&0x0f)==0x07) Serial.println("seven ");
   }

   if (digitalRead(BUTTON)==0) {

      delay(10);
      if (digitalRead(BUTTON)==0) {
          Serial.println("Next Detent");
          while(digitalRead(BUTTON)==0);
      }
   }
}

// A vald CW or CCW move returns 1, invalid returns 0.
在t8_t read_rotary() {
  static 在t8_t rot_enc_table[] = {0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0};

  prevNextCode <<= 2;
  if (digitalRead(DATA)) prevNextCode |= 0x02;
  if (digitalRead(CLK)) prevNextCode |= 0x01;
  prevNextCode &= 0x0f;

  return ( rot_enc_table[( prevNextCode & 0x0f )]);
}

使用上面的程序我按下旋转编码器按钮生成 the text "Next Detent"在将编码器转到下一个制动位置之前。 这允许您查看一个位置期间生成的所有代码 change.

您可以看到一些轮换导致大量代码但代码 在返回正确的一个之前,只能回到一个状态。 更重要的是,您可以看到最终的2个代码总是相同的 匹配2个完整旋转序列的最后一个啃咬:D42B和E817。

为了"bad"旋转编码器生成以下输出:

Poor Quality Rotary Encoder

KY-040 Quality test:
D 4 2 8 2 B eleven
Next Detent
D 4 2 8 2 B eleven
Next Detent
D 4 1 4 2 B eleven
Next Detent
E 8 2 8 2 8 2 8 1 4 1 7 seven
D 7 seven
Next Detent
E B eleven
E 8 2 8 2 8 1 7 seven
Next Detent
E 8 2 8 2 8 2 8 1 4 1 7 seven
Next Detent
E B eleven
E 8 2 8 2 8 1 4 1 4 1 7 seven
Next Detent
E 8 1 4 1 4 1 4 1 4 1 4 1 7 seven
Next Detent
E 8 1 4 1 7 seven
Next Detent
E 8 1 7 seven
Next Detent
E B eleven
E B eleven
E B eleven
E B eleven
E B eleven
E B eleven
E B eleven
E 8 2 8 2 8 1 4 1 7 seven
Next Detent

为了good quality encoder the following output was generated:

旋转编码器 test better quality encoder.

KY-040 Quality test:
E 8 1 7 seven
Next Detent
E 8 1 7 seven
Next Detent
E 8 1 7 seven
Next Detent
E 8 1 7 seven
Next Detent
E 8 1 7 seven
E B eleven
Next Detent
E B eleven
E B eleven
E B eleven
E B eleven
E B eleven
E B eleven
E B eleven
E B eleven
E B eleven
E 8 1 7 seven
Next Detent
D 4 2 B eleven
D 7 seven
D 7 seven
Next Detent
D 4 2 B eleven
Next Detent
D 4 2 B eleven
Next Detent

你可以看到两者之间的差异很大,第1个 一个生成更多的代码输出(由于开关弹跳)。实际代码 表示单一的制动到棘爪运动是E817和D42B 相同的值(在上面的有效二进制代码的讨论中显示) "valid"prevstate,揭幕编码。

你可以看到交换机之间有很多弹跳 偷偷性但不是达到结束时。所有代码输出都以其开头 正确的代码e或d然后反弹很多,然后用决赛结束 two codes.

改进的操作 Table Decode Code

下面的代码查找最后两个状态以指示有效的旋转代码 输出(0x2b和0x17)。这给了一个双重处理去抖动 - 第一个 being a "valid"输出和第二个是一个"valid rotation". This works very 嗯,甚至允许旋转编码器返回其原始位置 (旋转CW 20位置然后旋转CCW 20个位置),没有缺失代码 - 即使是一个非常嘈杂的旋转编码器。

您可以使用完整的16位十六进制代码(或高 质量的)。您的结果可能会有所不同。

请注意,这与编码器直接连接 - 无票据 电阻器或电容器(仅在突破上拉起10k电阻 board).

改进表的代码 Decode

// Robust Rotary encoder reading
//
// Copyright John Main - best-microcontroller-projects.com
//
#define CLK 2
#define DATA 7

void setup() {
  pinMode(CLK, INPUT);
  pinMode(CLK, INPUT_PULLUP);
  pinMode(DATA, INPUT);
  pinMode(DATA, INPUT_PULLUP);
  Serial.begin (115200);
  Serial.println("KY-040 Start:");
}

static uint8_t prevNextCode = 0;
static uint16_t store=0;

void loop() {
static 在t8_t c,val;

   if( val=read_rotary() ) {
      c +=val;
      Serial.print(c);Serial.print(" ");

      if ( prevNextCode==0x0b) {
         Serial.print("eleven ");
         Serial.println(store,HEX);
      }

      if ( prevNextCode==0x07) {
         Serial.print("seven ");
         Serial.println(store,HEX);
      }
   }
}

// A vald CW or  CCW move returns 1, invalid returns 0.
在t8_t read_rotary() {
  static 在t8_t rot_enc_table[] = {0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0};

  prevNextCode <<= 2;
  if (digitalRead(DATA)) prevNextCode |= 0x02;
  if (digitalRead(CLK)) prevNextCode |= 0x01;
  prevNextCode &= 0x0f;

   // If valid then store as 16 bit data.
   if  (rot_enc_table[prevNextCode] ) {
      store <<= 4;
      store |= prevNextCode;
      //if (store==0xd42b) return 1;
      //if (store==0xe817) return -1;
      if ((store&0xff)==0x2b) return -1;
      if ((store&0xff)==0x17) return 1;
   }
   return 0;
}



----


新的! Comments

让你说到你刚刚阅读的东西!留下下面的框中的评论。



隐私政策 | 接触 | 关于我

网站地图 | 使用条款


5894-118

ezoic.报告此广告

访问我们的Facebook页面:

   点击这里



最近的文章

  1. 如何使用ADS1115

    使用ADS1115精度16位ADC进行教程进行低功耗。

    阅读更多

  2. arduino.模拟输出...易模拟输出生成

    arduino.模拟输出:如何创建最精确的PWM模拟输出以及如何创建模拟PWM正弦波。

    阅读更多

  3. 数号和等效的快速宏。加快代码!

    了解DigitalWrite()的工作原理......现在使用17倍宏宏!

    阅读更多

  4. TCS230颜色传感芯片:如何运作以及如何使用它。

    如何使用TCS230(/ TCS3200)彩色检测器芯片并轻松将其添加到您的任何项目中。

    阅读更多

  5. 如何使用ADXL345进行运动感测等。

    使用ADXL345 Acellerometer,您可以检测到16G!您还可以了解如何使用它来点击检测等。

    阅读更多

  6. HMC5883L 3轴数字MAGENTOMTER如何运作

    HMC5883L - 如何制作数字罗盘,了解HMC5883L和QMC5883L之间的差异以及它们是否兼容。

    阅读更多



读者 Comments

"I wanted to thank
你这么好
对于所有信息
你已经提供了
你的网站's

高超极好的."

- 逃亡Potthath.

"This site really is
最好的和我最喜欢的。
我发现这里有很多很有用
项目和提示。"

- 米兰

Bursach.<at>gmail.com<

"Awesome site,
非常,非常容易和好
导航!"


-
镭_tr.<at>
wolf359.cjb.net.


学习微控制器

"Interested in
微控制器?"

注册
免费7天指南:

自由 GUIDE : CLICK HERE


"I am a newbie to PIC
我想说
 how great your
网站一直在为我。"


- 戴夫

de_scott.<at>bellsouth.net

"Your site is a great
和完美的工作。
恭喜。"


- SURESH.

IntegratedInfosys.<at>
Yahoo.com.

"I couldn't find the correct
要定义的词语
你的网页。

非常有用,揭开,
诚实明确。

非常感谢
你的时间和作品。
问候。"


- Anon.

回到顶部