Help with simple problem

So I've spent the last few hours with a ridiculously simple problem, but my logic appears to have an issue somewhere.

I'm trying to make a simple software latch for another project:

push button, led stays on
push button again, led stays off
push button again, led stays on

etc

I have it working except for one last thing, here is the code

//simple program to test making a latch
//button held low by 10k pull down, button pressed should latch led on
//button pressed again, led should latch off


//variables
boolean ledpin = 13;  //led on pin 13
boolean button = 12;  //button on pin 12
boolean state = 0;    //state of button pin
boolean newState = 0;  //new button state variable



void setup(){
  pinMode(ledpin, OUTPUT);  //led output
  pinMode(button, INPUT);  //button input
}

void loop() {
  
  state = (digitalRead(button));    //state is value of button
  
  
 
 if(state == 0 && newState == 0){  //if state and lastState are both 0 (button unpressed)
   digitalWrite(ledpin, LOW);       // led is off
   newState = 0;                  //lastState is still 0
    }
 
 if(state == 1 && newState == 0){  //if state is 1 (button press) and lastState is 0
   digitalWrite(ledpin, HIGH);      //led is on
   newState = 1;                   // lastState is now 1
 }
 if(state == 0 && newState == 1){  //if state is 0(button unpressed) and lastState is 1
   digitalWrite(ledpin, HIGH);      //led is on
   newState = 1;                    //lastState is still 1
 }
 if(state == 1 && newState == 1){  //if state is 1(button pressed) and lastState is 1
   digitalWrite(ledpin, LOW);   //turn led off
   //newState = 0;   //lastState should now be 0 again and loop repeats
   
   
 }
  }

//rinse and repeat

Now, that code will make the led latch on after pressing the button but when i push it again, the led blinks off but stays on when i release the button.

The commented out bit of the last If statement was my attempt to fix this but i'm having a logic issue somewhere. :stuck_out_tongue: I'v also tried setting both 'state' and 'newState' to 0 when 'state' and 'newState' = 1 but to no avail.

I know this will have a simple answer, can someone please tell me what i'm missing?

:slight_smile:

tell me what i'm missing?

The most likely problem is that the switch bounces. Add a small delay after reading the switch state, to prevent reading the bounces.

There is also the problem that you should be using elses.

if(state == 0 && newState == 0)
// Do something
else if(state == 1 && newState == 0)
// Do something
else if(state == 0 && newState == 1)
// Do something
else if(state == 1 && newState == 1)
// Do something

As it is right now, multiple if tests may succeed, as you change states in previous blocks.

The value that you want for newState is the value that is in state, regarless of which action occurred. So, remove the code for setting newState, and add
newState = state; after all the if tests.

I have tried delays but to no avail. I have the switch debounced in hardware on my actual circuit.

I'm thinking it must be something to do with the last If statement.

I edited my last post while you were posting...

I saw that yes. I tried your way initially and have just redone it, but now nothing happens at all when I press the button.

//simple program to test making a latch
//button held low by 10k pull down, button pressed should latch led on
//button pressed again, led should latch off


//variables
boolean ledpin = 13;  //led on pin 13
boolean button = 12;  //button on pin 12
boolean state = 0;    //state of button pin
boolean newState = 0;  //new button state variable



void setup(){
  pinMode(ledpin, OUTPUT);  //led output
  pinMode(button, INPUT);  //button input
}

void loop() {
  
  state = (digitalRead(button));    //state is value of button
  
  
 
 if(state == 0 && newState == 0){  //if state and lastState are both 0 (button unpressed)
   digitalWrite(ledpin, LOW);       // led is off
   newState = state;                  //lastState is still 0
    }
 
 else if(state == 1 && newState == 0){  //if state is 1 (button press) and lastState is 0
   digitalWrite(ledpin, HIGH);      //led is on
   newState = state;                   // lastState is now 1
 }
 
 
 else if(state == 0 && newState == 1){  //if state is 0(button unpressed) and lastState is 1
   digitalWrite(ledpin, HIGH);      //led is on
   newState = state;                    //lastState is still 1
 }
 
 else if(state == 1 && newState == 1){  //if state is 1(button pressed) and lastState is 1
   digitalWrite(ledpin, LOW);   //turn led off
   newState = state;   //lastState should now be 0 again and loop repeats
   
   
 }
  }

//rinse and repeat

Try this:

 if(state == 0 && newState == 0){  // switch is not and was not pressed
   digitalWrite(ledpin, LOW);
}

 else if(state == 1 && newState == 0){  // switch was just pressed
   digitalWrite(ledpin, HIGH);
}


 else if(state == 0 && newState == 1){  // switch was just released
   digitalWrite(ledpin, HIGH);      //led is on
}

 else if(state == 1 && newState == 1){  // switch is pressed and was pressed last time we checked
   digitalWrite(ledpin, LOW);   //turn led off
}
newState = state;  // newState is whatever the switch state was

Notice that I changed when the previous state is stored (newState is a lousy name for old state) and I changed the comments to reflect what test really means. You may need to change what happens in the block to agree with the comments.

I just got somewhere as I read your post. I tried your way but it didn't seem to work. I put a delay before the If statements in your code but when the button was pressed or depressed the led just flickers but no latching occurs.

I found this solution works, I was focusing on my 4th If statement but then I looked at my 3rd and made the following changes:

//simple program to test making a latch
//button held low by 10k pull down, button pressed should latch led on
//button pressed again, led should latch off


//variables
boolean ledpin = 13;  //led on pin 13
boolean button = 12;  //button on pin 12
boolean state = 0;    //state of button pin
boolean newState = 0;  //new button state variable



void setup(){
  pinMode(ledpin, OUTPUT);  //led output
  pinMode(button, INPUT);  //button input
}

void loop() {

  state = (digitalRead(button));    //state is value of button
  delay(70);  //button debounce (not needed if debounce circuit exists)


 if(state == 0 && newState == 0){  //if state and lastState are both 0 (button unpressed)
   digitalWrite(ledpin, LOW);       // led is off
   newState = state;                  //lastState is still 0
    }
 else if(state == 1 && newState == 0){  //if state is 1 (button press) and lastState is 0
   digitalWrite(ledpin, HIGH);      //led is on
   newState = state;                   // lastState is now 1
 }
 else if(state == 0 && newState == 1){  //if state is 0(button unpressed) and lastState is 1
   digitalWrite(ledpin, HIGH);      //led is on
   //newState = 1;                    //lastState is still 1
 }
 else if(state == 1 && newState == 1){  //if state is 1(button pressed) and lastState is 1
   digitalWrite(ledpin, LOW);   //turn led off
   newState = 0;   //lastState should now be 0 again and loop repeats


 }

 }

//rinse and repeat

I basically just took out the 'newState' change in the 3rd If statement and now it works. It should work better on my actual hardware debounce circuit.

:slight_smile:

Clean programming practices, the faster you learn it, the less time you will spend pulling out your hair.

This should work just as well and be easier to read:

if (buttonstate == 1){
switch (LEDstate){
case 0:
digitalWrite(ledpin, HIGH);
LEDstate=1;
break;
case 1:
digitalWrite(ledpin, LOW);
LEDstate=0;
break;
}
}

I'm always impressed by people who can code good. :slight_smile:

I'm always impressed by people who can code good.

Me too, I wish I was among them. ;D

Lefty