Arduino ESP32全功能旋钮 使用蓝牙连接和EC11旋转编码器

支持长按、短按、双击、顺时针逆时针、按钮按下顺时针逆时针
ec11编码器原理不再介绍

使用如下旋转编码器:
在这里插入图片描述
开发板如下:
在这里插入图片描述

接线:
 CLK --> GPIO14
 DT  --> GPIO12
 SW  --> GPIO19
 +   --> 3V3
 GND --> GND

使用如下库:

lib_deps = 
	mathertel/OneButton@^2.0.3
	t-vk/ESP32 BLE Keyboard@^0.3.2
	madhephaestus/ESP32Encoder@^0.10.1

库使用可参考文档和其他文章。
为了节省MCU利用率,使用中断方式而不使用轮询方式。

代码如下,可实现功能:
模式0自定义短按、双击、顺时针逆时针、按钮按下顺时针逆时针功能
模式1自定义短按、双击、顺时针逆时针、按钮按下顺时针逆时针功能
长按切换两种模式(可自行添加多种模式),(按下旋转松手后不会切换模式)

此示例中:
模式0:短按静音/取消静音,双击蓝牙输入测试,顺时针音量加,逆时针音量键、按钮按下顺时针逆时针无功能。
模式1:短按Enter,双击蓝牙输入测试,顺时针右方向键,逆时针左方向键,按钮按下顺时针下方向键,按钮按下逆时针上方向键。
烧录后串口查看当前动作、模式和编码器计数
电脑蓝牙连接ESP32-BleKeyboard

#include <Arduino.h>
#include "BleKeyboard.h"
#include "OneButton.h"
#include <ESP32Encoder.h>

//按键配置
#define EC11_A_PIN 12
#define EC11_B_PIN 14
#define EC11_K_PIN 19//按键引脚

//键盘名称:ESP32-BleKeyboard
BleKeyboard bleKeyboard("ESP32-Keyboard", "Espressif", 100);
ESP32Encoder encoder;
OneButton SW(EC11_K_PIN, true);

int lastEncoderValue = 0;
int now_count = 0;
int mode = 0;   //0,1两种mode,可自行添加
bool activate = true;

//按键单击回调函数
void click() {
    if (mode == 0) {
        Serial.println("Click: MUTE");
        bleKeyboard.write(KEY_MEDIA_MUTE);
    }
    if (mode == 1) {
        Serial.println("Enter");
        bleKeyboard.write(KEY_RETURN);
    }
}

//按键长按回调函数
void longclick() {
    if (activate) {   //如果旋钮转动,则不切换状态
        Serial.println("Longclick: Mode Change");
        Serial.print("current mode: ");
        if (mode == 0) {
            mode = 1;
            Serial.println("Arrow");
            return;
        }
        if (mode == 1) {
            mode = 0;
            Serial.println("Media");
            return;
        }
    }
    activate = true;
}

//按键双击回调函数
void doubleclick() {
    if (mode == 0) {
         Serial.println("Doubleclick: Input test");
   		 bleKeyboard.print("ESP32-BLEKeyboard Input Test");
    }
    if (mode == 1) {
         Serial.println("Doubleclick: Input test");
    	bleKeyboard.print("ESP32-BLEKeyboard Input Test");
    }
}

void setup() {
    Serial.begin(115200);
    ESP32Encoder::useInternalWeakPullResistors = UP;
    encoder.attachSingleEdge(EC11_A_PIN, EC11_B_PIN);

    pinMode(EC11_K_PIN, INPUT_PULLUP);

    //初始化按键事件检测
    SW.attachClick(click);
    SW.attachDoubleClick(doubleclick);
    SW.attachLongPressStop(longclick);
    SW.setDebounceTicks(20);//滤波(ms)
    SW.setClickTicks(200);
    SW.setPressTicks(500);

    Serial.println("Starting BLE work");
    bleKeyboard.begin();
}

