Newbie - Debounce help please - thanks in advance

Hi All

New to Arduino and amazed by the great projects that everyone creates and looking for a little help

I've started with a few basic things like button, debounce etc but finding it difficult adding extra code or modding the code to add extra items like inputs and outputs

My circuit is kinda simple, 3 inputs 2 outputs

1st input (switch) triggers 1st output using debounce to keep an redLED on
pressed again LED is off

2nd input (switch) triggers 2nd output using debounce to keep an greenLED on
pressed again LED is off

3rd input (switch) is to turn off the LED's if on

the 3rd input is where I am going wrong and cant figure out the code, I would like the 3rd input to turn off either LED if on

or further to this - the 1st and 2nd inputs can only turn ON and latch the corresponding LEDs and the 3 input turns them off,

the 1st and 2nd inputs cannot be activated if another LED is on - if RED led is on then GREEN cannot activate until RED led is turned off by input 3 and same for the GREEN Led

if anyone has any pointers, reference to projects, reference to code id be grateful for the direction

ive posted the code below for what I have so far

BR

const int redbutton = 3;    //First input
const int greenbutton = 4;  //Second input
const int stopbutton = 5;  //Third input
const int redled = 9;       //First output
const int greenled = 10;    //Second output


int redledState = HIGH;         
int greenledState = HIGH;
int redbuttonState;             
int greenbuttonState;
int stopbuttonState;
int redlastButtonState = LOW;   
int greenlastButtonState = LOW;
int stoplastButtonState = LOW;


long lastDebounceTime = 0;  
long debounceDelay = 50;    


void setup() {
  pinMode(redbutton, INPUT);
  pinMode(redled, OUTPUT);

  
  digitalWrite(redled, redledState);
  
  pinMode(greenbutton, INPUT);
  pinMode(greenled, OUTPUT);

  
  digitalWrite(greenled, greenledState);
  
  pinMode(stopbutton, INPUT);
  pinMode(redled, OUTPUT);
  pinMode(greenled,OUTPUT);
  
  digitalWrite(redled, redledState);
  digitalWrite(greenled, greenledState);
  
}

void loop() {
  
  
  int reading = digitalRead(redbutton);

  
  if (reading != redlastButtonState) {
    
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    
    
    if (reading != redbuttonState) {
      redbuttonState = reading;

      if (redbuttonState == HIGH) {
        redledState = !redledState;
      }
    }
  }

  digitalWrite(redled, redledState);

  
  redlastButtonState = reading;

{
  

  int reading = digitalRead(greenbutton);

  
  if (reading != greenlastButtonState) {
    
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    
    if (reading != greenbuttonState) {
      greenbuttonState = reading;

      
      if (greenbuttonState == HIGH) {
        greenledState = !greenledState;
      }
    }
  }

  
  digitalWrite(greenled, greenledState);

  
  greenlastButtonState = reading;
  
  {
  

  int reading = digitalRead(stopbutton);

  
  if (reading != stoplastButtonState) {
    
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    
    if (reading != stopbuttonState) {
      stopbuttonState = reading;

      
      if (stopbuttonState == HIGH) {
        greenledState = !greenledState;
      }
    }
  }

  
  digitalWrite(greenled, greenledState);
  
  stoplastButtonState = reading;

  }
  
  {

int reading = digitalRead(stopbutton);

  
  if (reading != stoplastButtonState) {
    
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    
    if (reading != stopbuttonState) {
      stopbuttonState = reading;

      
      if (stopbuttonState == HIGH) {
        redledState = !redledState;
      }
    }
  }

  
  digitalWrite(redled, redledState);
  
  stoplastButtonState = reading;
  
}
  

}
}

Google “Arduino state machine”.

First off, what exactly are you trying to do with those random braces?
Second, I'm actually surprised it even compiles without Errors or warnings. Why do you keep redefining int reading? By doing that you are recreating the wheel and either the Compiler will complain (it should) or it's smart enough to ignore it.

Third, once you have detected the stop button, just:

redledState = LOW;
greenledState = LOW;
digitalWrite(redled, redledState);
digitalWrite(greenled, greenledState);

and be done with it. There is no reason to try to flip flop or whatever. You stated that you want both LED to go off so these four lines of code are all you Need.

Groundfungus thanks will do

If you have three identical things, it can be helpful to use arrays.

const int nButtons= 3;

// these are indexes into the array
const int redButton= 0;
const int greenButton = 1;
const int stopButton = 2;

const byte buttonPin[nButtons] = {3,4,5};
// this holds the state of the button last time the loop was executed
boolean buttonState[nButtons];
// this holds if the button became pressed *this* execution of the loop
boolean buttonPressed[nButtons];
// this holds if the button is in a 'held down" state
boolean buttonHeld[nButtons];
uint32_t buttonDebounceMs[nButtons];

void setup() {
  for(int i = 0; i<nButtons; i++) {
    pinMode(buttonPin[i], INPUT_PULLUP);
  }
}

From there, you can write debounce code for your buttons. Let’s move that out into it’s own function:

void readButtons() {
  for(int i = 0; i<nButtons; i++) {
    buttonPressed[i] = false; // always clear this
    boolean prevState = buttonState[i];
    buttonState[i] = (digitalRead(buttonPin[i]) == LOW);

    if(buttonState[i]) {
      if(!prevState) {
        // start the debounce timer
        buttonDebounceMs[i] = millis();
      }
      else if(buttonHeld[i]) {
        // do nothing
      }
      else if(millis() -  buttonDebounceMs[i] > debounceDelay) {
        buttonPressed[i] = true;
        buttonHeld[i] = true;
      }
    }
    else {
      buttonState[i] = false;
      buttonHeld[i] = false;
    }
  }
}

once we have that, you can put some logic in your loop. We will assume that the buttons are never pressed simultaneously.

void loop() {
  readButtons();

  if(buttonPressed[redButton]) {
    // toggle the red led
  }
  if(buttonPressed[greenButton]) {
    // toggle the green led
  }
  if(buttonPressed[stopButton]) {
    // turn both leds off
  }
}

Now, rather than using separate button state and button held arrays, you can use a single array of byte that holds values OFF, DEBOUNCING, PRESSED, HELD to keep track of when to fire a “yes, this button has become pressed this time through the loop”. In this case, the code in the loop that responds to a PRESSED state is responsible for moving the button into its HELD state, the meaning of that being “yes, I have handled this button press”.

Paul thank you for your time and advice

BR

@groundfungus thanks for the direction, after a few failed attempts i've managed to modify the switch case example to complete it

The code may not look appealing to you pros, but thanks for everyones input

const int sensorMin = LOW;     
const int sensorMax = HIGH;    

void setup() {
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(3, INPUT);
  pinMode(5, INPUT);
  pinMode(4,INPUT);
}

void loop() {
 
  int sensorReading = digitalRead(3);
  int sensorReading1 = digitalRead(5);
  int sensorReading2 = digitalRead(4);
  
  int range = map(sensorReading, sensorMin, sensorMax, 0, 1);
  int range1 = map(sensorReading1, sensorMin, sensorMax, 2, 3);
  int range2 = map(sensorReading2, sensorMin, sensorMax, 4,5);
  
  switch (range) {
    case 1:    
      digitalWrite(9, HIGH);
      break;
  }
  
  delay(1);   

switch (range1) {
     case 3:    
      digitalWrite(9, LOW);
      digitalWrite(10, LOW);
      break;
  }

delay(1);   

switch (range2) {
    case 5:    
      digitalWrite(10, HIGH);
      break;
  }
  
  delay(1);     
  
}
  int range = map(sensorReading, sensorMin, sensorMax, 0, 1);

It hardly makes sense to map from one range to another range when the two ranges are the same.

The result of the mapping is NOT a range.

  int range1 = map(sensorReading1, sensorMin, sensorMax, 2, 3);

You COULD just add 2 to sensorReading1 to achieve the same result.

  switch (range) {
    case 1:   
      digitalWrite(9, HIGH);
      break;
  }

A switch statement with just one case is completely pointless. A simple if statement would suffice.

Hi PaulS

Thanks for your input, I'm (myself) still a work in progress and tbh I couldn't get the if statements to compile and driving me nuts

I also tried to complete your coding and got lost and returned errors I do apologise

Currently what I have is

Up button
Down button
Stop button

Red led for up
Green led for down

If the down button is pressed it turns on the green led

The green led remains lit until the stop button is pressed

if the up button is pressed it turns off the green and turns on red

The stop button also turns the red off when lit

What I need to intergrate now is

If stop button is pressed and held for 5s

Turn on red led and flash green for 5 clicks then turn off and remain as before

Any suggestions would be greatly appreciated

BR

If stop button is pressed and held for 5s

The state change detection example shows how to determine that a switch has become pressed or has become released.

Use millis() to record when the switch becomes pressed. On every pass through loop(), see if the switch is pressed. If so, you can determine how long is has been pressed by comparing now (millis()) to then (the recorded time). If it has been more than 5000 seconds, do whatever needs doing.