Created
January 4, 2024 15:07
-
-
Save NickCulbertson/9bb6122f4fb12c04d71e156c788c3985 to your computer and use it in GitHub Desktop.
This is an Arduino Sketch for a simple arcade button MIDI Controller using ESP32
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <BLEDevice.h> | |
#include <BLEUtils.h> | |
#include <BLEServer.h> | |
#include <BLE2902.h> | |
#define SERVICE_UUID "03b80e5a-ede8-4b33-a751-6ce34ec4c700" | |
#define CHARACTERISTIC_UUID "7772e5db-3868-4112-a1a9-f2669d106bf3" | |
BLECharacteristic *pCharacteristic; | |
bool deviceConnected = false; | |
unsigned long debounceDuration = 10; // millis | |
unsigned long lastTimeButton1StateChanged = 0; | |
unsigned long lastTimeButton2StateChanged = 0; | |
unsigned long lastTimeButton3StateChanged = 0; | |
unsigned long lastTimeButton4StateChanged = 0; | |
unsigned long lastTimeButton5StateChanged = 0; | |
unsigned long lastTimeButton6StateChanged = 0; | |
unsigned long lastTimeButton7StateChanged = 0; | |
unsigned long lastTimeButton8StateChanged = 0; | |
unsigned long lastTimeButton9StateChanged = 0; | |
unsigned long lastTimeButton10StateChanged = 0; | |
unsigned long lastTimeButton11StateChanged = 0; | |
unsigned long lastTimeButton12StateChanged = 0; | |
unsigned long lastTimeButton13StateChanged = 0; | |
unsigned long lastTimeButton14StateChanged = 0; | |
unsigned long lastTimeButton15StateChanged = 0; | |
unsigned long lastTimeButton16StateChanged = 0; | |
byte lastState1 = LOW; | |
byte lastState2 = LOW; | |
byte lastState3 = LOW; | |
byte lastState4 = LOW; | |
byte lastState5 = LOW; | |
byte lastState6 = LOW; | |
byte lastState7 = LOW; | |
byte lastState8 = LOW; | |
byte lastState9 = LOW; | |
byte lastState10 = LOW; | |
byte lastState11 = LOW; | |
byte lastState12 = LOW; | |
byte lastState13 = LOW; | |
byte lastState14 = LOW; | |
byte lastState15 = LOW; | |
byte lastState16 = LOW; | |
byte note1 = 0x33; | |
byte note2 = 0x32; | |
byte note3 = 0x31; | |
byte note4 = 0x30; | |
byte note5 = 0x2f; | |
byte note6 = 0x2e; | |
byte note7 = 0x2d; | |
byte note8 = 0x2c; | |
byte note9 = 0x2b; | |
byte note10 = 0x2a; | |
byte note11 = 0x29; | |
byte note12 = 0x28; | |
byte note13 = 0x27; | |
byte note14 = 0x26; | |
byte note15 = 0x25; | |
byte note16 = 0x24; | |
uint8_t midiPacket[] = { | |
0x80, // header | |
0x80, // timestamp, not implemented | |
0x00, // status | |
0x3c, // 0x3c == 60 == middle c | |
0x00 // velocity | |
}; | |
class MyServerCallbacks: public BLEServerCallbacks { | |
void onConnect(BLEServer* pServer) { | |
deviceConnected = true; | |
}; | |
void onDisconnect(BLEServer* pServer) { | |
deviceConnected = false; | |
} | |
}; | |
void setup() { | |
Serial.begin(115200); | |
pinMode( 5, INPUT_PULLUP); | |
pinMode(18, INPUT_PULLUP); | |
pinMode(19, INPUT_PULLUP); | |
pinMode(21, INPUT_PULLUP); | |
pinMode( 3, INPUT_PULLUP); | |
pinMode( 1, INPUT_PULLUP); | |
pinMode(22, INPUT_PULLUP); | |
pinMode(23, INPUT_PULLUP); | |
pinMode(13, INPUT_PULLUP); | |
pinMode(12, INPUT_PULLUP); | |
pinMode(14, INPUT_PULLUP); | |
pinMode(27, INPUT_PULLUP); | |
pinMode(26, INPUT_PULLUP); | |
pinMode(25, INPUT_PULLUP); | |
pinMode(33, INPUT_PULLUP); | |
pinMode(32, INPUT_PULLUP); | |
BLEDevice::init("Blue ESP32"); | |
// Create the BLE Server | |
BLEServer *pServer = BLEDevice::createServer(); | |
pServer->setCallbacks(new MyServerCallbacks()); | |
// Create the BLE Service | |
BLEService *pService = pServer->createService(BLEUUID(SERVICE_UUID)); | |
// Create a BLE Characteristic | |
pCharacteristic = pService->createCharacteristic( | |
BLEUUID(CHARACTERISTIC_UUID), | |
BLECharacteristic::PROPERTY_READ | | |
BLECharacteristic::PROPERTY_WRITE | | |
BLECharacteristic::PROPERTY_NOTIFY | | |
BLECharacteristic::PROPERTY_WRITE_NR | |
); | |
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml | |
// Create a BLE Descriptor | |
pCharacteristic->addDescriptor(new BLE2902()); | |
// Start the service | |
pService->start(); | |
// Start advertising | |
BLEAdvertising *pAdvertising = pServer->getAdvertising(); | |
pAdvertising->addServiceUUID(pService->getUUID()); | |
pAdvertising->start(); | |
} | |
void loop() { | |
if (deviceConnected) { | |
byte button1 = digitalRead(5); | |
byte button2 = digitalRead(18); | |
byte button3 = digitalRead(19); | |
byte button4 = digitalRead(21); | |
byte button5 = digitalRead(3); | |
byte button6 = digitalRead(1); | |
byte button7 = digitalRead(22); | |
byte button8 = digitalRead(23); | |
byte button9 = digitalRead(13); | |
byte button10 = digitalRead(12); | |
byte button11 = digitalRead(14); | |
byte button12 = digitalRead(27); | |
byte button13 = digitalRead(26); | |
byte button14 = digitalRead(25); | |
byte button15 = digitalRead(33); | |
byte button16 = digitalRead(32); | |
if (millis() - lastTimeButton1StateChanged >= debounceDuration) { | |
if (button1 != lastState1) { | |
lastTimeButton1StateChanged = millis(); | |
lastState1 = button1; | |
if (button1 == LOW) { | |
//Button Pressed | |
midiPacket[2] = 0x90; // note down, channel 0 | |
midiPacket[3] = note1; // key | |
midiPacket[4] = 127; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes | |
pCharacteristic->notify(); | |
}else{ | |
//Button Released | |
midiPacket[2] = 0x80; // note up, channel 0 | |
midiPacket[3] = note1; // key | |
midiPacket[4] = 0; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes) | |
pCharacteristic->notify(); | |
} | |
} | |
} | |
if (millis() - lastTimeButton2StateChanged >= debounceDuration) { | |
if (button2 != lastState2) { | |
lastTimeButton2StateChanged = millis(); | |
lastState2 = button2; | |
if (button2 == LOW) { | |
//Button Pressed | |
midiPacket[2] = 0x90; // note down, channel 0 | |
midiPacket[3] = note2; // key | |
midiPacket[4] = 127; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes | |
pCharacteristic->notify(); | |
}else{ | |
//Button Released | |
midiPacket[2] = 0x80; // note up, channel 0 | |
midiPacket[3] = note2; // key | |
midiPacket[4] = 0; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes) | |
pCharacteristic->notify(); | |
} | |
} | |
} | |
if (millis() - lastTimeButton3StateChanged >= debounceDuration) { | |
if (button3 != lastState3) { | |
lastTimeButton3StateChanged = millis(); | |
lastState3 = button3; | |
if (button3 == LOW) { | |
//Button Pressed | |
midiPacket[2] = 0x90; // note down, channel 0 | |
midiPacket[3] = note3; // key | |
midiPacket[4] = 127; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes | |
pCharacteristic->notify(); | |
}else{ | |
//Button Released | |
midiPacket[2] = 0x80; // note up, channel 0 | |
midiPacket[3] = note3; // key | |
midiPacket[4] = 0; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes) | |
pCharacteristic->notify(); | |
} | |
} | |
} | |
if (millis() - lastTimeButton4StateChanged >= debounceDuration) { | |
if (button4 != lastState4) { | |
lastTimeButton4StateChanged = millis(); | |
lastState4 = button4; | |
if (button4 == LOW) { | |
//Button Pressed | |
midiPacket[2] = 0x90; // note down, channel 0 | |
midiPacket[3] = note4; // key | |
midiPacket[4] = 127; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes | |
pCharacteristic->notify(); | |
}else{ | |
//Button Released | |
midiPacket[2] = 0x80; // note up, channel 0 | |
midiPacket[3] = note4; // key | |
midiPacket[4] = 0; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes) | |
pCharacteristic->notify(); | |
} | |
} | |
} | |
if (millis() - lastTimeButton5StateChanged >= debounceDuration) { | |
if (button5 != lastState5) { | |
lastTimeButton5StateChanged = millis(); | |
lastState5 = button5; | |
if (button5 == LOW) { | |
//Button Pressed | |
midiPacket[2] = 0x90; // note down, channel 0 | |
midiPacket[3] = note5; // key | |
midiPacket[4] = 127; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes | |
pCharacteristic->notify(); | |
}else{ | |
//Button Released | |
midiPacket[2] = 0x80; // note up, channel 0 | |
midiPacket[3] = note5; // key | |
midiPacket[4] = 0; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes) | |
pCharacteristic->notify(); | |
} | |
} | |
} | |
if (millis() - lastTimeButton6StateChanged >= debounceDuration) { | |
if (button6 != lastState6) { | |
lastTimeButton6StateChanged = millis(); | |
lastState6 = button6; | |
if (button6 == LOW) { | |
//Button Pressed | |
midiPacket[2] = 0x90; // note down, channel 0 | |
midiPacket[3] = note6; // key | |
midiPacket[4] = 127; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes | |
pCharacteristic->notify(); | |
}else{ | |
//Button Released | |
midiPacket[2] = 0x80; // note up, channel 0 | |
midiPacket[3] = note6; // key | |
midiPacket[4] = 0; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes) | |
pCharacteristic->notify(); | |
} | |
} | |
} | |
if (millis() - lastTimeButton7StateChanged >= debounceDuration) { | |
if (button7 != lastState7) { | |
lastTimeButton7StateChanged = millis(); | |
lastState7 = button7; | |
if (button7 == LOW) { | |
//Button Pressed | |
midiPacket[2] = 0x90; // note down, channel 0 | |
midiPacket[3] = note7; // key | |
midiPacket[4] = 127; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes | |
pCharacteristic->notify(); | |
}else{ | |
//Button Released | |
midiPacket[2] = 0x80; // note up, channel 0 | |
midiPacket[3] = note7; // key | |
midiPacket[4] = 0; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes) | |
pCharacteristic->notify(); | |
} | |
} | |
} | |
if (millis() - lastTimeButton8StateChanged >= debounceDuration) { | |
if (button8 != lastState8) { | |
lastTimeButton8StateChanged = millis(); | |
lastState8 = button8; | |
if (button8 == LOW) { | |
//Button Pressed | |
midiPacket[2] = 0x90; // note down, channel 0 | |
midiPacket[3] = note8; // key | |
midiPacket[4] = 127; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes | |
pCharacteristic->notify(); | |
}else{ | |
//Button Released | |
midiPacket[2] = 0x80; // note up, channel 0 | |
midiPacket[3] = note8; // key | |
midiPacket[4] = 0; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes) | |
pCharacteristic->notify(); | |
} | |
} | |
} | |
if (millis() - lastTimeButton9StateChanged >= debounceDuration) { | |
if (button9 != lastState9) { | |
lastTimeButton9StateChanged = millis(); | |
lastState9 = button9; | |
if (button9 == LOW) { | |
//Button Pressed | |
midiPacket[2] = 0x90; // note down, channel 0 | |
midiPacket[3] = note9; // key | |
midiPacket[4] = 127; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes | |
pCharacteristic->notify(); | |
}else{ | |
//Button Released | |
midiPacket[2] = 0x80; // note up, channel 0 | |
midiPacket[3] = note9; // key | |
midiPacket[4] = 0; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes) | |
pCharacteristic->notify(); | |
} | |
} | |
} | |
if (millis() - lastTimeButton10StateChanged >= debounceDuration) { | |
if (button10 != lastState10) { | |
lastTimeButton10StateChanged = millis(); | |
lastState10 = button10; | |
if (button10 == LOW) { | |
//Button Pressed | |
midiPacket[2] = 0x90; // note down, channel 0 | |
midiPacket[3] = note10; // key | |
midiPacket[4] = 127; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes | |
pCharacteristic->notify(); | |
}else{ | |
//Button Released | |
midiPacket[2] = 0x80; // note up, channel 0 | |
midiPacket[3] = note10; // key | |
midiPacket[4] = 0; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes) | |
pCharacteristic->notify(); | |
} | |
} | |
} | |
if (millis() - lastTimeButton11StateChanged >= debounceDuration) { | |
if (button11 != lastState11) { | |
lastTimeButton11StateChanged = millis(); | |
lastState11 = button11; | |
if (button11 == LOW) { | |
//Button Pressed | |
midiPacket[2] = 0x90; // note down, channel 0 | |
midiPacket[3] = note11; // key | |
midiPacket[4] = 127; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes | |
pCharacteristic->notify(); | |
}else{ | |
//Button Released | |
midiPacket[2] = 0x80; // note up, channel 0 | |
midiPacket[3] = note11; // key | |
midiPacket[4] = 0; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes) | |
pCharacteristic->notify(); | |
} | |
} | |
} | |
if (millis() - lastTimeButton12StateChanged >= debounceDuration) { | |
if (button12 != lastState12) { | |
lastTimeButton12StateChanged = millis(); | |
lastState12 = button12; | |
if (button12 == LOW) { | |
//Button Pressed | |
midiPacket[2] = 0x90; // note down, channel 0 | |
midiPacket[3] = note12; // key | |
midiPacket[4] = 127; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes | |
pCharacteristic->notify(); | |
}else{ | |
//Button Released | |
midiPacket[2] = 0x80; // note up, channel 0 | |
midiPacket[3] = note12; // key | |
midiPacket[4] = 0; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes) | |
pCharacteristic->notify(); | |
} | |
} | |
} | |
if (millis() - lastTimeButton13StateChanged >= debounceDuration) { | |
if (button13 != lastState13) { | |
lastTimeButton13StateChanged = millis(); | |
lastState13 = button13; | |
if (button13 == LOW) { | |
//Button Pressed | |
midiPacket[2] = 0x90; // note down, channel 0 | |
midiPacket[3] = note13; // key | |
midiPacket[4] = 127; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes | |
pCharacteristic->notify(); | |
}else{ | |
//Button Released | |
midiPacket[2] = 0x80; // note up, channel 0 | |
midiPacket[3] = note13; // key | |
midiPacket[4] = 0; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes) | |
pCharacteristic->notify(); | |
} | |
} | |
} | |
if (millis() - lastTimeButton14StateChanged >= debounceDuration) { | |
if (button14 != lastState14) { | |
lastTimeButton14StateChanged = millis(); | |
lastState14 = button14; | |
if (button14 == LOW) { | |
//Button Pressed | |
midiPacket[2] = 0x90; // note down, channel 0 | |
midiPacket[3] = note14; // key | |
midiPacket[4] = 127; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes | |
pCharacteristic->notify(); | |
}else{ | |
//Button Released | |
midiPacket[2] = 0x80; // note up, channel 0 | |
midiPacket[3] = note14; // key | |
midiPacket[4] = 0; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes) | |
pCharacteristic->notify(); | |
} | |
} | |
} | |
if (millis() - lastTimeButton15StateChanged >= debounceDuration) { | |
if (button15 != lastState15) { | |
lastTimeButton15StateChanged = millis(); | |
lastState15 = button15; | |
if (button15 == LOW) { | |
//Button Pressed | |
midiPacket[2] = 0x90; // note down, channel 0 | |
midiPacket[3] = note15; // key | |
midiPacket[4] = 127; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes | |
pCharacteristic->notify(); | |
}else{ | |
//Button Released | |
midiPacket[2] = 0x80; // note up, channel 0 | |
midiPacket[3] = note15; // key | |
midiPacket[4] = 0; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes) | |
pCharacteristic->notify(); | |
} | |
} | |
} | |
if (millis() - lastTimeButton16StateChanged >= debounceDuration) { | |
if (button16 != lastState16) { | |
lastTimeButton16StateChanged = millis(); | |
lastState16 = button16; | |
if (button16 == LOW) { | |
//Button Pressed | |
midiPacket[2] = 0x90; // note down, channel 0 | |
midiPacket[3] = note16; // key | |
midiPacket[4] = 127; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes | |
pCharacteristic->notify(); | |
}else{ | |
//Button Released | |
midiPacket[2] = 0x80; // note up, channel 0 | |
midiPacket[3] = note16; // key | |
midiPacket[4] = 0; // velocity | |
pCharacteristic->setValue(midiPacket, 5); // packet, length in bytes) | |
pCharacteristic->notify(); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I suggest wirring midi 4*4 by matrix method