Remembering button state

Hello i am new here but i have done programming and some parallax in highschool know in college everything is Arduino based.i was just wondering how can you get a button to input a state and remember the state when the the button is depressed then follow the procedure and then go through with the loop if the button is not pressed

how can you get a button to input a state and remember the state

int currState = digitalRead(somePin);

and remember the state

static const int somePin=9; // your input pin

int lastState;  // define outside to keep its value 

void setup() 
{
   lastState = digitalRead(somePin); 
}

void loop()
{
    int currState = digitalRead(somePin);
    // compare currState with lastState here 
    // ...


   lastState = currState; // remember for next loop round
}

int lastState; // define outside to keep its value

Or define it "static" inside loop:

void loop()
{
  static int laststate = LOW;
  int currentstate = digitalRead(somePin)

  if(currentstate != laststate)
  {
    laststate = currentstate;
    // do something
  }
}

seems to be not working i forgot to mention i am trying to simulate a stop light so when i press the button the light delays goes to yellow then red while at red the cross walk goes on . i think the traffic light is the best way to get started with programming my code is below it works the way i want it to but i have to be holding down the button which also means that red will stay on as long the button is HIGH i would like it to go back into the loop after red light.

feed back on my code greatly appreciated

const int red = 5;                //red led is on pin 5 
const int yellow = 4;          //yellow led on pin 4 
const int green = 3;          //green led on pin 3 
const int crosswalk = 6;   //crosswalk button on pin 6 
int buttonState = 0;       // button state is LOW

void setup() 

{
  Serial.begin(9600);  

  pinMode(red, OUTPUT);     //pins red- green set as Outputs 
  pinMode(yellow, OUTPUT);  
  pinMode(green, OUTPUT);  

  pinMode(crosswalk, INPUT);   //crosswalk button set as input device 

}

void loop(){    
buttonState = digitalRead(crosswalk);

    if (buttonState == HIGH){  
    delay(500);
    digitalWrite(yellow, LOW);
    delay(500);
    digitalWrite(red, HIGH);
    delay(100);
 }
else
{
    digitalWrite(yellow, LOW);
    
  Serial.println("red");
  digitalWrite(red, HIGH);    // set the LED on
  delay(8000);                     // wait for eight seconds
  digitalWrite(red, LOW);    // set the LED off
  delay(1000);                     // wait for a second
  
  Serial.println("green");
  digitalWrite(green, HIGH);   // set the LED on
  delay(5000);              // wait for 5 seconds
  digitalWrite(green, LOW);    // set the LED off
  delay(1000);   
  
  Serial.println("yellow");
  digitalWrite(yellow, HIGH);    // set the LED on
  delay(3000);                          // wait for three seconds 
  digitalWrite(yellow, LOW);    // set the LED off
  delay(1000);   
  
}
}

Your whole logic is wrong.

What you want is a sequence more like this:

  1. Turn on green light.
  2. Wait for button to be pressed.
  3. Turn off green, turn on yellow, delay.
  4. Turn off yellow, turn on red, delay.
  5. Turn on crosswalk, delay.
  6. Turn off crosswalk, delay.
  7. Turn on yellow, delay.
  8. Turn off red & yellow, turn on green. Go back to 2.

or whatever sequence your country uses.

I'd write it something like (untested) this:

void setup()
{
  pinMode(green,OUTPUT);
  pinMode(yellow,OUTPUT);
  pinMode(red,OUTPUT);
  pinMode(crosswalk,OUTPUT);
  pinMode(button,INPUT);
  digitalWrite(green,HIGH);
  digitalWrite(yellow,LOW);
  digitalWrite(red,LOW);
  digitalWrite(crosswalk,LOW);
}

void loop()
{
  // Wait for button press
  while(digitalRead(button)==LOW);

  // Yellow on, green off
  digitalWrite(yellow,HIGH);
  digitalWrite(green,LOW);
  delay(1000);

  // Red on, yellow off
  digitalWrite(red,HIGH);
  digitalWrite(yellow,LOW);
  delay(1000);

  // Crosswalk on
  digitalWrite(crosswalk,HIGH);
  delay(5000);

  // Crosswalk off
  digitalWrite(crosswalk,LOW);
  delay(1000);

  // Yellow on
  digitalWrite(yellow,HIGH);
  delay(1000);

  // Green on, yellow off, red off.
  digitalWrite(green,HIGH);
  digitalWrite(yellow,LOW);
  digitalWrite(red,LOW);

  // loop() runs again.
}

