In this experiment, no additional hardware is introduced. Instead, we focus on an important software concept: procedures. The common definition of the word procedure is a series of actions conducted in a certain order. In this sense of the word we already have been writing procedures. In everyday life, there are all sorts of procedures. For example, Bridgestone Tires offers an 18 step procedure to change a car tire:
The cool thing is that we have internalized many procedures, meaning someone can just tell us the name of the procedure and we know how to do it.
When someone says mow the lawn we know the steps involved. Perhaps the first step is to walk around the yard looking for and removing dog toys, branches and other obstacles. Then we might check the lawn mower for gas. If a friend tells us to come over to their house we know the procedure for that: the roads to take and the turns to make. Perhaps the first time we visited our friend told us how to get there:
Once we learn that procedure, our friend can just say come over and we know how to do that.
Wouldn’t it be great if we could just tell the computer this is how you blink the red led and give it instructions like
digitalWrite(red, HIGH);
delay(wait);
digitalWrite(red, LOW);
delay(wait);
and after the computer learns that, we can tell it to blink red instead of repeating those instructions?
The good news is that we can. We can give a sequence of instructions a name, and then use that name when we want to execute those instructions. The magical incantation to do that is
void blinkRed(){
}
And my English gloss of that is this is how to blinkRed. I am calling it a magical incantation because at this point I am not going to explain what void
does or what can go inside the parentheses. That will be a later experiment.
Let’s look at a complete example:
int redLed = 3;
int blueLed = 4;
int wait = 200;
void setup(){
pinMode(redLed, OUTPUT);
pinMode(blueLed, OUTPUT);
}
void blinkRed(){
digitalWrite(redLed, HIGH);
delay(wait);
digitalWrite(redLed, LOW);
delay(wait);
}
void blinkBlue(){
digitalWrite(blueLed, HIGH);
delay(wait);
digitalWrite(blueLed, LOW);
delay(wait);
}
void loop(){
blinkRed();
blinkRed();
blinkBlue();
blinkBlue();
}
The procedures setup
and loop
are required for any Arduino program.
I gloss void setup()
as this is how to setup and then in the setup procedure we set the pinMode of the red and blue led pins to OUTPUT.
void blinkRed()
tells the computer how to blinkRed. Namely, execute the four instructions (turn on the red led, wait a while, turn off the red led and wait some more)
void blinkBlue()
tells the computer the set of instructions for the blinkBlue procedure
void loop()
describes the required loop procedure. In it we tell the computer to execute the blinkRed()
procedure which we defined earlier in the program. And then blink it again. And then execute blinkBlue()
twice.
Notice that we define a procedure with
void blinkBlueAndRed()
and after we define it, the syntax for using it is:
blinkBlueAndRed()
without the void
.
As with variable names, we can name procedures pretty much anything we want. There is nothing special about the names blinkRed
and blinkBlue
The following program would execute identically to the one above:
int banana = 3;
int apple = 4;
int blueberry = 200;
void setup(){
pinMode(banana, OUTPUT);
pinMode(apple, OUTPUT);
}
void ann(){
digitalWrite(banana, HIGH);
delay(blueberry);
digitalWrite(banana, LOW);
delay(blueberry);
}
void mary(){
digitalWrite(apple, HIGH);
delay(blueberry);
digitalWrite(apple, LOW);
delay(blueberry);
}
void loop(){
ann();
ann();
mary();
mary();
}
They execute the same, but this one is much harder for us to read. blinkRed
describes what the procedure does while ann
does not.
Notice that the procedure blinkRed
in the above is nested inside the loop
procedure. Suppose we want to blink Morse Code messages. The fundamental units of Morse code are dots and dashes. Here are the rules:
With that we can start our program:
int led = 13;
int unit = 200;
void setup(){
pinMode(led, OUTPUT);
}
Next, we define the procedures for dot and dash:
void dot(){
// a dot is one time unit long
digitalWrite(led, HIGH);
delay(unit);
// the space between a dot or dash within a
// letter is one time unit long
digitalWrite(led, LOW);
delay(unit);
}
void dash(){
// a dash is three time units long (i.e., 3 dots)
digitalWrite(led, HIGH);
delay(unit * 3);
digitalWrite(led, LOW);
delay(unit);
}
Now with dots and dashes defined, we can define a few letters.
Let’s say we want to send out an SOS. So we need the letters S (three dots) and O (three dashes):
void S(){
dot();
dot();
dot();
// since the space between letters is three
// time units long, we need to add two more
delay(unit * 2);
}
void O(){
dash();
dash();
dash();
delay(unit * 2);
}
Finally, we can write the SOS procedure:
void SOS(){
S();
O();
S();
delay(unit * 4);
}
void loop(){
SOS();
}
Code that uses procedures is highly organized. The lines of your code that do one particular thing are within their own procedure. This often results in programs that are shorter. All this makes your code easier to debug. Notice how much easier it is to read something like:
...
void when(){
w();
h());
e();
n();
delay(unit\*4);
}
...
void chapter1(){
when();
I();
wrote();
the();
following()
pages();
or();
rather();
the()
bulk();
of();
them();
}
...
void loop(){
chapter1();
chapter2();
chapter3();
}
then something like:
void loop(){
digitalWrite(led, HIGH);
delay(unit);
digitalWrite(led, LOW);
delay(unit);
digitalWrite(led, HIGH);
delay(unit _ 3);
digitalWrite(led, LOW);
delay(unit);
digitalWrite(led, HIGH);
delay(unit _ 3);
digitalWrite(led, LOW);
delay(unit \* 3);
digitalWrite(led, HIGH);
delay(unit);
digitalWrite(led, LOW);
delay(unit);
digitalWrite(led, HIGH);
delay(unit);
digitalWrite(led, LOW);
delay(unit);
digitalWrite(led, HIGH);
delay(unit);
digitalWrite(led, LOW);
delay(unit);
...
}
which is Morse code for only wh. You can see where this would be hard to debug.
You can reuse code in different parts of your program without copying the lines. In our SOS program we used the S procedure twice.
Construct a circuit with two LEDs. Using the SOS example above as an example write and upload code that will blink the Leds to display a 2 or 3 word message. For example,
void loop(){
work();
to();
code()
delay(unit \* 5);
}
This is a remix of the beats from the button experiment:
We are going to use the patterns we constructed for experiment one: double tap, slow n fast, and Cylon. Here is the behavior of your circuit:
You will need to construct four procedures:
and then use them with the if-statements inside the loop procedure.
This is a remix of the bike light from the potentiometer experiment. As with the remix above, you will need to construct procedures for each of your patterns. For example,
Then, use these procedures inside the if-statements in the loop function.