Arduino: Simple MIDI footswitch
I just wanted to share my code for the simple MIDI footswitch I made for live looping. The buttons are all connected like this: http://www.arduino.cc/en/Tutorial/button, and they all send normal midi note on / off commands. The midi out port is connected like this: http://www.roguescience.org/wordpress/building-a-midi-out-controller/part-7-add-a-midi-port/exercise-13/.
You will need the MIDI library and the Bounce library for this code to compile. EDIT: Use the new version of the code and skip the Bounce library.
The footswitch I made has five buttons, but you can easily modify the code for more or fewer buttons. The only things you need to change is the NUMBUTTONS define and the array with midi notes (int note[NUMBUTTONS] = {24,26,28,25,27};). You can also change the midi channel, by changing the MIDICHANNEL define.
Here is the code, short and simple:
/* Simple MIDI footswitch 1.0 by Mikael Norrgard 2012 <http://www.witchmastercreations.com> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <Bounce.h> #include <MIDI.h> #define BUTTON1 2 // The pin for first button #define NUMBUTTONS 5 // The number of buttons #define MIDICHANNEL 11 // The midi channel to use // For the for-loops byte i=0; // Define arrays Bounce *bouncer; // pointer to bouncer objects byte value[NUMBUTTONS]; // keeping track of the current pin values byte previousValue[NUMBUTTONS]; // keeping track of the previous pin values int note[NUMBUTTONS] = {24,26,28,25,27}; // the array for the midi notes to send, in my case C0, D0, E0, C#0, Eb0 void setup() { // Allocate memory for the bouncer objects bouncer = (Bounce *) malloc(sizeof(Bounce) * NUMBUTTONS); for(i=0;i<NUMBUTTONS;i++) { // Instantiate five Bounce objects with a 5 millisecond debounce time bouncer[i] = Bounce( BUTTON1+i,5 ); // Initiate the values value[i] = LOW; previousValue[i] = LOW; // Set input pins pinMode(BUTTON1+i,INPUT); } //initialize MIDI MIDI.begin(MIDICHANNEL); } void loop() { // Cycle through all inputs for(i=0;i<NUMBUTTONS;i++) { // Update the bouncer object bouncer[i].update(); // Read the current pin-values value[i] = bouncer[i].read(); // Has the value changed, in other words, has the button been pressed or released? if(value[i] != previousValue[i]) { // If button has become pressed, send a midi note on message if(value[i] == HIGH) { MIDI.sendNoteOn(note[i], 127, MIDICHANNEL); // Send note on } // Otherwise, send a note off message else { MIDI.sendNoteOff(note[i], 0, MIDICHANNEL); // Send note off } // Pause for 300ms (this is to further help with button bounces, my buttons are VERY bouncy. // This delay does not hurt the function in my case, since the latency for pushing a button is still very short delay(300); // Set the previous pin state to the current one for next check previousValue[i] = value[i]; } } }
Below is the updated source for 7 buttons (you can easlily modify the code for more buttons). This version does not use the bounce library and uses direct port manipulation for the buttons.
/* Hiduino ProductID: 0x2050 Hiduino Name: DaemonPedal Simple MIDI footswitch 2.0 by Mikael Norrgard 2015 http://www.witchmastercreations.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. BUTTON CONNECTIONS --------------------------- Connect one lead of each button to the input pin and one lead to ground, simple. This code assume buttons on pins 2-8. */ #include <MIDI.h> #define BUTTON1 2 // The pin for first button #define NUMBUTTONS 7 // The number of buttons #define MIDICHANNEL 15 // The midi channel to use #define LATENCY 50 // The latency #define DEBOUNCE_TIME 100 #define BUTTON_PRESSED 0 // Define arrays int note[NUMBUTTONS] = {36,37,38,39,40,41,42};// The array for the midi notes to send byte button_state[NUMBUTTONS] = {1, 1, 1, 1, 1, 1, 1}; // Values are 0 when buttons are pressed long button_time_changed[NUMBUTTONS] = {0, 0, 0, 0, 0, 0, 0}; // The time in milliseconds when the button changed status int i; // For loops byte iDigitalRead = 0; // Temporary variable for reading buttons byte iBitValue = 0; // Temporary variable for reading bits from bytes // Timer unsigned long currentTime; // the current "time" variable void setup() { for(int i=BUTTON1;i<BUTTON1+NUMBUTTONS;i++) { pinMode(i, INPUT); digitalWrite(i, HIGH); } //initialize MIDI MIDI.begin(MIDI_CHANNEL_OMNI); //initialize MIDI at all channels MIDI.setThruFilterMode(Full); currentTime = millis(); // reset the timer } void loop() { currentTime = millis(); // get the current "time" // Read input midi MIDI.read(); // Check the first 6 buttons iDigitalRead = PIND; // Pins 0-7 for(i=2;i<=7;i++) { // Bits 2-7 are pins 2-7, the button_state array is offset iBitValue = bitRead(iDigitalRead, i); if(currentTime > (button_time_changed[i-2] + DEBOUNCE_TIME) && iBitValue != button_state[i-2]) { button_state[i-2] = iBitValue; button_time_changed[i-2] = currentTime; if(iBitValue == BUTTON_PRESSED) { // The button has been pressed MIDI.sendNoteOn(note[i-2], 127, MIDICHANNEL); // Send note on } else { MIDI.sendNoteOff(note[i-2], 0, MIDICHANNEL); // Send note off } } } // Check the last button iDigitalRead = PINB; // Pins 8-13 for(i=0;i<=0;i++) {// Bit 0 is pin 8 iBitValue = bitRead(iDigitalRead, i); if(currentTime > (button_time_changed[i+6] + DEBOUNCE_TIME) && iBitValue != button_state[i+6]) { button_state[i+6] = iBitValue; button_time_changed[i+6] = currentTime; if(iBitValue == BUTTON_PRESSED) { // The button has been pressed MIDI.sendNoteOn(note[i+6], 127, MIDICHANNEL); // Send note on } else { MIDI.sendNoteOff(note[i+6], 0, MIDICHANNEL); // Send note off } } } }
Photo from the bottom of the pedal with the bottom cover removed:
25 Responses to Arduino: Simple MIDI footswitch
Leave a Reply Cancel reply
You must be logged in to post a comment.
Donations
As you can see I have no ads on this page. Donations for keeping this site alive are most welcome.
thank you very much ! needed a little help to set this one up
I can’t get it to work, I’m constantly getting the message: ‘MIDI’ was not declared in this scope. I think I installed the libraries correctly so I can’t figure out what goes wrong. Got any idea?
I’m sorry for the late reply, did you get it working already perhaps?
Hi, good job ! I’ll start to make ! The physical interface looks pretty cool and solid. Could you please explain the way you assemblied it ? It seems it is wood made but it’s hard to figure out where are electronics, arduino and connectors on your photography ..
I uploaded an image to the post taken from the bottom of the pedal with the bottom cover removed. It’s made from wood yes all the pieces are glued except the bottom cover, the Arduino is fastened using hot glue in three spots (seems to be enough).
I have since this updated the code for the pedal to be more responsive and not needing the bounce library. You can also connect the buttons in a simpler way than the way I suggested, by connecting one wire from the buttons to ground and one wire to the input pin, you then enable the internal pull-up resistor of the the input pins and the buttons will be active low. By connecting the buttons like this there is no need for any external resistors.
Brilliant work! Nice looking enclosure to. Any chance of the updated code?
Thanks
Thanks! The updated code is now found underneath the old code, it’s much more efficient. Like I mentioned earlier I made it USB MIDI compatible so I can connect it directly to a USB port on the computer, works perfectly! 🙂
Can’t thank you enough! works fantastic and no need for the resistors!
I had to add “MIDI_CREATE_DEFAULT_INSTANCE();”
and had to change “MIDI.setThruFilterMode(Full);” to MIDI.setThruFilterMode(midi::Full);
I’ll try and do the USB Midi next.
thanks again this is brilliant 🙂
Cool! Flashing the Serial to USB chip on the Arduino is quite straightforward when you have the correct (cheap) tools. 🙂
I have also made my pedal a usb compatible midi device.
Thank you for the picture ! About the usb compatible pedal you’re talking about, is it this one ? You means the code allows now to use the usb port of the arduino for the midi communication ?
It’s this one but to enable midi communication over usb you need to flash the usb-serial chip of the Arduino with HIDUINO. See here for more about that: https://github.com/ddiakopoulos/hiduino
Great ! Thank you !
Hi there i’m having issues verifying this sketch I get the following errors,
sketch_nov11d.ino: In function ‘void setup()’:
sketch_nov11d:45: error: no matching function for call to ‘Bounce::Bounce(int, int)’
/Users/bigmac/Documents/Arduino/libraries/Bounce2/Bounce2.h:46: note: candidates are: Bounce::Bounce()
/Users/bigmac/Documents/Arduino/libraries/Bounce2/Bounce2.h:43: note: Bounce::Bounce(const Bounce&)
sketch_nov11d:56: error: ‘MIDI’ was not declared in this scope
sketch_nov11d.ino: In function ‘void loop()’:
sketch_nov11d:74: error: ‘MIDI’ was not declared in this scope
sketch_nov11d:78: error: ‘MIDI’ was not declared in this scope
I have the Bounce2 and Midi libraries installed on my machine
I was using an older version of the Bounce library, Bounce2 library is a bit different and has other calls. Use the new version of the code and skip the Bounce library altogether.
To make the script work i had to add
MIDI_CREATE_DEFAULT_INSTANCE();
After #include
And change
MIDI.setThruFilterMode(Full);
to
MIDI.setThruFilterMode(midi::Full);
Thanks for letting others know! I don’t remember which version of the MIDI library I used for this, but it’s functionality has changed somewhat since that.
Thanks SOOO much!!
I build a arcade button midi controller with this.
Only having trouble reading beyong button 7… 🙁 i suck 😀
Amazon project!!
Would it be possible to share the schematics?
I would like to make something similar.
Thank you very much!
Sorry but I have 1 more question….
Where are the MIDI notes recorder? Inside Arduino?
Because I can see a button that says “recorder”. And it can recorder MIDI is very interesting for me.
Thank’s again!!!
Pablo
This pedal only sends out MIDI note on/off messages, so the “record” text is just to remember what I use the button for in my DAW.
Hi! Been thinking of recreating this. Does anyone have the code to this project with midi communication over usb only? Need it to use with ableton live. Thanks 🙂
Hi! Awesome. I have been searching for a midi in/out solution for a while. My question, do you have the schematics so I know how everything hooks up together 🙂 Thanks!
The wiring is simple, notes are in the source code.
Can be used with be Behringer Vamp