Arduino Ladder · Bozoma Innovation Hub

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.

Time
100 min
You need
1 LED, 1 resistor, 1 button, buzzer, 7 jumper wires
At once
Everybody at once
Before this
Finish Band 5 up to Part 8. This replaces Simon Says as the build you are assessed on.

Sketches for this project

Every file opens with a plain-English header saying what it does and how to wire it, hole by hole.

Why

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
  • tone and pitch
  • random, and why it needs seeding
  • millis, 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.

Build

Seven wires

25 min
+ − − + j i h g f e d c b a 1 5 10 15 20 25 30 35 40 45 USB ARDUINO UNO + + 220 220 button button + + buzzer buzzer a1 a1 a21 a21 a3 a3 a4 a4 a40 a40 a42 a42 b1 b1 b3 b3 b4 b4 b40 b40 b42 b42 e19 e19 e21 e21 f19 f19 f21 f21 j19 j19 SCL SCL SDA SDA AREF AREF GND GND 13 13 12 12 11 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 IOR IOR RST RST 3V3 3V3 5V 5V GND GND GND GND VIN VIN A0 A0 A1 A1 A2 A2 A3 A3 A4 A4 A5 A5
Seven wires. Band 5's board with everything but one light, one button and the buzzer taken off.
Which rail pairYour board has two + rails and two − rails, one pair along each long edge, and on most boards the two pairs are not joined to each other. On this page, “the rail” always means the pair along the bottom edge, nearest row a, 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.
Before you startUSB unplugged. Clear the board completely, including anything left from Band 4. A0 in particular must have nothing wired to it, and the reason is in the Look closer section.
PartPinHolesWiring
Light7long b3, short b4Resistor a3 to a1; wire b1 to pin 7; wire a4 to − rail
Button2legs in e19, e21, f19, f21Wire j19 to pin 2; wire a21 to − rail
Buzzer8long b40, short b42Wire 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.
GroundGND—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.

If your buzzer is the active kindThe two different sounds in the sketch will come out as the same note, because an active buzzer cannot change pitch. The game is completely unaffected. Run 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.

You should seeThe light blinking once a second, and then a steady 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.

You should seeGet 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.
If it says “Too early” every single roundThe button is reading as held down. Two of its wires are on a joined pair of legs rather than a diagonal: move one wire so the two are in different columns and different halves of the board.
If the light comes on but nothing happens when you pressThe button is not being seen at all. Test it again with the serial watch sketch.
If the wait is the same length every single timeRead the Look closer section. Something is wired to A0.

Play it ten times and write down your best. Then hand it to somebody else and watch them play, without explaining anything.

If there is nobody to hand it toPlay it ten more times with your other hand, and ten more with your eyes shut until the buzzer sounds. Both make you a fresh user of your own device, which is most of what watching somebody else buys you. Write down the three sets of times and what surprised you. If you can, film yourself playing and watch it back; you will see hesitations you did not feel.
You should seeTimes somewhere between 200 and 350 thousandths of a second once you have settled down. Under 150 means you guessed rather than reacted, and the sketch cannot tell the difference. Only you know. Write down your real best, not your luckiest.
Look closer

Four small ideas, one at a time

35 min

a. 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
  1. Why could this not have been written with delay(howLong)?
  2. It hands back true or false. What do those two mean here, in words?
  3. There are two return lines. 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
  1. Comment out the randomSeed line and upload. Play four rounds and write down the four waits, which the sketch prints for you at the start of each round.
  2. Press the reset button on the Arduino. Play four more rounds and write those down.
You should seeThe same four waits, in the same order, every time you reset. Then put the line back and do it again, and they differ.
If they still repeat with the line put backThen 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.
Change it

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 timeOnePress as 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 ledPin to 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, using millis throughout, make sure the game never stops responding, even during the penalty.
If you do Silver, one thing worth noticingYour function will have to hand back which button won, not just how long it took. So it needs to give back two things at once, and a single 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.
Done

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 randomSeed experiment
  • 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.