Programming a switch to send midi note ...

Hi All,

I am very new to this and what I am trying to do is probably very simple but I'm stuck at the first hurdle. Basically I want to use some old keyboard foot pedals to send midi notes. I want to keep it simple as possible with no matrix just one switch per input as I have a Mega which has loads of inputs and only need one and a half octaves worth of switches.

I've tried to work out through the examples how to do this starting with just one switch and have come up with something that works... but not how I expect it too..... the code I've borrowed and cobbled together from two places is as follows....

// constants won't change. They're used here to
// set pin numbers:
const int buttonPin = 2;     // the number of the pushbutton digital input pin
// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status
void setup() {
   // initialize the pushbutton pin as an input:
 pinMode(buttonPin, INPUT);
 //  Set MIDI baud rate for MIDI comunication:
Serial.begin(31250);
}
void loop() {
 // read the state of the pushbutton value:
 buttonState = digitalRead(buttonPin);
 // check if the pushbutton is pressed.
 // if it is, the buttonState is HIGH:
 if (buttonState == HIGH) {
   //Note on channel 1 (0x90), chosen note value, middle velocity (0x45):
  noteOn(0x90, 0x5A, 0x45);
  delay(1000);
 } else {
   //Note on channel 1 (0x90), chosen note value, silent velocity (0x45):
 noteOn(0x90, 0x5A, 0x00);
  //delay(1000);
 }
}
//  plays a MIDI note.  Doesn't check to see that
//  cmd is greater than 127, or that data values are  less than 127:
void noteOn(int cmd, int pitch, int velocity) {
Serial.write(cmd);
Serial.write(pitch);
Serial.write(velocity);
}

I thought this would code would play a note if the switch was made continuously and then turn it off (or at least send a zero velocity message) when the switch was open but what happens is when I make contact with the switch two short notes play and then nothing. The delay seems to change the time between notes.

I didn't see any any reason for the "delay" but when I removed it I would get a squealing noise so have put it back in.

If anyone could explain what I am doing wrong, and particularly why I get two single notes playing and not one continuos one I would be very grateful ..... then I presume all i need to do is repeat the code for every switch (button) pressed and hey presto.... although I'm sure before that I need to read the debounce tutorial to

Many thanks

A few things that may help:

  • Please post using code tags. These are the </> tags at the top left of the edit box. Also see the sticky on how to post. You can edit your previous post to correct this.

  • You need to detect the change of state of the switch. You want to send a message when the switch transitions from OFF to ON and from ON to OFF. If you only check the level then you will send messages continuously. There is a StateChange example in the IDE to look at on how this works.

  • If you want to handle more than one switch then at some point you will need to get rid of the delay() in your code and use the same techniques as the BlinkWithoutDelay example to keep track of time. When you get to this learning about arrays of variable will also make your life much easier.

Thank you for the pointers, I have amended original post so code is in a box and will now investigate the other examples you suggested.

I do understand the principal of arrays so will also look into how to use one in my project when I get passed making one switch work.

Thanks again, hopefully I can now find the answers

Hello again, I've tried to use state change detection but now my sketch won't compile. I've been looking at it for ages now and read through a few other peoples posts but can't seem to find an answer that works.

It says "noteOn was not declared in this scope" which I don't understand as it worked perfectly in my previous version.....

Sorry if I'm a bit new and possibly trying to run before I can walk but I thought it would be a fairly simple project. Any clues or hints where to look to solve this would be appreciated

/*
  State change detection (edge detection) used to send MIDI note information

*/

// set pin number:

const int  switchPin = 2;    // the pin that the pushswitch is attached to

// Variables will change:

int switchState = 0;         // current state of the switch
int lastswitchState = 0;     // previous state of the switch

void setup() {
  // initialize the switch pin as a input:
  pinMode(switchPin, INPUT);

  //  Set MIDI baud rate for MIDI comunication:
  Serial.begin(31250);

}


