当前位置:网站首页>【Arduino使用旋转编码器模块】

【Arduino使用旋转编码器模块】

2022-08-02 03:29:00 WENJIE科技

前言

旋转编码器是一种机电位置传感器,可用于识别旋转轴的角位置。这种类型的传感器或模块根据旋转轴的运动和方向产生电信号。该编码器由机械部件构成,因此传感器非常坚固,可用于许多应用,如机器人、计算机鼠标、CNC 机器和打印机。旋转编码器有两种类型:一种是绝对编码器,另一种是增量编码器。

旋转编码器模块引脚

旋转编码器模块有 5 个引脚;分别是 GND、+(VCC)、SW(Switch)、DT 和 CLK。这个传感器模块的所有引脚都是数字的,除了 VCC 和地。旋转编码器模块的引脚排列如下所示:
在这里插入图片描述在这里插入图片描述

旋转编码器模块如何工作?

如果我们拆下旋转编码器,我们会看到有一个圆盘,上面有很多孔。编码器板连接到公共地线,两个触点如下所示。
在这里插入图片描述当编码器的轴转动时,输出 A 和输出 B 端子以特定顺序与公共板接触,具体顺序取决于旋转方向。如果编码器轮顺时针旋转,输出 A 将首先连接,然后输出 B 将连接到公共板。如果编码器以逆时针方向旋转,则会发生相反的情况,但最终,输出 A 和输出 B 生成的信号将始终彼此相差 90*。

在上面的动画中,如果我们顺时针转动编码器的轴,针脚A先连接,然后针脚B连接。通过跟踪先连接哪个针脚,我们可以确定旋转方向,因此我们可以增加或减少a根据旋转方向计数。
在这里插入图片描述如果您仔细查看旋转编码器模块,PCB 本身并没有太多东西,在顶部,我们有旋转编码器和用于连接的插头引脚,而在底部,我们只有上拉电阻。这构成了我们的整个旋转编码器模块。由于旋转编码器是一种机械设备,因此可以在 3.3V 和 5V 工作电压下工作。

旋转编码器模块电路图

该模块由非常通用且随时可用的组件制成,您只需要三个电阻器和编码器本身即可自行构建。旋转编码器模块的示意图如下所示。
在这里插入图片描述
如上图所示,旋转编码器模块中没有太多东西,只需要三个10K上拉电阻即可自行构建模块。如果您要从模块构建 PCB,则此原理图可以派上用场。

Arduino旋转编码器模块电路连接图

现在我们已经完全了解了旋转编码器模块的工作原理,我们可以将所有必需的电线连接到 Arduino 并编写代码以从传感器中获取所有角位置数据。旋转编码器模块与 Arduino 的连接图如下所示
在这里插入图片描述将旋转编码器模块连接到Arduino非常简单,我们只需将旋转编码器的CLK和DT引脚连接到Arduino的外部中断引脚,即Arduino的D2和D3 in,我们需要连接SW引脚连接到 Arduino 的 D4 引脚,我们将其配置为引脚更改中断引脚。这就是从旋转编码器到 Arduino 的硬件连接的全部内容,我们现在可以转到代码部分。
在这里插入图片描述

代码说明

从旋转编码器读取角度数据的Arduino 旋转编码器代码如下所示。代码非常简单易懂。对于此代码,我们将使用中断从旋转编码器获取角度数据。我们使用中断是因为中断出错的可能性非常小。

我们通过包含所有必需的库开始我们的代码,我们还为时钟、数据和按钮引脚定义了 Arduino 引脚。

#include "PinChangeInterrupt.h"
#define CLK 2
#define DT 3
#define SW 4

接下来,我们为旋转编码器定义了保持按钮状态和计数器状态所需的所有变量。

int counter = 0;
int currentState;
int initState;
unsigned long bebounceDelay = 0;

接下来,我们有我们的设置功能。在设置函数中,我们将之前定义的三个引脚设置为输入,并初始化串行监视器窗口以进行调试。

