// Connect some buttons per
// https://forum.arduino.cc/t/how-to-wire-and-program-a-button/1196000/2?u=davex
// https://forum.arduino.cc/t/share-tips-you-have-come-across/428745/999
// and https://forum.arduino.cc/t/wiring-a-button-pull-down-bad-vs-input-pullup-best/116298566
//
// Also demos blocking and non-blocking button reading and blinking

const byte S1Pin = 10; // external pull down Normally Open button
const byte S2Pin = 5; // external pull up Normally Open button
const byte S3Pin = 3; // Internal pullup Normally Open Button

const byte D1Pin = 8; // active low LED
const byte D2Pin = 7; // active high LED
const uint32_t interval = 1000;

void setup() {
  Serial.begin(115200);
  pinMode(S1Pin, INPUT); // rely on extrernal pull-down
  pinMode(S2Pin, INPUT); // rely on extrernal pull-UP
  pinMode(S3Pin, INPUT_PULLUP); // us internal pullup resistor

  // Active LOW LED:
  digitalWrite(D1Pin, HIGH); // turn off before setting as output
  pinMode(D1Pin, OUTPUT); // Active LOW led
  //digitalWrite(D1Pin,LOW); // turn on

  // Active HIGH LED
  pinMode(D2Pin, OUTPUT); // Active HIGH led
  digitalWrite(D2Pin, LOW); // turn off
  //digitalWrite(D2Pin,HIGH); // turn on
}

void loop() {
  switch ( 1 ) { // Choose from scheme 1,2, or 3
    case 1: blockingLoop(); break;// read the buttons and blink the lights using delay
    case 2: nonBlockingLoop(); break; // poll the button and blink without delay
    case 3: nonBlockingEdgeDetectionLoop(); break; // read the buttons changes and blink the lights cooperatively
  }
}


void blockingLoop(void) {
  int S1Active = digitalRead(S1Pin) == HIGH;  // External oulldown is active HIGH
  int S2Active = digitalRead(S2Pin) == LOW;  // Exrernal pullup is active LOW
  int S3Active = digitalRead(S3Pin) == LOW;  // Internal pullup is active LOW
  Serial.print( digitalRead(S1Pin) == LOW ? "S1=Open" : "S1 Closed");
  Serial.print(' ');
  Serial.print( digitalRead(S2Pin) == HIGH ? "S2=Open" : "S2=Closed");
  Serial.print(' ');
  Serial.println( S3Active ? "S3=Closed" : "S3=Open");
  if (S1Active || S2Active || S3Active ) {
    digitalWrite(D1Pin, digitalRead(D1Pin) == HIGH ? LOW : HIGH);
    digitalWrite(D2Pin, digitalRead(D2Pin) == HIGH ? LOW : HIGH);
  }
  delay(interval);  // pause for polling/blinking
}

void nonBlockingLoop(void) {
  static uint32_t lastPoll = 0;
  if (millis() - lastPoll > interval) {
    lastPoll = millis();
    int S1Active = digitalRead(S1Pin) == HIGH;  // External oulldown is active HIGH
    int S2Active = digitalRead(S2Pin) == LOW;  // Exrernal pullup is active LOW
    int S3Active = digitalRead(S3Pin) == LOW;  // Internal pullup is active LOW
    Serial.print( digitalRead(S1Pin) == LOW ? "S1=Open" : "S1 Closed");
    Serial.print(' ');
    Serial.print( digitalRead(S2Pin) == HIGH ? "S2=Open" : "S2=Closed");
    Serial.print(' ');
    Serial.println( S3Active ? "S3=Closed" : "S3=Open");
    if (S1Active || S2Active || S3Active ) {
      digitalWrite(D1Pin, digitalRead(D1Pin) == HIGH ? LOW : HIGH);
      digitalWrite(D2Pin, digitalRead(D2Pin) == HIGH ? LOW : HIGH);
    }
  }
}

void nonBlockingEdgeDetectionLoop(void) {
  const byte numSwitches = 3;
  const uint8_t switchPins[] = {S1Pin, S2Pin, S3Pin};
  const uint8_t InactiveLevels[] = {LOW, HIGH, HIGH};
  const char *names [] = {"S1", "S2", "S3"};
  const int debounceMs = 20;
  static uint32_t changeTimes[numSwitches];
  static int lastState[numSwitches];  // memory for edge detection
  static uint32_t lastBlinkTime = 0;
  uint32_t currentTime = millis();
  for (int sw = 0 ; sw < numSwitches ; ++ sw) {
    int currentState = digitalRead(switchPins[sw]);
    // check for button state-changes
    if (currentState != lastState[sw] && currentTime - changeTimes[sw] > debounceMs) {
      lastState[sw] = currentState ;
      changeTimes[sw] = currentTime;
      Serial.print(names[sw]);
      Serial.print(":");
      Serial.print(currentState == InactiveLevels[sw] ? "Open" : "Closed");
      Serial.println(".");
    }
  }
  // Blink the LEDs while any button is active
  // test all switches
  bool anyActive = false;
  for (int sw = 0; sw < numSwitches ; ++sw) {
    if (lastState[sw] != InactiveLevels[sw]) {
      anyActive = true;
    }
  }
  if (anyActive && currentTime - lastBlinkTime > interval) {
    lastBlinkTime = currentTime;
    digitalWrite(D1Pin, digitalRead(D1Pin) == HIGH ? LOW : HIGH);
    digitalWrite(D2Pin, digitalRead(D2Pin) == HIGH ? LOW : HIGH);
  }
}
D1 Active LOW
D2 Active HIGH
SW1 See NOTE
SW2
SW3
R4 10K External pull-DOWN
R1 10K External Pull-up
R2 220R
R3 220R
Typical switch wiring and simple LED Connection
Best S3 -- Internal Pull Up -- pinMode(3,INPUT_PULLUP) -- Goes LOW on push
Good S2 -- External Pull Up -- pinMode(5,INPUT_PULLUP) -- Goes LOW on push
Bad S1 -- External Pull Down -- pinMode(10,INPUT_PULLUP) -- Goes HIGH on push
https://forum.arduino.cc/t/share-tips-you-have-come-across/428745/999
NOTE: SW1 & R4 circuit is not recommended as there is a possibility of shorting +5 to ground