void loop() {
    SW.tick();

    if (bleKeyboard.isConnected()) {
        if (lastEncoderValue != encoder.getCount()) {
            now_count = encoder.getCount();
            if (now_count != lastEncoderValue) {
                if (!SW.isIdle()) {         //检测按键是否空闲
                    activate = false;
                    Serial.print("(Long_pressed)Encoder value: ");
                    Serial.println(now_count);
                } else {
                    Serial.print("Encoder value: ");
                    Serial.println(now_count);
                }
            }

            if (now_count > lastEncoderValue) {
                if (!SW.isIdle()) {         //检测按键是否空闲
                    if (mode == 0) {}     //模式0按钮按下顺时针功能
                    if (mode == 1) {		//模式1按钮按下顺时针功能
                        bleKeyboard.write(KEY_DOWN_ARROW);
                        Serial.println("DOWN_ARROW");
                    }
                } else {
                    if (mode == 0) {	//模式0顺时针功能
                        bleKeyboard.write(KEY_MEDIA_VOLUME_UP);
                        Serial.println("MEDIA_VOLUME_UP");
                    }
                    if (mode == 1) {	//模式1顺时针功能
                        bleKeyboard.write(KEY_RIGHT_ARROW);
                        Serial.println("RIGHT_ARROW");
                    }
                }
            }
            if (now_count < lastEncoderValue) {
                if (!SW.isIdle()) {         //检测按键是否空闲
                    if (mode == 0) {}    //模式0按钮按下逆时针功能
                    if (mode == 1) {	//模式1按钮按下逆时针功能
                        bleKeyboard.write(KEY_UP_ARROW);
                        Serial.println("UP_ARROW");
                    }
                } else {
                    if (mode == 0) {	//模式0逆时针功能
                        bleKeyboard.write(KEY_MEDIA_VOLUME_DOWN);
                        Serial.println("MEDIA_VOLUME_DOWN");
                    }
                    if (mode == 1) {	//模式1逆时针功能
                        bleKeyboard.write(KEY_LEFT_ARROW);
                        Serial.println("LEFT_ARROW");
                    }
                }
            }
            lastEncoderValue = now_count;
        }
    }
}

  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用以下步骤来实现: 1. 连接EC11旋转编码器和57步进电机到Arduino板上。EC11旋转编码器一般有3个引脚,包括正极(+)、负极(-)和信号引脚(SW)。57步进电机一般有4个引脚,包括A+、A-、B+和B-。 2. 在Arduino IDE中编写代码。代码需要包括两个函数:一个函数用于读取旋转编码器旋转方向,另一个函数用于控制57步进电机的旋转方向和步数。 3. 在代码中定义旋转编码器的引脚和步进电机的引脚。这样可以让代码更加清晰易懂。 4. 在代码中初始化旋转编码器和步进电机。初始化包括将引脚模式设置为输入或输出,以及将步进电机的初始位置设置为0。 5. 在代码中编写循环函数,用于不断读取旋转编码器旋转方向,并根据旋转方向控制步进电机的旋转方向和步数。循环函数可以使用Arduino的delay函数来控制每次旋转的时间。 下面是一个简单的示例代码: ```c++ #include <Stepper.h> // 定义旋转编码器的引脚 const int ec11PinA = 2; const int ec11PinB = 3; const int ec11PinSW = 4; // 定义57步进电机的引脚 const int stepperPinA = 8; const int stepperPinB = 9; const int stepperPinC = 10; const int stepperPinD = 11; // 定义步进电机的步数和速度 const int stepsPerRevolution = 200; const int speed = 10; // 初始化步进电机 Stepper myStepper(stepsPerRevolution, stepperPinA, stepperPinB, stepperPinC, stepperPinD); // 初始化旋转编码器 int lastPosition = 0; int currentPosition = 0; void setup() { // 将旋转编码器的引脚设置为输入 pinMode(ec11PinA, INPUT); pinMode(ec11PinB, INPUT); pinMode(ec11PinSW, INPUT); // 将步进电机的引脚设置为输出 pinMode(stepperPinA, OUTPUT); pinMode(stepperPinB, OUTPUT); pinMode(stepperPinC, OUTPUT); pinMode(stepperPinD, OUTPUT); // 设置步进电机的初始位置为0 myStepper.setSpeed(speed); myStepper.step(0); } void loop() { // 读取旋转编码器旋转方向 int delta = readEncoder(); // 如果旋转方向不为0,控制步进电机旋转 if (delta != 0) { int steps = delta * 10; // 每次旋转10步 myStepper.step(steps); lastPosition = currentPosition; currentPosition += steps; } // 等待一段时间,再次读取旋转编码器 delay(50); } // 读取旋转编码器旋转方向 int readEncoder() { int delta = 0; int a = digitalRead(ec11PinA); int b = digitalRead(ec11PinB); if (a != b) { if (a == HIGH) { delta = 1; } else { delta = -1; } } return delta; } ``` 这个例子中,每次旋转编码器,步进电机就会旋转10步。你可以根据需要自行调整步数。同时,如果需要控制步进电机的左右旋转,可以根据步进电机的旋转方向来控制。例如,如果需要向左旋转,可以将步数设置为负数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值