Is it possible to have a simultaneous button press to turn on a LED

Hi

I am working on a three LED, four button project at present and have got to a stage where it works, but not exactly how I need it to and after reviewing the forums for other user experiences and queries, I would would like to seek your advice.

Currently I have a button assigned to activate each LED colour, with the fourth button clearing the sequence/turning all active LEDs off. However I would like to change this so that the GREEN led only turns on when both the SWITCH_MASTER & SWITCH_GREEN buttons are pressed together..

Once I have solved this issue, I may extend my MASTER switch to activate another output when pressed on its own. But I am not yet ready for that as I am trying to get this working first (but to no avail).

I have seen in previous forum posts that "even if you hit it with a hammer you can not press both buttons at the same time", however I am hoping this maybe different, as my MASTER_SWITCH will in fact be pressed and held down, whilst the SWITCH_GREEN is then pressed.

In addition, I would also like to change my RED LED to blink/flash, rather than just coming on and staying on. I did see in another forum posting a suggestion of

 digitalWrite(pin, millis() & 0x100);

but have not managed to get this to work. My LED would not activate at all when the button was pressed :frowning:

Please can I ask if you can review the below code to see whether there is something that conflicts/prevents the blink and for suggestions to get the two buttons to trigger the GREEN Led together?

Additionally I'd appreciate any feedback as to whether you think this code is ok or if there are areas that need cleaning up or whether there is something else I should be using?

Below is my current code, which I have adapted from other projects and suggestions within the forum:

const byte maxDataLength = 20;
char receivedChars[21] ;
boolean newData = false;

const byte RED_PIN = 9;
const byte AMBER_PIN = 10;
const byte GREEN_PIN = 11;
const byte SWITCHRED_PIN = 3;
const byte SWITCHAMBER_PIN = 4;
const byte SWITCHGREEN_PIN = 2;
const byte SWITCHMASTER_PIN = 5;

boolean RED_State = false;
boolean AMBER_State = false;
boolean GREEN_State = false;
boolean SWITCHRED_State = false;
boolean SWITCHAMBER_State = false;
boolean SWITCHGREEN_State = false;
boolean SWITCHMASTER_State = false;
boolean oldSWITCHRED_State = false;
boolean oldSWITCHAMBER_State = false;
boolean oldSWITCHGREEN_State = false;
boolean oldSWITCHMASTER_State = false;

void setup()  
{
    pinMode(SWITCHRED_PIN, INPUT); 
    pinMode(SWITCHAMBER_PIN, INPUT);     
    pinMode(SWITCHGREEN_PIN, INPUT); 
    pinMode(SWITCHMASTER_PIN, INPUT); 

    pinMode(RED_PIN, OUTPUT);  digitalWrite(RED_PIN,LOW);
    pinMode(AMBER_PIN, OUTPUT);  digitalWrite(AMBER_PIN,LOW);
    pinMode(GREEN_PIN, OUTPUT);  digitalWrite(GREEN_PIN,LOW);
  
    Serial.begin(9600);
    Serial.println(" ");
     
}
 
 
void loop()  
{
       checkSwitch();
       recvWithStartEndMarkers();                
       if (newData)  {   processCommand();  }
}

