手势识别与触摸传感器测试之蓝牙MIDI控制器
拿到DF送测的手势识别与触摸传感器一周了,趁周末有时间写了下程序检验传感器的实际使用效果,先简单概述一下,串口通信上手很简单,官方示例代码简单明了,简单修改代码就能融入现有的程序中,手势识别高度可定义的确方便不少,一定程度上降低了误操作,在实际使用中手势一定要标准,不然还是会出现一定几率的误识别,尽管可以使能手势。个人感觉适合交互场景不太繁琐的项目,频繁手势切换会降低准确率。
小广告走一走{:5_144:}两个LOGO你都认识么
连接真的是很简单,给传感器一个近景(晚上灯光效果不太好)
先放演示视频,手势向前控制play/pause,向后选中BeatLoop,手势向上开关FX,向左切换下一个FX,向右切换FX时长,五个触摸按键分别启动固定的FX
https://www.bilibili.com/video/av67127652/
几乎所有的宿主软件都支持MIDI Learn,因此使用手势识别触摸传感器直接发送音符作为开关就是最简单的控制方式,代码主要是BLE-MIDI发送MIDI消息,Gesture识别发送的Note。
代码如下:
#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 = {39, 38};
boolean buttonFlags = {false, false};
uint8_t buttonNote = {68, 70};
//uint8_t buttonCC = {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_tchannel, uint8_tcontrol, uint8_tvalue) {
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, 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);
if (buttonValue == LOW && buttonFlags == false) {
if (deviceConnected) {
noteOn(0, buttonNote, 127);
// M5.Lcd.setTextSize(3);
}
delay(100);
buttonFlags = true;
} //if
if (buttonValue == LOW && buttonFlags == true) {
if (deviceConnected) {
// noteOff
noteOff(0, buttonNote, 127);
}
delay(100);
buttonFlags = false;
} // if
} //for
if(digitalRead(buttonPins) == 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;
}
}
}
}
页:
[1]