You know those delays keep your project from seeing what is going on with the switch(es)?

You can keep track of time passed with millis(). Store millis() in unsigned long and when you add or subtract times it won't matter if the variables 'roll over'.

The OP is new to programming the Arduino... Keep it simple. One button, no intermediate interaction. I didn't want to confuse the poor boy with talk of state machines and such.

Look at the OP's code again maybe? edit: and then the thread title. BTW, how complicated do you think a state machine is? He needs three states; green, yellow, red, and none for the button.

What do -you- want he should have?

What do -you- want he should have?

A PIC16F88 :P

I only use Arduino for things for other people who use Arduino. Anything else - i.e., things I make myself, I use a dedicated microcontroller - usually a PIC - and I get the right one for the job.

Oh, and if you remember from http://arduino.cc/forum/index.php/topic,107202.0.html I know all about state machines and recommend them in the right place.

Something as simple as this, while it could[/u] be done with a state machine, doesn't need to be done with a state machine. As you can see from that other thread, a state machine is simple once you know how to do them. Trying to get a novice coder to understand them whilst trying to get them to understand the basics of programming at the same time is not an easy task. First steps first.

I wrote my first state machines back around 1980-1981 and to me they can make things simpler, certainly reduce code and indent levels.

In his case, he only needs to track what light is on (the 'machine state') to know what to do if the button is pressed.

The "big" lesson for him is learning how to get around using delay() and to work time-based. Another good lesson will be to lose the top-down approach to coding which running on state should do inherently.

Considering that he's not a complete newb to programming, it shouldn't be a real problem.

Hello i am new here but i have done programming and some parallax in highschool

so to get my code to work i need to do major changes to get the button to remember the sate for the lights for a set time? & executing the loop. also by getting rid of a delay i can use "millis" is millis a built in timer ?

is millis a built in timer ?

millis() is a function which returns an unsigned long value. That value is a counter which starts at 0 at power-on and is incremented once every 1 millisecond. It uses one of the internal timers of the AVR chip to give reasonably accurate interrupt driven timing.

240sx: so to get my code to work i need to do major changes to get the button to remember the sate for the lights for a set time? & executing the loop. also by getting rid of a delay i can use "millis" is millis a built in timer ?

You already have a basic idea of what you want, maybe the hardest part even if you change how it is to work. The more specific you are about that, the easier it will be to code. Honest, changing the spec while coding has led to umpteen missed deadlines.

Nick Gammon on this forum has a page where he compares coding to making egg and toast for breakfast. The top-down way, first you cook the egg for X minutes and then you cook the toast for Y minutes and then you are done. IRL you start the egg and take note of the time then start the toast and take note of that time. When X minutes have gone by, the egg is done. When Y minutes have gone by, the toast is done. It doesn't matter of X is more than Y since you watch the time rather than depend on the egg or toast being done first. Every second you are only watching for something to be done.

You can use loop() that way (don't have to). Every time through loop() what code is run depends on conditions you have saved as 'states'. Your code is always "in the now". So in your case you can get by just saving what color light is lit and when it started. If the color is green then you want to watch for 5 seconds to have gone by before turning green off, switching yellow on and changing the color state from green to yellow. During that 5 seconds loop() will run many millions of times, letting your code watch for button press. If the button is pressed it doesn't matter what color light is lit, you change the light and the color state then that becomes "the now" for the next time through loop(). You can even have extra "color states" that have different timing, like flashing yellow or red or an Officer in charge mode that only changes with a button press, though how you get into such a mode is up to you. Once you have the basic code it is not a big deal to add such modes.

The important thing is to change from the fixed sequence (first green, the yellow, then red) inside of loop() to controlling what code runs during each pass through loop() using stored conditions/states and whatever happens, like a button press. It will liberate you from having to integrate exceptions and time-watching and any new ideas into the same structure that controls the fixed step 1 then step 2 then step 3 sequence.

thanks for the the input guys; GoForSmoke i understand what not to do with that write up now so am going to take a hit at millis to get rid of the delays. but would i still need a delay so lager amount of code dose not pile up ? any tips on millis would help

Here is the official Blink Without Delay Example:

It shows the basics of dealing with millis() and uses one variable for led state = on or off.

If you wanted to add a button to that it would be easy enough. The new code would be outside of the " if(currentMillis - previousMillis > interval) {" block and could change the led & ledstate as well as previousMillis to make whatever change you want/can get away with.

Once you learn millis(), look up micros().