void checkSwitch()
{
     boolean state1 = digitalRead(SWITCHRED_PIN); delay(1);
     boolean state2 = digitalRead(SWITCHRED_PIN); delay(1);
     boolean state3 = digitalRead(SWITCHRED_PIN); delay(1);
  	 boolean state4 = digitalRead(SWITCHRED_PIN); delay(1);
     if ((state1 == state2) && (state1==state3)&& (state1==state4)) 
     { 
          
          SWITCHRED_State = state1;  
          if ( (SWITCHRED_State == HIGH) && (oldSWITCHRED_State == LOW) )
          {
               RED_State = ! RED_State;  
               if ( RED_State == HIGH) 
               {  
                    digitalWrite(AMBER_PIN,LOW);  
                    digitalWrite(GREEN_PIN,LOW);
                    digitalWrite(RED_PIN,HIGH);
                    Serial.println("RED"); 
               }    
          }          
          oldSWITCHRED_State = SWITCHRED_State;
      }

     // Simple toggle switch function with very simple debouce.
     state1 = digitalRead(SWITCHAMBER_PIN); delay(1);
     state2 = digitalRead(SWITCHAMBER_PIN); delay(1);
     state3 = digitalRead(SWITCHAMBER_PIN); delay(1);
     state4 = digitalRead(SWITCHAMBER_PIN); delay(1);
     if ((state1 == state2) && (state1==state3) && (state1==state4))   
     { 
          SWITCHAMBER_State = state2;  
          if ( (SWITCHAMBER_State == HIGH) && (oldSWITCHAMBER_State == LOW) )
          {
               AMBER_State = ! AMBER_State;  
               if ( AMBER_State == HIGH) 
               {  
                    digitalWrite(GREEN_PIN,LOW);
                    digitalWrite(RED_PIN,LOW);
                    digitalWrite(AMBER_PIN,HIGH);
                    Serial.println("AMBER"); 
               }    
          }          
          oldSWITCHAMBER_State = SWITCHAMBER_State;
      }

     // Simple toggle switch function with very simple debouce.
     state1 = digitalRead(SWITCHGREEN_PIN); delay(1);
     state2 = digitalRead(SWITCHGREEN_PIN); delay(1);
     state3 = digitalRead(SWITCHGREEN_PIN); delay(1);
  	 state4 = digitalRead(SWITCHGREEN_PIN); delay(1);
     if ((state1 == state2) && (state1==state3)&& (state1==state4))  
     { 
          SWITCHGREEN_State = state3;  
          if ( (SWITCHGREEN_State == HIGH) && (oldSWITCHGREEN_State == LOW) )
          {
               GREEN_State = ! GREEN_State;  
               if ( GREEN_State == HIGH) 
               {  
                    digitalWrite(RED_PIN,LOW);  
                    digitalWrite(AMBER_PIN,LOW); 
                    digitalWrite(GREEN_PIN,HIGH);
                    Serial.println("GREEN"); 
               }    
          }          
          oldSWITCHGREEN_State = SWITCHGREEN_State;
      }
  
     // Simple toggle switch function with very simple debouce.
     state1 = digitalRead(SWITCHMASTER_PIN); delay(1);
     state2 = digitalRead(SWITCHMASTER_PIN); delay(1);
     state3 = digitalRead(SWITCHMASTER_PIN); delay(1);
     state4 = digitalRead(SWITCHMASTER_PIN); delay(1);
     if ((state1 == state2) && (state1 == state3)&& (state1 == state4))   
     { 
         SWITCHMASTER_State = state4;  
          if ( (SWITCHMASTER_State == HIGH) && (oldSWITCHMASTER_State == LOW) )
          {
               GREEN_State = ! GREEN_State;  
               if ( GREEN_State == HIGH) 
               {   
                   digitalWrite(AMBER_PIN,LOW); 
                   digitalWrite(RED_PIN,LOW); 
                   digitalWrite(GREEN_PIN,LOW);  
                   Serial.println("ALL LIGHTS OFF");    
               }    
          }          
          oldSWITCHGREEN_State = SWITCHGREEN_State;
      }
}


void processCommand()
{

}

void recvWithStartEndMarkers()
{
     static boolean recvInProgress = false;
     static byte ndx = 0;
     char startMarker = '<';
     char endMarker = '>';
     char rc;

}

jayjayuk80s:
I have seen in previous forum posts that "even if you hit it with a hammer you can not press both buttons at the same time", however I am hoping this maybe different, as my MASTER_SWITCH will in fact be pressed and held down, whilst the SWITCH_GREEN is then pressed.

Yes, that is fine. If you require that the master switch is pressed first, just check if the switch is pressed before performing the green switch logic.
You do not even need to debounce the master switch to do this (since, as it is already pressed, any debounce is over).

Once I have solved this issue, I may extend my MASTER switch to activate another output when pressed on its own. But I am not yet ready for that as I am trying to get this working first (but to no avail).

That's a problem then. You are back to your chicken and egg situation with trying to decided "Did the user press the master button so they could press it in conjunction with another button, or did they press it on it's own?".

Your problem can be solved, but not by using your simple "linear" logic you have here. You need to time when buttons are pressed or released and wait for a period of time before deciding on if any action should be taken or not. That allows you to discard button presses which are just one button being pressed slightly before another one in a multi-button sequence. On the plus side this will also do your debounce logic.

