MIDI Guitar Foot Pedal - Sanity check needed (possible issue freezing up DAW)

ntbutler

New member
Hi everyone.

So I've tried to make a 4 switch USBMIDI Guitar foot pedal, which seems to be mostly working, but my music software (Mainstage 3) is freezing up every now and then.

Due mainly to local availability, the foot switches that I bought are toggle switches. This posed a little challenge as I want to use the pedal with Mainstage 3, so if I was to change patches and the virtual pedal state in mainstage switches from off to on, then the physical state of the switch wouldn't match. So I've opted to code the sketch to locally track the virtual state of each switch/midi control. That way, if a patch changes, the sketch should see the Control Change update, then update it's internal state to match. Then on when the physical switch state changes (rising or falling edge), it will toggle that tracked state, then send the MIDI signal. I may also use that in the future to add some status LED's next to each switch, and have them update to match the state of the channel in the DAW.

So that's all basically working, I can use the pedal and toggle 4 virtual foot pedals OK, but I've noticed that Mainstage is beachballing every now and then, particularly if I move between Layout and Edit mode. What I think might be happening is a hangup in the processing of the midi updates that I think are all getting sent when the patch reloads when going into edit mode.

So this is really just asking for a sanity check - have I programmed this horribly, or missed something important (particularly in the handling of the MIDI updates) that might cause Mainstage to hang up? Here's the code:

Code:
/* 3D Printed USB MIDI Guitar Pedal
 *  4 x foot switches
 *  Switches are Toggle, not momentary (push-on, push-off), so state needs to be tracked to match midi reads
 */

#include <Bounce.h>

// the MIDI channel number to send messages
const int MIDIchannel = 15;
const int MIDIhigh = 127;

// internal state trackers of each switch. Start with all switches off
int state_button0 = 0;
int state_button1 = 0;
int state_button2 = 0;
int state_button3 = 0;

// control signal assignments for each switch - designed to match my Mainstage layout
const int control_button0 = 43;
const int control_button1 = 41;
const int control_button2 = 35;
const int control_button3 = 33;


// Create Bounce objects for each button.
Bounce button0 = Bounce(0, 5);
Bounce button1 = Bounce(1, 5);  // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 5);  // which is appropriate for good
Bounce button3 = Bounce(3, 5);  // quality mechanical pushbuttons


void myControlChange(byte channel, byte control, byte value) {
  // Update pedal state to match incoming state changes from DAW (e.g. on change of patch)
  if (channel == MIDIchannel) { //try to filter out any unimportant updates
    switch (control) {
      case control_button0:
        state_button0 = value;
        break;
      case control_button1:
        state_button1 = value;
        break;
      case control_button2:
        state_button2 = value;
        break;
      case control_button3:
        state_button3 = value;
        break;
    }
  }

/*  Serial.print("Control Change, ch=");
  Serial.print(channel, DEC);
  Serial.print(", control=");
  Serial.print(control, DEC);
  Serial.print(", value=");
  Serial.println(value, DEC);
*/
}

void setup() {
  Serial.begin(115200);
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  usbMIDI.setHandleControlChange(myControlChange);
}

void checkButtons() {
  button0.update();
  button1.update();
  button2.update();
  button3.update();

  
  if (button0.fallingEdge() || button0.risingEdge()) {
    //toggle internal switch state tracker, and send MIDI control change
    state_button0 = (127 - state_button0);
    usbMIDI.sendControlChange(control_button0, state_button0, MIDIchannel);
  }
  if (button1.fallingEdge() || button1.risingEdge()) {
    state_button1 = (127 - state_button1);
    usbMIDI.sendControlChange(control_button1, state_button1, MIDIchannel);
  }
  if (button2.fallingEdge() || button2.risingEdge()) {
    state_button2 = (127 - state_button2);
    usbMIDI.sendControlChange(control_button2, state_button2, MIDIchannel);
  }
  if (button3.fallingEdge() || button3.risingEdge()) {
    state_button3 = (127 - state_button3);
    usbMIDI.sendControlChange(control_button3, state_button3, MIDIchannel);
  }
  

}

void loop() {
  // Check to see if foot switches have been changed.
  // If changed, send the MIDI control change
  checkButtons();
  
  // MIDI Controllers should discard incoming MIDI messages.
  // http://forum.pjrc.com/threads/24179-Teensy-3-Ableton-Analog-CC-causes-midi-crash
  while (usbMIDI.read()) {
    // ignore incoming messages
  }
}

Thanks
Nathan
 
have you got a MIDI monitor software? you could check to see if the buttons are bouncing like crazy and sending enough MIDI data to interfere with Mainstage?
 
What I could imagine is that the Teensy is so fast, it recognizes crackle and bounce on the signal lines as separate switching events when the switch is pressed and so sends massive amounts of midi data at high speed.
That could lock up the DAW if more data is sent than it can handle, especially if the data trigger context switching or similar functions.
A solution could be the Bounce2 library.
 
Doesn't appear to be a code problem (I did not compile).


Try much higher bounce times and see if it's better.

If that fixes it try slightly higher than 5 until it's stable.

If it doesn't report back but I'd start thinking hardware connection.

(If you have not soldered your Teensy's header pins you can slink away quitely.)
 
Thanks all for the suggestions. I ran some monitoring for a while and inexplicably couldn't get it freeze up anymore, so at least for now, rock on!
Cheers
Nathan
 
Back
Top