..and here is a version of the same thing, with multiple buttons being handled simultaneously:

Code:
// Original code by Mark Lord; free for any use; no conditions.
#define BUTTON1_PIN 7
#define BUTTON2_PIN 8
#define BUTTON3_PIN 9

static bool lightsAreOn;
static int  colorSelection;

// Get a non-zero timeout:
static inline long get_timeout (unsigned int t)
{
   long m = millis() + t;
   return m ? m : 1;
}

// Compare against current time, handling wraparound:
static inline bool time_after (long a, long b)
{
  return (b - a) < 0;
}
#define time_before(a,b) time_after((b),(a))

struct button_s {
  int  pin;
  bool pressed;
  bool tmp_value;
  long timer;
  const char *name;
} buttons[]= {{BUTTON1_PIN,0,0,0,"FirstButton"}, 
              {BUTTON2_PIN,0,0,0,"SecondButton"}, 
              {BUTTON3_PIN,0,0,0,"ThirdButton"}, 
              {-1,0,0,0,NULL}};

static bool debounce_button (struct button_s *b)
{
  bool new_value = (digitalRead(b->pin) == LOW);
  if (new_value != b->tmp_value) {
    b->tmp_value = new_value;
    b->timer     = get_timeout(10);
    return false;  // no change (debouncing)
  }
  if (b->timer && time_after(millis(), b->timer)) {
    b->timer   = 0;
    if (b->pressed != new_value) {
      b->pressed = new_value;
      return true;  // button changed
    }
  }
  return false;  // no change (yet)
}

void loop ()
{
  for (button_s *b = buttons; b->pin != -1; ++b) {
    if (debounce_button(b)) {
      Serial.print(b->name);
      Serial.print("=");
      Serial.println(b->pressed ? "on" : "off");
    }
  }
}

void setup ()
{
  Serial.begin(115200);
  for (button_s *b = buttons; b->pin != -1; ++b) {
    pinMode(b->pin, INPUT_PULLUP);
  }
}


Edited by mlord (25/11/2022 03:47)