void loop() {
  // read the pushswitch input pin:


  switchState = digitalRead(switchPin);

  // compare the switchState to its previous state
  // and check to see if switch is pressed

  if (switchState != lastswitchState) {

    if (switchState == HIGH) {
      // if the current state is HIGH then the button
      // went from off to on:

      //Play Note on channel 1 (0x90), chosen note value,  middle velocity (0x45):

      noteOn(0x90, 0x5A, 0x90);

    } else {

      // if the current state is LOW then the switch went from on to off
      //Play note on channel 1 (0x90), chosen note value, silent velocity (0xoo):

      noteOn(0x90, 0x5A, 0x00);

      // Delay a little bit to avoid bouncing
      delay(50);

    }


    // save the current state as the last state,
    //for next time through the loop

    lastswitchState = switchState;

    //  plays a MIDI note.  Does't check to see that
    //  cmd is greater than 127, or that data values are  less than 127:n


    void noteOn(int cmd, int pitch, int velocity) {
      Serial.write(cmd);
      Serial.write(pitch);
      Serial.write(velocity);

    }
  }

}

Your braces are mismatched and note on is actually part of the loop function.

Thank you again, that problem is now solved and sketch now compiles, however it doesn't seem to play any notes now.

To check my hardware I've tried loading the StateChangeDetection sketch and that works so my switch is OK and I ran my previous working (but badly) midi sketch and that still plays two notes so My midi connections are also OK. Therefore this is a software problem (no surprise there)

Your previous advice has helped me think for myself, and so far has worked so I would be very grateful if you could again give me a hint as to the direction to look in to resolve my lack of output. Many thanks in advance!

My latest attempt is below.

/*
  State change detection (edge detection) used to send MIDI note information

*/

// set pin number:

const int  switchPin = 2;    // the pin that the pushswitch is attached to

// Variables will change:

int switchState = 0;         // current state of the switch
int lastswitchState = 0;     // previous state of the switch

void setup() {
  // initialize the switch pin as a input:
  pinMode(switchPin, INPUT);

  //  Set MIDI baud rate for MIDI comunication:
  Serial.begin(31250);}

void loop() 
{
    switchState = digitalRead(switchPin);

    if (switchState != lastswitchState) // compare the buttonState to its previous state
   {
      if (switchState == HIGH)          // if the state has changed, play a note
     {
         noteOn(0x90, 52, 0x90);        //Note on channel 1 (0x90), any note value, velocity (0x90):
     }
     else                               // if the current state is LOW then the button
                                        // went from on to off so play note with no velocity (volume)
          {
            noteOn(0x90, 52, 0x00);{    //Note on channel 1 (0x90), any note value, silent velocity (0x00):
            delay(50);}                 // Delay a little bit to avoid bouncing
           }

    lastswitchState = switchState;      // save the current state as the last state,
    }                                    //for next time through the loop
   
}

    void noteOn(int cmd, int pitch, int velocity) 
   {
      Serial.write(cmd);
      Serial.write(pitch);
      Serial.write(velocity);
   }

I may have sorted this one out myself so please do not worry about replying to the above.

I think my hex value for the note velocity was wrong. I've discovered I don't need to use hex so have replaced the note and velocity values with decimal numbers, setting velocity at 127 which are easier to understand and I am now getting a note. I'm not sure if it is sustaining for the whole time the switch is mad, which is what I will need eventually, so I will have to locate a different sound on the module to check this.

I'm also getting some bounce problems even with the "delay" so I think next is to read up about how to cure that before moving on to the array suggestion above for multiple switches.

Hi again,

I've been trying to work this out for my self and tried various things with this but can't make it perform as I want. At the moment it plays a note through my synth for about 1 seconds then stops.

What I'm trying to achieve and can't see why its not working is for the note to play for as long as the switch is on and only turn off when the switch is off.

