In this lab, we’re going to remove the piezo element and use two more LEDs, for a total of three LEDs.
Background
When writing software, there innumerable times when you need to do a certain action more than once. Copying and pasting code to do the same thing multiple times is a direct violation of the DRY (Don’t Repeat Yourself) principle, and WET solutions (We Enjoy Typing) make code that is both difficult to understand and maintain.
One of the fundamental tools used to avoid WET solutions is the loop. There are three major kinds of loops in C++: for, while, and do..while. Combining these three will allow you to minimize repetition. Here is an example of each:
for loop example: iterating an equation a known number of times
int x = 1;
for (int i = 2; i <= 10; i++)
{
x = x * i;
}
the value of x is now 10 factorial. If we read the value of x at the end of each loop, we see this output:
x = 2
x = 6
x = 24
x = 120
x = 720
x = 5040
x = 40320
x = 362880
x = 3628800 (10!, or 10 factorial)
while loop example: iterating a mathematical equation until it converges to within the constraint provided
int x = 244;
while (x - 3 > 8)
{
x = x / 2;
}
x is now 7, and 7 - 3 = 4 which is less than 8, therefore the while loop stopped looping.
here is the value of x at the end of each loop, so you can see the iterations:
x = 122
x = 61
x = 30
x = 15
x = 7
(Note the integer truncation that happened from 61 to 30. Integers can’t hold the value 30.5)
do..while example:
int x;
do
{
x = get_number_from_user();
} while (x != 64)
This example uses an imaginary function called get_number_from_user that will return whatever integer the user types in.
If the user types in any number but 64, it will keep asking them until they guess 64. In the case of an input loop, do..while
is actually often better than a while loop. Below, I’ve rewritten the do..while using a traditional while, so you can see how
the do..while enables a more DRY implementation in certain situations.
int x = get_number_from_user();
while (x != 64)
{
x = get_number_from_user();
}
Duly note that there is actually an even more concise form for this situation, since we’re not using the value in any way except to block the program and wait for the user to provide ‘64’. This wouldn’t work for every case.
//the immediate semicolon indicates the code should stay on this line until the condition is false.
while (get_number_from_user() != 64);
As you can see, the different major types all do approximately the same thing, but there are subtle differences that can be convenient.
The Lab
For this lab, we will have three LEDs connected to the Arduino, one each on pin 10, pin 11, and pin 12. There should be a button connected to pin 2. If we imagine that this is a water bottle filling station, it would be nice to have some LEDs blinking to draw attention to it. While no one is pushing the button to dispense water, we want to blink all of the LEDs in sequence once per second, from top to bottom. But, while someone is pushing the button we will blink all of them (effectively) at the same time on and then off, repeating, once per second.
For this prototype of the LED system, we are only using 3 LEDs, but there is discussion that the production version could use upwards of 20 LEDs. It is conceivable that you could write a line of code for each LED to turn it on and then to turn it off when there are only 3, but it will quickly become unmaintainable on the production version, so you should use a for loop. A for loop is excellent for this, because it will repeat an action over a precisely known set of times.
for (int i = 10; i <= 12; i++) will iterate such that i = 10, 11, and then 12. Using the cumulative knowledge you’ve built up to this point, see what you can do to make this happen.