Only send out value upon change.

Hi guys,

I'm really new to this but have followed a guide thus far and am getting an output (as MIDI message to max).

My problem is that the messages are coming through too fast but simultaneously update very slowly. I need the value to change only when I press or release a button and for this to happen immediately when I do so. I think that it is probably to do with the two 250 delays in the code, however when I changed them the messages came through even faster.

I have 4 switch buttons that I am reading on analog inputs set to digitalread and my code is as follows:

const int buttonOne = 14; // assign button pin to variable
const int buttonTwo = 15; // assign button pin to variable

MIDI_CREATE_INSTANCE(HardwareSerial,Serial, midiOut); // create a MIDI object called midiOut

void setup() {
  pinMode(buttonOne,INPUT); // setup button as input
  pinMode(buttonTwo,INPUT); // setup button as input
  Serial.begin(9600); // setup MIDI output
}

void loop() {
  if(digitalRead(buttonOne) == HIGH) { // check button state
    delay(10); // software de-bounce
    if(digitalRead(buttonOne) == HIGH) { // check button state again
      midiOut.sendControlChange(56,127,1); // send a MIDI CC -- 56 = note, 127 = velocity, 1 = channel
      delay(250); }}
   else if (digitalRead(buttonOne) == LOW) {
    delay(10); // software de-bounce
      midiOut.sendControlChange(56,0,1); // MIDI note off
      delay(250);
  }
  
 
  if(digitalRead(buttonTwo) == HIGH) { // check button state
    delay(10); // software de-bounce
    if(digitalRead(buttonTwo) == HIGH) { // check button state again
      midiOut.sendControlChange(42,127,1); // send a MIDI CC -- 42 = note, 127 = velocity, 1 = channel
      delay(250); }}
   else if (digitalRead(buttonOne) == LOW) {
    delay(10); // software de-bounce
      midiOut.sendControlChange(42,0,1); // MIDI note off
      delay(250);    
  }

Hope you can help!

I suspect you want to look at the state change detection example. Send a message when the switch BECOMES pressed, not when the switch IS pressed (even if that requires holding the switch for 10 milliseconds).

Put EVERY } on a line BY ITSELF.
Put EVERY { on a line BY ITSELF.
Use Tools + Auto Format.
Your code will be a lot more readable.

I'm quite new to this as well, but would like to try to help. What may benefit you is adding in some specific text to each of your conditions. The serial monitor will update at the rate of the delay ms value (I believe) so lowering the 250 value will increase your messages, increasing it will cause it to wait longer to display. Once you set the serial com in your setup I'm not sure there is a way to only update during a change (I''m sure someone smarter than me can confirm), but you can change some of the text that is displayed, may make it easier to know when the specific condition is present, as stated I'm very new as well so not sure if I'm helpful at all.

void loop() {
  if(digitalRead(buttonOne) == HIGH) { // check button state
    delay(10); // software de-bounce
    if(digitalRead(buttonOne) == HIGH) { // check button state again
      midiOut.sendControlChange(56,127,1); // send a MIDI CC -- 56 = note, 127 = velocity, 1 = channel
    Serial.print("\t Specific text to show what condition it is in");
      delay(250); }}
   else if (digitalRead(buttonOne) == LOW) {
    delay(10); // software de-bounce
      midiOut.sendControlChange(56,0,1); // MIDI note off
      delay(250);
  }

That's not a complete program. Which MIDI library are you using? It seems a bit odd sending Control Changes and calling them NoteOn/NoteOff? I normally use sendNoteOn() and sendNoteOff(). Still, if it works for you...

Anyway you could set a flag the first time you send a particular NoteOn message. Unset the flag when you send a NoteOff. If the flag is set don't resend the message.

Or even better you could send a message only when the button is first pressed or is first released (i.e. the state of a button changes) rather than all the time the button is pressed down (see the StateChangeDetection example sketch in the IDE).

Steve

  static bool noteIsAlreadyOn = false;
  if(buttonIsPressed()) {
    if(noteIsAlreadyOn) {
      //Do nothing different
    } else {
      noteIsAlreadyOn = true;
      noteOn();
    }
  } else {
    //button is not currently pressed
    if(noteIsAlreadyOn) {
      noteIsAlreadyOn = false;
      noteOff();
    } else {
      //Do nothing different
    }

Hey guys thanks for the help!

I did indeed find my solution from looking at the state change example and using this to trigger the MIDI out messages. I am using the FortySevenEffects MIDI library. Hmm yeah Steve I'll rename it to imply CC instead.

My next venture will be how to send this through bluetooth with minimal latency. Think BLE should be below about 20ms or thereabouts.