OpenSongApp is designed to work with any foot pedal (Bluetooth or USB) that sends key events or midi control messages.
If you wish to use a MIDI device as a foot pedal, you first have to connect the device in the MIDI page and then switch it on in the foot pedal options. If you are not using this option, switch it off as it will override the key event listener that most pedals use.
Most users only have a pedal with two buttons. OpenSongApp allows you to use these pedals to simulate up to six options. This is done by allowing next / previous pedals to also scroll before changing songs. This makes a two pedal function like a four pedal set up (scroll up, scroll down, previous song, next song). By also allowing additional long press commands (key event only, not MIDI), you can also assign two additional functions to your pedals taking them to a six pedal set up!
If you find that long press actions are not working for your pedal, you can switch on 'AirTurn mode'. This changes the way long presses are detected by using a timer. This is common for AirTurn branded pedals and any pedals made using Arduino or ESP32 boards.
Unlike many apps that limit you to standard set ups, or certain pedal boards, OpenSongApp allows you to freely customise pedals with up to 8 buttons (along with long press and scroll before turn gives you up to 18 commands!).
The commands available can be viewed on the Available commands page.
To customise the pedal actions for your foot pedal, connect it using Android's default method (either plug it in if it is USB, or pair as a Bluetooth device). If this is a MIDI pedal, remember to connect it to the app first using the MIDI page, then switch on the 'Listen for incoming MIDI' button in the pedal settings page.
Scroll to the pedal 1 and click on the button (by default it will be set to KEYCODE_DPAD_LEFT and MIDI note C3). It will then say 'Waiting for button'. Tap the desired button on your foot pedal and it will be assigned as pedal 1. Choose a short press/tap action and an additional long press action. Repeat this process for each button on your foot pedal.
If you use a 2 pedal controller, I'd recommend setting the left button short press command to "Previous" and the right button short press command to "Next". You should also switch on the "Try to scroll before move" option.
If you are worried about accidentally moving to the next song when trying to scroll to the bottom, you can switch on the "Show warning" option. This displays a warning prompt before moving to the next song and requires you to press the button again within 2 seconds. If you do this, you get 10 seconds grace time (to allow skipping songs) before the warning is reactivated.
Any pedal made from a USB/Bluetooth keyboard
Any pedal made using an Arduino, ESP32 or BlueFruit board (sometimes requires AirTurn mode for long press actions)
Most AirTurn pedals (you will likely need to switch on AirTurn mode for long press actions). AirTurn Ped Pro works, but not particularly responsive on some surfaces and can be slow to detect presses according to some users
Lekato / M-VAVE / CuVave wireless foot pedal (some versions require switching the pedal to iOS mode or mode 2 to send key events). Unsure if long press action is detected
Donner Wireless Turner
Coda wireless turner and Coda stomp
If you have any information on working/not working foot pedals, please let us know via the forum thread.
If you fancy having a go at making a Bluetooth foot pedal, you can do this without spending too much money. It's also a relatively straightforward project if you know how to use a soldering iron and can follow simple instructions and wiring diagrams!
Unfortunately the Bluetooth board I originally used (AdaFruit EZ-Key) is not currently available, but thanks to our amazing community Leo gave me some tips to build an alternative using a ESP32 WiFi/Bluetooth development board. It's also a lot cheaper. I've since rewritten the code and changed the set up slightly.
Equipment you will need (I've included links to suppliers I've used so you can see what the bits look like):
Hammond enclosure - the size required will depend on how many buttons you plan on adding and if you are including a battery, etc. I'd recommend a minimum height of 3cm. Metal enclosures are sturdier than plastic ones, but will likely reduce the Bluetooth range to a few metres (I still use a metal case).
Some SPST switches (one for each foot switch button you need)
ESP32 WiFi/Bluetooth development board (approx £6/€8)
Female-Female Dupont Wires / Jumper Wires (approx £1 / €1.50) - you can use simple cable wire, but these reduce the risk to your board and allow quick connect/disconnect
LEDs, resistors, and mounts (about £1/€1) total . Use this website to help you calculate the best resistor size to use depending on your input voltage and led voltage, however, most LEDs will cope with a resistor between 200 Ohms and 1k Ohms. The Vf (forward voltage) of the LED should be approx 3.3-3.5V meaning it should have a minimum working voltage of about 2.7V. The ESP32 board supplies a voltage of 3.3V. You'll need two of each LED, resistor and mount.
Heat shrink tube or electrical tape and some foam or an old sponge to safely mount the board in the hammond enclosure to avoid shorts.
Solder iron, solder and cold running water for when you burn yourself...
ESP32 development board
Download the free Arduino IDE software for your PC/Mac operating system and boot it up
Follow the instructions on this webpage to make sure you can use the ESP32 board properly in Arduino: https://randomnerdtutorials.com/installing-the-esp32-board-in-arduino-ide-windows-instructions/
Download the ESP32-BLE-Keyboard-master.zip Arduino zip library from my files listed below (this is a slightly modified version of the original library that fixes potential compile issues). You can try the built in library, but you may encouter build issues.
In the Arduino IDE, go to the Sketch menu and select Include Library then select Add ZIP Library... Select the zip file you downloaded in the previous step.
Either download and open the GarethBluetoothPageFlip.ino file into Arduino, or copy and paste in the code further down the page. This code is for a 5 pedal setup and will work fine if you only want to use 2 pedals. You can also adapt the code if you want to add more pedals - you should be able to follow the code!
Plug in your ESP32 board to your PC using a USB cable and select the appropriate Board from the menu in Arduino. These should be recognised automatically if you've followed the steps above. Click on the upload button to load the code from my file in Arduino into your ESP32 board. Unplug the board once done and proceed with the pedal construction!
A simple circuit diagram is shown below for my 5 button pedal setup. By default you power the pedal via the USB port (cut a hole in the side of the hammond enclosure for the USB port and use a glue gun to attach the board in place, making sure you avoid shorting the board if using a metal case, with the USB port in the hole).
The ESP32 should not be powered by a 9V guitar power supply unless you take steps to reduce this voltage first using a 9V to 5V step down voltage circuit inline. Running without this could cause the ESP32 board to overheat as it tries to regulate the excess voltage by converting to heat.
I later added a rechargeable 3.7V Li-Po battery along with a charging circuit and voltage booster circuit to convert to a stable 5V output. I then positioned the USB input for the charging circuit into the hole in the hammond enclosure and also added an on/off switch inline with the battery output from the charge circuit and the boost circuit input (battery should not be charged and discharged simultaneously). Alternatively, use a cheap USB power bank to plug in and power your pedal.
The code in GarethBluetoothPageFlip.ino file
// The libraries used
#include <BleKeyboard.h>
extern "C" esp_err_t esp_wifi_stop(void);
#include <esp_bt.h>
// The button information that can be changed
// Each array should have the same number of entries
// The first array is the pins to use for the footswitch controls
// I have this code set up to use up to 5 switches on a foot pedal (you can use less)
const int buttonPins[] = {12, // 1
14, // 2
27, // 3
26, // 4
25}; // 5
// The next array is the keycode that is sent when each footswitch/pin above is pressed
const int keyCodes[] = {KEY_LEFT_ARROW, // 1
KEY_RIGHT_ARROW, // 2
KEY_UP_ARROW, // 3
KEY_DOWN_ARROW, // 4
KEY_HOME}; // 5
// Finally the default button state when starting - each should be BUTTON_RELEASED
int buttonStates[buttonCount] = {BUTTON_RELEASED, // 1
BUTTON_RELEASED, // 2
BUTTON_RELEASED, // 3
BUTTON_RELEASED, // 4
BUTTON_RELEASED}; // 5
// You shouldn't need to change any of the code below unless you want to change how the pedal functions
bool debug = false;
#define DBG(...) if (debug) Serial.printf(__VA_ARGS__)
// The state for on/off as high/low states
constexpr int LED_ON = HIGH;
constexpr int LED_OFF = LOW;
// Buttons pulled-up, so LOW means pressed
constexpr int BUTTON_PRESSED = LOW;
constexpr int BUTTON_RELEASED = HIGH;
int connectedLEDState = LED_OFF;
// Check the array sizes match
constexpr size_t buttonCount = sizeof(buttonPins) / sizeof(buttonPins[0]);
constexpr size_t keyCount = sizeof(keyCodes) / sizeof(keyCodes[0]);
static_assert(buttonCount == keyCount, "Mismatch between buttonPins and keyCodes");
// The pins to use for the LEDs
constexpr int pinLEDPress = 33;
constexpr int pinLEDConnected = 32;
// The timings for flashes (when paired/not paired)
unsigned long previousMillis = 0;
const long notConnectedInterval = 500;
const long connectedInterval = 5000;
const long ledOnInterval = 50;
// The settings for registering and flashing when buttons are pressed
bool pressLEDActive = false;
unsigned long pressLEDMillis = 0;
constexpr unsigned long pressLEDDuration = 100; // milliseconds
// Debounce tries to avoid flickers/multiple commands rapidly due to intermittent connections
unsigned long lastDebounceTime[buttonCount] = {0};
constexpr unsigned long debounceDelay = 20;
// Define the starting device name, manufacturer and initial battery charge
BleKeyboard bleKeyboard("PageFlip", "OpenSongApp", 100);
// Setup code initialises all of the settings for the pedal
void setup() {
// Start the system and log this
Serial.begin(115200);
Serial.println("PageFlip Pedal starting...");
Serial.flush();
// Turn of WiFi for power optimisation
esp_wifi_stop();
// Set the mode of the led pins as outputs
pinMode(pinLEDPress, OUTPUT);
pinMode(pinLEDConnected, OUTPUT);
// For each button pin, initialise it as a input_pullup
for (size_t i = 0; i < buttonCount; i++) {
pinMode(buttonPins[i], INPUT_PULLUP);
}
// Start with the LEDs off
digitalWrite(pinLEDPress, LED_OFF);
digitalWrite(pinLEDConnected, connectedLEDState);
// Use maximum Bluetooth power (better range).
// If range isn't an issue, you can lower to ESP_PWR_LVL_P3 or ESP_PWR_LVL_DEFAULT
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT, ESP_PWR_LVL_P9);
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, ESP_PWR_LVL_P9);
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_SCAN, ESP_PWR_LVL_P9);
// Start the keyboard function and wait for a short period for initialisation
bleKeyboard.begin();
delay(100);
}
// This next part is the code that constantly runs in the background
void loop() {
// The lastButtonState is part of the debounce check
static int lastButtonState[buttonCount] = {BUTTON_RELEASED};
// Go through the buttons and see if any have changed state on/off and haven't been a debouce
for (size_t i = 0; i < buttonCount; i++) {
int currentState = digitalRead(buttonPins[i]);
if (currentState != lastButtonState[i]) {
if ((millis() - lastDebounceTime[i]) > debounceDelay) {
lastDebounceTime[i] = millis();
lastButtonState[i] = currentState;
// If a button was pressed, send the matching keycode as a keydown event
if (currentState == BUTTON_PRESSED) {
DBG("\nButton %d pressed", i + 1);
sendKey(keyCodes[i], true);
// Otherwise, send the matching keycode as a keyup event
} else {
DBG("\nButton %d released", i + 1);
sendKey(keyCodes[i], false);
triggerPressLED();
}
}
}
}
// Update the led press to off and check the connected led pulse
updatePressLED();
connectedLEDPulse();
}
// Pulse the led to show it isn't paired (fast), or is connected (slow with quick flash)
void connectedLEDPulse() {
unsigned long currentMillis = millis();
int interval;
if (bleKeyboard.isConnected()) {
interval = (connectedLEDState == LED_ON) ? ledOnInterval : connectedInterval;
} else {
interval = notConnectedInterval;
}
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
connectedLEDState = (connectedLEDState == LED_ON) ? LED_OFF : LED_ON;
digitalWrite(pinLEDConnected, connectedLEDState);
}
}
// Switch the button pressed led on
void triggerPressLED() {
digitalWrite(pinLEDPress, LED_ON);
pressLEDActive = true;
pressLEDMillis = millis();
}
// Turn off the button pressed led after a pause
void updatePressLED() {
if (pressLEDActive && (millis() - pressLEDMillis >= pressLEDDuration)) {
digitalWrite(pinLEDPress, LED_OFF);
pressLEDActive = false;
}
}
// Send the keycode and keyup/keydown via Bluetooth
void sendKey(int keyCode, bool keyDown) {
if (bleKeyboard.isConnected()) {
if (keyDown) {
bleKeyboard.press(keyCode);
} else {
bleKeyboard.release(keyCode);
}
}
}
Some other user submitted pedals: