Good code example for BOUNCE lib using more than (2) switches and (1) LEDS

I have spent considerable time looking for code that will take, say 8 buttons and control 8 LED's with state change detection. I have the Bounce v.2 library and their example code only covers multiple switches (inputs) and a single LED output. My project is at it's most basic, 8 buttons that will trigger 8 relays (using optoisolators or essentially LED's) for the outputs. The CHANGE example in the BOUNCE library is fine but I can't figure out how to get more than one output to be triggered. I am new to coding so this has been a steep learning curve for me. Unfortunately, I learn best by dissecting something that works and modifying it to do what I need it to do. Haven't crossed paths with the right script yet. I am using a MEGA 2560 for the board so I have lots of inputs/outputs to work with. Got any suggestions or references on scripts to accomplish this?

There are no scripts on an Arduino. Just sketches, code, or source code.

The TM1638 library that I use has debounced read functions for the 8 on panel pushbuttons. But it might not be the best cadaver for dissection. :)

Unlikely_Phoenix:
Got any suggestions or references on scripts to accomplish this?

You can try something like this, without using the library. 57 bytes:

const byte buttonPins[] = {1,2,3,4,5,6,7,8};  // arbitrary pin numbers


void setup()
{
  for (byte i = 0; i < sizeof(buttonPins); i++)
  {
    pinMode(buttonPins[i], INPUT_PULLUP);
  }
}

void loop()
{
  int8_t pressedButton = checkMyButtons();
  switch (pressedButton)  // set up for eight pins
  {
    case 0:  //
      //
      break;
    case 1:  // 
      //
      break;
    case 2:
      //
      break;
    case 3:
      //
      break;
    case 4:  //
      //
      break;
    case 5:  // 
      //
      break;
    case 6:
      //
      break;
    case 7:
      //
      break;
    default:
      // do nothing
      ;
  }
}

int8_t checkMyButtons()
{
  static int8_t lastButtonState[sizeof(buttonPins)] = {1};
  static unsigned long lastMillis[sizeof(buttonPins)] = {0};
  int8_t pressedButton = -1;
  for (byte i = 0; i < sizeof(buttonPins); i++)
  {
    if (millis() - lastMillis[i] > 15UL) // debounce
    {
      lastMillis[i] = millis();
    }
    else
    {
      continue;
    }
    byte state = digitalRead(buttonPins[i]);
    if (state != lastButtonState[i])
    {
      if (state == 0)
      {
        pressedButton = i;
      }
    }
    lastButtonState[i] = state;
  }
  return pressedButton;
}

or mess about with the Bounce2.h library, something like this, but with a lot more overhead. 121 Bytes:

#include <Bounce2.h>

const byte buttonPins[] = {1, 2, 3, 4, 5, 6, 7, 8}; // arbitrary pin numbers
Bounce debouncer[sizeof(buttonPins)];

void setup()
{
  for (byte i = 0; i < sizeof(buttonPins); i++)
  {
    pinMode(buttonPins[i], INPUT_PULLUP);
    debouncer[i].attach(buttonPins[i]);
    debouncer[i].interval(5);
  }
}

void loop()
{
  byte pressedButton = checkPin();
  switch (pressedButton)  // set up for eight pins
  {
    case 0:  //
      //
      break;
    case 1:
      //
      break;
    case 2:
      //
      break;
    case 3:
      //
      break;
    case 4:
      //
      break;
    case 5:
      //
      break;
    case 6:
      //
      break;
    case 7:
      //
      break;
    default:
      // do nothing
      ;
  }
}

int checkPin()
{
  static byte lastPress[sizeof(buttonPins)] = {HIGH};
  for (byte i = 0; i < sizeof(buttonPins); i++)
  {
    byte value = debouncer[i].read();
    if (value == LOW && lastPress[i] == HIGH)
    {
      lastPress[i] = LOW;
      return i;
    }
    lastPress[i] = value;
  }
  return -1;
}

(compiles but untested)

aarg and Bulldog, Thank you for the code ideas. Sorry about 'scripts'... not sure where I was when that came to mind.

I still have the same issue though... what to do when the state changes in addition to keeping track of it. I need it to control the outputs and unless I am overlooking it, I don't see the code doing that. When switch 1 goes high, I need it to turn on output 1. Same with switch 2 and so on. The Bounce library example that has more than one switch only triggers one LED and I could not figure out how to scale that up to match the number of switches I am using.

The examples you have given me make sense and were pretty easy to understand the flow of the process and how it functions. Just doesn't toggle any kind of output. Did I miss something?

Unlikely_Phoenix:
Did I miss something?

yes, each button pressed will cause the return of its number, which will get executed in the switch/case block.

edit the function to actually do something in each case (i.e. each button press).

void loop()
{
  int8_t pressedButton = checkMyButtons();
  switch (pressedButton)  // set up for eight pins
  {
    case 0:  //
      // <<<<<<<< Do something here it means the zeroeth button was pushed
      break;
    case 1:  // 
      // <<<<<<<< Do something here it means the first button was pushed
      break;
    case 2:
      //<<<<<<<<<  etc
      break;
    case 3:
      //
      break;
    case 4:  //
      //
      break;
    case 5:  // 
      //
      break;
    case 6:
      //
      break;
    case 7:
      //
      break;
    default:
      // do nothing
      ;
  }
}

Okey Doke! That makes so much more sense. Thank you. I greatly appreciate your help. I am determined to be fluent in this.

Bulldog... I was able to plug stuff into the case function code and get an initial button press to provide an action. Such as

digitalWrite(ledPin1, HIGH); //obviously turns the LED on that pin on.

I have tried to apply a number of different things in those areas and have been successful. However, I can't get them to turn off after the button has been pressed again. I am not sure what code to apply or where to put it. If I read the code right, which I am probably not, the following code in the sketch should return the button back to it's original state upon second button press:

{ lastPress = LOW; * return i;* * }* _ lastPress = value;_ * }* * return -1;* Thank you for your patience. I am waiting for the 'I get it' light to go on in my head. Just hasn't happened yet. BTW, do you have any suggestions on YouTube videos or some other good references that teach coding? I have watched a bunch of hours on Arduino stuff but a lot of it is just rehash of the example sketch booklets in the starter kits. Good but doesn't do a great job of explaining the mechanics of the code.

Unlikely_Phoenix:
Bulldog… I was able to plug stuff into the case function code and get an initial button press to provide an action. Such as

digitalWrite(ledPin1, HIGH); //obviously turns the LED on that pin on.

I have tried to apply a number of different things in those areas and have been successful. However, I can’t get them to turn off after the button has been pressed again. I am not sure what code to apply or where to put it. If I read the code right, which I am probably not, the following code in the sketch should return the button back to it’s original state upon second button press:

{
lastPress = LOW;

  • return i;*
  • }*
    _ lastPress = value;_
    * }*
    * return -1;*
    Thank you for your patience. I am waiting for the ‘I get it’ light to go on in my head. Just hasn’t happened yet.
    BTW, do you have any suggestions on YouTube videos or some other good references that teach coding? I have watched a bunch of hours on Arduino stuff but a lot of it is just rehash of the example sketch booklets in the starter kits. Good but doesn’t do a great job of explaining the mechanics of the code.
    [/quote]
    something like:
    *_ <em>*digitalWrite(ledPin, !digitalRead(ledPin);  // toggle my pin!!!*</em> _*
    or:
    *_ <em>*if(ledIsOn) {  digitalWrite(ledPin, LOW);    ledIsOn = false;               // a persistant variable (e.g. Global or declared Static within loop()) } else {  digitalWrite(ledPin, HIGH);  ledIsOn = true; }*</em> _*
    all kidding aside, look at C++ for Dummies, start there and read on. There are GREAT online references too.

An object oriented version, limited to 4 buttons as that’s what I had at hand for testing, but you’ll have to assign your own button pin assignments.

Button press posts on release!

// <https://forum.arduino.cc/index.php?topic=380594.0>

#define NUM_ENTRIES(ARRAY)      (sizeof(ARRAY) / sizeof(ARRAY[0]))

// ... (ALMOST) ALWAYS NAME YOUR PINS ...
const uint8_t   pinBUTTON_1 =  4;
const uint8_t   pinBUTTON_2 = 34;
const uint8_t   pinBUTTON_3 = 36;
const uint8_t   pinBUTTON_4 = 37;
#if 0
const uint8_t   pinBUTTON_5 = <assign your value here>;
const uint8_t   pinBUTTON_6 = <assign your value here>;
const uint8_t   pinBUTTON_7 = <assign your value here>;
const uint8_t   pinBUTTON_8 = <assign your value here>;
#endif

const uint8_t   BUTTON_UP   = LOW;
const uint8_t   BUTTON_DOWN = HIGH;

const uint32_t  tmsDEBOUNCE = 50UL;

struct button_t
{
    const uint8_t   _pin;
    uint8_t         _stateTriggerOn: 1;

    uint8_t         _state:          1;
    uint8_t         _statePrev:      1;
    uint8_t         _statePress:     1;
    uint32_t        _tmsPrev;
    
    button_t(uint8_t const pin, uint8_t const stateTriggerOn = BUTTON_UP)
        : _pin(pin)
        , _stateTriggerOn(stateTriggerOn)

        , _state(BUTTON_UP)
        , _statePrev(BUTTON_UP)
        , _statePress(BUTTON_UP)
        , _tmsPrev(0UL)
    {   }
    
    void begin()
    {
        pinMode(_pin, ((HIGH == BUTTON_UP) ? INPUT_PULLUP : INPUT));
    }

    bool check()
    {
	    _statePress         = false;
        int8_t state_button = digitalRead(_pin);
        if ( state_button != _statePrev )
        {
            _tmsPrev = millis();
        }

        if ( (millis() - _tmsPrev) > tmsDEBOUNCE )
        {
            if ( state_button != _state )
            {
                _state = state_button;
                if ( _state == _stateTriggerOn)
                {
                    _statePress = !_statePress;
                }
            }
        }

        _statePrev = state_button;

        return ((BUTTON_DOWN == _statePress) ? true : false);
    }
};

button_t    buttons[] =
{
    // ... AND THEN USE YOUR PIN NAMES INSTEAD OF THE BARE NUMBER...
    // ... CONSTRUCT INSTANCES OF 'buton_t' OBJECT FOR EACH NAMED BUTTONS ..
      button_t(pinBUTTON_1)
    , button_t(pinBUTTON_2)
    , button_t(pinBUTTON_3)
    , button_t(pinBUTTON_4)
#if 0
    , button_t(pinBUTTON_5)
    , button_t(pinBUTTON_6)
    , button_t(pinBUTTON_7)
    , button_t(pinBUTTON_8)
#endif
};

// ... returns 0 if no button pressed else which button was pressed ...
uint8_t checkButtons()
{
    for ( size_t i = NUM_ENTRIES(buttons); i--; )
    {
        if ( true == buttons[i].check() )
        {
            return i + 1;
        }
    }

    return 0;
}

void loop()
{
    uint8_t button_num = checkButtons();
    switch ( button_num )
    {

        case 0:  break; // NO BUTTON PRESSED
#if 0
        case 1:  break;
        case 2:  break;
        case 3:  break;
        case 4:  break;
        case 5:  break;
        case 6:  break;
        case 7:  break;
        case 8:  break;
#endif
        default:
            Serial.print("Button ");
            Serial.print(button_num);
            Serial.println(" has been pressed!");

            break;
    }
}

void setup()
{
    Serial.begin(9600);
    
    for ( size_t i = NUM_ENTRIES(buttons); i--; )
    {
        buttons[i].begin();
    }
}