查看: 703|回复: 0

[手势识别] 手势识别与触摸传感器测试之蓝牙MIDI控制器

[复制链接]
IMG_7064.JPG
拿到DF送测的手势识别与触摸传感器一周了,趁周末有时间写了下程序检验传感器的实际使用效果,先简单概述一下,串口通信上手很简单,官方示例代码简单明了,简单修改代码就能融入现有的程序中,手势识别高度可定义的确方便不少,一定程度上降低了误操作,在实际使用中手势一定要标准,不然还是会出现一定几率的误识别,尽管可以使能手势。个人感觉适合交互场景不太繁琐的项目,频繁手势切换会降低准确率。
小广告走一走两个LOGO你都认识么
IMG_8682.JPG

连接真的是很简单,给传感器一个近景(晚上灯光效果不太好)

IMG_1449.JPG IMG_1056.JPG

先放演示视频,手势向前控制play/pause,向后选中BeatLoop,手势向上开关FX,向左切换下一个FX,向右切换FX时长,五个触摸按键分别启动固定的FX


几乎所有的宿主软件都支持MIDI Learn,因此使用手势识别触摸传感器直接发送音符作为开关就是最简单的控制方式,代码主要是BLE-MIDI发送MIDI消息,Gesture识别发送的Note。


代码如下:
[C] 纯文本查看 复制代码
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <DFRobot_Gesture_Touch.h>
#include <M5Stack.h>
HardwareSerial    mySerial(2);
DFRobot_Gesture_Touch   DFGT(&mySerial);

///// Button
const uint8_t buttonPins[2] = {39, 38};
boolean buttonFlags[2] = {false, false};
uint8_t buttonNote[2] = {68, 70};
//uint8_t buttonCC[2] = {79, 80};
uint8_t velocity = 127;
BLECharacteristic *pCharacteristic;
bool deviceConnected = false;

#define MIDI_SERVICE_UUID        "03b80e5a-ede8-4b33-a751-6ce34ec4c700"
#define MIDI_CHARACTERISTIC_UUID "7772e5db-3868-4112-a1a9-f2669d106bf3"

void printConnectionStatus(const char* message){
  M5.Lcd.fillRect(0, 210, 320, 20, BLACK);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setCursor(160,210);
  M5.Lcd.printf("%13s", message);
}

BLEServer *pServer;  // ■
BLESecurity *pSecurity;  //■

class MyServerCallbacks: public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
    printConnectionStatus("connected");
    Serial.println("connected");
  }
  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
    printConnectionStatus("disconnected");
    Serial.println("disconnected");
  }
};

void noteOn(uint8_t channel, uint8_t pitch, uint8_t velocity) {
  uint8_t midiPacket[] = {0x80, 0x80,  (uint8_t)(0x90 | channel), pitch, velocity };
  //Serial.println((uint8_t)(0x90 | channel));
  pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes
  pCharacteristic->notify();
}
void noteOff(uint8_t channel, uint8_t pitch, uint8_t velocity) {
  uint8_t midiPacket[] = {0x80, 0x80,  (uint8_t)(0x80 | channel), pitch, velocity };
  //Serial.println((uint8_t)(0x80 | channel));
  pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes)
  pCharacteristic->notify();
}
void controlChange(uint8_t  channel, uint8_t  control, uint8_t  value) {
  uint8_t midiPacket[] = {0x80, 0x80, (uint8_t)(0xB0 | channel), control, value };
  pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes)
  pCharacteristic->notify();
}

