基于M5StickC的两种蓝牙键盘实现-Arduino中文社区 - Powered by Discuz! Archiver

沧海笑1122 发表于 2020-2-10 22:36

基于M5StickC的两种蓝牙键盘实现

本帖最后由 沧海笑1122 于 2020-2-11 11:32 编辑

【基于M5StickC的两种蓝牙键盘实现】这次不讲故事了,代码比较简单,直接上代码了。接线都写在备注里面了,请玩家参考。

一、游戏摇杆+按键套装+m5stickc的ble键盘实现
/**
* This example turns the ESP32 into a Bluetooth LE keyboard that writes the words, presses Enter, presses a media key and then Ctrl+Alt+Delete
*/
//==M5StickC +摇杆按键游戏套件模拟ble键盘
//==date:2020-02-09
//==借鉴:   // (1) M5StickC的官方display & IMU demo// (2) 感谢https://github.com/T-vK/ESP32-BLE-Keyboard
// (3) 感谢https://mc.dfrobot.com.cn/thread-298175-1-1.html
// 谢谢作者zoologist提醒,需要修改\ESP32-BLE-Keyboard-master\BleKeyboard.cpp 文件,
//在前面插入HIDINPUT 和HIDOUTPUT的定义:
//==功能:BLE键盘使能、四个键盘方向键模拟,玩家可以离开电脑,用游戏按键控制目标,如俄罗斯方块。
//==使用方法:   将摇杆键盘套件的四个方向键以及摇杆的中间KEY连接到m5stickc上。打开C之后,
//      新增PC的蓝牙设备,可以找到一个esp32 ble keyboard,配对后即可连接使用,摇杆的中间KEY是使能键,
//       按一次开启BLE键盘功能,再按一次则不使能,可循环。
//=====
//=====

//==========M5stickc init

#include <M5StickC.h>
#include <BleKeyboard.h>

BleKeyboard bleKeyboard;

//=========键盘硬件设置
int enableButton = 36; // 摇杆按键,用作键盘功能使能按键,m5stickC G36
int upButton = 26;   // 上方按键,G26
int downButton = 33;   // 下方按键,G33
int leftButton = 0;   // 左按键,G0
int rightButton =32;// 右按键,G32

int uppreviousButtonState = HIGH;   // up之前按键状态
int downpreviousButtonState = HIGH;   // down之前按键状态
int leftpreviousButtonState = HIGH;   // left之前按键状态
int rightpreviousButtonState = HIGH;   // right之前按键状态

boolean enable = false;               // 模拟鼠标功能是否可用
boolean lastEnableButtonState = HIGH; // 上一次使能按键读值
//======================

void setup() {
    // 初始化按键引脚,如果没有上拉电阻,需要使用INPUT_PULLUP
pinMode(upButton, INPUT);
pinMode(downButton, INPUT);
pinMode(leftButton, INPUT);
pinMode(rightButton, INPUT);
pinMode(enableButton, INPUT);

Serial.begin(115200);
Serial.println("Starting BLE work!");
// M5 init
Serial.begin(115200);
M5.begin();
M5.update();
M5.Lcd.setRotation(1);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextSize(1);
M5.Lcd.setCursor(30, 20);
M5.Lcd.println("M5StickC init.");
   // bleKeyboard
   bleKeyboard.begin();
   //lcd

}

void loop() {

if(bleKeyboard.isConnected()) {
M5.Lcd.setCursor(30, 20);
M5.Lcd.println("            ");
M5.Lcd.setCursor(30, 20);
M5.Lcd.println("BKConnected..");
    Serial.println("Sending 'Hello world'...");
   // 使能按键按一次使能,再按一次不使能
boolean EnableButtonState = digitalRead(enableButton);
if ((EnableButtonState == LOW) && (EnableButtonState != lastEnableButtonState)) {
    enable = !enable;
}
lastEnableButtonState = EnableButtonState;//使能键用于下一次比较

if (enable) {
   
    //=====读UP按键状态
    int upbuttonState = digitalRead(upButton);
    // 如果up按键状态改变,且当前按键状态为高电平
    if ((upbuttonState != uppreviousButtonState) && (upbuttonState == HIGH)) {
      bleKeyboard.write(KEY_UP_ARROW);
   }
    // 保存up当前按键状态,用于下一次比较
    uppreviousButtonState = upbuttonState;
    //=====读DOWN按键状态
    int downbuttonState = digitalRead(downButton);
    // 如果down按键状态改变,且当前按键状态为高电平
    if ((downbuttonState != downpreviousButtonState) && (downbuttonState == HIGH)) {
      bleKeyboard.write(KEY_DOWN_ARROW);
   }
    // 保存down当前按键状态,用于下一次比较
    downpreviousButtonState = downbuttonState;
       //=====读LEFT按键状态
    int leftbuttonState = digitalRead(leftButton);
    // 如果left按键状态改变,且当前按键状态为高电平
    if ((leftbuttonState != leftpreviousButtonState) && (leftbuttonState == HIGH)) {
      bleKeyboard.write(KEY_LEFT_ARROW);
   }
    // 保存left当前按键状态,用于下一次比较
    leftpreviousButtonState = leftbuttonState;
   //=====读RIGHT按键状态
    int rightbuttonState = digitalRead(rightButton);
    // 如果right按键状态改变,且当前按键状态为高电平
    if ((rightbuttonState != rightpreviousButtonState) && (rightbuttonState == HIGH)) {
      bleKeyboard.write(KEY_RIGHT_ARROW);
   }
    // 保存right当前按键状态,用于下一次比较
    rightpreviousButtonState = rightbuttonState;
}

}

}


二、基于M5StickC姿态传感器的ble体感键盘

//=====M5StickC BLE 体感键盘
//=date:2020-02-09
//=借鉴:
//   (1) M5StickC的官方display & IMU demo
//   (2)感谢https://github.com/T-vK/ESP32-BLE-Keyboard
//    (3)感谢https://mc.dfrobot.com.cn/thread-298175-1-1.html ,
//   谢谢作者zoologist提醒,需要修改\ESP32-BLE-Keyboard-master\BleKeyboard.cpp 文件,
//    在前面插入HIDINPUT 和HIDOUTPUT的定义:
//=功能:实现up-down-left-right四个方向键的体感模拟
//=   buttonA(表面M5大按钮)为使能键,按一次可以进入模拟键盘,再按一次就退出模拟键盘,以此类推
//=使用方法:在PC打开蓝牙设备,找到esp32_bleKeyboard,配对,观察显示连接后,按动C上的使能按钮,
//             开始模拟四个方向键,每个姿态模拟一次键盘按动,需要回到水平位置后开始下一个姿态。


#include <M5StickC.h>
#include <BleKeyboard.h>
BleKeyboard bleKeyboard;
//===姿态数据
float accX = 0;
float accY = 0;
float accZ = 0;
//=========键盘硬件设置
boolean uppreviousButtonState= false;   // up之前按键状态
boolean downpreviousButtonState = false;   // down之前按键状态
boolean leftpreviousButtonState = false;   // left之前按键状态
boolean rightpreviousButtonState = false;   // right之前按键状态
boolean upButtonState= false; //姿态传感器判断的up状态,下同
boolean downButtonState= false;//
boolean leftButtonState= false;//
boolean rightButtonState= false;//
boolean enable = false;               // 模拟键盘功能是否可用
boolean lastEnableButtonState = false; // 上一次使能按键读值
boolean EnableButtonState=false; //使能按钮状态,按动A键后,为true
//======================

void setup() {
// M5 init
Serial.begin(115200);
M5.begin();
M5.update();
M5.Lcd.setRotation(1);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextSize(1);
M5.Lcd.setCursor(30, 20);
M5.Lcd.println("ARROW");
M5.Lcd.setCursor(0, 30);
// M5.Lcd.println("X       Y       Z");
M5.MPU6886.Init();
// bleKeyboard
bleKeyboard.begin();
}

