[solved]Getting started with Arduino-example 03B-help understanding transition

Hi all!

First let me say that I have googled it and also searched inside the forum. I did find one answer, but alas, to example 03C!
I’m using Linux (Mint 15) and an Arduino Uno R3. The code works and everything is fine, this is just a doubt I have!

I have some scripting experience with Actionscript, Python and Processing. what is messing with my head is the conjunction of electronics and programming, I think. I don’t know what values are being passed.
I’ll post t he code and then do my question:

// example 03B: Turn a LED on while the button is pressed
//and keep it on after it is released
//Now with new and improved formula

#define LED 13 //the pin for the led
#define BUTTON 7 //the input pin where 
                 //the pushbutton is connected
int val = 0; //val will be used to store the state of 
            //the input pin
int old_val = 0; // this variable stores the previous
                 // value of "val"
int state = 0; //0 == LED off while 1 == LED on

void setup()
  pinMode(LED, OUTPUT); //tell Arduino LED is an output
  pinMode(BUTTON, INPUT);//and button is an input

void loop()
  val = digitalRead(BUTTON); //read input value and store it
  //check whether the input is HIGH -> button pressed
  if ((val == HIGH) && (old_val == LOW))
   state = 1 - state;

  old_val = val; //val is now old, let's store it

  if(state == 1)
     digitalWrite(LED, HIGH); //turn LED on
    digitalWrite(LED, LOW);

So this is my doubt: At the beginning we assign 0 as the value of teh variables val and old_val. 0 I assume is understood as LOW.

When you enter in the loop() function you read the value of BUTTON to check if it is pressed or not. So, button pressed will pass a value of 1 (or HIGH) to val, right?

Then you check for a transition in the state and this is where all gets fuzzy! :wink:

 if ((val == HIGH) && (old_val == LOW))
   state = 1 - state;

So, if I pressed the button, val gets assign 1(HIGH) and is true. Since it’s my 1st button press, old_val still has the value assigned at the beginning, so 0(Low) and is also true, so state is assigned the value 1 and the LED is ready to shine!

old_val = val; //val is now old, let's store it
Old_val gets assigned the value 1(HIGH)

Since state is now 1, the next if is true and the condition is met and the LED shines!
All fine here! But then it confuses me… The 2nd time, the first if is not met, because val is HIGH (we did press the button) but old_val is also HIGH so we skip changing the state… but that means that state is still 1 so the LED would still be on… and old_val would (again) get the value HIGH so it would be an endless cycle so the LED would be always on…

That’s my confusion… unless is something like Arduino constantly checking and saying ("yesyesyesyesyesyesyes…ononon!) and when you press the 2nd time it checks and interrupts the “yes stream” and gets a NO!.. That would make sense but I’m not sure, so any help/thoughts would be welcomed! :wink:

I know that inside the loop everything is in a… loop! So it is repeating! I guess I’m confused with the values of the input!


You got it quite right. Arduino runs the loop function constantly after setup. So you have to check not only for levels but changes in levels (edges or transitions).
Once you got it there are quicker ways to do things:

//macro for detection af raising edge
#define RE(signal, state) (state=(state<<1)|(signal&1)&3)==1
#define LED 13 //the pin for the led
#define BUTTON 7 //the input pin where the pushbutton is connected

int buttonState;
//setup as previous

void loop(){
  if RE(digitalRead(BUTTON), buttonState) digitalWrite(LED, !digitalRead(LED));

This does the same thing… have some time to think over it and then com back and you get an explanation

The point is to ensure the state only changes once per button press.

Since loop() might run 100,000 or 1,000,000 times a second its crucial to recognise only the transition from LOW to HIGH, otherwise the state will simply be changed repeatedly all the time the button is pressed.

So the old_val state allows the determination of the transition (also called a positive-going edge) on the input pin. The state is thus only changed once per edge.

The second test to update the LED could be done inside the first if, it happens to be done separately for no deep reason - the LED output needs to be updated from the state at least once on each transition, here it is continually updated, but that still works because state is always valid.

Hi nilton61 and MarkT!

Thank you both for your very fast answers.

Edges, transitions... new world!

I'm afraid I don't know enough of the sintax yet to make full sense of the faster way you show nilton61, but I will! It looks like you are creating a function with 2 parameters (signal and state) and then you define the default values(?) of said parameters in the next bit... but not sure! ;)

Ok MarkT! I had to read your answer a couple of times... I knew the why but couldn't get the how. Mixing both your answers makes now perfect sense! So you say you would/could nest the 2nd if inside the 1st one, right? What would be the prefered method, in terms of code clarity/understanding? And are there any guides for "proper" (sorry for the proper, it's the only word I can think of now...) coding? (like PEP 8 in Python, which is the style guide...)


Ok, maybe its time for some more explanation.

Let me introduce you to the concept of a scan cycle. This is one iteration of the loop() . This goes on cycle after cycle at some quite high speed. Exactly how fast depends on the code being executed and it doesn't matter as long as it is fast enough. Then there are things going on outside the scan cycle like serial communication, updating timers and handling interrupts. We don't care about them right now. If you want to detect a raising edge, that is a transition from 0 to 1, you need a record of the signal in the previous scan cycle. Now we have 4 and only these 4 possibilities:

  • The current signal is 0 and the previous was 0. We have a constant low signal
  • The current signal is 1 and the previous was 0. We have a transition from 0 to 1 or a raising edge
  • The current signal is 1 and the previous was 1. We have a constant high signal
  • The current signal is 0 and the previous was 1. We have a transition from 1 to 0 or a falling edge.

Raising or falling edges are only valid for exactly 1 scan cycle so you have to act on them during that cycle. There are many methods to detect this change. Two of them being shown here. The common thing for all of them is that you need a record of the previous state.

Hi again nilton61!

I think I got all you said and more importantly (not more important than your answer, but equally important) is the name you said "scan cycle". A quick and dirty google search revealed some interesting links, including an youtube video with a full lecture! ;) Not that I'm sure I'll get all of it, but will for sure broaden my horizons!

I'll mark this thread as solved! i'm sure I'll be seeing you all here many, many times!

Thanks for your help and explanations!