Three Push Buttons, One LED

Hello,

I have 3 pushbuttons and i'd like each one to do something different to a single LED:

Button 1 : Press and release = LED stays on

Button 2 : Used as a 'cutoff' button, i.e. when button 1 is pressed and released and the LED is on, button 2 can be pressed and released to turn off the LED.

Button 3 : Press and hold = LED stays on, release button = LED turns off

I'm able to achieve button 1 and 2 working as above, but button 3 is causing me trouble (since an "else if button 3 == LOW, digital write LED LOW" would stop button 1 "latching"), does anyone have an idea of how i could go about this?

The code is as follows:

const int button1 = 12; // manual on
const int button2 = 8; // stop
const int button3 = 7; // auto on
const int led = 13; 

void setup(){ 
pinMode(led, OUTPUT); 
pinMode(button1, INPUT); 
pinMode(button2, INPUT);
pinMode(button3, INPUT);
}

void loop(){ 
if(digitalRead(button1) == HIGH){     // i.e. latch the LED on until stop button is pressed
  digitalWrite(led, HIGH);
}

if(digitalRead(button2) == HIGH){
  digitalWrite(led, LOW);
}
}

Its not clear (without code) when you think button 3 should do?

You state: " release button = LED turns off" for button 3…

So it would seem that it is working as intended?

Explain your secnario(s)

If button 1 turns on the led… and then button 3 is pressed… what should happen? What should happen when button 3 is released then?

Without knowing your desired outcome/results… I can only suggest then when button 3 is pressed you also check the state of led (or perhaps button 1 if it is truly a latching switch)…

If the led is ON when button 3 is pressed, and you do NOT want it to turn off when released… then in effect button 3 has no bearing on the project/led if its already on…

actually saving the led STATE to a variable in all button action is probably the best approach… or even just saving the button that triggered the led… (so you know when its ok for button 3 to turn things off or not)

maybe something along the lines like: (not tested, sitting at work still)

const int button1 = 12; // manual on
const int button2 = 8; // stop
const int button3 = 7; // auto on
const int led = 13;
int buttonTrigger = 0;

void setup(){
	pinMode(led, OUTPUT);
	pinMode(button1, INPUT);
	pinMode(button2, INPUT);
	pinMode(button3, INPUT);
}

void loop(){
	if(digitalRead(button1) == HIGH){     // i.e. latch the LED on until stop button is pressed
	  digitalWrite(led, HIGH);
	  ledState = 1;
	  buttonTrigger = 1;
	}

	if(digitalRead(button2) == HIGH){
	  digitalWrite(led, LOW);
	  ledState = 0;
	  buttonTrigger = 2;
	}
}

if(digitalRead(button3) == HIGH){
	//check led state
	if(digitalRead(led) == HIGH){
		//behave accordingly:
		//already on, do nothing
	}else{
		//behave accordingly:
		//led if currently off, its ok to turn it on)
		buttonTrigger = 3;
		digitalWrite(led, HIGH);
	}  
}else{
	//button 3 is low/released
	if(buttonTrigger == 3){
		//button 3 turned it on, so its ok to turn off
		digitalWrite(led, LOW);
	}
}

explain more and you can get help.

CBlewitt1:
I'm able to achieve button 1 and 2 working as above, but button 3 is causing me trouble (since an "else if button 3 == LOW, digital write LED LOW" would stop button 1 "latching"), does anyone have an idea of how i could go about this?

In the IDE, investigate : File/examples/digital/state change detection. Rather than sensing when button 3 _is _LOW, you need to sense when it _becomes _LOW. This can also be applied to the other switches to sense press and release.

The essential idea is that the **change of state ** is only true for one 'scan', or pass through the sketch, as opposed to button == LOW being true/false continously

Ok, i've renamed buttons 1, 2 and 3 to AutoRaise, Stop and ManualRaise (basically this code is eventually to be used on a materials testing rig, with vices that require manual and automatic movement, and a stop button) and ammended the code as per your suggestions.

AutoRaise leaves the LED on once released (and also, of course, turns it off once pressed again, as the counter changes - not ideal but no biggie)

ManualRaise turns the LED on only when held in, turning off when released - perfect.

The Stop button is still causing issues however since the counter modulo can be 0 whilst the autoraise counter is 0 therefore fighting against each other i assume.

I really need to figure out a way to say "if a change of state is detected in the stop button WHILE the LED is on (i.e. while "AutoRaiseCounter % 2 == 0" ) then digitalWrite(LedPin, LOW); "

Not sure how to do this though...

const int  AutoRaisePin = 7;
const int ManualRaisePin = 8;
const int StopPin = 12;
const int LedPin = 13;

int AutoRaiseCounter = 1;
int AutoRaiseState = 0;
int AutoRaiseLastState = 0; 

int ManualRaiseState = 0;
int ManualRaiseLastState = 0;

int StopCounter = 1;
int StopState = 0;
int StopLastState = 0;


void setup() {
  pinMode(AutoRaisePin, INPUT);
  pinMode(ManualRaisePin, INPUT);
  pinMode(StopPin, INPUT);
  pinMode(LedPin, OUTPUT);
}


void loop() {
  
////////////////AUTO-RAISE///////////////////////

  AutoRaiseState = digitalRead(AutoRaisePin);
  if (AutoRaiseState != AutoRaiseLastState) {
    if (AutoRaiseState == HIGH) {
      AutoRaiseCounter++;
    }
    delay(50);
  }
  
  AutoRaiseLastState = AutoRaiseState;
  if (AutoRaiseCounter % 2 == 0) {
    digitalWrite(LedPin, HIGH);
  } else {
    digitalWrite(LedPin, LOW);
  }

////////////////MANUAL-RAISE///////////////////////

  ManualRaiseState = digitalRead(ManualRaisePin);
  if (ManualRaiseState == ManualRaiseLastState) {
    if (ManualRaiseState == HIGH) {
      digitalWrite(LedPin, HIGH);
    }
    delay(50);
  } 
  
  else {
    digitalWrite(LedPin, LOW);
  }
  
  ManualRaiseLastState = ManualRaiseState;
  
////////////////STOP-BUTTON///////////////////////  
  
  StopState = digitalRead(StopPin);
  if(StopState != StopLastState){
   if(StopState == HIGH){
   StopCounter++;
  }
  delay(50);
  }

   if(StopCounter % 2 == 0){
     digitalWrite(LedPin,LOW);
   }
   
   StopLastState = StopState;
}

xl97:
Its not clear (without code) when you think button 3 should do?

You state: " release button = LED turns off" for button 3..

So it would seem that it is working as intended?

Explain your secnario(s)

If button 1 turns on the led.. and then button 3 is pressed.. what should happen? What should happen when button 3 is released then?

Without knowing your desired outcome/results.... I can only suggest then when button 3 is pressed you also check the state of led (or perhaps button 1 if it is truly a latching switch)..

If the led is ON when button 3 is pressed, and you do NOT want it to turn off when released.. then in effect button 3 has no bearing on the project/led if its already on.....

actually saving the led STATE to a variable in all button action is probably the best approach.. or even just saving the button that triggered the led... (so you know when its ok for button 3 to turn things off or not)

maybe something along the lines like: (not tested, sitting at work still)

const int button1 = 12; // manual on

const int button2 = 8; // stop
const int button3 = 7; // auto on
const int led = 13;
int buttonTrigger = 0;

void setup(){
pinMode(led, OUTPUT);
pinMode(button1, INPUT);
pinMode(button2, INPUT);
pinMode(button3, INPUT);
}

void loop(){
if(digitalRead(button1) == HIGH){     // i.e. latch the LED on until stop button is pressed
 digitalWrite(led, HIGH);
 ledState = 1;
 buttonTrigger = 1;
}

if(digitalRead(button2) == HIGH){
 digitalWrite(led, LOW);
 ledState = 0;
 buttonTrigger = 2;
}
}

if(digitalRead(button3) == HIGH){
//check led state
if(digitalRead(led) == HIGH){
//behave accordingly:
//already on, do nothing
}else{
//behave accordingly:
//led if currently off, its ok to turn it on)
buttonTrigger = 3;
digitalWrite(led, HIGH);
}  
}else{
//button 3 is low/released
if(buttonTrigger == 3){
//button 3 turned it on, so its ok to turn off
digitalWrite(led, LOW);
}
}







explain more and you can get help.

Ok this works perfectly! declaration of led state and a couple extra brackets added:

const int button1 = 12; // manual on
const int button2 = 8; // stop
const int button3 = 7; // auto on
const int led = 13;
int buttonTrigger = 0;
int ledState = 0;

void setup(){
 pinMode(led, OUTPUT);
 pinMode(button1, INPUT);
 pinMode(button2, INPUT);
 pinMode(button3, INPUT);
}

void loop(){
 if(digitalRead(button1) == HIGH){     // i.e. latch the LED on until stop button is pressed
  digitalWrite(led, HIGH);
  ledState = 1;
  buttonTrigger = 1;
 }

 if(digitalRead(button2) == HIGH){
  digitalWrite(led, LOW);
  ledState = 0;
  buttonTrigger = 2;
 }

if(digitalRead(button3) == HIGH){
 //check led state
 if(digitalRead(led) == HIGH){
 //behave accordingly:
 //already on, do nothing
 }else{
 //behave accordingly:
 //led if currently off, its ok to turn it on)
 buttonTrigger = 3;
 digitalWrite(led, HIGH);
 }  
}else{
 //button 3 is low/released
 if(buttonTrigger == 3){
 //button 3 turned it on, so its ok to turn off
 digitalWrite(led, LOW);
 }
}
}

Thanks!!

I dont even think you need the ledstate var/stuff anymore.. (I thought I had removed it?)

Just FYI you can do timing using the Arduino millis() and micros() commands to get time since startup and by subtracting a start time from an end time get the difference, the time elapsed between start and end. By using unsigned values, the same code works across rollover as not.

Both millis() and micros return unsigned long values. You can use smaller variables but unsigned long works for being able to measure long intervals.

So if you have a button press event with time and the release event time you can know how long the button was down.

The maybe tricky part is that the events never occur in the same pass through loop(). You have to save states and data though if data == 0 is one state and data > 0 is the other then the data IS the state and one less variable to confuse things is needed.