Menu Buttons Confusion

Hi, I made a small midi controller for my pedalboard,
3 buttons, up, down, select,
when I use select button to enter a sub menu, the button becomes a send button

my problem is when I enter the sub menu it also sends midi data,
I don't want to send any data until I press the send button

I fixed that by adding canSend = true; to each of the sub menu switch cases
but now when I enter the sub menu I can't send data until I change the switch case with up or down buttons

how can I fix this?


//****************************************UP BUTTON**************************************************



void readUpButton() {

  // UP BUTTON
  byte upButtonState = digitalRead (upButton);
  if (upButtonState != oldUpButtonState) {
    if (millis () - buttonPressTime >= debounceTime) { // debounce
      buttonPressTime = millis ();  // when we closed the switch
      oldUpButtonState =  upButtonState;  // remember for next time
      longPressTriggered = false;

      if (upButtonState == LOW && mainMenu == true) {   // if button up pressed & main menu is active

        menuPage ++; //increment the current menu page's position count
        if (menuPage > 4) {
          menuPage = 0;  //0-4 (5 menu pages)
        }
      }

      if (upButtonState == LOW && subMenu == true) {   // if button up pressed & sub menu is active
        subPage ++;
        if (subPage > 23) {
          subPage = 0;  ///0-23 (24 sub menu pages)
        }
      } // end of else if

      if (upButtonState == LOW && looperMenu == true && looperPage == 0) {
        // undo
        MIDI.sendControlChange (27, 127, 4); // number, value, channel
      }

      if (upButtonState == LOW && looperMenu == true && looperPage == 1) {
        // pitch+
        MIDI.sendControlChange (29, 127, 4); // number, value, channell
      }

      if (upButtonState == LOW && looperMenu == true && looperPage == 2) {
        // erase
        MIDI.sendControlChange (49, 127, 4); // number, value, channel
      }

    }  // end if debounce time up
  } // end of state change

  if ( longPressTriggered == false && upButtonState == LOW && subMenu == true && millis() - buttonPressTime >= longPressTime ) {
    // Do long press stuff here!!
    // shortcut to sub page 1
    subPage += 5;

    longPressTriggered = true;
  }
} // end of function



//*************************************************DOWN BUTTON************************************


void readDownButton() {

  // DOWN BUTTON
  byte downButtonState = digitalRead (downButton);
  if (downButtonState != oldDownButtonState) {
    if (millis () - buttonPressTime >= debounceTime) { // debounce
      buttonPressTime = millis ();  // when we closed the switch
      oldDownButtonState =  downButtonState;  // remember for next time
      longPressTriggered = false;

      if (downButtonState == LOW && mainMenu == true) {   // if down button pressed & main menu is active

        menuPage --; //decrement the current menu page's position count
        if (menuPage > 200) {
          menuPage = 4;  ///0-4 (5 menu pages)
        }
      }

      if (downButtonState == LOW && subMenu == true) {   // if down button pressed & sub menu is active
        subPage --;
        if (subPage > 200) {
          subPage = 23;  ///0-23 (24 sub menu pages)
        }
      } // end of else if

      if (downButtonState == LOW && looperMenu == true && looperPage == 0) {
        // reverse
        MIDI.sendControlChange (28, 127, 4); // number, value, channel
      }

      if (downButtonState == LOW && looperMenu == true && looperPage == 1) {
        // pitch-
        MIDI.sendControlChange (30, 127, 4); // number, value, channel
      }

      if (downButtonState == LOW && looperMenu == true && looperPage == 2) {
        // stuttter
        MIDI.sendControlChange (48, 127, 4); // number, value, channel
      }

    }  // end if debounce time up
  } // end of state change

  if ( longPressTriggered == false && downButtonState == LOW  && millis() - buttonPressTime >= longPressTime ) {
    // Do long press stuff here!!
    // shortcut to sub page 1
    loadMenu();

    longPressTriggered = true;
  }
} // end of function



//********************************************SELECT BUTTON*********************************************