void loop() {
if(bleKeyboard.isConnected()) {//判断蓝牙键盘是否与PC连接
M5.Lcd.setCursor(30, 20);
M5.Lcd.println("            ");
M5.Lcd.setCursor(30, 20);
M5.Lcd.println("BKConnected..");
if(M5.BtnA.wasPressed())
    {
   Serial.println("BtnAwasPressed...");
      EnableButtonState = true;
    // 使能按键按一次使能,再按一次不使能
   if ((EnableButtonState == true) && (EnableButtonState != lastEnableButtonState)) {
      enable = true;
       M5.Lcd.setCursor(30, 20);
       M5.Lcd.println("                ");
       M5.Lcd.setCursor(30, 20);
       M5.Lcd.println("Enable..");
   }
      else
   {
   enable = false;
}

lastEnableButtonState = enable;//使能键用于下一次比较
//Serial.print("enable=");
//Serial.println(enable);
}
if (enable) {
    getimu();   //读取各个姿态用于判断
    //Serial.println("getimu...");
    //Serial.print(upButtonState);
    //Serial.println(uppreviousButtonState);
    //=====读UP按键状态
    // 如果up按键状态改变,且当前判定满足up条件
    if ((upButtonState != uppreviousButtonState) && (upButtonState ==true)) {
       //Serial.println("up");
      bleKeyboard.write(KEY_UP_ARROW);
   }
    // 保存up当前按键状态,用于下一次比较
    uppreviousButtonState = upButtonState;
    //=====读DOWN按键状态
    // 如果down按键状态改变,且当前判定满足down条件
    if ((downButtonState != downpreviousButtonState) && (downButtonState == true)) {
      bleKeyboard.write(KEY_DOWN_ARROW);
      //Serial.println("down");
   }
    // 保存down当前按键状态,用于下一次比较
    downpreviousButtonState = downButtonState;
    //=====读LEFT按键状态
    // 如果left按键状态改变,且当前判定满足left条件
    if ((leftButtonState != leftpreviousButtonState) && (leftButtonState == true)) {
      bleKeyboard.write(KEY_LEFT_ARROW);
      //Serial.println("left");
   }
    // 保存left当前按键状态,用于下一次比较
    leftpreviousButtonState = leftButtonState;
    //=====读RIGHT按键状态
    // 如果right按键状态改变,且当前判定满足right条件
    if ((rightButtonState != rightpreviousButtonState) && (rightButtonState == true)) {
      bleKeyboard.write(KEY_RIGHT_ARROW);
      //Serial.println("right ");
   }
    // 保存right当前按键状态,用于下一次比较
    rightpreviousButtonState = rightButtonState;
}

}
M5.update();
delay(10);
}


void getimu(){    //获取各种姿态子程序
//-900~900是x/y针对水平姿态的+-90的数值,玩家可以自己设置灵敏区域
//delay(10)可以自行设置反应时间

M5.MPU6886.getAccelData(&accX,&accY,&accZ);
//M5.Lcd.setCursor(0, 45);
//M5.Lcd.printf("%.2f   %.2f   %.2f      ",accX * 1000,accY * 1000, accZ * 1000);
if ((accX * 1000>-350) and (accX * 1000<250) and (accY * 1000>-350) and (accX * 1000<350)){//手腕水平放置
      //M5.Lcd.setCursor(30, 20);
      //M5.Lcd.println("          ");
      //M5.Lcd.setCursor(30, 20);
      //M5.Lcd.println("NONE");
      leftButtonState = false;
      rightButtonState = false;
      downButtonState = false;
      upButtonState=false;
}

if (accX * 1000>350) {
      M5.Lcd.setCursor(30, 20);
      M5.Lcd.println("          ");
      M5.Lcd.setCursor(30, 20);
      M5.Lcd.println("LEFT");
      leftButtonState = true;
}
if (accX * 1000<-450) {
      M5.Lcd.setCursor(30, 20);
      M5.Lcd.println("         ");
      M5.Lcd.setCursor(30, 20);
      M5.Lcd.println("RIGHT");
      rightButtonState = true;
}
if (accY * 1000>450) {
   // M5.Lcd.setCursor(30, 20);
   // M5.Lcd.println("         ");
   // M5.Lcd.setCursor(30, 20);
   // M5.Lcd.println("DOWN");
      downButtonState = true;
}
if (accY * 1000<-450) {
    //M5.Lcd.setCursor(30, 20);
    //M5.Lcd.println("         ");
    //M5.Lcd.setCursor(30, 20);
    //M5.Lcd.println("UP");
      upButtonState= true;
}
delay(10);
}


小结:
就用户体验而言,方案一肯定体验更好。方案二(体感方案)可以说是一种方法的尝试,供参加参考。

这个特殊艰难的日子,不放弃前进的脚步。
沧海合十。祝愿安康平顺。

分享上述两组代码以及修改过的ble keyvborad库。










zk19031903 发表于 2020-3-19 16:17

顶个贴:lol

topdog 发表于 2020-4-11 19:18

沧海笑出品,必是精品!
页: [1]
查看完整版本: 基于M5StickC的两种蓝牙键盘实现