void setup() {  
  M5.begin();  //LCD
  dacWrite(25, 0);
  mySerial.begin(9600);
  DFGT.setGestureDistance(15);             // suggest default value
  DFGT.enableFunction(DFGT_FUN_ALL); 
  DFGT.disableFunction(DFGT_FUN_PULLUP);
  BLEDevice::init("M5-MIDI"); //Device Name ■

  // Create the BLE Server
  //BLEServer *pServer = BLEDevice::createServer(); // ■
  pServer = BLEDevice::createServer(); // ■
  pServer->setCallbacks(new MyServerCallbacks());
  BLEDevice::setEncryptionLevel((esp_ble_sec_act_t)ESP_LE_AUTH_REQ_SC_BOND);
    
  // Create the BLE Service
  BLEService *pService = pServer->createService(BLEUUID(MIDI_SERVICE_UUID));

  // Create a BLE Characteristic
  pCharacteristic = pService->createCharacteristic(
                      BLEUUID(MIDI_CHARACTERISTIC_UUID),
                      BLECharacteristic::PROPERTY_READ   |
                      BLECharacteristic::PROPERTY_NOTIFY |
                      BLECharacteristic::PROPERTY_WRITE_NR
                    );
  pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);

  // Create a BLE Descriptor
  pCharacteristic->addDescriptor(new BLE2902());

  // Start the service
  pService->start();

  // Start advertising
  //BLESecurity *pSecurity = new BLESecurity(); //■
  pSecurity = new BLESecurity();
  pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_BOND);
  pSecurity->setCapability(ESP_IO_CAP_NONE);
  pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);

  pServer->getAdvertising()->addServiceUUID(MIDI_SERVICE_UUID);
  pServer->getAdvertising()->start();


  for (int i = 0; i < 3; i++) {
    pinMode(buttonPins[i], INPUT); //GPIO #38 39
  }


  M5.Lcd.setCursor(100,0);
  M5.Lcd.setTextSize(2);
  M5.Lcd.printf("BLE MIDI");

}  //setup

void loop() { 
//    velocity = map(analogRead(36), 0, 1024, 0, 100);
    M5.Lcd.setTextSize(2); 
    for (int i = 0; i < 2; i++) { // 3: button, 5: footswitch
      int buttonValue = digitalRead(buttonPins[i]);
      if (buttonValue == LOW && buttonFlags[i] == false) {
        if (deviceConnected) {
          noteOn(0, buttonNote[i], 127);
         // M5.Lcd.setTextSize(3);
         
        }
        delay(100);
       buttonFlags[i] = true;
      } //if

      if (buttonValue == LOW && buttonFlags[i] == true) {
       if (deviceConnected) {
          // noteOff
          noteOff(0, buttonNote[i], 127);          
        }
        delay(100);
        buttonFlags[i] = false;
      } // if
    } //for
   if(digitalRead(buttonPins[2]) == LOW ){
        int8_t    rslt = DFGT.getAnEvent();  // get an event that data saved in serial buffer
         if(rslt != DF_ERR) {
            switch(rslt) {
                    case DFGT_EVT_BACK: {
                      noteOn(0, 40, velocity);
                    } break;
                    case DFGT_EVT_FORWARD: {
                      noteOn(0, 41, velocity);
                    } break;
                    case DFGT_EVT_RIGHT: {
                      noteOn(0, 42, velocity);
                    } break;
                    case DFGT_EVT_LEFT: {
                      noteOn(0, 43, velocity);
                    } break;
                    case DFGT_EVT_PULLUP: {
                      noteOn(0, 45, velocity);
                    } break;
                    case DFGT_EVT_PULLDOWN: {
                      noteOn(0, 46, velocity);
                    } break;
                    case DFGT_EVT_PULLREMOVE: {
                      noteOn(0, 47, velocity);
                    } break;

              }
         }
   }else {
      int8_t    rslt = DFGT.getAnEvent();  // get an event that data saved in serial buffer
      if(rslt != DF_ERR) {
          switch(rslt) {                   
                    case DFGT_EVT_TOUCH1: {
                      noteOn(0, 48, velocity);
                    } break;
                    case DFGT_EVT_TOUCH2: {
                      noteOn(0, 52, velocity);
                    } break;
                    case DFGT_EVT_TOUCH3: {
                      noteOn(0, 56, velocity);
                    } break;
                    case DFGT_EVT_TOUCH4: {
                      noteOn(0, 60, velocity);
                    } break;
                    case DFGT_EVT_TOUCH5: {
                      noteOn(0, 64, velocity);
                    } break;
           }
      }
    }
}







您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2020 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail