Control Statements

Up until this chapter, our source code has been relatively straightforward. The Arduino microcontroller reads the lines of code in our sketches from the top of the code until it reaches the end at the bottom, and, when there are no more commands to execute, will bounce back to the top of the loop() function and start over again. The order or direction in which code is executed is called program flow and the ability to alter this order of executing commands is something called flow control.

There are two kinds of statements available in Arduino C for controlling program flow: conditional statements that make decisions based on whether or not a condition is true and iterative statements that perform things a certain number of times or until a condition becomes false. Conditional statements that include the if and switch statements selectively perform certain actions based on the state of a condition. Iterative statements that include the for and while statements are often called loops because, just like our loop() function, they will loop to the beginning of the statement and repeat their code when a condition has been met.

If

The if statement is the simplest of the control structures and is among the most prominent method for Arduino decision making. It will perform a block of code if a specific condition is met. The basic syntax for an if statement looks as follows:

if (condition) {
  statements
}

Following the keyword if, a pair of parentheses encloses a conditional expression. If we wanted to test a certain variable to see if it is equal to the value 5, we would begin the statement like the following:

if (myValue == 5)

In this example, if myValue is equal to 5, the statement would execute any following simple statement or block of statements enclosed by curly braces. If the condition is not met, in that they return the value false, then the following statement(s) will be ignored and are not executed.

A common use for the if statement is to read the state of a digital pin and perform an action based on its condition. As a hypothetical example, this could look something like the following:

tiltSwitch = digitalRead(switchPin);
if (tiltSwitch == HIGH) digitalWrite(13, HIGH);

This is a simple example that reads the value of switchPin assigning that value to the variable tiltSwitch and then tests the condition of tiltSwitch. If tiltSwitch is equal to the constant HIGH, then it will call the digitalWrite() function to change the state of the digital pin 13 to HIGH, which would have the effect of turning on the pin 13 LED on the Arduino interface board. Notice that this is another example of a simple statement that does not require curly braces.

If we wanted the LED to only turn on when the switch is activated and to remain off the rest of the time, we would use an if…else statement. Take the following example:

tiltSwitch = digitalRead(switchPin);
if (tiltSwitch == HIGH) digitalWrite(13, HIGH);
else digitalWrite(13, LOW);

Like the previous example, this statement will turn on the LED if the switch has been activated, however, by using the else keyword it is possible to turn off the LED the rest of the time. Essentially, if the condition is true, only the first statement will be executed and if it is false, only the second statement will be executed. In plain English, this statement would be similar to saying

"If the switch is on then turn on the LED, otherwise turn off the LED."

So far, our if statements have been checking for a specific condition using the == (is equal to) operator although any of the comparative or logical operators as shown could be used instead. Take for example, the following:

if (myValue >= 10 && myValue <= 20) {
  statements
}

This if statement will check for a range of values, only executing the following statements if the value of myValue is somewhere between 10 and 20.

if (!myValue) {
  statements
}

This sample uses the ! (not) operator so that the enclosed statements will only be executed if the variable myValue is false, which also corresponds to 0 or LOW, but we will get to that a little later in the next chapter.

For

The for statement, or for loop, is an iterative statement that allows the Arduino to repeatedly execute lines of code in a loop a specified number of times. What makes the for loop unique is that it is based on a counter, or a specific variable that is incremented each time the loop is repeated. This counter is even quite useful, as the counter itself can be used just like any other variable by statements that reside inside the loop, as you will see in later examples. The basic syntax of a for loop follows:

for (declaration; condition; increment) {
  statements
}

The for loop begins with three statements that include: variable declaration, conditional statement, and incremental statement. Of these, the first is the counter variable declaration or initialization and is run only once the first time through the loop. The second statement is the conditional statement using comparative operators just like those found in the if statement and is tested each time through the loop. If the condition remains true, the following code bracketed by the curly braces will be executed. If, however, the condition returns false, the for loop will end. The third and final statement increments the counter variable each time the enclosed block of code is executed.

Let’s say we wanted to blink an LED five times quickly, we could use a for loop similar to the following:

for (int i = 0; i < 5; i++) {
  digitalWrite(13, HIGH);
  delay(250);
  digitalWrite(13, LOW);
  delay(250);
}

In this sample code, the first time through the for loop, we declare an integer type variable to serve as our index or counter and assign it the value 0 in this statement:

int i = 0;

Each time through the loop, the conditional statement will be checked to see if the condition remains true. Take, for example, the following:

i < 5;

In this statement as long as i is less than 5, the enclosed statements will be executed, turning on pin 13, waiting for 250 milliseconds, turning pin 13 off, then waiting another 250 milliseconds.

Each time through the loop, after all of the statements within the curly braces have been executed, the variable i is incremented, in an increment statement:

i++;

In this case we add 1 to the value of i and reassign this new value back to i so that each time through the loop i increases by 1. Remember the compound operator i++ is functionally identical to i = i + 1. In this way, i starts at 0 the first time through the loop, incrementing 5 times each time through the loop until its value is no longer less than 5, consequently ending the loop. In our project code, an example of the for loop in action includes the following example:

for (int i=0; i<3; i++) pinMode(rgb[i], OUTPUT);

Here, we are using a local variable i declared inside the loop to be used as a counter and assigned the value 0. For as long as i remains less than 3, expressed in the conditional statement i<3;, the code following the for statement will be executed. The for loop will then repeat three times, and each time the pinMode() function will be executed, setting a pin, as defined by the rgb[] array, as an output. Because we only needed a single simple statement to be executed, the curly braces are not required.

You can also see that we have used the counter i to increment the position of the array rgb[] being referenced. After that statement has been executed, the counter i will be incremented by one. Once i has reached the value 3, the for loop will terminate and proceed with the standard program flow to the following line of code.

While

The for statement is fairly common to Arduino programmers, but there are other ways to structure iterative loops. Where the if statement executed a statement once if a condition was met, and the for loop cycles through a specified number of times, the while statement, or while loop, is used to continuously execute a statement so long as the condition remains true. The basic syntax of a while statement looks like the following:

while (condition) {
  statements
}

Using the while statement, we could rewrite the previous for loop example to blink an LED five times in the following manner:

int i = 0;
while (i < 5) {
  digitalWrite(13, HIGH);
  delay(250);
  digitalWrite(13, LOW);
  delay(250);
  i++:
}

The first line, int i = 0; declares the index variable and assigns the value 0. The program flow reaches the while statement and compares the value 5 to the variable i, with the first time evaluating as true. The enclosed statements are then executed, which includes the line i++; used to increment the value of i at the end of the block of code.

When the end of the statements is reached, it loops back to the conditional statement of the while loop and if the condition remains true, the following statements are executed all over again. If, however, the condition is false, then the while loop ends and control passes to the following statements in the program.

So with the for loop, why would you need the while loop? If the previous example was all you were ever going to do with it, then no there is really not much use for it. However, if you think of the while statement more as a continuous if statement, then it becomes quite useful in the right situation. From our project code, we needed to do one thing over and over again while the switch remained triggered and to prevent the continuation of normal program flow until that condition is no longer met. In other words, as long as the switch was triggered in our project example, we wanted to continue to cycle through each of the seven colors until such time as the switch was no longer triggered.

A simpler way to write this code would be something like the following:

while (digitalRead(2) == HIGH) digitalWrite(13, HIGH);

In this example, for as long as the digital input on pin 2 is equal to HIGH, if for example a switch has been activated and is on, then the while loop will continue to keep pin 13 on, or HIGH, and will never exit the loop. Only when the conditional expression digitalRead(2) == HIGH returns false will the next following line of code be executed.

Do

Like the for statement, the while statement evaluates its condition before executing its block of code so that if the condition is not met, its code will never run. Sometimes it would be nice to always run the enclosed code at least once before evaluating its condition and for that we would use the do statement, or do loop. The do loop is like a modified while statement in that it executes a line or lines of code and then tests for a condition at the end of the loop rather than the beginning before deciding to loop to the beginning again or not. The following is the basic syntax for a do loop:

do {
 statements
} while (condition);

Rethinking the last code sample, we might want to make sure that the LED is off if the switch is off before continuing on with the rest of our sketch. Using the do…while loop we could write the statement like the following:

do digitalWrite(13, LOW);
while (digitalRead(2) == LOW);

In this sample, no matter the condition, the do statement will turn off the LED on pin 13 at least once and then test the input pin 2. While the expression digitalRead(2) == LOW remains true, the do loop will repeat infinitely, keeping the LED off. When the condition is no longer true, the do loop will exit and return to normal program flow.

Switch

The switch statement is like a really nifty version of the if statement in that it can execute one or more blocks of code, depending on a range of conditions. Basically, the switch statement compares the value of an expression against a list of cases executing whatever code begins after that case when a match is found. switch is a fairly powerful and complex control structure so we will only scratch the surface here, revisiting it in later chapters when we can better apply it. The basic syntax of the switch statement follows:

switch (expression) {
  case constant:
    statements;
  case constant:
    statements;
  default:
    statements;
}

The number of cases can be as many as you need (or have the memory for), but each one should have a unique constant or single-byte character following it—variables like myValue are not allowed as a case. After the colon that defines the case, we can have a block of code that is executed when that case is true. The default case allows for code to be executed when a specific case has not been previously specified.

To get a better idea for how the switch statement works, let’s say we want to modify the early LED blink sketch using the switch statement so that when the tilt switch is activated, the LED will stay on rather than blink. To do that we could use the following code sample:

switch (digitalRead(2)) {
  case 0:
    digitalWrite(13, LOW);
    delay(1000);
  case 1:
    digitalWrite(13, HIGH);
    delay(1000);
}

Beginning with the expression following the switch statement, we will read the state of the digital input pin 2. If the tilt switch is activated then the pin will read as HIGH, which if you remember is basically equal to the value 1, and the code for case 1 will be executed. If the tilt switch is not activated it will read as LOW or 0, so the code beginning with case 0 will be executed until the end of the switch statement. This will also include the code following case 1 because the normal program flow did not reach the closing curly brace yet.

What this means is that, assuming the switch statement is the only code in our loop() function, when the tilt switch is off, the LED will blink on and off every 1 second but when the tilt switch is on, the LED will stay on and not turn off again until the tilt switch is turned off.

Break

The break statement can be used inside other control statements to immediately end the loop or statement. If we borrow our five-blink sample from before, we could add an if statement followed by the break statement to exit out of the loop if a switch is activated. This would look like the following:

for (int i = 0; i < 5; i++) {
  if (digitalRead(2) == HIGH) break;
  digitalWrite(13, HIGH);
  delay(250);
  digitalWrite(13, LOW);
  delay(250);
}

Normally, in this example the for loop will complete its cycle five times before continuing on with the rest of the program. The additional line if (digitalRead(2) == HIGH) break; will check the status of pin 2 and if it is equal to HIGH, from a switch being activated, the break statement will cause the for loop to quit immediately and program control will resume with the next line of code after the for loop.

To go back to the earlier example for the switch statement, if rather than the LED blinking when the switch is LOW, we could use the break statement to break out of the switch statement by adding the break keyword at the end of case 0, like in the following modified example:

switch (digitalRead(2)) {
  case 0:
    digitalWrite(13, LOW);
    delay(1000);
    break;
  case 1:
    digitalWrite(13, HIGH);
    delay(1000);
}

Using break, when the code for case 0 has been executed, the statement is broken and program flow continues with the code after the end of the switch statement. With the modified code, we should be left with an LED that is on when the switch is on and off when the switch is off. The added bonus with the break statement is that it gives us the ability to have a loop that is conditional on multiple factors or behaviors. This is also effectively a way to end any loop structure through external sources.

Continue

The continue statement does not exit or quit an iterative loop like break does, but rather it skips over any remaining statements inside the loop and goes on to the next repetition of the loop. The continue statement only works on iterative statements like the for, while, and do loops and can be used among other things to skip odd or even numbers in a for loop. For example, if we had five separate LEDs connected to the Arduino on pins 9 through 13 and wanted to turn on and off only the odd number LEDs in sequence, we could use something like the following:

for (int i = 9; i <= 13; i++) {
    if (i % 2 == 0) continue;
    digitalWrite(i, HIGH);
    delay(500);
    digitalWrite(i, LOW);
    delay(500);
  }

In the line of code, if (i % 2 == 0) continue;, we have added a conditional test based on the modulus operator in i % 2 so that if the number in the loop is an even number, it will evenly divide by 2 leaving a 0 remainder. If that condition is true, the continue statement will skip any further instructions inside of the loop and head back to the increment component of the for statement and resume normal operation.

In this example we also started our for loop with the value 9 (i = 9), incrementing i by 1 each time through the loop (i++), so long as i is less than or equal to 13 (i <= 13) for a total of five possible iterations. We are also using the indexing variable to correspond to a specific digital pin by using i in the statements like digitalWrite(i, HIGH);. In the end, the even numbers will be ignored and the LEDs connected to pins 9, 11, and 13 will turn on and off in sequence.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.196.217