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:

footswitch_bottom

Tagged with:
 

24 Responses to Arduino: Simple MIDI footswitch

  1. Daniel says:

    thank you very much ! needed a little help to set this one up

  2. Floris says:

    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?

  3. internetact says:

    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 ..

    • Mick says:

      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.

      • Andy says:

        Brilliant work! Nice looking enclosure to. Any chance of the updated code?
        Thanks

        • Mick says:

          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! 🙂

          • Andy says:

            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 🙂

    • Mick says:

      I have also made my pedal a usb compatible midi device.

  4. Mark says:

    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

    • Mick says:

      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.

  5. Etienne says:

    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);

    • Mick says:

      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.

  6. David says:

    Thanks SOOO much!!
    I build a arcade button midi controller with this.
    Only having trouble reading beyong button 7… 🙁 i suck 😀

  7. Pablo says:

    Amazon project!!

    Would it be possible to share the schematics?
    I would like to make something similar.

    Thank you very much!

  8. Pablo says:

    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

    • Mick says:

      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.

  9. Uzair Ahmad says:

    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 🙂

  10. Shay says:

    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!

Leave a Reply to Daniel Cancel reply

Your email address will not be published.

The annoying part... * Time limit is exhausted. Please reload the CAPTCHA.