BTW: I've no idea where this 3 times reading each button came from - it seems a very complex way to do debounce (if that's what indeed it is).

In addition, I would also like to change my RED LED to blink/flash, rather than just coming on and staying on. I did see in another forum posting a suggestion of

 digitalWrite(pin, millis() & 0x100);

but have not managed to get this to work. My LED would not activate at all when the button was pressed :frowning:

This code will work. Put it at the start of loop() and NOT inside any other IF statement.

My guess is when you tried it you replaced this line in your current code...

digitalWrite(RED_PIN,LOW);

That won't work because that line one executes ONCE each time the button press changes state.

You would need to instead set a variable "true" when you want the led to flash..

redLedFlash = true;

And then continuously in loop...

if (redLedFlash)
{
   digitalWrite(RED_PIN, millis() & 0x100);
}
else
{
   digitalWrite(RED_PIN, LOW);
}

I explained this in a previous post. If one button is held down, it is not momentary. I would recommend debouncing the individual LED buttons, but it shouldn't be necessary with the master button that is held down.

Something like (untested)...

enum BUTTONS { NONE = 0, RED = 1, AMBER = 2, GREEN = 4, MASTER = 8 };

const byte maxDataLength = 20;
char receivedChars[21] ;
boolean newData = false;

const byte RED_PIN = 9;
const byte AMBER_PIN = 10;
const byte GREEN_PIN = 11;
const byte SWITCHRED_PIN = 3;
const byte SWITCHAMBER_PIN = 4;
const byte SWITCHGREEN_PIN = 2;
const byte SWITCHMASTER_PIN = 5;

uint32_t lastChanged;
BUTTONS lastButtons;
BUTTONS pressedButtons;

void setup() 
{
    pinMode(SWITCHRED_PIN, INPUT);
    pinMode(SWITCHAMBER_PIN, INPUT);     
    pinMode(SWITCHGREEN_PIN, INPUT);
    pinMode(SWITCHMASTER_PIN, INPUT);

    pinMode(RED_PIN, OUTPUT);  digitalWrite(RED_PIN,LOW);
    pinMode(AMBER_PIN, OUTPUT);  digitalWrite(AMBER_PIN,LOW);
    pinMode(GREEN_PIN, OUTPUT);  digitalWrite(GREEN_PIN,LOW);
 
    Serial.begin(9600);
    Serial.println(" ");
     
}
 
 
void loop() 
{
       checkSwitch();
       recvWithStartEndMarkers();               
       if (newData)  {   processCommand();  }
}

void checkSwitch()
{
  uint32_t now = millis();

  // Get currently pressed buttons
  BUTTONS buttons = BUTTONS::NONE;
  if (digitalRead(SWITCHRED_PIN)) buttons |= BUTTONS::RED;
  if (digitalRead(SWITCHAMBER_PIN)) buttons |= BUTTONS::AMBER;
  if (digitalRead(SWITCHGREEN_PIN))  buttons |= BUTTONS::GREEN;
  if (digitalRead(SWITCHMASTER_PIN)) buttons |= BUTTONS::MASTER;

  // Start debounce timer
  if (buttons != lastButtons)
  {
    lastChanged = now;
    lastButtons = buttons;
  }

  // Debounce over
  if (now - lastChanged > 100)
  {
    // No keys were pressed and something changed?
    if (pressedButtons == BUTTONS::NONE && buttons != pressedButtons)
    {
      switch (buttons)
      {
        // Just RED pressed
        case BUTTONS::RED:
          digitalWrite(AMBER_PIN,LOW); 
          digitalWrite(GREEN_PIN,LOW);
          digitalWrite(RED_PIN,HIGH);
          Serial.println("RED");
          break;
  
        // Just AMBER pressed
        case BUTTONS::AMBER:
          digitalWrite(GREEN_PIN,LOW);
          digitalWrite(RED_PIN,LOW);
          digitalWrite(AMBER_PIN,HIGH);
          Serial.println("AMBER");
          break;
        
        // Just GREEN pressed
        case BUTTONS::GREEN:
          digitalWrite(RED_PIN,LOW); 
          digitalWrite(AMBER_PIN,LOW);
          digitalWrite(GREEN_PIN,HIGH);
          Serial.println("GREEN");
          break;

        // MASTER **and** GREEN pressed together
        case BUTTONS::MASTER | BUTTONS::GREEN:
          // Do somwthing different....
          break;
      }
    }
    pressedButtons = buttons;
  }
}

