warning lights when two buttons clicked

Hi all,

I’m a complete newbie to arduino and not a well programmer, but I hope there is some out who can help.

What I’m trying to do ?

I intend to use arduino to control the lightning of my motorcycle.
Currently, I’m trying to implement the control of the flashlights. I will use the left button for the left flash, the right button for the right flash, an when both buttons were clicked the warning lights should turn on.

But I got stuck with the implementation of the warning lights. I have no idea of how to check, if two buttons were clicked at the same time.

In the past I already had problems to figure out of how to implement a click instead of the status “button is pressed” or “button is not pressed”. That I solved by comparing the status of the current status with the last status of the loop.

But due to the main loop and the microseconds arduino needs to run through one loop, the following condition won’t work. You’ll never realease both buttons at exactly the same time:

if (leftClick == HIGH && lastLeftClick == LOW && rightClick == HIGH && lastRightClick == LOW) …

Has anyone a solution for this ?

Thanks,
Hoshi

The current status of my sketch looks as follows:

// Included Libraries
#include <Bounce.h>

// Define Input / Output
#define leftButton 8
#define rightButton 11
#define leftLED 9
#define rightLED 10

// Variables independent from flashlight
long blinkInterval = 750;       // interval at which to blink (milliseconds)

// Variables left flashlight
int LEDstateLF = LOW;           // will store status of left flashlight LED status
int toggleLF = LOW;             // will store if flashlight is turned on or off
int lastLeftClick = LOW;        // will store status of last click
long previousMillisLF = 0;      // will store time left flash blinked last time

// Variables right flashlight
int LEDstateRF = LOW;           // will store status of left flashlight LED status
int toggleRF = LOW;             // will store if flashlight is turned on or off
int lastRightClick = LOW;       // will store status of last click
long previousMillisRF = 0;      // will store time left flash blinked last time


// Instantiate a Bounce object with a 5 millisecond debounce time
Bounce leftBouncer = Bounce( leftButton,5 ); 
Bounce rightBouncer = Bounce( rightButton,5 ); 

void setup() {
  Serial.begin(9600);
  pinMode(leftButton,INPUT);
  pinMode(leftLED,OUTPUT);
  pinMode(rightButton,INPUT);
  pinMode(rightLED,OUTPUT);
}

void loop() {
 // Update the debouncer
  leftBouncer.update ( );
  rightBouncer.update ( );

 // Get the update value
 int leftClick = leftBouncer.read();
 int rightClick = rightBouncer.read();
 
 //when clicked, turn left button into toggle
 if (leftClick == HIGH && lastLeftClick == LOW){
   if (toggleLF == LOW){
      toggleLF = HIGH;
   } 
   else if (toggleLF ==HIGH){
      toggleLF = LOW;
   }
 }
  lastLeftClick = leftClick;

//when clicked, turn right button into toggle
 if (rightClick == HIGH && lastRightClick == LOW){
   if (toggleRF == LOW){
      toggleRF = HIGH;
   } 
   else if (toggleRF ==HIGH){
      toggleRF = LOW;
   }
 }
  lastRightClick = rightClick;

/* 
--> Case 1: no flash activated --> left click --> left flash = On, right flash = Off
--> Case 2: no flash activated --> right click --> left flash = Off, right flash = On
--> Case 3: no flash activated --> left & right click --> left flash = On, right flash = On (warning lights)
--> Case 4: left flash activated --> left click --> left flash = Off, right flash = Off
--> Case 5: left flash activated --> right click --> left flash = Off, right flash = Off
--> Case 6: left flash activated --> left & right click --> left flash = Off, right flash = Off
--> Case 7: right flash activated --> left click --> left flash = Off, right flash = Off
--> Case 8: right flash activated --> right click --> left flash = Off, right flash = Off
--> Case 9: right flash activated --> left & right click --> left flash = Off, right flash = Off
--> Case 10: left & right flash activated --> left click --> left flash = On, right flash = Off
--> Case 11: left & right flash activated --> right click --> left flash = Off, right flash = On
--> Case 12: left & right flash activated --> left & right click --> left flash = Off, right flash = Off
*/

} //loop end main function

void flashOn(){
  //Blink left flashlight
  if (millis() - previousMillisLF > blinkInterval) {
        // save the last time you blinked the LED 
        //Serial.println(previousMillisLF);
        //Serial.println(millis());
        previousMillisLF = millis();   
        // if the LED is off turn it on and vice-versa:
        if (LEDstateLF == LOW)
          LEDstateLF = HIGH;
        else
          LEDstateLF = LOW;
        // set the LED with the ledState of the variable:
        digitalWrite(leftLED, LEDstateLF);
  }
}

void flashOff(){
  //Turn of flashlight
    digitalWrite(leftLED, LOW);
}

Getting two buttons pressed at exactly the same time rarely works. What you need to do is record when each button was pressed, using millis(). If the time between the two button presses is short enough (you get to define what that means), consider them simultaneous.

By the way, the value returned by millis is unsigned long, not long.

Thanks PaulS,

that was the important hint. I got it.

What I have done, for those who might have similar problems:

Defined variables:
wlTiming - time intervall within both buttons must be clicked to activate or deactivate warning lights
action - left click = 1, right click = 2, both clicked = 3

What took me some time is to figure out the right conditions, especially (millis() - timeClicked?? > wlTiming) for the left and right click. It is absolutely important, to wait for the duration of wlTiming. If you clicked the left button, you have to wait for wlTiming, because a right click might follow. In that case, the user clicked both buttons to activate or deactivate the warning lights.

First I didn’t consider that point and worried why “left click” or “right click” was always shown before “both clicked” in the debugging monitor.

Greetings,
Hoschi

Here a part of the code:

// Check action to take
// First if condition to avoid warning lights at startup
if (timeClickedLB != 0 || timeClickedRB != 0){
  //check if user wanted a left click  
  if ((timeClickedLB - timeClickedRB > wlTiming) && (timeClickedLB > timeClickedRB) && (millis() - timeClickedLB > wlTiming)){ 
     action = 1;
  }
  //check if user wanted a right click 
  else if ((timeClickedRB - timeClickedLB > wlTiming) && (timeClickedRB > timeClickedLB) && (millis() - timeClickedRB > wlTiming)){
     action = 2;
  }
  //both buttons clicked
  else if ((timeClickedLB - timeClickedRB < wlTiming) || (timeClickedRB - timeClickedLB < wlTiming)){  //If both clicks within wlTiming, than both clicked
     action = 3;
  } 
}

It should be possible to solve your task as follows....

Pseudo-code... RHB= right hand button, LHB= left hand button

loop{
if LHB down: wait until it is released.
     while waiting, check whether RHB down at any time.

if LHB wasn't down....
    {
       if RHB down: wait until it is released.
             while waiting, check whether LHB down at any time.
    }

DoFlashes, according to what you've recently seen

}

That would work to turn the flashing on, to continue even after button or buttons released. You would have to have some way of turning the flashing off again, too! (Get the first part working... and then maybe add code so that, if lights are flashing, briefly pressing either button cancels the flashing.)

Buried within that code would be a variable, let's call it WhatFlash which starts the day set to zero (no flash) and is set to 1, 2 or 3 for "flash left", "flash right" or "flash both" respectively. Note that thre's good scope for use of binary logic here... but it isn't necessary. but what IS necessary is to understand that the "ifs" can "promote" WhatFlash from zero to 1,2 or 3... but they would NOT set it back to zero in the event that no button was pressed.