Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 4 of 4

Thread: An action when 2 buttons pressed - MIDI

  1. #1

    An action when 2 buttons pressed - MIDI

    Hello guys !

    I'm building a simple device with buttons that triggers Midi notes.

    I want to add an action to my code : when you press 2 buttons simultaneously, an other note is played. Do you know how to do that ?

    Thanks guys !

    Code:
    /* Buttons to USB MIDI Example
    
       You must select MIDI from the "Tools > USB Type" menu
    
       To view the raw MIDI data on Linux: aseqdump -p "Teensy MIDI"
    
       This example code is in the public domain.
    */
    
    #include <Bounce.h>
    
    // the MIDI channel number to send messages
    const int channel1 = 1;
    
    // Create Bounce objects for each button.  The Bounce object
    // automatically deals with contact chatter or "bounce", and
    // it makes detecting changes very simple.
    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
    Bounce button4 = Bounce(4, 5);
    Bounce button5 = Bounce(5, 5);  // if a button is too "sensitive"
    Bounce button6 = Bounce(6, 5);  // to rapid touch, you can
    Bounce button7 = Bounce(7, 5);  // increase this time.
    Bounce button8 = Bounce(8, 5);
    Bounce button9 = Bounce(9, 5);
    Bounce button10 = Bounce(10, 5);
    Bounce button11 = Bounce(11, 5);
    Bounce button12 = Bounce(12, 5);
    Bounce button13 = Bounce(24, 5);  // 5 = 5 ms debounce time
    Bounce button14 = Bounce(25, 5);  // which is appropriate for good
    Bounce button15 = Bounce(26, 5);  // quality mechanical pushbuttons
    Bounce button16 = Bounce(27, 5);
    Bounce button17 = Bounce(28, 5);  // if a button is too "sensitive"
    Bounce button18 = Bounce(29, 5);  // to rapid touch, you can
    Bounce button19 = Bounce(30, 5);  // increase this time.
    Bounce button20 = Bounce(31, 5);
    Bounce button21 = Bounce(32, 5);
    Bounce button22 = Bounce(33, 5);
    Bounce button23 = Bounce(34, 5);
    Bounce button24 = Bounce(35, 5);
    Bounce button25 = Bounce(36, 5);  // 5 = 5 ms debounce time
    Bounce button26 = Bounce(37, 5);  // which is appropriate for good
    Bounce button27 = Bounce(38, 5);  // quality mechanical pushbuttons
    Bounce button28 = Bounce(39, 5);
    Bounce button29 = Bounce(22, 5);
    Bounce button30 = Bounce(23, 5);  // if a button is too "sensitive"
    Bounce button31 = Bounce(24, 5);  // to rapid touch, you can
    Bounce button32 = Bounce(14, 5);
    Bounce button33 = Bounce(15, 5);
    Bounce button34 = Bounce(16, 5);
    Bounce button35 = Bounce(17, 5);
    Bounce button36 = Bounce(18, 5);
    Bounce button37 = Bounce(19, 5);  // 5 = 5 ms debounce time
    Bounce button38 = Bounce(20, 5);  // which is appropriate for good
    Bounce button39 = Bounce(21, 5);  // quality mechanical pushbuttons
    
    
    void setup() {
    
      
      // Configure the pins for input mode with pullup resistors.
      // The pushbuttons connect from each pin to ground.  When
      // the button is pressed, the pin reads LOW because the button
      // shorts it to ground.  When released, the pin reads HIGH
      // because the pullup resistor connects to +5 volts inside
      // the chip.  LOW for "on", and HIGH for "off" may seem
      // backwards, but using the on-chip pullup resistors is very
      // convenient.  The scheme is called "active low", and it's
      // very commonly used in electronics... so much that the chip
      // has built-in pullup resistors!
      pinMode(0, INPUT_PULLUP);
      pinMode(1, INPUT_PULLUP);
      pinMode(2, INPUT_PULLUP);
      pinMode(3, INPUT_PULLUP);
      pinMode(4, INPUT_PULLUP);
      pinMode(5, INPUT_PULLUP);
      pinMode(6, INPUT_PULLUP);  // Teensy++ 2.0 LED, may need 1k resistor pullup
      pinMode(7, INPUT_PULLUP);
      pinMode(8, INPUT_PULLUP);
      pinMode(9, INPUT_PULLUP);
      pinMode(10, INPUT_PULLUP);
      pinMode(11, INPUT_PULLUP); // Teensy 2.0 LED, may need 1k resistor pullup
      pinMode(12, INPUT_PULLUP);
      pinMode(24, INPUT_PULLUP);
      pinMode(25, INPUT_PULLUP);
      pinMode(26, INPUT_PULLUP);
      pinMode(27, INPUT_PULLUP);
      pinMode(28, INPUT_PULLUP);
      pinMode(29, INPUT_PULLUP);  // Teensy++ 2.0 LED, may need 1k resistor pullup
      pinMode(30, INPUT_PULLUP);
      pinMode(31, INPUT_PULLUP);
      pinMode(32, INPUT_PULLUP);
      pinMode(33, INPUT_PULLUP);
      pinMode(34, INPUT_PULLUP); // Teensy 2.0 LED, may need 1k resistor pullup
      pinMode(35, INPUT_PULLUP);
      pinMode(36, INPUT_PULLUP);
      pinMode(37, INPUT_PULLUP);
      pinMode(38, INPUT_PULLUP);
      pinMode(39, INPUT_PULLUP);
      // pinMode(A21, INPUT_PULLUP);
      // pinMode(A22, INPUT_PULLUP);  // Teensy++ 2.0 LED, may need 1k resistor pullup
      // pinMode(13, INPUT_PULLUP);
      pinMode(14, INPUT_PULLUP);
      pinMode(15, INPUT_PULLUP);
      pinMode(16, INPUT_PULLUP);
      pinMode(17, INPUT_PULLUP); // Teensy 2.0 LED, may need 1k resistor pullup
      pinMode(18, INPUT_PULLUP);
      pinMode(19, INPUT_PULLUP);
      pinMode(20, INPUT_PULLUP);
      pinMode(21, INPUT_PULLUP);
      pinMode(22, INPUT_PULLUP);
      pinMode(23, INPUT_PULLUP);
    
    
    }
    
    
    void loop() {
    
      // Update all the buttons.  There should not be any long
      // delays in loop(), so this runs repetitively at a rate
      // faster than the buttons could be pressed and released.
      button0.update();
      button1.update();
      button2.update();
      button3.update();
      button4.update();
      button5.update();
      button6.update();
      button7.update();
      button8.update();
      button9.update();
      button10.update();
      button11.update();
      button12.update();
      button13.update();
      button14.update();
      button15.update();
      button16.update();
      button17.update();
      button18.update();
      button19.update();
      button20.update();
      button21.update();
      button22.update();
      button23.update();
      button24.update();
      button25.update();
      button26.update();
      button27.update();
      button28.update();
      button29.update();
      button30.update();
      button31.update();
      button32.update();
      button33.update();
      button34.update();
      button35.update();
      button36.update();
      button37.update();
      button38.update();
      button39.update();
    
      // Check each button for "falling" edge.
      // Send a MIDI Note On message when each button presses
      // Update the Joystick buttons only upon changes.
      // falling = high (not pressed - voltage from pullup resistor)
      //           to low (pressed - button connects pin to ground)
      if (button0.fallingEdge()) {
        usbMIDI.sendNoteOn(48, 127, channel1);  // C2
      }
      if (button1.fallingEdge()) {
        usbMIDI.sendNoteOn(49, 127, channel1);  // C#2
      }
      if (button2.fallingEdge()) {
        usbMIDI.sendNoteOn(50, 127, channel1);  // D2
      }
      if (button3.fallingEdge()) {
        usbMIDI.sendNoteOn(51, 127, channel1);  // D#2
      }
      if (button4.fallingEdge()) {
        usbMIDI.sendNoteOn(52, 127, channel1);  // E2
      }
      if (button5.fallingEdge()) {
        usbMIDI.sendNoteOn(53, 127, channel1);  // F2
      }
      if (button6.fallingEdge()) {
        usbMIDI.sendNoteOn(54, 127, channel1);  // F#2
      }
      if (button7.fallingEdge()) {
        usbMIDI.sendNoteOn(55, 127, channel1);  // G2
      }
      if (button8.fallingEdge()) {
        usbMIDI.sendNoteOn(56, 127, channel1);  // G#2
      }
      if (button9.fallingEdge()) {
        usbMIDI.sendNoteOn(57, 127, channel1);  // A2
      }
      if (button10.fallingEdge()) {
        usbMIDI.sendNoteOn(58, 127, channel1);  // A#2
      }
      if (button11.fallingEdge()) {
        usbMIDI.sendNoteOn(59, 127, channel1);  // B2
      }
      if (button12.fallingEdge()) {
        usbMIDI.sendNoteOn(60, 127, channel1);  // C3
      }
      if (button13.fallingEdge()) {
        usbMIDI.sendNoteOn(61, 127, channel1);  // C#3
      }
      if (button14.fallingEdge()) {
        usbMIDI.sendNoteOn(62, 127, channel1);  // D3
      }
      if (button15.fallingEdge()) {
        usbMIDI.sendNoteOn(63, 127, channel1);  // D#3
      }
      if (button16.fallingEdge()) {
        usbMIDI.sendNoteOn(64, 127, channel1);  // E3
      }
      if (button17.fallingEdge()) {
        usbMIDI.sendNoteOn(65, 127, channel1);  // F3
      }
      if (button18.fallingEdge()) {
        usbMIDI.sendNoteOn(66, 127, channel1);  // F#3
      }
      if (button19.fallingEdge()) {
        usbMIDI.sendNoteOn(67, 127, channel1);  // G3
      }
      if (button20.fallingEdge()) {
        usbMIDI.sendNoteOn(68, 127, channel1);  // G#3
      }
      if (button21.fallingEdge()) {
        usbMIDI.sendNoteOn(69, 127, channel1);  // A3
      }
      if (button22.fallingEdge()) {
        usbMIDI.sendNoteOn(70, 127, channel1);  // A#3
      }
      if (button23.fallingEdge()) {
        usbMIDI.sendNoteOn(71, 127, channel1);  // B3
      }
      if (button24.fallingEdge()) {
        usbMIDI.sendNoteOn(72, 127, channel1);  // C4
      }
      if (button25.fallingEdge()) {
        usbMIDI.sendNoteOn(73, 127, channel1);  // C#4
      }
      if (button26.fallingEdge()) {
        usbMIDI.sendNoteOn(74, 127, channel1);  // D4
      }
      if (button27.fallingEdge()) {
        usbMIDI.sendNoteOn(75, 127, channel1);  // D#4
      }
      if (button28.fallingEdge()) {
        usbMIDI.sendNoteOn(76, 127, channel1);  // E4
      }
      if (button39.fallingEdge()) {
        usbMIDI.sendNoteOn(77, 127, channel1);  // D#5
      }
      if (button29.fallingEdge()) {
        usbMIDI.sendNoteOn(78, 127, channel1);  // E5
      }
      if (button30.fallingEdge()) {
        usbMIDI.sendNoteOn(79, 127, channel1);  // F5
      }
      if (button32.fallingEdge()) {
        usbMIDI.sendNoteOn(80, 127, channel1);  // G#4
      }
      if (button33.fallingEdge()) {
        usbMIDI.sendNoteOn(81, 127, channel1);  // A4
      }
      if (button34.fallingEdge()) {
        usbMIDI.sendNoteOn(82, 127, channel1);  // A#5
      }
      if (button35.fallingEdge()) {
        usbMIDI.sendNoteOn(83, 127, channel1);  // B5
      }
      if (button36.fallingEdge()) {
        usbMIDI.sendNoteOn(84, 127, channel1);  // C5
      }
      if (button37.fallingEdge()) {
        usbMIDI.sendNoteOn(85, 127, channel1);  // C#5
      }
      if (button38.fallingEdge()) {
        usbMIDI.sendNoteOn(86, 127, channel1);  // D5
      }
    
    
    
    
    
      // Check each button for "rising" edge
      // Send a MIDI Note Off message when each button releases
      // For many types of projects, you only care when the button
      // is pressed and the release isn't needed.
      // rising = low (pressed - button connects pin to ground)
      //          to high (not pressed - voltage from pullup resistor)
      if (button0.risingEdge()) {
        usbMIDI.sendNoteOff(48, 0, channel1);  
      }
      if (button1.risingEdge()) {
        usbMIDI.sendNoteOff(49, 0, channel1);  
      }
      if (button2.risingEdge()) {
        usbMIDI.sendNoteOff(50, 0, channel1);
      }
      if (button3.risingEdge()) {
        usbMIDI.sendNoteOff(51, 0, channel1);  
      }
      if (button4.risingEdge()) {
        usbMIDI.sendNoteOff(52, 0, channel1);  
      }
      if (button5.risingEdge()) {
        usbMIDI.sendNoteOff(53, 0, channel1);  
      }
      if (button6.risingEdge()) {
        usbMIDI.sendNoteOff(54, 0, channel1); 
      }
      if (button7.risingEdge()) {
        usbMIDI.sendNoteOff(55, 0, channel1);  
      }
      if (button8.risingEdge()) {
        usbMIDI.sendNoteOff(56, 0, channel1);  
      }
      if (button9.risingEdge()) {
        usbMIDI.sendNoteOff(57, 0, channel1);  
      }
      if (button10.risingEdge()) {
        usbMIDI.sendNoteOff(58, 0, channel1);  
      }
      if (button11.risingEdge()) {
        usbMIDI.sendNoteOff(59, 0, channel1);  
      }
      if (button12.risingEdge()) {
        usbMIDI.sendNoteOff(60, 0, channel1);  
      }
      if (button13.risingEdge()) {
        usbMIDI.sendNoteOff(61, 0, channel1);  
      }
      if (button14.risingEdge()) {
        usbMIDI.sendNoteOff(62, 0, channel1);
      }
      if (button15.risingEdge()) {
        usbMIDI.sendNoteOff(63, 0, channel1);  
      }
      if (button16.risingEdge()) {
        usbMIDI.sendNoteOff(64, 0, channel1);  
      }
      if (button17.risingEdge()) {
        usbMIDI.sendNoteOff(65, 0, channel1);  
      }
      if (button18.risingEdge()) {
        usbMIDI.sendNoteOff(66, 0, channel1); 
      }
      if (button19.risingEdge()) {
        usbMIDI.sendNoteOff(67, 0, channel1);  
      }
      if (button20.risingEdge()) {
        usbMIDI.sendNoteOff(68, 0, channel1);  
      }
      if (button21.risingEdge()) {
        usbMIDI.sendNoteOff(69, 0, channel1);  
      }
      if (button22.risingEdge()) {
        usbMIDI.sendNoteOff(70, 0, channel1);  
      }
      if (button23.risingEdge()) {
        usbMIDI.sendNoteOff(71, 0, channel1);  
      }
      if (button24.risingEdge()) {
        usbMIDI.sendNoteOff(72, 0, channel1);  
      }
      if (button25.risingEdge()) {
        usbMIDI.sendNoteOff(73, 0, channel1);  
      }
      if (button26.risingEdge()) {
        usbMIDI.sendNoteOff(74, 0, channel1);
      }
      if (button27.risingEdge()) {
        usbMIDI.sendNoteOff(75, 0, channel1);  
      }
      if (button28.risingEdge()) {
        usbMIDI.sendNoteOff(76, 0, channel1);  
      }
      if (button39.risingEdge()) {
        usbMIDI.sendNoteOff(77, 0, channel1);  
      }
      if (button29.risingEdge()) {
        usbMIDI.sendNoteOff(78, 0, channel1);  
      }
      if (button30.risingEdge()) {
        usbMIDI.sendNoteOff(79, 0, channel1);  
      }
      if (button32.risingEdge()) {
        usbMIDI.sendNoteOff(80, 0, channel1);  
      }
      if (button33.risingEdge()) {
        usbMIDI.sendNoteOff(81, 0, channel1);  
      }
      if (button34.risingEdge()) {
        usbMIDI.sendNoteOff(82, 0, channel1);  
      }
      if (button35.risingEdge()) {
        usbMIDI.sendNoteOff(83, 0, channel1);  
      }
      if (button36.risingEdge()) {
        usbMIDI.sendNoteOff(84, 0, channel1);  
      }
      if (button37.risingEdge()) {
        usbMIDI.sendNoteOff(85, 0, channel1);  
      }
      if (button38.risingEdge()) {
        usbMIDI.sendNoteOff(86, 0, channel1);
      }
    }

  2. #2
    Senior Member
    Join Date
    Apr 2013
    Posts
    1,874
    Several different approches, but one is to go into the two relevant if(button.fallingEdge()) statements and instead of sending the not, set a previously defined (and zeroed)variable to one, say buttonOneDown and ButtonTwoDown

    Then you have if statements, either
    if (buttoneOneDown==1&&ButtonTwoDown==1) usbMIDI.sendNoteOn(XX, 127, channel1);
    else{
    if(buttoneOneDown==1)usbMIDI.sendNoteOn(49, 127, channel1);
    if(buttoneTwoDown==1) usbMIDI.sendNoteOn(50, 127, channel1);
    }
    Or you can
    if (buttoneOneDown==1&&ButtonTwoDown==1) usbMIDI.sendNoteOn(xx, 127, channel1);
    if (buttoneOneDown==1&&ButtonTwoDown==0) usbMIDI.sendNoteOn(49, 127, channel1);
    if (buttoneOneDown==0&&ButtonTwoDown==1) usbMIDI.sendNoteOn(50, 127, channel1);
    Or there are various other logic processes to the same end, largely comes down the the one that will not make your head explode when you have a whole nest of them later

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,068
    The hard part about doing something when a human presses 2 buttons, and also do something different when they press just 1 of those buttons, is what to do the instant you first detect just 1 button press. The big question is how long do you wait. If you immediately do the 1 button action, that will appear as a mistake to the user if their fingers are on both buttons and the 2nd button event occurs several milliseconds later. So you must wait, which can feel like you're making an unresponsive system while writing the code, but it's a necessity if you want to avoid the "wrong" behavior.

    Usually this task involves creating 2 variables. You'll need a way to remember which state you're in. You'll go from idle, to 1 button pressed but waiting, and from that state, you'll go the 1 button confirmed if too much time elapses, or to the 2 buttons if you detect the other button before the timeout period expires.

    elapsedMillis is the simplest way to do the check for how much time has elapsed.

    https://www.pjrc.com/teensy/td_timin...pedMillis.html

    How long to wait for the 2nd button press, before you do the action for only 1 button is sort of an open question. It really can depend on the type of buttons you have, maybe other aspects of your project. But as a rule of thumb, humans perceive "instant" reaction if you give a response within ~50 ms, so that's a good starting point for the timeout setting.

  4. #4
    Ok thanks a lot to both of you !! Very helpful and logical. It's a complicated quest !

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •