Newbie confused with if statement

Hi all, I've just started with electronics and programming so please bear with me. I am trying to work through this example and I cannot figure out how the first if statement can ever run after the first time it runs. The first time it runs, all is ok, but lower down in the program, the value for val is assigned to old_val which means its value will always be 1 or HIGH. If this is the case, the first if condition can never be repeated again if old_val == 1 :

void loop(){
val = digitalRead(BUTTON);

if ((val == HIGH) && (old_val == LOW)) //first if statement
{
state = 1 - state;
delay(10);
}

old_val = val;

if (state == 1)
{
digitalWrite(LED, HIGH);
} else
{
digitalWrite(LED, LOW);
}
}

old_val = val;

is outside of the if statement. So on a future time through the digitalRead returns a LOW, then the if statement will not execute, but old_val will be set to LOW. Then the next time that val is HIGH the if statement will run again.

Now the

state = 1 - state;

confuses me a bit though.

Hey all,

It's ok, we all have to start from somewhere!

It changes because of the digitalRead function. The digitalRead function looks at the pin and is "high". Have a look at the digitalRead tutorials.

and the
state = 1 - state;

if state = 0, it becomes 1, if states is 1, it becomes 0. So it is a simple way of toggling the variable "state" between 1 and 0.

I've gone through this and commented on this persons code for you...

void loop(){ \

 /*
 Every time the loop goes through, check what value the
 button is at.  
 
 If the button is being pushed, the value put in "val" is
 "HIGH"; otherwise it is "LOW"
 */
 val = digitalRead(BUTTON); 

 /*
 val == HIGH -> the buton needs to be pushed
 old_val == LOW -> the last time the code went through
 loop, the value for "val" was LOW
 
 ie: If the button has just been pushed...
 */
 if ((val == HIGH) && (old_val == LOW)) 
 { 
   /*
   if state was 0...
   state = 1 - 0 = 1
   
   if state was 1...
   state = 1-1 = 0
   */
   state = 1 - state;
   
   /*
   This delay is for debouncing.
   might be worth a google search on why you need 
   this.  Basically, the button "bounces" when closed
   */
   delay(10);
 } 

 /*
 This is where the value of the button is remembered for 
 the next time the button goes around the loop...
 */
 old_val = val;

 /*
 if there was a button pushed, turn on an LED light,
 otherwise turn it off
 */
 if (state == 1) 
 {      
   digitalWrite(LED, HIGH);  
 } else 
   { 
     digitalWrite(LED, LOW); 
   } 
}//go back to the top of the loop

Can you see that the first time that you push the button, the LED will turn on, and then the second time you push it, it will turn off?

Hey all,

Thanks for the fantastic feedback. The code works fine and does what it should - one push on, another push off. I think I'm getting this, and the "state" part is pretty well understood. One question though. Does "val" go high each time the button is pressed? If so, then I still cannot see how "old_val" can ever be passed a value other than 1 given that old_val = val; I'm clearly missing something here but if val goes high each time the button is pressed, then old_val must be 1 as well which means that in "if ((val == HIGH) && (old_val == LOW)) ", val ==1 and old_val == 1.

   /*
   if state was 0...
   state = 1 - 0 = 1

   if state was 1...
   state = 1-1 = 0
   */
   state = 1 - state;

I guess that's fine if you declared state as a boolean type. (It wasn't shown in the code snippet.) But wouldn't it be more straightforward to use:

state = !state;

...which would also work for byte or int data types.

dezignit:

The digitalRead checks the condition of the input each time it is called, so it would return LOW if the button is not currently pressed, and HIGH if it is. The code in the "loop()" function is being executed over and over as fast as the Arduino can process it, so it's not waiting at any point for you to push the button. That is also why you have the old_val and the "if" statement.... the loop function (and the digitalRead) might get run 1000 times while you're holding the button down. So old_val remembers that the button was down the last time the loop run and therefore a HIGH in val means you're still holding the button instead of it being a new press.

Basically you have 4 possible conditions:
val = HIGH and old_val = LOW means you just now pushed the button
val = HIGH and old_val = HIGH means you're still holding the button
val = LOW and old_val = HIGH means you just let go of the button
val = LOW and old_val = LOW means the button is still up

Hey, that's much better! I think I can work with that. Thanks for the help and the quick repsonse. :wink: