Band 5 · Simon Says
Swap Reaction race
Every Band 5 idea with one light and one button. Functions, tone, random and millis, a quarter of the wiring.
Sketches for this project
Every file opens with a plain-English header saying what it does and how to wire it, hole by hole.
The whole band, a quarter of the wiring
Simon Says needs four lights, four buttons, four resistors and a buzzer, joined by about twenty wires. That is thirteen parts, and if it does not work you have thirteen suspects.
This build needs one light, one button and a buzzer. It teaches every single idea in Band 5:
- Functions you write yourself, with values handed in and answers handed back
toneand pitchrandom, and why it needs seedingmillis, and the difference between waiting and watching- A job broken into pieces small enough to name
If four buttons is more wiring than you want to fight with today, come here. You are not taking an easier band. You are taking the same band with less to go wrong at the bench, which is a reasonable thing to want.
Seven wires
25 mina, the same pair Band 5 uses, and the one your parts sit next to. Put every rail wire on that pair and it works; split them across both and nothing lights, with nothing visibly wrong.| Part | Pin | Holes | Wiring |
|---|---|---|---|
| Light | 7 | long b3, short b4 | Resistor a3 to a1; wire b1 to pin 7; wire a4 to − rail |
| Button | 2 | legs in e19, e21, f19, f21 | Wire j19 to pin 2; wire a21 to − rail |
| Buzzer | 8 | long b40, short b42 | Wire a40 to pin 8; wire a42 to − rail. No resistor. If the legs will not reach two holes apart, use b40 and b43, and move the − wire to a43. |
| Ground | GND | — | One wire from the − rail to a GND pin |
The light's pin wire goes in b1, not a1: the resistor leg is already there and a hole takes one leg only.
id_01_which_buzzer.ino if you are not sure which you have, and if you would rather it were silent, delete the two beep lines.Test the light and the button separately first, exactly as Band 5's staged build tells you to. Blink on pin 7, then the serial watch sketch on pin 2.
1 changing to 0 for as long as you hold the button.Upload b5_06_reaction_race.ino and open the serial monitor at 9600.
Get ready..., then the printed length of this round's wait, then that wait, which is somewhere between two and six seconds, then the light comes on. Press the button and it prints your time in thousandths of a second and beeps. Then it goes round again, keeping your best.Play it ten times and write down your best. Then hand it to somebody else and watch them play, without explaining anything.
Four small ideas, one at a time
35 mina. Read loop first
Go to the bottom of the sketch. The whole round is there and it reads like a description of the game: get ready, wait a random time, check for cheating, light on, time the press, compare with the best. Everything complicated is behind a name.
b. The function that hands back an answer
unsigned long timeOnePress() {
unsigned long startedAt = millis();
while (!isPressed()) {
if (millis() - startedAt > 10000) {
return 0;
}
}
return millis() - startedAt;
}
This one starts with unsigned long rather than void, because it hands something back. That is what return does, and it is the half of functions that Band 5 Part 5 introduces.
Inside it is a while loop that does nothing but watch. That is blocking, on purpose, and it is fine here because there is genuinely nothing else the game needs to do while it waits for a press. Band 5 taught you when blocking is a problem; this is what it looks like when it is not.
The if in the middle is the one escape. After ten seconds with no press it gives up and hands back 0, and loop reads that 0 as “no press seen” and starts the round again. Without it, a badly wired button would leave the board sitting there for ever looking dead, with no message and nothing to work from. Any loop that waits for the outside world needs a way out that does not depend on the outside world. Write that in your log; it is one of the most useful sentences in the course.
c. The function that catches cheating
bool waitWithoutCheating(unsigned long howLong) {
unsigned long startedAt = millis();
while (millis() - startedAt < howLong) {
if (isPressed()) {
return false;
}
}
return true;
}
Answer before you read on
- Why could this not have been written with
delay(howLong)? - It hands back
trueorfalse. What do those two mean here, in words? - There are two
returnlines. What happens to the rest of the function when the first one runs?
Check your answers
1. Because delay stops everything. During a delay the button cannot be watched, so an early press would be invisible and the cheat would go unnoticed. This is exactly the Band 5 lesson: waiting and watching while time passes are different things, and only one of them lets you notice anything.
2. true means the wait finished properly. false means somebody pressed during it. The name is written so that the if in loop reads almost like English.
3. Nothing else runs. return leaves the function immediately, which is why the cheat case does not fall through into the honest one.
d. Why A0 must be empty
randomSeed(analogRead(A0));
random is not really random. It runs a calculation, and from the same starting point it produces the same sequence every time. Without seeding, this game would wait exactly the same series of times after every power-up, and you could learn them.
analogRead on a pin with nothing connected gives a drifting, meaningless number, because the pin is floating. You met floating pins in Band 3 as a problem. Here it is the solution. Meaningless is exactly what a seed needs to be.
Prove it to yourself
- Comment out the
randomSeedline and upload. Play four rounds and write down the four waits, which the sketch prints for you at the start of each round. - Press the reset button on the Arduino. Play four more rounds and write those down.
A0 is not floating enough on your board to be a good seed. It happens: a pin sitting near a steady voltage gives a nearly steady reading, and a nearly steady seed gives a nearly repeating game. Make sure nothing at all is in A0, then try touching the pin with your finger, which makes it drift much more. If you want a seed you can rely on, the honest answer is that a floating pin is a cheap trick rather than a good source, and real programs use the time of the first button press instead. Try that: call randomSeed(millis()) just after the player's very first press, and say in your log why the moment a human presses a button is a better source of unpredictability than a wire.Make it yours
40 min- Bronze
- Make it a game of five rounds that then prints your average as well as your best. You will need somewhere to keep a running total and a count, and you will meet whole-number division from Band 4 on the way.
- Silver
- Make it a two-player game: a second button, and whoever presses first wins the round. This is harder than it sounds. You cannot use
timeOnePressas it stands, because it watches only one button, and the honest fix is to write a function that watches both and hands back which one won. - Gold
- Add a false start that is properly fair. First move the LED's pin wire from pin 7 to pin 6 and change
ledPinto match, because pin 6 has a~and pin 7 does not, and you cannot dim a light on a pin without one. Then light the LED dimly for a moment at a random point before the real signal, and count a press during that as a fault. Then, usingmillisthroughout, make sure the game never stops responding, even during the penalty.
return hands back one thing. There are two honest ways out. The first is to hand the function two places to write its answers into: open b4_07_room_monitor.ino even if you never built it, and look at dht.read(&temperature, &humidity, NULL), which is exactly that. The second is to make one thing that holds both, which C++ calls a struct. Neither is taught in this course. Read about one of them, use it, and say in your log which you chose and why.You still owe Band 5 the same evidence
This Swap replaces Simon Says as the build you are assessed on. To claim Band 5 you still need:
- A video of somebody playing it, which may be you if you are working alone, and your own best time
- The list of your own functions with one sentence each saying what they do
- Your notes from the counting activity in Part 1
- Your before-and-after waits from the
randomSeedexperiment - Your build log
- Your completed timing table from Part 10a, done on paper with
b5_04. This Swap does not replace it - Five or six correct answers in Part 13, the Check yourself questions, including question 4
Part 13's question 4 is the one that matters most in the band: a delay hidden inside a function that looks like it is using millis properly from outside. You have now built both kinds of waiting on purpose, so you are in a better position to answer it than somebody who only built the game.
Ship it
One video under sixty seconds, and one post of five lines. You built something different from the person next to you, so your video is the one nobody else in the room can post. Say in the post which build you chose and why — that choice is itself worth a line.
The four shots: three seconds of the thing still, fifteen of you doing something to it, fifteen of it responding all the way to the end, and ten of your measurement or the thing that went wrong first.
Show your work has the template and the three checks to
make before anything goes public. Tag it #BozomaBuilds.