Arduino 旋转编码器驱动 正反转检测(纯软件,稳定去抖动)

在工作中需要用到旋转编码器,发现按照百度上的例子正反转检测抖动非常厉害,所以经过一天反复测试重写了一个,纯软件去抖动简单易理解,废话不多说,直接贴码。

点击此处下载例程

Encoder.h

#ifndef ENCODER_H
#define ENCODER_H

#define Enc_CLK 26
#define Enc_DT 25
#define Enc_SW 17

u8 encodeCnt=0;

#endif

Encoder.c

#include "Encoder.h"

void Encoder_Init()
{
  pinMode (Enc_CLK, INPUT);
  pinMode (Enc_DT, INPUT);
  pinMode (Enc_SW, INPUT);
  digitalWrite(Enc_SW, HIGH);
  attachInterrupt(digitalPinToInterrupt(Enc_CLK), Encode_ISR, CHANGE);

}

void Encode_ISR()
{
  bool clkValue = digitalRead(Enc_CLK);
  bool dtValue = digitalRead(Enc_DT);
  static u8 checkCnt = 0;
  static bool lastCLK;
  static u32 timee = 0;
  if (lastCLK != clkValue && millis() - timee > 5)
  {
    lastCLK = clkValue;

    if (++checkCnt == 2)
    {
      checkCnt = 0;
      encodeCnt = (clkValue != dtValue ? 1 : -1);
      Serial.print("encodeCnt:");
      Serial.println(encodeCnt);
    }

    timee = millis();
  }

}

结果,正转敲1,反转敲255,非常稳定。
在这里插入图片描述
2021.08.03更新

把中间按键的单击,双击,长按功能也写了,稍微封装成一个类,直接在主函数中调用
myEncoder.Get_TouchStatus();
即可。

#ifndef MYENCODER_H
#define MYENCODER_H
#include "Arduino.h"

#define Enc_CLK 2
#define Enc_DT 5
#define Enc_SW 3

class MyEncoder
{
    enum
    {
      None,
      ONE,
      DOUBLE,
      LONG,
    };
  public:

    static unsigned char encodeCnt;
    static unsigned long RisTime;
    static unsigned long FallTime;
    static unsigned long oneTime;
    static bool isOne;
    static int touchStatus;
    MyEncoder()
    {
      pinMode (Enc_CLK, INPUT);
      pinMode (Enc_DT, INPUT);
      pinMode (Enc_SW, INPUT);
      digitalWrite(Enc_SW, HIGH);
      attachInterrupt(digitalPinToInterrupt(Enc_CLK), Encode_ISR, CHANGE);
      attachInterrupt(digitalPinToInterrupt(Enc_SW), EncSW_FALLING_ISR, FALLING);
    }
    
    static void EncSW_FALLING_ISR()
    {
      FallTime = millis();

      if (abs(FallTime - RisTime) < 10)
      {
        return;
      }

      if ( RisTime != 0 && FallTime - RisTime < 150)
      {

        touchStatus = 2;
        isOne = 0;
      }
      else
      {
        isOne = true;

        oneTime = millis();
      }


      attachInterrupt(digitalPinToInterrupt(Enc_SW), EncSW_RISING_ISR, RISING);
    }

    static void EncSW_RISING_ISR()
    {
      RisTime = millis();
      if (RisTime - FallTime > 700 && RisTime != 0)
      {
        touchStatus = 3;
        isOne = 0;
      }
      attachInterrupt(digitalPinToInterrupt(Enc_SW), EncSW_FALLING_ISR, FALLING);
    }

    void Get_TouchStatus()
    {
      static u32 timeStatus = 0;

      static u32 testNum = 0;
      if (millis() - timeStatus > 10)
      {
        timeStatus = millis();

        if (isOne && touchStatus == 0 && millis() - oneTime > 250 && digitalRead(Enc_SW) != 0)
        {
          isOne = 0;   //Serial.println("bbbbbb");
          touchStatus = 1;
        }

        switch (touchStatus)
        {
          case None:   /*按键无点击情况*/   break;
          case ONE:    Serial.println("按键 OK");
            /*按键单击情况*/     break;
          case DOUBLE: /*按键双击情况*/ Serial.println("按键双击");    break;
          case LONG:
            testNum++;
            Serial.print("-------------测试 ");
            Serial.print(testNum);
            Serial.println("结束-------------");
            /*按键长按情况*/     break;
        }
        touchStatus = 0;
      }
    }


    static void Encode_ISR()
    {
      bool clkValue = digitalRead(Enc_CLK);
      bool dtValue = digitalRead(Enc_DT);
      static u8 checkCnt = 0;
      static bool lastCLK;
      static u32 timee = 0;
      if (lastCLK != clkValue && millis() - timee > 5)
      {
        lastCLK = clkValue;

        if (++checkCnt == 2)
        {
          checkCnt = 0;
          encodeCnt = (clkValue != dtValue ? 1 : -1);
          if (encodeCnt == 1)
          {
            Serial.println("左转");
          }
          else
          {
            Serial.println("    右转");
          }
        }
        timee = millis();
      }
    }
};


unsigned long MyEncoder::RisTime = 0;
unsigned long MyEncoder::FallTime = 0;
unsigned long MyEncoder::oneTime = 0;
bool MyEncoder::isOne = 0;
int MyEncoder::touchStatus = 0;
unsigned char MyEncoder::encodeCnt = 0;

MyEncoder myEncoder;
#endif
  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ou.cs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值