void setup() {
    
  pinMode(CLK, INPUT);
  pinMode(DT, INPUT);
  pinMode(SW, INPUT_PULLUP);
  // Setup Serial Monitor
  Serial.begin(9600);

接下来,我们读取编码器CLK 引脚的当前状态并将其存储在initState 变量中。这很重要,如果没有这一步,编码器计数器将无法工作。

 initState = digitalRead(CLK);

最后,在setup函数中,我们声明了中断并将其配置为 CHANGE,以便我们可以捕获来自编码器的任何中断。

  attachInterrupt(0, encoder_value, CHANGE);
  attachInterrupt(1, encoder_value, CHANGE);
  attachPCINT(digitalPinToPCINT(SW), button_press, CHANGE);
}

接下来,我们有我们的循环部分,循环部分将保持为空,因为我们在循环部分内什么都不做。

void loop(){
    
}

接下来,我们有我们的button_press()函数,该函数将在中断发生时自动调用。在此函数中,我们读取SW 引脚并检查该引脚是否为低电平。如果它很低,那么我们等待一定的时间来检查按钮是否真的被按下或者它是否是随机噪音。这样我们可以减少按钮的去抖动错误。如果按钮被按下,我们打印按钮被按下!串行监视器窗口上的消息。

void button_press()
{
    
  int buttonVal = digitalRead(SW);
  //If we detect LOW signal, button is pressed
  if (buttonVal == LOW) {
    
    if (millis() - bebounceDelay > 200) {
    
      Serial.println("Button pressed!");
    }
    debounceDelay = millis();
  }
}

接下来,我们有编码器值函数。在此函数中,我们检查编码器位置及其方向,并根据编码器的旋转增加计数器。如果旋转是顺时针方向,我们增加计数器,如果它是逆时针方向,我们减少计数器。

void encoder_value() {
    

  currentState = digitalRead(CLK);

  if (currentState != initState  && currentState == 1) {
    

    if (digitalRead(DT) != currentState) {
    
      counter ++;
    } else {
    

      counter --;
    }

    Serial.print("Counter: ");
    Serial.println(counter);
  }

  initState = currentState;
}

这标志着我们代码部分的代码部分的结束,我们可以继续下一部分,了解这个与 Arduino 的基本接口项目。

完整代码

#include "PinChangeInterrupt.h"


#define CLK 2


#define DT 3


#define SW 4


int counter = 0;


int currentState;


int initState;


unsigned long debounceDelay = 0;


void setup() {
    


  pinMode(CLK, INPUT);


  pinMode(DT, INPUT);


  pinMode(SW, INPUT_PULLUP);


  // Setup Serial Monitor


  Serial.begin(9600);


  // Read the initial state of CLK


  initState = digitalRead(CLK);


  // Call encoder_value() when any high/low changed seen


  // on interrupt 0 (pin 2), or interrupt 1 (pin 3)


  attachInterrupt(0, encoder_value, CHANGE);


  attachInterrupt(1, encoder_value, CHANGE);


  attachPCINT(digitalPinToPCINT(SW), button_press, CHANGE);


}


void loop()


{
    


}


void button_press()


{
    


  int buttonVal = digitalRead(SW);


  //If we detect LOW signal, button is pressed


  if (buttonVal == LOW) {
    


    if (millis() - debounceDelay > 200) {
    


      Serial.println("Button pressed!");


    }


    debounceDelay = millis();


  }


}


void encoder_value() {
    


  // Read the current state of CLK


  currentState = digitalRead(CLK);


  // If last and current state of CLK are different, then we can be sure that the pulse occurred


  if (currentState != initState  && currentState == 1) {
    


    // Encoder is rotating counterclockwise so we decrement the counter


    if (digitalRead(DT) != currentState) {
    


      counter ++;


    } else {
    


      // Encoder is rotating clockwise so we increment the counter


      counter --;


    }


    // print the value in the serial monitor window


    Serial.print("Counter: ");


    Serial.println(counter);


  }


  // Remember last CLK state for next cycle


  initState = currentState;


}
原网站

版权声明
本文为[WENJIE科技]所创,转载请带上原文链接,感谢
https://blog.csdn.net/m0_46509684/article/details/126011272