sending message on button *release*

I have working code for a midi foot controller that sends midi note on/off each time you press a switch (and displays a 4 digit 7 segment number)

However, my hardware device requires a “long press” for a specific function, so I need to send the note on immediately but only send the note off when the button is released. I’m still a relative beginner and the coding logic of this is defeating me.

Technically, this only applies for case 0, but I put it outside the switch statement since it wouldn’t hurt the other cases and I thought it might be easier!

Here’s the code so far, which works apart from the highlighted area, which was my best guess. Any help really appreciated

#include <MIDI.h>
#include <midi_Defs.h>
#include <midi_Message.h>
#include <midi_Namespace.h>
#include <midi_Settings.h>
MIDI_CREATE_DEFAULT_INSTANCE();

#include <TM1637Display.h>

uint8_t arse[] = {
  0, 0, 0, 0,
  SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G,    // A
  SEG_E | SEG_G,                                    // r
  SEG_A | SEG_C | SEG_D | SEG_F | SEG_G,            // s
  SEG_A | SEG_D | SEG_E | SEG_F | SEG_G,    // E
  };
// Constants   
#define SWITCH1 2
#define SWITCH2 3
#define SWITCH3 4
#define SWITCH4 5
#define SWITCH5 6
#define SWITCH6 7
#define SWITCH7 8
#define SWITCH8 9
#define SWITCH9 10
#define SWITCH10 12
#define SWITCHES 10    // how many switches?
#define BOUNCEDELAY 200
const int CLK = A0; //Set the CLK pin connection to the display
const int DIO = A1; //Set the DIO pin connection to the display
TM1637Display display(CLK, DIO); //set up the 4-Digit Display.
// Variables: 
int notes[SWITCHES] = { 38, 39, 40, 41, 42, 49, 48, 44, 43 };
int switches[SWITCHES] = { SWITCH1, SWITCH2, SWITCH3, SWITCH4, SWITCH5, SWITCH6, SWITCH7, SWITCH8, SWITCH9, SWITCH10 };
int switchState[SWITCHES] = { HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH  };   // Initial state of switch is high due to internal pullup
int currentSwitch = 0;
int delayStatus = 0;
int bank = 0;  // initial bank
int numbanks = 2; // how many banks?

void setup() 
{
MIDI.begin(1);  // start serial with midi baudrate 31250 or 38400 for debugging
Serial.begin(31250);        
  Serial.flush();    
//  Serial.begin(9600);      // for serial monitor:    
  display.setBrightness(0x0a); //set the diplay to maximum brightness
  for (int i=0; i<5; i++)   // show "welcome" message
    {  
    display.setSegments(arse+i);
    delay(1000); 
    }
  uint8_t data[] = {0x0, 0x0, 0x0, 0x0}; 
  display.setSegments(data);   // blank the display

  for( currentSwitch = 0; currentSwitch < SWITCHES; currentSwitch++ )   // Setup Switches 
      {
      pinMode( switches[currentSwitch], INPUT );          // Set pin for switch
      digitalWrite( switches[currentSwitch], HIGH );      // Turn on internal pullup
      }  
}

void loop() 
{
display.showNumberDec(bank,false,1,0);  
for( currentSwitch = 0; currentSwitch < SWITCHES; currentSwitch++ )  // check each switch
  {
  if ( (digitalRead(switches[currentSwitch]) != switchState[currentSwitch] ) && (switchState[currentSwitch] == HIGH) )    // switch has changed
     {  
      MIDI.sendNoteOn(notes[currentSwitch],127,1);  // Send a Note 
 
// this is the part that doesn't work
//~~~~~~~~~~~~~~~
      if (  (digitalRead(switches[currentSwitch]) != switchState[currentSwitch] ) && (switchState[currentSwitch] == LOW) )  // button was released since last checked
        {
        MIDI.sendNoteOff(notes[currentSwitch],0,1);   // Stop the note       
        }
//~~~~~~~~~~~~~~~      
 
      switch( currentSwitch ) 
      {
      case 0:     // 
        display.showNumberDec(0,false,1,2);   // record 38
        display.showNumberDec(1,false,1,3);           
        break;
      case 1:      // 
        display.showNumberDec(0,false,1,2);   // overdub 39
        display.showNumberDec(2,false,1,3);           
        break;
      case 2:    // 
        display.showNumberDec(0,false,1,2);   // multiply 40
        display.showNumberDec(3,false,1,3);           
        break;
      case 3:      //      
        display.showNumberDec(0,false,1,2);   // insert 41
        display.showNumberDec(4,false,1,3);           
        break;        
      case 4:      //      
        display.showNumberDec(0,false,1,2);   // mute 42
        display.showNumberDec(5,false,1,3);         
        break;   
      case 5:      //      
        display.showNumberDec(0,false,1,2);  // rev 49
        display.showNumberDec(6,false,1,3);        
        break;  
      case 6:      //      
        display.showNumberDec(0,false,1,2);    // speed   48
        display.showNumberDec(7,false,1,3);         
        break;        
      case 7:      //      
        display.showNumberDec(0,false,1,2);  // next 44
        display.showNumberDec(8,false,1,3);         
        break;        
      case 8:      //      
        display.showNumberDec(0,false,1,2);    // undo 43
        display.showNumberDec(9,false,1,3);         
        break;        
      case 9:      //      
        bank ++;
        if (bank > numbanks) (bank = 0); 
        break;        
      }
      delay( BOUNCEDELAY );
    }    // end if switch has changed
    switchState[currentSwitch] = digitalRead( switches[currentSwitch] );
  }    // end check all switches
}     // end void loop

It appears that your code for detecting the switch-released is inside the if() which detected that it was pressed. It cannot be both pressed and released at the same time.

Move that code so that it is always checked on every iteration of loop().

I moved the code to just above the final line

} // end void loop

Is that what you meant? It didn't work, sadly ;(

No, not to the end of the loop(), but out the if() that checks if it IS pressed.

Or, if you want really easy, grab a library like Bounce2.

septillion:
No, not to the end of the loop(), but out the if() that checks if it IS pressed.

Or, if you want really easy, grab a library like Bounce2.

ALWAYS easy! Will look into that.

However, outside the "if pressed loop", it has to be after is pressed, so the only other place would be before or after the

switchState[currentSwitch] = digitalRead( switches[currentSwitch] );

line 123 ??

Thanks for your help :wink:

Before that line.

Wow, got it working. Many thanks!