GitHub - microplc/FR_RotaryEncoder: 一个Arduino库用于旋转编码器 (型号 KY-040/EC11 或类似)

"FR_RotaryEncoder" 是一个用于内嵌PUSH开关的机械旋转编码器的Arduino库.

Copyright (c) 2019 by Ilias Iliopoulos info@fryktoria.com

This file is part of "FR_RotaryEncoder".

Licensed under GNU General Public License, version 3 of the License
  https://www.gnu.org/licenses/  

The part related to the debouncing of the rotary encoder is based on
an idea documented in http://www.technoblogy.com/list?28Y4 
The article and code is copyrighted as:

  David Johnson-Davies - www.technoblogy.com - 7th July 2018
  Arduino/Genuino Uno   
  CC BY 4.0
  Licensed under a Creative Commons Attribution 4.0 International license: 
  http://creativecommons.org/licenses/by/4.0/  

This code is implemented with the Arduino IDE and has been tested with IDE 1.8.10, on an Arduino Nano.

  • 包含库

    #include "FR_RotaryEncoder.h"
  • 创建类实例并指定用于A (SCK), B (DT) 和 PUSH开关 (SW)的针脚。 把 A 脚设置为支持中断功能的 PIN 2 或 PIN 3 是非常重要的。 另外把 SW 脚设置为 A 脚不用的 PIN 2 或 3也是非常重要的。 B脚可以是任何其他的Arduino I/O 脚。 下面的类名 rencoder 是随意起的。

    RotaryEncoder rencoder(pinSCK, pinDT, pinSW);

    常见Arduino板子的中断资源列表:

    板子型号-----int.0,int.1,int.2,int.3,int.4,int.5,Level

    Uno, Mini, Pro, ATmega168, ATmega328-----PIN2,PIN3,5v

    Mega2560-----PIN2,PIN3,PIN21,PIN20,PIN19,PIN18,5v

    Leonardo, Micro, ATmega32U4-----PIN3,PIN2,PIN0,PIN1,PIN7,5v

    Digistump, Trinket, ATtiny85-----2/physical pin 7,5v

    Due, SAM3X8E-----all digital pins,3v

    Zero, ATSAMD21G18-----all digital pins, except pin 4,3v

    Blue Pill, STM32F103xxxx boards-----all digital pins, maximun 16 pins at the same time,3v

    ESP8266-----all digital pins, except gpio6 - gpio11 & gpio16,3v/5v

    ESP32-----all digital pins,3v

  • 检查旋转编码器的线路,默认情况下 , Arduino 输入被设置为 without 上拉。 如果模块有上拉电阻在 PIN A 和 B,你不需要做任何事。但是如果模块没有上拉电阻, 你必须手动设置使用内部 MCU 上拉。

    rencoder.enableInternalRotaryPullups(); 

    如果模块 PUSH 开关也没有上拉电阻,你也需要激活内部上拉电阻设置:

    rencoder.enableInternalSwitchPullup(); 
  • 有上拉电阻并且开关连接到 GND ,稳定状态 (switch not pressed)是 1 , 激活状态 (switch pressed) 是 0。如果你的硬件有一个下拉电阻从 PIN 到 Vcc 你可以反转逻辑如下:

    rencoder.setSwitchLogic(true);

    你也可以使用 rencoder.setRotaryLogic() 来反转旋转的方向。

  • 设置旋转编码器正负极限值和 wrap-around 模式:

    rencoder.setRotaryLimits(rotaryMinimum, rotaryMaximum, rotaryWrapMode);

    rotaryWrap 模式就是循环。

    false: 增加方向永远小于最大值,减少方向永远大于最小值

    需要关注的是这种模式后跟 setRotationalStep()并且步进值不为 1. 假设你在 逆时针方向设置 max=10 并且 min=-9 步进值为 2,位置值应该是 0, -2, -4, -6 , -8 但下一个步进值应该是比 min小的 -10。 如果被允许取值 -9,顺时针方向随 后被取值为 -7, -5, -3, -1, 1 等。 这好像不是很令人满意。最小值应该是 -8, 无需理会小于最小值的事实。

    true: 当超过最大值时,位置将被设置为最小值,而不管旋转步进值。另一个方向类似。

  • 你可以任意设置运行参数,详见文档 FR_RotaryEncoder.h

    // 设置方向 // CW = Clockwise // CCW = Counter-clockwise // NOT_MOVED = Not moved since initialization or setPosition() int getDirection();

    // 返回编码器当前方向 int getPosition();

    // 设置起始位置 void setPosition(int newPosition);

    // 设置编码器最大值 void setMaxValue(int newMaxValue);

    // 设置编码器最小值 void setMinValue(int newMinValue);

    // 设置循环模式,如果在同一方向超出最大最小值 // true goes from maxValue to minValue // false stays at maxValue or minValue, if continued in the same direction void setWrapMode(bool newWrapMode);

    // 设置旋转敏感度 // false (default): Requires two clicks per transition // true: Requires one click per transition (except the first after setup // which depends on the initial switch position) void setSensitive(bool fast);

    // 设置步进值 void setRotationalStep(int step);

    // 更新编码器状态 void rotaryUpdate();

    // PUSH开关

    // 使能内部开关上拉电阻 void enableInternalSwitchPullup();

    // 设置开关逻辑 // true means: switch ON if pin is 1, OFF if pin is 0 // false means: switch OFF if pin is 1, ON if pin is 0 void setSwitchLogic(bool logic);

    // 设置开关消抖时间,单位ms void setSwitchDebounceDelay(unsigned long dd);

    // 返回开关状态 // See enum SwitchState // SW_OFF OFF // SW_ON ON // SW_LONG Long press int getSwitchState();

    // 设置长按的时间闸门 void setLongPressTime(unsigned long longPress);

    // 开关被按压返回TRUE bool keyPressed();

    // 返回开关被按压的时间,单位ms unsigned long keyPressedTime();

  • 如果你想使用中断,你需要创建自己的中断处理函数,比如:interrupt handling routine(s) or Interrupt Service Routines (ISR)

    // Interrupt handling routine for the rotary
    void ISRrotary() {
       rencoder.rotaryUpdate();
    }
    // Interrupt handling routine for the switch
    void ISRswitch() {
      rencoder.switchUpdate();
    }

    setup() 中你必须与中断引脚建立关联,例如:

    attachInterrupt(digitalPinToInterrupt(pinSCK), ISRrotary, CHANGE);
    attachInterrupt(digitalPinToInterrupt(pinSW), ISRswitch, CHANGE);

    如果你不想使用中断而使用轮询,你可以使用任何 Arduino I/O 引脚而非必须使用 PIN 2 或 3。

    这种情况下你必须把处理编码器的语句置入 loop() ,如:

    如果你仅仅使用PUSH开关,可以:

    如果你两个都用,可以:

  • 如果你希望使用长按 Long Press 功能,为了识别开关是否被连续按压,或者想通过 函数rencoder.keyPressedTime() 返回保持按压的时间,即便是你使用中断模式, 也要在 Loop 循环里置入rencoder.switchUpdate()rencoder.update()

  • The library is accompanied with lots of examples which demonstrate most of the library features.