The Monodrone, Part III
This post is part of a series of notes and exercises for a summer camp on making musical instruments with Arduino and Pure Data.
There’s something wrong with our monodrone. It plays a lot of notes at the same time! Why does this happen? To find out, hit the close 1
message back in Pure Data to release the serial port. Replace write
with println
and upload your sketch. Open the Serial Monitor and check the output.
So, why do we get some many overlapping notes? Because of the loop
function in our Arduino sketch. It runs continuously, asking the button about its state continuously and sending a 0 or 1 across the serial port continuously. While a button is held down, it will send 1, 1, 1, 1, 1, 1, 1, 1, 1… Our Pure Data patch generates a note for each of these 1s, and that’s why we hear the rapid-fire sound that we do.
We can fix this by only printing a 0 or 1 only when the button changes. To detect a change, we must keep a history of what the button’s state used to be. Let’s add this variable outside our two functions:
int old_button = LOW;
void setup() {
...
}
void loop() {
...
}
When we declare a variable outside the functions, it has a lifetime that exceeds the functions. If we declared it inside a function, that variable would disappear once the function finished executing. Since old_button
has to maintain a history of what happened in the past, we can’t let it disappear. Computer scientists call the lifetime of a variable its scope. Variable old_button
has a wide scope.
LOW
is another name for 0 and better describes electrical voltage. (Similarly, HIGH
is another name for 1.) To remember what the button was a moment ago, we hang on to the current reading as the very last step of loop
:
int old_button = LOW;
void setup() {
...
}
void loop() {
int button = digitalRead(7);
Serial.println(button);
old_button = button;
}
The next time loop
runs, old_button
will tell us what the button used to be. To detect a change, then, we ask if button
and old_button
are different. In C++, we can ask that question with the !=
(not equals) operator.
To run some code when the two values are different, we embed the code in a conditional statement, which has this form:
if (button != old_button) {
// code to run when the values are not equal
}
Add a conditional statement like this to loop
. Move the last two lines (the print and the old_button
assignment) inside its curly braces. Test your new program. Do you see messages in the Serial Monitor only when the button is pressed or released?
Once that’s working, switch println
back to write
. Test it with Pure Data. You should no longer hear the echoes. It should sound decent, but boring. That’s the monodrone being itself.
Challenges
After you get your monodrone working, answer the following questions on a piece of scratch paper.
- Encode a secret message in Morse code. What is that message as dots and dashes? Emit it using your monodrone.
- What happens when you use the
==
(equals) operator instead of!=
? Imagine you are the Arduino and think about the state of the variables as the program runs. Reason out loud and on paper.