I would really appreciate it if someone could explain why this doesn't perform the way I expected and point me in the direction of a solution, baring in mind I am still incredibly inexperienced.

Many thanks

My Code is as follows

/*
  State change detection (edge detection) used to send MIDI note information

*/

// set pin number:

const int  switchPin = 2;    // the pin that the pushswitch is attached to

// Variables will change:

int switchState = 0;         // current state of the switch
int lastswitchState = 0;     // previous state of the switch
int bouncedelay = 0;
void setup() {
  // initialize the switch pin as a input:
  pinMode(switchPin, INPUT);

  //  Set MIDI baud rate for MIDI comunication:
  Serial.begin(31250);}

void loop() 
{
    switchState = digitalRead(switchPin);

    if (switchState != lastswitchState) // compare the buttonState to its previous state
   {
      if (switchState == HIGH)          // if the state has changed, play a note
     {
         noteOn(144, 48, 127); {
           delay(bouncedelay);}  //Note on channel 1 (0x90 or 144), any note value, velocity (0x90):
         }
     }
     else                               // if the current state is LOW then the button
           {                             // went from on to off so play note with no velocity (volume)
          {
            noteOn(144, 48, 0);{    //Note on channel 1, note value (48 being C2), silent velocity (0x00):
          delay(bouncedelay);}                 // Delay a little bit to avoid bouncing
           }

    lastswitchState = switchState;      // save the current state as the last state,
    }                                    //for next time through the loop
   
}

    void noteOn(int cmd, int pitch, int velocity) 
   {
      Serial.write(cmd);
      Serial.write(pitch);
      Serial.write(velocity);
   }

Is the instrument you are playing one that has a continuous note, like an organ? Something like a piano note will play the note and then decay to silence.

That is a very good question and initially I was using a piano sound so I couldn't tell what was happening so I switched to using a synth with a pad sound which would normally play continuously as long as the key is held, however even with this sound I only seem to get a short burst of the note .

Bouncedelay seems to be zero. Are you actually debouncing the switch?

The other thing I would suggest is tracking when you turn the note on and off. Can do this by tracing the MIDI message if you are using a computer MIDI synth or lighting a LED in the noteOn function when you turn a note on and turning it off when you turn it off.

I have a small digital switch library on my libraries site (link below) that you can use to quickly debounce the switch, or just find another library in the Arduino site.

Hi, I have been trying the Bouncedelay at various different timings and must've set it to zero on the last trial to turn it off to see what effect this had.

I have now made some progress and I am now wondering if I have some hardware issue as I have tried this sketch again tonight (after four days of it not working) and it is has begun to behave as expected.

I am confused to say the least, but pleased also that I was doing things right. I think I will make up a more sturdy circuit to test with and possibly try a different USB/midi cable for input to the softsynth to eliminate more possible errors or at least possible hardware errors.

I like the idea of adding an LED as a visual help and maybe will do this tomorrow as it is now very late here and thank you for the link to your switch library, I will also look at this tomorrow.

I've only issue I've had now is that occasionally it seems I can confuse the loop and the switch will start to work in reverse i.e. note plays when switch is not made and turns off when made!

I've been trying to replicate this scenario now for some time to see if I can figure out why this happens but unfortunately even though it happened three times earlier now it won't do it, which is good news in some ways but not if it occurs in my finished project so will keep testing.

But for now at least I am working as expected.

Sounds like switch bounce.

GrahamTriggs:
I am confused to say the least, but pleased also that I was doing things right. I think I will make up a more sturdy circuit to test with and possibly try a different USB/midi cable for input to the softsynth to eliminate more possible errors or at least possible hardware errors.

All good but I just gotta ask. Why do you send a noteon message with a velocity of zero to silence the note. (Does that even work?) Why not send the noteoff message, as the midi specification suggests?

Either way is valid in the midi spec. Sending note on with zero velocity has the advantage of fewer bytes as you can avoid sending the command byte in a stream of messages.