void processCommand()
{
}

void recvWithStartEndMarkers()
{
     static boolean recvInProgress = false;
     static byte ndx = 0;
     char startMarker = '<';
     char endMarker = '>';
     char rc;
}

But you are masking bit 8...

millis() & 0x100

That is zero every 256 milliseconds and stays zero (LOW) for 256 milliseconds.
Then it is 0x100 for the next 256 miliseconds, etc.

And digtalWrite takes any non zero value as ON.

Unfortunately it also only takes a byte parameter. So masking with 0x100 won't work.

Either of the following will work...

digitalWrite(pin, (millis() & 0x100) != 0);
digitalWrite(pin, millis() & 0x80);

Hi Guys, firstly thank you for the feedback and comments.

I am really new to all of this but am attempting to improve the code based on the comments and suggestions (currently unsuccessfully, but hope this will change shortly) and will post an update and my updated code as soon as I manage to resolve it.

@pcbbc - I did also try your untested code suggestion, but unfortunately I received the following error:

In function 'void checkSwitch()':
54:43: error: invalid conversion from 'int' to 'BUTTONS' [-fpermissive]
55:45: error: invalid conversion from 'int' to 'BUTTONS' [-fpermissive]
56:46: error: invalid conversion from 'int' to 'BUTTONS' [-fpermissive]
57:46: error: invalid conversion from 'int' to 'BUTTONS' [-fpermissive]
exit status 1

at the following stage:

[ code ]
// Start debounce timer
if (buttons != lastButtons)
{
lastChanged = now;
lastButtons = buttons;
[ /code]

Thanks again guys for the help

No errors here when I compile the exact code I posted.

The errors you give do not correspond to the code snippet you posted either. None of those lines have 43, 45 or 46 characters.

Code tags must be without spaces: [​code]code tags[​/code]

Apologies (twice), somehow I put extra spaces in my code tags which is why it did not post correctly. This time round I clicked the Preview button first :wink:

Secondly @pcbbc, as I had to create my diagram from the original post I used tinkercad, so cheating I thought I'd quickly test your code on there too. It was when I compiled on there previously it came up with those errors I meanted. This was probably was also not the best idea to do, as I would not also be able to press two buttons at the same time :confused:

But when I upload your code (which I have saved as suggestion.ino in thre below) on to my physical arduino it does compile, but I do receive the following red text before the confirmation is received:

My C Drive Location/suggestion.ino:In function 'void checkSwitch()':
My C Drive Location/suggestion.ino:49:43: warning: invalid conversion from 'int' to 'BUTTONS' [-fpermissive]
   if (digitalRead(SWITCHRED_PIN)) buttons |= BUTTONS::RED;
                                   ~~~~~~~~^~~~~~~~~~
My C Drive Location/suggestion.ino:50:45: warning: invalid conversion from 'int' to 'BUTTONS' [-fpermissive]
   if (digitalRead(SWITCHAMBER_PIN)) buttons |= BUTTONS::AMBER;
                                     ~~~~~~~~^~~~~~~~~~
C Drive Location/suggestion.ino:51:46: warning: invalid conversion from 'int' to 'BUTTONS' [-fpermissive]
   if (digitalRead(SWITCHGREEN_PIN))  buttons |= BUTTONS::GREEN;
                                      ~~~~~~~~^~~~~~~~~~
C Drive Location/suggestion.ino:52:46: warning: invalid conversion from 'int' to 'BUTTONS' [-fpermissive]
   if (digitalRead(SWITCHMASTER_PIN)) buttons |= BUTTONS::MASTER;
                                      ~~~~~~~~^~~~~~~~~~

[

That said it this does work and does exactly what I asked in my original post re the two buttons. So thank you again!

However after testing your suggestion, its now got me thinking about the logical way I will use this solution and I'm going to make some changes, as I now believe the Master button will be pressed and held down, prior to the green button then being pressed a few seconds afterwards. This is different to my original thinking when I thought it would be pressed at the same time, so I will investigate some further changes.

thank you again @Perehama & @pcbbc for all your help and feedback.