The idea behind the game is simple, but sometimes finding a device that will perform the "first to respond" lockout function can be problematic. Here is YAQGC (Yet Another Quiz Game Controller :) based on some pretty neat lighted buzzers and an Arduino put in to a project box.
While the "Lights and Sounds Buttons" from Learning Resources were designed as "stand alone" devices, a few modifications allows them to be connected to and controlled by an Arduino controller. The "Lights and Sounds Buzzers" make a professional looking and fun implementation of a Quiz Game controller.
The buzzers are modified to plug into a base unit and provide "button press" signals and accept an "activation" signal.
The control box houses the Arduino Uno, the reset button, and four LEDs.
While the button modifications are a little tedious, intermediate soldering skills and patience will produce a nice looking and fun to use Quiz Game Controller.
In addition to capturing the first to respond "winner", the controller also captures 2nd, 3rd, and 4th place in order of button press. The order is indicated on the control box LEDs. Of course the beauty of having a programmable controller is tuning it to just the way you want it. Other game modes are possible, including "Wheel of Fortune" modes, although this version of the Arduino program only implements the "Jeopardy" style game.
Let's get started!
YouTube demo of completed system
Background and instructions on www.projectnotions.com
Step 1: Components
- (quantity) Description
- (1) Set of "Lights and Sounds Buzzers" by Learning Resources
- (4) Mini Reed Relays (Radio Shack 275-0232 or similar)
- (1) Arduino Uno
- (1) Project Box
- (4) LEDs, one each in Red, Blue, Green, Yellow (with included resistor or similar)
- (5) resistors, 2.2K (RS 275-1301 or similar) (or any value you have from 220 to 2.2K should work)
- (8) 2.5mm stereo mini phone jacks
- (1) Reset Button, Normally Open, Momentary Contact (RS 275-609 or similar)
- (2) 3 feet 2.5mm Male To 2.5mm Male - Stereo
- (2) 6 feet 2.5mm Male To 2.5mm Male - Stereo
- (1) Project Box
- hookup wire
- Soldering iron
- screwdrivers (phillips and flat head)
- Dremel type tool for cutting and countersinking holes
- (computer to load the Arduino code)
Step 2: Button Modifications
The button is modified to accomplish three functions: * First, to bring to the control box a line when the button is pressed. * Second, to bring a line from the control box to the button to turn on the lights and sound. * Third, provide a relay that allows the sound to be turned off.
Because there are 4 things we want to do (ground, button press, activate lights, activate sound) and we only have 3 wires, we have to combing two functions using one wire. We accomplish this by taking advantage that the logic on the button does it’s own management of the lights and sounds function. When the “activate” line goes high for about 20ms the button logic activates the light and sound. By connecting a compact relay to this same line we can control the sound in an independent way.
Here are the states we manage on the “activate” line.
- Low - The button is off. If it was previously activated, it will turn itself off after about 2.5 to 3 seconds.
High Pulse - We drive the activate button high for 20ms, and then drive it low again. The button logic will turn on the lights and sound for 2.5 to 3 seconds, but because we connected the speaker through the relay, the relay will only stay on for 20ms. So, we don’t really hear any sound because the relay has disconnected the speaker from the circuit.-
- High Solid - We drive the activate button high for about 2.5 seconds. The relay keeps the speaker connected to the circuit for the entire duration of the button’s “activation time.” and we both see the lights AND heard the sound.
The button schematic is below.
With these modifications we can program the Arduino to mange the lights and sounds independently. Our initial program turned both lights and sounds on for the first cycle, and then just turned the lights on over and over again until the reset button was pressed or until the timeout expired.
It is somewhat of a tight fit in the button and we chose a 2.5mm stereo phone jack for the connector to minimize the space required. The four main changes are:
Cut the pc board trace to separate the “button press” signal from the “activation line.”
Drill a hole, countersink it, and mount the phone jack.
Mount the compact relay.
Cut and solder the necessary wires.
Step by step instructions:
1. Collect the parts
4x Lights and Sounds Buzzers
4x Submini phone Jacks
4x Reed relays
2. Disassemble the buttons
Remove the four feet from the bottom (A small flathead screwdriver might help.)
Remove the four screws
Remove the battery compartment cover
Repeat for each button
3. Drill a hole in the button base for the submini jack
Location position for hole for submini jack
Drill pilot hole using Dremel or similar tool
Carefully expand the hole using a 5/32” drill bit
Check for fit, and carefully recess the hole from the inside, so the jack can be threaded
Do not mount the submini jack in the hole yet
Repeat for each button
4. Cut the button PC board where the pushbutton switch makes contact
Put batteries (2 AAA) in the unit, and press the button confirming it works
Remove the batteries
Remove plastic tape covering the trace (save to put back later, and be careful to leave most of the tape that holds the button in place. If just cutting the tape around the trace area seems to be easier, then use a small sissors and tweesers to remove the tape.
Using an exacto knife carefully cut the PC board trace (see picture below)
Leave enough trace on the board to solder a wire on each end of the broken trace.
After cutting the trace, replace the batteries and press the button while holding a jumper wire on both sides of the cut trace. This will confirm that the button is still working.
Button PC Board Trace Cut Point
6. Connect and solder the wires to components
Using the schematic as a guide, solder the wires to connect the components.
7. Assemble the button and test it
It might be helpful to assemble a 2.5mm male plug with individual wires to facilitate testing. Use the plug (or even put a plug partially in the jack) and make a connection between the middle and the tip. Press the button and it should activate the lights and sounds as normal. With the plug removed pressing the button should have no effect.
Repeat for each button and you have done over half the work!
Step 3: Control Box
- Four submini phone jacks.
- Four male to male 3.5mm stereo extension cords. Each button is connntected to the control box with one of these cords.
- Four LEDS, one RED, one GREEN, one BLUE, and one YELLOW. We chose LEDs with included resistors to minimize wiring.
- One Arduino UNO (or compatible)
- One momentary contact push button, normally open to use as a RESET button.
- One project box to put everything in.
- One power supply. We found a 5V AC to DC power supply in our “project supply pile.” Note that the control box will get it’s power from the USB conector when connected to a computer for programming the Arduino.
The control box provides several functions:
- It connects to the buttons to detect when the buttons are presssed.
- It controls starting the button lights. (The lights stop on their own with the built in button logic.)
- It controls whether the button sound is switched to the speaker or not.
- Four colored LEDS on the control box indicate 1st, 2nd, 3rd, and 4th place (for a Jeopardy style game.)
- It provides a reset switch for resetting the game, and enabling other functions (i.e. light test mode.)
- It contains “pull down” resisters on lines that would be “floating” otherwise. This ensures reliable operation.
The schematic below shows the components and interconnections.
We used a project box with approximate dimensions of 6” wide x 3 3/4” depth x 1 3/4” high. Any size that fits the components will do. It might be nice to fit batteries inside the box, but we used the power connector with an external supply, either AC or battery powered. The general steps we followed were:
- Plan for LED, phone jack, Arduino UNO, and reset button placement.
- Drill holes for the phone jacks, countersink, and ensure good fit.
- Drill holes for the LEDs and Reset switch.
- Cut openings for the Arduino UNO USB connecation and power jack.
- Wire and solder the connections.
Step by step instructions:
1. Collect the parts
One project box
4x LEDs (one RED, one GREEN, one BLUE, one YELLOW)
4x Submini phone Jacks
5x 2.2K resistors
1x Arduino UNO
Pins for soldering connections to the Arduino bin blocks
2. Plan and drill holes
Drill holes for the phone jacks, countersink, and fit.
Drill holes for the LEDS and fit
Drill hole for the reset button and fit.
This step may be tedious. We used a Dremel tool to cut the holes for the Arduino UNO.
Make sure you have a way to fasten the UNO to the control box. Use stand-offs if necessary.
3. Connect and solder wires
Refer to the schematic for correct wiring connections.
We soldered the 2.2k pull down resister for the button switch directly on the phone jack connector.
We only put the LEDs and the reset button on the top to make it easier to take the top off with a big wiring mess.
4. Assemble and test
Check the wiring carefully as you go along.
It is easiest to test with the Arduino programmed, so you may like to proceed to the next step for programming the Arduino.
Step 4: Arduino Program
If you are not familiar with programming the Arduino, take some time before proceeding to learn the basics of programming the Arduino. The Arduino Uno has a convenient USB port that provides a connection to the computer and also powers on the Arduino from USB power. You need to know how to program the Arduino and download programs to it so that you can download the program with these instructions into the Arduino. Or... you can also create your own variations. It’s one of the great aspects of this project, is the possibilites are limitless!
The Arduino web site (http://arduino.cc/) has downloadable programming environments and many resources to quickly get you up to speed on programming the Arduino.
OK, now that you are familiar with the Arduino Uno and can load a progam to it, we will go over the operation of V1.1 of the program supplied with these instructions.
The behavior we want to achieve from the control box is as follows:
After being turned on, the buttons are waiting to be pressed.
The first button pressed is the “winner” and the lights and sounds on that button are activated. Since the button turns itself off after about 2 seconds, the controller will wait for 2.5 seconds and then will reactivate the lights only on the button, but not the sound. This keeps visible the button that was pressed first, but does not keep the noise level up, which would become annoying.
Other buttons may be pressed after the first button (this is what will normally happen) and the order in which the buttons are pressed is detected by the controller.
The LEDs on the control box are lighted as follows, showing the order in which the buttons were pressed:
1st place - the LED is on solid
2nd place - the LED is flashing quickly
3rd place - the LED if flashing slowly
4th place - the LED is off
Pressing the reset button will turn off all the LEDs on the control box, and stop driving the “activate” line to the winning button. This will cause all the buttons to be silent and have their lights off after the winning button has completed the last 2.5s cycle.
If the reset button is not pressed, 60 seconds after the “winner” button is pressed, the system will automatically reset itself. Of course you can adjust the 60 second timeout value in the code to something else if you would like.
We put an “Easter Egg” in the code as something fun for people to try to find. We will leave it to you to find it, and to change the program for any of your own “Easter Eggs” that you might think of.
Theory of Operation
We will go over some of the key approaches and techniques in the program.
Polling vs. Delay
Many of the Arduino example programs will use the delay(n); statement to achieve blinking LED’s. Given that we want to not only capture what button was pressed 1st, but also the buttons after this, the “delay” approach will not work for us. Wonder if the 1st button was pressed and we were in a loop to drive the LED with a 500 ms (1/2 second) delay. 1/2 second is a LONG time and there might have been two or even three buttons pressed during the “delay” time and we would have no way of knowing about it! Several things could happen, when we read the buttons, all three are pressed, or perhaps one is pressed because the other button was pressed and released already! This would make the players very unhappy with our game.
So, we cannot use the “delay” function. Instead we will program the “void loop()” logic in a “polling” method. Basically this means we will try to miniminze any delays in our code and keep looping over and over again checking the status of the buttons. We will also see if it’s time for us to change the status of a LED or buttton. In a timing of the pooling loop in V1.1 we measured the average time spend in the loop to be about 0.1ms or 100 microseconds. That seems to be a pretty quick loop, and minimizes the chance of multiple button presses happening within a single loop.
But, if the loop is just checking to see if a LED needs to be turned off or on, what tells us what we are supposed to do on any given loop?
LED State Machine and Profiles
To manage the buttons and LED’s we create a “State Sequence Array.” Within the array we define a Profile. An example of a profile is “Blink the lights quickly,” or “Turn on the light.” For each profile there is a sequence of states (or step). For example in the int LED_SEQ array, we define a profile for blinking the lights quickly. That profile consists of the following state definitions:
HIGH, 250, 1, /* Profile 2 (2nd place) begin, step 0 - "Blink Quickly" */
LOW, 250, 0, /* Profile 2, step 1 */
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0, /* Profile 2 end, step 7 */
So a profile consits of state definitions that have 3 values. The first value is one of three choices, HIGH, LOW, or -1.
HIGH - when going into this state, drive the output (to the LED or BUTTON) to HIGH.
LOW - when going into this state, drive the output to LOW.
-1 - when going into this state, don’t make any change to the output.
The second value is the length of time (in milliseconds) that that state should be in effect before moving to the next state. So Profile 2 in the code fragment above, says to maintain state 1 for 250ms (or 1/4 second) and to also maintain state 2 for 250ms.
The third value is the “next step” or state. In profile 2 step 0, the next step is step 1. The next step after step 1 is step 0. So, you can see that this sequence of states or steps is in a loop. step 0 to step 1 to step 0 and so on.
Defining a “State Sequence Array” lets us easily change the behavior of the buttons and lights by just changing the “program” in the Stage Sequence Array rather than changing C code. For example we experimented with the lights behaving in this way:
First place - blink one time and wait 1 second.
Second place - blink two times and wait 1 second.
Third place - blink three times and wait 1 second.
Fourth place - blink four times and wait 1 second.
In testing this method with a few people they liked a “on solid,” “blink fast,” “blink slowly,” and “off” as the indication of 1st to 4th place respectively.
Note that we made those changes in the light behavior by ONLY changing the profiles in LED_SEQ array and we didn’t have to change the C program at all!
So now that we see how the state (or steps) are defined, how do we keep track of what state the different colored LEDs are in?
LED Sequence State
The program keeps track of where each color LED is in the “State Sequence Array” (int LED_SEQ array with three variables:
First the “profile index” - this is an index into LED_SEQ for the profile (or set of steps) being run. The index starts with zero.
Second the “step index” - this is an index of the step within the profile. The index starts with zero.
Third and last, the long integer that holds the time that the step was started. This value is set at the time a step was stared from the builin funtion millis().
These values are held in the lLSS array for each color. So there are 12 entries. For each of the four colors there are the 3 state sequence variables above. With four colors and three entries for each color, 4 x 3 = 12.
So for each “polling loop” in our code, the LED state machine processing loop does the following:
For each color (zero to 3)
Looks up the current profile.
Looks up the current step
Looks up the current step start time.
Adds the step duration time to the step start time. If the current time is less than the “step duration + step start time,” then don’t do anything. If the current time is greater than the “step duration + step start time,” then look up the next step number. Then perform the action of the next step, and update the “current step,” “current profile,” and “step start time” indexes.
So, with this program technique, we can change the LED states in complicated ways and STILL watch for button press events in a timely manner. In addition, it’s easy to change the way the LEDS behave without having to change the logic of the C code. We just have to change the profiles and steps in the LED-SEQ array.
In fact this is how we programmed our “Easter Egg” behavior. Can you find it? Do you want to put in your own “Easter Egg” behavior. Go ahead and do it! The job isn’t finished untill the “Easter Egg” is done!
Button State Machine and Profiles
The process for manipulating the button behavior is exactly the same as described for the LEDs above. The Button state variable” containing the “profiles” and “steps” or “sequences” is the int BTN_SEQ array.
Similarily, the current profle and step for each color is maintained in the long lBSS array.
The discussion for the LEDs then applies to the buttons with substitution of the above button variables.
Overall program flow
The various variables are declared, and the variable names for the Arduino I/O pin assignments are declared. See the appendix, the code, or the schematic for the Arduino pins used.
The polling loop then consists of the general steps below:
Check for button presss, and record the order.
Manage the Button Sequence State for each color button.
Manage the LED Sequence State for each color LED
Check for the Reset button (and then reset the Button/LED Sequence State array to Profile 0, or “off”)
Check for any special Reset Button conditions (i.e. held for > TEST_MODE milliseconds, then go into a profile for “Lights Test” mode.
The special case handling of the buttons to independently manage both lights and sound with only one signal line is described in more detail in the section on Button Modifications.
See the appendix for the complete program listing.
Did we miss something that you think would be really neat? For example, perhaps there could be a “Wheel of Fortune” game mode also, where a Color is selected at random, and given a pre-determined amount of time to answer.
Or invent your own new game mode.
That’s the beauty of a microcontroller implemting the logic. Simply create your own program and make it behave exactly the way you want it to.
Let your imagination run wild, and happy Arduino programming!
The program source can be downloaded at www.projectnotions.com.
Step 5: Final Touches and Conclusion
If you are new to Arduino, then you’ve also learned a lot about using an Arduino in a DIY project.
The final touches include:
Getting a box to put it in. A fishing tackle box can make a great carrying case, and will fit extra question cards, phone cords, etc.
A battery power souce. In addition to an AC to DC power supply it is nice to be able to run the system on batteries. A holder and power plug with four AA batteries works nicely.
Using the system to play games!
We hope that these instructions have been helpful to you.
Our web site at www.projectnotions.com has a video that demonstrates operation of the Quiz Game controller.
If you have questions or comments, feel free to email us.
May all your projects go smoothly!