Thanks

Back in 1980 something, I helped out a musician acquaintance by writing a bit of assembly code for his Atari ST. He wanted to control some relays from his sequencing software. I remember having to read the Midi message spec but not much more than that.

Oh here I found it. Midi Running Status.

Hi again,

I'm trying to progress from one switch to two sending two notes but it doesn't behave as I hoped. I've basically taken the working code for one switch and duplicated it but giving everything numbers relating to the different switches. I know it's not elegant or the best way (clearly as it doesn't work) but I am still learning so taking small steps.

I have looked at Arrays but not worked out how to use them in this instance, but will continue to try once I get my head around this step.

My code follows and I would appreciate it if anyone could help point out the error of my thinking or even show me a better solution to pursue.

Many thanks in advance

/*  State change detection (edge detection) used to send MIDI note information triggered by two switches. 
this is not working as should as notes do not switch off when button released and sometimes swap the notes to the wrong switch
*/

// set pin numbers:

const int  switchPin2 = 2;
const int  switchPin3 = 3;

   // the pin that the pushswitch is attached to

// Variables will change:

int switchState2 = 0;          // current state of the switch2
int lastswitchState2 = 0;     // previous state of the switch2
int switchState3 = 0;          // current state of the switch3
int lastswitchState3 = 0;     // previous state of the switch3

void setup() {
  // initialize the switch pin as a input:
  pinMode(switchPin2, INPUT);
  pinMode(switchPin3, INPUT);

  //  Set MIDI baud rate for MIDI comunication:
  Serial.begin(31250);}

void loop() 
{
    switchState2 = digitalRead(switchPin2);  // looking at sitch on digital pin 2

    if (switchState2 != lastswitchState2) // compare the buttonState to its previous state
   {
      if (switchState2 == HIGH)        // if the state has changed, play a note
     {
       noteOn(0x90, 48, 127);         //Note on channel 1 (0x90), any note value, velocity (0x90):
     }
     else                               // if the current state is LOW then the button
                                        // went from on to off so play note with no velocity (volume)
          {
            noteOn(0x90, 48, 0);{    //Note on channel 1 (0x90), any note value, silent velocity (0x00):
            delay(50);}                 // Delay a little bit to avoid bouncing
           }

    lastswitchState2 = switchState2;      // save the current state as the last state,
    }                                    //for next time through the loop
   
{
    switchState3 = digitalRead(switchPin3);  //  now repaeat everything looking at switch on pin 3

    if (switchState3 != lastswitchState3)       // compare the buttonState to its previous state
   {
      if (switchState3 == HIGH)                     // if the state has changed, play a note
     {
       noteOn(0x90, 49, 127);                      //Note on channel 1 (0x90), any note value, velocity (0x90):
     }
     else                                                      // if the current state is LOW then the button
                                                                 // went from on to off so play note with no velocity (volume)
          {
            noteOn(0x90, 49, 0);{          //Note on channel 1 (0x90), any note value, silent velocity (0x00):
            delay(50);}                         // Delay a little bit to avoid bouncing
           }

    lastswitchState3 = switchState3;      // save the current state as the last state,
    }                                                    //for next time through the loop
   
}
}


    void noteOn(int cmd, int pitch, int velocity) 
   {
      Serial.write(cmd);
      Serial.write(pitch);
      Serial.write(velocity);
   }

The code you posted does something. You seem to have forgotten to say what it actually does.

How are the switches wired?

Sorry , I had put it into the comments at the top of the code, (so I know next time I go back to it) but thats probably not very helpful.

What happens is, the switches each send notes when pressed but the note isn't turned off when the switch is released. Then to further confuse things the switches will play the wrong note, i.e. the note allocated to switch2 will play when switch3 is pressed.

If I comment out the second half of the loop, relating to switch3, it all works normally.

So first problem is how to stop the note playing and second how to keep the correct note to the allocated switch. It's possible one solution will cure both things if I'm lucky.

The switches are wired from + to switch then after switch is split one way to the allocated pin and one to ground via a resistor. As per the pull up examples.

hope that explains things enough.

I now seem to have this working as I expected. Once again I have not changed much so wonder if the problem is hardware related. I've now soldered a little home made shield containing a midi out and two switches to test with and hopefully this will stop loose connections etc. I believe I am getting some problems relating to switch bounce and have already been told to look at a better way to do that, however what I would like to do first is follow an earlier piece of advice and incorporate an array to save some code but I can't see how to do this. ( I am a real novice!) So could anybody give me some pointers on how to use an array to modify the code below. If I could see how to do it for my two switch set up I could then easily work out how to use it for all 16 switches.

I've also attached a log of the midi activity showing the overlaps in case it is useful in any way

As always, many thanks in advance to anyone who can help.

/*  State change detection (edge detection) used to send MIDI note information triggered by two switches. 
 *   this seems to be working fairly well.  The midi monitor seems to report an overlapping note when switch 
 *   pressed but turns off ok and is inaudible.  I presume this is caused by switch bounce so will need to
 *   find a better way to eliminate that.  Apart from that this seems to work correctly most of the time.
*/

// set pin numbers:

const int  switchPin2 = 2;    // the pin that the push switch is attached to
const int  switchPin3 = 3;
const int delaytime = 60;     // the delay time
   

// Variables will change:

int switchState2 = 0;          // current state of the switch2
int lastswitchState2 = 0;     // previous state of the switch2
int switchState3 = 0;          // current state of the switch3
int lastswitchState3 = 0;     // previous state of the switch3

void setup() {
  // initialize the switch pins as a input:
  pinMode(switchPin2, INPUT);
  pinMode(switchPin3, INPUT);

  //  Set MIDI baud rate for MIDI comunication:
  Serial.begin(31250);}

void loop() 
{
    switchState2 = digitalRead(switchPin2);  // looking at sitch on digital pin 2

    if (switchState2 != lastswitchState2)   // compare the buttonState to its previous state
   {
      if (switchState2 == HIGH)               // if the state has changed, play a note
     {
       noteOn(0x90, 48, 127); {               //Note on channel 1 (0x90), any note value, velocity (0x90):
       delay(delaytime);}                         // Delay a little bit to avoid bouncing
           
     }
     else                                               // if the current state is LOW then the button
                                                         // went from on to off so play note with no velocity (volume)
          {
            noteOn(0x90, 48, 0);{    //Note on channel 1 (0x90), any note value, silent velocity (0x00):
            delay(delaytime);}                 // Delay a little bit to avoid bouncing
          }

    lastswitchState2 = switchState2;      // save the current state as the last state,
    }                                                     //for next time through the loop
   
{
    switchState3 = digitalRead(switchPin3);  //  now repeat everything looking at switch on pin 3

    if (switchState3 != lastswitchState3)       // compare the buttonState to its previous state
   {
      if (switchState3 == HIGH)                     // if the state has changed, play a note
     {
       noteOn(0x90, 49, 127);{     //Note on channel 1 (0x90), any note value, velocity (0x90):
       delay(delaytime);}                         // Delay a little bit to avoid bouncing
           
       
     }
     else                                                      // if the current state is LOW then the button
                                                                // went from on to off so play note with no velocity (volume)
          {
            noteOn(0x90, 49, 0);{          //Note on channel 1 (0x90), any note value, silent velocity (0x00):
            delay(delaytime);}                         // Delay a little bit to avoid bouncing
           }

    lastswitchState3 = switchState3;      // save the current state as the last state,
    }                                                    //for next time through the loop
   
}
}


    void noteOn(int cmd, int pitch, int velocity) 
   {
      Serial.write(cmd);
      Serial.write(pitch);
      Serial.write(velocity);
   }

MidiMonitorLog.txt (16.5 KB)