void readSelectButton() {

  // Select Button
  byte selectButtonState = digitalRead (selectButton);
  if (selectButtonState != oldSelectButtonState) {
    if (millis () - buttonPressTime >= debounceTime) { // debounce
      buttonPressTime = millis ();  // when we closed the switch
      oldSelectButtonState =  selectButtonState;  // remember for next time

      if (selectButtonState == LOW && mainMenu == true) {
        loadSub(); // load sub menu
      }

      if (selectButtonState == LOW && menuPage == 4) {
        loadLooper(); // load looper menu
      }

      if (selectButtonState == LOW && looperMenu == true) {   // if button up pressed & looper menu is active
        looperPage ++;                                        // increase looper page
        if (looperPage > 2) {
          looperPage = 0;  ///0-2 (3 looper menu pages)
        }
      }
      if (selectButtonState == LOW && subMenu == true && canSend == true) { // !! added can send to fix auto sending when first loading submenu !!
        midiSend();
      }

    }  // end if debounce time up
  } // end of state change
} // end of function


I suspect that when you use the button to enter a sub menu you are also picking up the same press to “send”. It is similar to debouncing

@pmagowan makes a good point

consider (for reading multiple buttons)

// check multiple buttons and toggle LEDs

enum { Off = HIGH, On = LOW };

byte pinsLed [] = { 10, 11, 12 };
byte pinsBut [] = { A1, A2, A3 };
#define N_BUT   sizeof(pinsBut)

byte butState [N_BUT];

// -----------------------------------------------------------------------------
int
chkButtons ()
{
    for (unsigned n = 0; n < sizeof(pinsBut); n++)  {
        byte but = digitalRead (pinsBut [n]);

        if (butState [n] != but)  {
            butState [n] = but;

            delay (10);     // debounce

            if (On == but)
                return n;
        }
    }
    return -1;
}

// -----------------------------------------------------------------------------
void
loop ()
{
    switch (chkButtons ())  {
    case 2:
        digitalWrite (pinsLed [2], ! digitalRead (pinsLed [2]));
        break;

    case 1:
        digitalWrite (pinsLed [1], ! digitalRead (pinsLed [1]));
        break;

    case 0:
        digitalWrite (pinsLed [0], ! digitalRead (pinsLed [0]));
        break;
    }
}

// -----------------------------------------------------------------------------
void
setup ()
{
    Serial.begin (9600);

    for (unsigned n = 0; n < sizeof(pinsBut); n++)  {
        pinMode (pinsBut [n], INPUT_PULLUP);
        butState [n] = digitalRead (pinsBut [n]);
    }

    for (unsigned n = 0; n < sizeof(pinsLed); n++)  {
        digitalWrite (pinsLed [n], Off);
        pinMode      (pinsLed [n], OUTPUT);
    }
}

How do I debounce the midiSend part?

void readSelectButton() {

  // Select Button
  byte selectButtonState = digitalRead (selectButton);
  if (selectButtonState != oldSelectButtonState) {
    if (millis () - buttonPressTime >= debounceTime) { // debounce
      buttonPressTime = millis ();  // when we closed the switch
      oldSelectButtonState =  selectButtonState;  // remember for next time

      if (selectButtonState == LOW && mainMenu == true) {
        loadSub(); // load sub menu
      }

      if (selectButtonState == LOW && menuPage == 4) {
        loadLooper(); // load looper menu
      }

      if (selectButtonState == LOW && looperMenu == true) {   // if button up pressed & looper menu is active
        looperPage ++;                                        // increase looper page
        if (looperPage > 2) {
          looperPage = 0;  ///0-2 (3 looper menu pages)
        }
      }
      if (selectButtonState == LOW && subMenu == true && canSend == true) { // !! added can send to fix auto sending when first loading submenu !!
        midiSend();
      }

    }  // end if debounce time up
  } // end of state change
} // end of function

I think i need to debounce these, I tried a delay but it just delays the unwanted sending

      if (selectButtonState == LOW && mainMenu == true) {
        loadSub(); // load sub menu
      }

      if (selectButtonState == LOW && subMenu == true) { 
        midiSend();
      }

is 10 ms too much of a delay? it can be done after sending

I solved it, I just swapped the order

      if (selectButtonState == LOW && subMenu == true) { 
        midiSend();
      }

      if (selectButtonState == LOW && mainMenu == true) {
        loadSub(); // load sub menu
      }

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.