Skip to content

Instantly share code, notes, and snippets.

@tbekaert
Last active September 5, 2025 15:52
Show Gist options
  • Select an option

  • Save tbekaert/a890fd0519223f3258ce9793bd0f49f3 to your computer and use it in GitHub Desktop.

Select an option

Save tbekaert/a890fd0519223f3258ce9793bd0f49f3 to your computer and use it in GitHub Desktop.
Arduino - BLE midi footswitch (4 buttons)

BLE midi footswitch

I wanted a bluetooth footswitch for my pedalboard to be able to control my band's playback system without having to go to the computer.

Features

  • 4 footswitches
  • Single, double and long press handling
  • Powered by a standard 9v guitar pedal power supply
  • RGB LED for press feedback

Pictures

inside outside

#include <BLEMIDI_Transport.h>
#include <hardware/BLEMIDI_ArduinoBLE.h>
// https://github.com/poelstra/arduino-multi-button
#include <PinButton.h>
/*********************
* Options
**********************/
const int MIDIChannel = 1;
int COLOR_DEFAULT[3] = {10, 10, 10}; // Grey
int COLOR_WAITING_CONNECTION[3] = {0, 0, 255}; // Blue
int COLOR_SINGLE_PRESS[3] = {0, 255, 0}; // Green
int COLOR_DOUBLE_PRESS[3] = {255, 255, 0}; // Yellow
int COLOR_LONG_PRESS[3] = {255, 100, 0}; // Orange
/*********************
* Config
**********************/
// Create midi controller instance
BLEMIDI_CREATE_INSTANCE("TOMBEK CTRL", MIDI);
/* LED Pin */
const int PIN_LED_R = A1;
const int PIN_LED_G = A2;
const int PIN_LED_B = A3;
/* Buttons */
PinButton button1(2);
PinButton button2(5);
PinButton button3(8);
PinButton button4(11);
bool isLongPress = false;
/* LED concurrency */
const int ledInterval = 300;
unsigned long previousLedMillis = 0;
bool isDefaultColorActive = true;
/* MIDI */
bool isConnected = false;
/* MIDI beacon concurrency */
const int MIDICommandeInterval = 300;
unsigned long lastMIDIcommand = 0;
/* Millis */
unsigned long currentMillis = 0;
/*********************
* Setup
**********************/
void setup() {
// Serial.begin(9600);
// Set LED color to "waiting connection"
setLEDColor(COLOR_WAITING_CONNECTION);
BLEMIDI.setHandleConnected(OnConnected);
BLEMIDI.setHandleDisconnected(OnDisconnected);
// Start MIDI
MIDI.begin();
}
/*********************
* Main loop
**********************/
void loop() {
currentMillis = millis();
MIDI.read();
if (isConnected) {
button1.update();
handleButton(button1, 20, 21, 22);
button2.update();
handleButton(button2, 23, 24, 25);
button3.update();
handleButton(button3, 26, 27, 28);
button4.update();
handleButton(button4, 29, 30, 31);
resetLEDColor();
sendMIDIBeacon();
}
}
/*********************
* Utils
**********************/
/* Buttons */
void handleButton(PinButton button, int singlePressController, int doublePressController, int longPressController) {
// Press handling
if (button.isSingleClick()) {
// Serial.println(("Single press"));
setLEDColor(COLOR_SINGLE_PRESS);
sendCC(singlePressController);
}
if (button.isDoubleClick()) {
// Serial.println(("Double press"));
setLEDColor(COLOR_DOUBLE_PRESS);
sendCC(doublePressController);
}
if (button.isLongClick()) {
// Serial.println(("Long press"));
setLEDColor(COLOR_LONG_PRESS);
sendCC(longPressController);
isLongPress = true;
}
// LED handling
if (button.isReleased() && isLongPress) {
setLEDColor(COLOR_LONG_PRESS);
isLongPress = false;
}
}
/* LED */
void resetLEDColor () {
if (!isDefaultColorActive && ledInterval + previousLedMillis < currentMillis && !isLongPress) {
// Serial.println("Reset LED color");
setLEDColor(COLOR_DEFAULT);
}
}
void setLEDColor(int color[3]) {
// Serial.println((String)"Set LED color to rgb(" + color[0] + ", " + color[1] + ", " + color[2] + ")");
isDefaultColorActive = color == COLOR_DEFAULT;
analogWrite(PIN_LED_R, (color[0]));
analogWrite(PIN_LED_G, (color[1]));
analogWrite(PIN_LED_B, (color[2]));
previousLedMillis = currentMillis;
}
/* MIDI */
void sendCC(int controller) {
// Serial.println((String)"Sending midi CC " + controller);
MIDI.sendControlChange(controller, 127, MIDIChannel);
lastMIDIcommand = currentMillis;
}
// Keep midi connection alive in between sending commands
void sendMIDIBeacon () {
if (currentMillis > MIDICommandeInterval + lastMIDIcommand) {
// Serial.println(("Sending MIDI beacon (active sense)"));
MIDI.sendActiveSensing();
lastMIDIcommand = currentMillis;
}
}
void OnConnected() {
// Serial.println(("Connected"));
isConnected = true;
resetLEDColor();
}
void OnDisconnected() {
// Serial.println(("Disconnected"));
isConnected = false;
setLEDColor(COLOR_WAITING_CONNECTION);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment