Midification of Pedalboard Keys – Reed Switch, usbMidi, Debounce

Hi arduino-Istas,

I am on my first code programming roller coaster ride, trying to midify my organ pedalbaord.
I use normally-open reed switches, a teensy 3.5, the Arduino IDE with teensy add on and as midi software to link the Microcontroller-Input to my laptop's speakers I use MIDI-OX.

I spent couple of days watching tutorials, trying to understand suitable Arduino C++ coding examples, which worked out preatty well and now I am about to successfully fail in trying to adapt them to my needs.

It feels like it should be such a short and straightforward simple code, since it just needs to do the following:

• constantly reading the digital input pins, that are connected to normally open reed switches;

• Once a reed switch is being detected to be closed,

  • Switch Debouncing should prevent “bouncing” over 5ms
  • A usbMidisendNoteOn command should make a to a laptop connected speaker to sound a specific note, at a specific velocity/loudness, on a specific midi output channel
  • The onboard led should switch on

• Once this reed switch is being detected to be opened,

  • Switch Debouncing should prevent “bouncing” over 5ms
  • A usbMidisendNoteOff command should make a to the laptop connected speaker to stop sounding this note
  • The onboard led should switch off

That's it. Here is my attempt.
I checked the midi software, the hardware setup works, too... but with this following code I just get the proper Led reaction, but the note is missing...

const int REED_PIN = 2; // Pin connected to reed switch
const int LED_PIN = 13; // LED pin - active-high

void setup() {
  pinMode(REED_PIN, INPUT_PULLUP);
  pinMode(LED_PIN, OUTPUT);
}

void loop() {
  int proximity = digitalRead(REED_PIN); // Read the state of the switch
  if (proximity == LOW) // If the pin reads low, the switch is closed.
  {
    usbMIDI.sendNoteOn(36, 99, 1);  // 60 = C4
    digitalWrite(LED_PIN, HIGH); // Turn the LED on
  }
  else {
    usbMIDI.sendNoteOff(36, 0, 1);  // 60 = C4
    digitalWrite(LED_PIN, LOW); // Turn the LED off
  }
}

I would be really glad if you guys could tell me, what I am doing wrong here and point me in the right direction.

In the code above I deleted the parts with which I tried to debounce the reed switches, cause I concluded, that what I found so far, doesn't work with my reed switch concept.

The one methode I found is about using the bounce.h library. I assume that this library just works with buttons rather than reed switches.

The second much more elaborated coding example by the eeenthusiast (link below), is what I really fancy on using in my project. I like the structure and logic of this piece of code.
blog: Welcome eeenthusiast.com - BlueHost.com
youtube: Ep. 58 - Arduino Advanced Input & Button Control, Debouncing, Counters & Multitasking - YouTube

This second concept, as well uses push buttons and just makes things change after a butten is pushed and released. Furthermore, as debouncing method, you need to push the button for at least 50ms in order to be counted as "button pushed".

In my case (as MorganS rightly pointed out, I am editing), the code needs to react upon the first "closing" of the reed switch, and "instantly" requesting the note to be sounded, while ignoring whatever happens to this switch for the following 5ms.

So I ll continue to tackle eeenthusiast's code, especially the debounce logic and try to make it work for my application.

but in case you guys have any hints or advice, shoot me a message. :slight_smile:

Keep track of the state of the reed switch. When it CHANGES to low, note the time using millis.

If the state is low and millis tells you 5ms have passed, turn the led on & do your midi thing.

Similar thing for a change to high.

Look at the stateChangeDetection example in the IDE.

Most of the debounce tutorials you find online are awful. They just use dumb delays.

For most purposes that is OK. You can't detect that the light went on 5ms after you pushed the button: it appears to be instantaneous.

The same applies to music: two keys pressed 5ms apart sound like a chord and not two notes. However there are other delays in the MIDI system. The command takes time to transmit, to be decoded and executed. So I would start right by not adding any delays.

So how do you do debounce with no delay? Well there must be some time period. Let's say we never want to play a MIDI note shorter than 5ms. (A 200th of a second.) So after first detecting that the switch has moved and sending the MIDI command, we ignore any changes from the switch for the next 5ms.

The Arduino has other important tasks to do during that time such as checking the other switches. So keep the loop running. Just look at your millis() timer the next time the switch changes to see if 5ms has passed.

The teensy bounce library update() calls digitalRead() and keeps track of the state of each switch without using delay(). It is not limited to buttons. In other words, the bounce update() replaces your digitalRead() logic.

@wildbill: thanks for the explenation and advice. I will look up the stateChangeDetection example!

@MorganS: true. There are few things I learned so far about programming, which makes me close all coding examples that use delay() as a command. Cause in my application, the show must go on under any circumstances! 8)
so, the millis() command it is!

@gbafamily: mh ok. So I ll give this method another shot then.

I got my code running using the bounce.h library.
Can anyone tell me, what the defined debounce time (e.g. 10ms) according to this bounce.h library specifically does?

Let's say I push one of my pedalboard keys and keep it pushed down (state goes from open to closed).
Does the software instantaniously react to the first recognized state change (by sounding a note) and ignores all further state changes from this first state change for 10ms?
Or does it take 10ms for the software to accept the state change and then after 10ms sound the note?


I'd like to get the other possible coding solution (the arduino debounce example) running, but I am stuck with the question on how to "lock out" state changes for a given debounce time.

Do you have any advice on what commands to use?

void loop() {
  for (int i = 0; i < numOfKeys; i++) {  // read the switch input pins:
    int reading = digitalRead(keyInputPins[i]);  // compare the buttonState to its previous state
    if (reading != lastButtonState[i]) {  // state has changed

          *insert debounce code? like ""millis() count to 10 while lock out Statechanges"*

      if (reading == LOW) {   // if the current state is LOW then the button went from off to on:
        usbMIDI.sendNoteOn(midiNotes[i], velocity, channel);
        digitalWrite(ledPin, HIGH);
      }
      else {  // if the current state is HIGH then the button went from on to off:
        usbMIDI.sendNoteOff(midiNotes[i], 0, channel);
        digitalWrite(ledPin, LOW);
      }
    }
  lastButtonState[i] = reading;  // save the current state as the last state, for next time through the loop
  }
}

If you are using Bounce2.h here then you can use the "prompt detection" method.

// Uncomment the following line for "BOUNCE_WITH_PROMPT_DETECTION" debounce method
//#define BOUNCE_WITH_PROMPT_DETECTION

I think the "lock out" method will also work for you. You definitely don't want the default "stable interval" method.

I upgraded my bounce-code to bounce2. Thank you for the hint @MorganS.

I totally get the two states "stable interval" and "lock-out interval" that are explained here - GitHub - thomasfredericks/Bounce2: Debouncing library for Arduino and Wiring . But I don't really get, what the "prompt detection" really does...
Could someone briefly explain how the "prompt detection" differs from "stable"- and "lock-out" method?

From the 5 seconds I spent reading it, "prompt" requires the signal to be stable BEFORE the transition. I don't know how it would not be, since the first sign of instability is promptly reported as a change event.