Introduction: Jeopardy Ring-in Buttons With Built-in Rules
There are several good Jeopardy/Game Show lockout buttons/buzzers, but none incorporate the timing rules of Jeopardy. I am learning about the Arduino and I thought that this would be a great project to practice with.
The rules include a question reading period with no timeout to reading the question. During this period, any player who tries to ring in receives a 250 ms penalty. When the question is finished, players have a five second window to ring in and a five second timeout to answer. After an answer timeout or a wrong answer, there is another five second window to ring in and the flow proceeds until a player answers correctly or all players have rung in and have answered incorrectly or the ring-in window has timed out.
Initially, I built my project on a solder-less breadboard. When I got the connections worked out I moved to a Radio Shack Universal Component PC Board with 780 Holes which I happened to have bought several years ago. My intention was to use as much from my junk box as possible. I recommend that, if you plan to make this, you consider using the MakerShield Kit from Maker Shed. It is more expensive but it will have the parts you need and save time.
I have not included a lot of detailed instructions on wiring the PC board, since I don't recommend that you use the same board as I did and the circuit is fairly simple. The circuit and the breadboard layout are included.
Step 1: Gather Materials
As I said, much of what went into this came from my junk box. I did have to purchase the push-button switches. The minimum parts list is:
1 Blue LED
1 Green LED
1 Red LED
1 Yellow LED
1 White LED
6 Pushbutton (Radio Shack Catalog #: 275-1556 or Catalog #: 275-1548)
6 10k Ω Resistor
4 220 Ω Resistor
1 Arduino (processor ATmega; variant Arduino UNO R3)
1 solder-less breadboard
jumper wires
In addition, if you want to go beyond breadboarding, you might need:
5 LED Holders (Radio Shack Catalog #: 276-079)
1 Project Box (I used a piece of sheet metal bent to a box size of 5"x8"x3", with wood ends. This size provided plenty of room.)
4 3.5MM Mono Male Plug (Ebay)
4 Panel 3.5mm Female Mono Headphone Jack (Ebay)
4 5" sections 1/2" PVC pipe
4 1/2" PVC end caps
20 gauge or 22 gauge ZIP Cord or Speaker Wire
1 MakerShield Kit (MakerShed)
or
1 prototyping breadboard
1 set Shield stacking headers for Arduino (Adafruit)
After I had built the project, I noticed some other projects which had used the MakerShield board with a solder-less breadboard on its top. This is a great idea because it allows you to easily put the project together and then reuse the MakerShield when you move on to the next project.
Step 2: The Ring-In Buttons
The Ring-In Buttons each consist of a 5" length of 1/2" PVC pipe, a 1/2" PVC pipe cap, a push-button switch and the wire to the game console (the Project Box). Begin with drilling a hole on the end of the pipe cap for the switch. The switches I used require a 1/4" hole. The thickness of the end of the cap will prevent the threads of the switch from protruding sufficiently to screw on the mounting nut, so the end must be sanded or ground down. I used a disc sander.
Step 3: Let the Wiring Begin
If you are the adventuresome kind, take the schematic and go at it. I prefer to breadboard a project to be sure that I haven't overlooked something. I used the free software from http://fritzing.org/ to create the breadboard layout and schematic. It is great software since, as you are creating, the auto-route feature performs a check which is a great help in potential missing connections. It may not help if you simply put a wire on the wrong pin.
The software does not contain a model for every possible component and I have not progressed to the point where I can create a new one. Consequently, the switch model is meant to be mounted on a PC board or breadboard, not hanging in mid-air or mounted on a chassis somewhere. It also has a PC board layout feature that I am starting to get used to, but have not mastered.
If you follow the breadboard layout, cross checking with the schematic, you should be able to upload the Arduino sketch below and, after setup, see the player LEDs light in chase-mode.
Attachments
Step 4: Beyond the Breadboard
When you have confidence that you want to commit the design to something more permanent, you will need a project box. If you are like me, cheap frugal, you might take a piece of sheet metal (I thought I had some aluminum but it turned out to be brass) something about 20 or 22 gauge should work, cut it to 8"x13" and bend it to have a center area of 5"x8" with two 3"x8" 90 degree flaps. I have an old 18" "bending brake" to do the bending. There are instructables in how to build your own, but it might be more expeditious to consider buying one. Harbor Freight sells one for about thirty dollars. Complete the box with two pieces of wood to fit on the ends. Don't forget to make a hole or slot for the power or USB cord to go through.
If you are not into that sort of thing, just go buy a project box of about the same size.
For the circuit board, I recommend the MakerShield kit. I did not use it, but my final attempt was very similar to it, just using stuff I had around. My first plan was to use wire wrapping. I was pretty good at it, thirty years ago, but not now and I don't recommend it.
In the build, the layout is not critical. Neatness is very helpful. if you are consistent in placement, when you have components, like resistors, performing a similar function, laid out with similar connections, if something looks out of place,it is worth double-checking.
Step 5: Uploading
//
// This sketch implements a "Jeopardy" style contestant response tiebreaker.
//
// Each contestant has a pushbutton switch.
// After setup, the waitingForQuestion function is invoked. This uses a
// local loop, rather than the Arduino loop, to wait for the moderator
// to begin. While waiting, the player lights are illuminated in chase mode.
// When the moderator presses the switch S6 button, the QUESTION_READING
// state begins. There is no time limit here. In this phase the player
// LEDs will light in chase mode. During this time, if a player button is
// pressed, a penalty of 0.25 seconds is applied for the next phase. When
// the moderator presses the switch S5 button and releases it, the
// READY_FOR_ANSWER_LIGHT is turned on, player LEDs will be extinguished and
// the game will proceed to the WAITING_FOR_RING_IN state.
// In WAITING_FOR_RING_IN, the READY_FOR_ANSWER_LIGHT is
// illuminated. There is a five second timeout which, at its expiration,
// causes the game to resetAll to clear variables, the waitingForQuestion
// function is invoked and the state changes to QUESTION_READING. When
// a player presses a button, if the player is not BLOCKED from a prior
// wrong answer and any delay time imposed in the QUESTION_READING phase,
// that player's light is turned and READY_FOR_ANSWER_LIGHT is turned off.
// The game proceeds to the WAITING_FOR_ANSWER state.
// In WAITING_FOR_ANSWER, after a five second timeout or
// a player giving a wrong answer, the game proceeds to
// WAITING_FOR_RING_IN, if there are players not yet buzzed in. If a
// player gives a correct answer or all players have attempted to answer,
// resetAll clears variables, the waitingForQuestion function is invoked
// and the state changes to QUESTION_READING.
//
// Note: This program is set up to handle up to four players. If there are fewer
// players, it will handle them, although when those players have rung in and
// incorrectly answered, the program will time out, instead of immediately
// recognizing that there are no remaining players. For the traditional three
// player purists or those who cannot wait the extra five seconds, MAX_PLAYERS
// can be changed to three and the program recompilied and uploaded. It will then
// only recognize players one through three.
// 2012.12.18 Initial release.
/*
* Environment definitions
*/
#define MAX_PLAYERS 4
#define TIMEOUT_PERIOD 5000
#define DELAY_TIME 250
#define NO_ANSWER 0
#define CORRECT_ANSWER 1
#define WRONG_ANSWER -1
/*
* Hardware definitions
*/
#define TOP_LED 13
#define TOP_SWITCH 9
// The CORRECT_ANSWER_BUTTON is switch S6
#define CORRECT_ANSWER_BUTTON 3
// The WRONG_ANSWER_BUTTON is switch S5
#define WRONG_ANSWER_BUTTON 4
#define READY_FOR_ANSWER_LIGHT 5
/*
* Housekeeping definitions
*/
int buzzedInPlayer = -1;
int buzzedInPlayerCount = 0;
unsigned long timeout = 0;
int blockedPlayers = 0;
int moderator;
char ESC_CHAR = 27;
#define PUT_CURSOR_MIDSCREEN\
Serial.print(ESC_CHAR);\
Serial.print("[2J");\
delay(2);\
Serial.print(ESC_CHAR);\
Serial.print("[10;1H");
/*
* Button press definitions
*/
#define NOT_PUSHED HIGH
#define PUSHED LOW
#define BLOCKED -1
/*
* LED state definitions
*/
#define LED_ON HIGH
#define LED_OFF LOW
/*
* Game States
*/
#define QUESTION_READING 1
#define WAITING_FOR_RING_IN 2
#define WAITING_FOR_ANSWER 3
int phase = QUESTION_READING;
#define DEBOUNCE_TIME 10
struct player_t {
int light;
int buttonPin;
int button;
unsigned timePenalty;
} ;// End struct playerStruct_t
struct player_t player[MAX_PLAYERS];
// Reset player time.
void resetPlayerTime()
{
int i;
for (i = 0; i < MAX_PLAYERS; i++)
{
player[i].timePenalty = 0;
};
} // End resetAll
// Reset to the initial state.
void resetAll()
{
int i;
moderator = NO_ANSWER;
phase = QUESTION_READING;
for (i = 0; i < MAX_PLAYERS; i++)
{
digitalWrite(player[i].light, LED_OFF);
player[i].button = NOT_PUSHED;
resetPlayerTime();
};
buzzedInPlayer = -1;
buzzedInPlayerCount = 0;
} // End resetAll
int readModerator()
{
// Button release is the trigger for a button having been pushed.
// Debounce is used to sense the button release.
if (digitalRead(CORRECT_ANSWER_BUTTON) == PUSHED) {
for(;;) {
delay(DEBOUNCE_TIME);
if (digitalRead(CORRECT_ANSWER_BUTTON) == NOT_PUSHED) {
break;
}
}
return CORRECT_ANSWER;
} else if (digitalRead(WRONG_ANSWER_BUTTON) == PUSHED) {
for(;;) {
delay(DEBOUNCE_TIME);
if (digitalRead(WRONG_ANSWER_BUTTON) == NOT_PUSHED) {
break;
}
}
return WRONG_ANSWER;
} else {
return NO_ANSWER;
}
}
void readPlayers()
{
// States of all player buttons are saved into the player array.
int i;
for (i = 0; i < MAX_PLAYERS; i++)
{
if (player[i].button != BLOCKED) {
if (digitalRead(player[i].buttonPin) == PUSHED) {
player[i].button = PUSHED;
} else {
player[i].button = NOT_PUSHED;
}
}
}
}
void waitingForQuestion()
{
int i;
digitalWrite(READY_FOR_ANSWER_LIGHT, LED_OFF);
Serial.println("\tModerator, Press S6 and begin reading");
Serial.println("\tModerator, Press S5 when you have finished the Question");
while (!(readModerator() == CORRECT_ANSWER)) {
for (i = 0; i < MAX_PLAYERS; i++) {
digitalWrite(player[i].light, LED_ON);
delay(250);
digitalWrite(player[i].light, LED_OFF);
}
}
PUT_CURSOR_MIDSCREEN
Serial.println("\tPlayers, Wait for question to finish");
}
void setup()
{
int i;
for (i = 0; i < MAX_PLAYERS; i++) {
// Assign the LEDs, cathodes connected to ground
player[i].light = TOP_LED - i;
pinMode(player[i].light, OUTPUT);
// Assign the pushbutton switches; connect the input to ground when closed.
player[i].buttonPin = TOP_SWITCH - i;
pinMode(player[i].buttonPin, INPUT);
digitalWrite(player[i].buttonPin, HIGH); // Enable pullup
}
pinMode(READY_FOR_ANSWER_LIGHT, OUTPUT);
pinMode( WRONG_ANSWER_BUTTON, INPUT );
digitalWrite( WRONG_ANSWER_BUTTON, HIGH); // Enable pullup
pinMode( CORRECT_ANSWER_BUTTON, INPUT );
digitalWrite( CORRECT_ANSWER_BUTTON, HIGH); // Enable pullup
resetAll();
Serial.begin(9600); // set up Serial library at 9600 bps
PUT_CURSOR_MIDSCREEN
waitingForQuestion();
}
void loop()
{
int i;
switch (phase) {
case QUESTION_READING: {
// Moderator has pressed the reset button
// or the questioned has been answeredd
// or all players have answered incorrectly.
// No timing for this phase.
// Any Buzz-ins will suffer 0.25 second delay when next state entered.
readPlayers();
// Apply Penalty for eager button pressers
for (i = 0; i < MAX_PLAYERS; i++) {
if ((player[i].button == PUSHED) &&
(player[i].timePenalty == 0)) {
player[i].timePenalty = DELAY_TIME;
Serial.print("\tPlayer ");
Serial.print(i+1);
Serial.println(" gets a penalty");
}
}
moderator = readModerator();
if (moderator == WRONG_ANSWER) {
phase = WAITING_FOR_RING_IN;
timeout = millis() + TIMEOUT_PERIOD;
digitalWrite(READY_FOR_ANSWER_LIGHT, LED_ON);
for (i = 0; i < MAX_PLAYERS; i++) {
player[i].timePenalty += millis();
}
PUT_CURSOR_MIDSCREEN
Serial.println("\tWaiting for Ring In");
Serial.println();
blockedPlayers = 0;
}
break;
} // End case QUESTION_READING
case WAITING_FOR_RING_IN: {
// Moderator has pressed the ANY BUTTON while in QUESTION_READING state.
// Five seconds for this phase.
if (blockedPlayers >= MAX_PLAYERS) {
PUT_CURSOR_MIDSCREEN
Serial.println("\tAll players have rung in");
Serial.println("\tModerator, Please read the next Question");
phase = QUESTION_READING;
resetAll();
waitingForQuestion();
break;
} else {
buzzedInPlayer = -1;
if (timeout >= millis()) {
readPlayers();
for (i = 0; i < MAX_PLAYERS; i++) {
if ((player[i].timePenalty <= millis()) &&
player[i].button == PUSHED) {
buzzedInPlayer = i;
buzzedInPlayerCount += 1;
digitalWrite(player[buzzedInPlayer].light, LED_ON);
digitalWrite(READY_FOR_ANSWER_LIGHT, LED_OFF);
phase = WAITING_FOR_ANSWER;
timeout = millis() + TIMEOUT_PERIOD;
player[i].button = BLOCKED;
blockedPlayers += 1;
PUT_CURSOR_MIDSCREEN
Serial.print("\tPlayer Number ");
Serial.println(i+1);
}
}
} else {
Serial.println("\tTimed out waiting for a RING_IN ");
Serial.println("\tModerator, Please read the next Question");
phase = QUESTION_READING;
resetAll();
waitingForQuestion();
break;
}
break;
} // End else
} // End case WAITING_FOR_RING_IN
case WAITING_FOR_ANSWER: {
// A player has PUSHED the button while in WAITING_FOR_RING_IN state.
// Five seconds for this phase.
if (timeout < millis()) {
if (buzzedInPlayerCount <= MAX_PLAYERS) {
PUT_CURSOR_MIDSCREEN
Serial.println("\tWAITING_FOR_RING_IN");
timeout = millis() + TIMEOUT_PERIOD;
digitalWrite(player[buzzedInPlayer].light, LED_OFF);
digitalWrite(READY_FOR_ANSWER_LIGHT, LED_ON);
phase = WAITING_FOR_RING_IN;
PUT_CURSOR_MIDSCREEN
Serial.print("\tPlayer Number ");
Serial.print(buzzedInPlayer+1);
Serial.println(" timed out waiting for an answer ");
}
}
moderator = readModerator();
if (moderator == CORRECT_ANSWER) {
digitalWrite(player[buzzedInPlayer].light, LED_OFF);
PUT_CURSOR_MIDSCREEN
Serial.print("\tPlayer Number ");
Serial.print(buzzedInPlayer+1);
Serial.println(", that is correct");
Serial.println("\tModerator, Please read the next Question");
phase = QUESTION_READING;
resetAll();
waitingForQuestion();
} else
if (moderator == WRONG_ANSWER) {
phase = WAITING_FOR_RING_IN;
timeout = millis() + TIMEOUT_PERIOD;
digitalWrite(player[buzzedInPlayer].light, LED_OFF);
digitalWrite(READY_FOR_ANSWER_LIGHT, LED_ON);
Serial.println("\tOooo, sorry, that is wrong");
Serial.println("\tWaiting for Ring In");
resetPlayerTime();
}
break;
} // End case WAITING_FOR_ANSWER
default: {
Serial.print("default: phase = ");
Serial.println(phase);
}
} // End switch (phase)
}
Attachments
Step 6: Playing the Game
For the computer interaction, you will need a telnet client. Windows users might try TeraTerm Pro, my favorite or Putty, both free applications. Both of these support VT100 emulation (without VT100 emulation the output may contain unexpected characters and will not be formatted properly). Mac and Linux users are on you own. Whichever client you use, select SERIAL at a baud rate of 9600.
Whether you use the telnet client or not, the play is the same. The participants are the moderator (which may actually be two people, one to read the questions and one to operate the console) and one (yes, one) to four players.
The game steps are:
- The console will begin lighting the player LEDs in chase mode indicating the Waiting For Question period, which has no timeout.
- Moderator presses switch S6 and holds until the chase lights stop, which begins the Question Reading period.
- During Question Reading, if a player presses a ring-in button, a 0.25 second ring-in penalty is given to the player. The player is blocked from ringing in for 0.25 seconds once the ring-in period starts.
- Moderator finishes the question and presses S5 which begins the Ring-In period.
- The Ring-In period lasts for five seconds.
- If no eligible player rings in within the five seconds, the question is finished and the game reverts to Waiting For Question period, step 1.
- The LED of the first player to ring in will light and the Answer period will begin.
- The Answer period will last up to five seconds.
- If no answer is given and there is at least one player eligible to ring in, the current player is blocked from ringing in on this question and the game reverts to the Ring-In period, step 5.
- If an incorrect answer is given the moderator presses switch S5 (Wrong Answer) and if there is at least one player eligible to ring in, the current player is blocked from ringing in on this question and the game reverts to the Ring-In period, step 5.
- If an incorrect answer or no answer is given and there is not at least one player eligible to ring in, the question is finished and the game reverts to Waiting For Question period, step 1.
- If the correct answer is given, the question is finished and the game reverts to Waiting For Question period, step 1.
Step 7: Conclusion
I had some ideas for enhancements:
- Add a speaker and output sounds, for example, a "Time's Up" beep.
-
Create a host computer application which would parse the text it receives from the Arduino and does more than simply print the text.
- Have it deliver more intricate sounds than just a beep
- Make it interactive so that there could be a Final Jeopardy phase
- Make it portable, to work with Macs and Linux
- Add a small LCD screen to the console, to display the text that would normally go to the host computer
Have fun and SHARE.
24 Comments
Question 5 years ago
Why do I get then following error in the downloaded code for the Jeopardy project ? How do I correct it? This is my first arduino project and have only programmed with PICbasic.
a function-definition is not allowed here before '{' token
void resetPlayerTime()
{
int i;
for (i = 0; i < MAX_PLAYERS; i++)
{
player[i].timePenalty = 0;
};
} // End resetAll
// Reset to the initial state.
void resetAll()
7 years ago
Hello! I'm trying to make this, but am running into a significant hiccup.
I've wired it up (in both real life and in AutoDesk), and it boots up fine; the lights are in chase mode, yay! However, when I hit S5, it doesn't seem to kick things into 'reading the question,' mode, so players can't ring in afterwards.
You can see what I've set up here. If you could tell me where I zigged when I should have zagged, I'd appreciate the feedback.
Reply 7 years ago
Sasha, I figured it out. The wiring diagram shows input 3 as the Ready light, while the code, has it as input 5. Switch the 3 and the 5 and it should work. Below is the code to match the wiring diagram:
// The CORRECT_ANSWER_BUTTON is switch S6
#define CORRECT_ANSWER_BUTTON 5
// The WRONG_ANSWER_BUTTON is switch S5
#define WRONG_ANSWER_BUTTON 4
#define READY_FOR_ANSWER_LIGHT 3
Reply 7 years ago
Sasha! I'm so glad to see you're having the same problem I am. I started this project quite a while ago but abandoned it as I ran out of time. I'm picking it back up now and hope to have it fixed and done soon. I will work on it on my end and update here if I get any results. Please do the same if you get an answer to this question. THANKS!
Reply 7 years ago
Sasha,
I wish I could help but you haven't included any clues, in the way of pictures or anything. Even so, it is really difficult to debug at a distance. might I suggest that you add some debugging to the code to verify that you have hit S5 and the action was actually detected. Once you have done that, follow the code to verify the next action.
Good luck,
Art
8 years ago on Introduction
Not sure if anyone is still active with this but im having a few issues that I would love some help with if possible. Thanks.
9 years ago on Introduction
This is awesome and I'm about to embark on building it. One quick question about the 5-second timeframe the contestant has to answer the question... If the contestant gives the answer within 5 seconds but it takes the game show host a couple of seconds to hit the "correct" button, does the contestant automatically get the question counted as wrong (i.e., as if it was a timeout)?
10 years ago on Introduction
Would it be possable to add the LCD kit to the Arduino to do the Count Down Timer?
Reply 10 years ago on Introduction
If you are talking about the Serial Enabled LCD Kit from Sparkfun, then I am pretty sure that you can. This LCD Module requires only one pin besides the 5v supply and ground. Whether you use the four player or six player version, there should be sufficient resources.
I wish I had more time to experiment but I don't see that happening for a while. Good luck if you are going to try & let me know what successes you have.
10 years ago on Introduction
Could it be possible to add two more players? If so how and what do I need to modify so I have a total of 6 players playing? Thanks.
Reply 10 years ago on Introduction
I have not given this much thought, but It should be fairly simple.
Move the player switches to the analog pins. This frees up contiguous pins for LEDs, See the forum answer at . There is a bad link in the answer to a button tutorial, which should be http://arduino.cc/en/Tutorial/Button.
Actual changes should be, define MAX_PLAYERS as 6, TOP_SWITCH as 19. Move the player switches to analog pins A0-A3 and add switches to A4 and A5. Add LEDs for players 5 and 6 to pins 8 and 9.
It may be quite a while before I have a chance to test this, Let me know if you are able to try it and please, tell me if I got anything wrong.
10 years ago on Introduction
Nice job. I recently finished a similar project for a friend to use in his classroom. I think it has a lot of the same functionality just made out of different things, well, that and mine is a stand alone device. Adding sound was a fun challenge- well, at least getting the sound to play why the controller did other things. You can check it out on my website:
www.projectsbykec.com/projects/electronics/quizgame
Reply 10 years ago on Introduction
Kurt- Wow! Your project is very impressive! I really like it.
In mine, I tried to keep it simple and in a relatively small package. I like your timer display. I had wanted to include a timer display, probably LCD, but needed a ROUND TUIT.
As for the stand-alone property, if you leave the computer at home, mine can be powered by a nine volt battery. The computer display is not necessary.
Reply 10 years ago on Introduction
Thank you. Sometimes I have problems with keeping things simple... My imagination runs away and takes my logic with it.
10 years ago on Introduction
Does any one else think the buzzers look like pipe bombs?
10 years ago on Introduction
Very nice work.
10 years ago on Introduction
Excellent! Nice work. For bonus points, try carrying this with you on your next flight. TSA has all kinds of fun with things like this.
10 years ago on Introduction
Very nice! Years ago, I built a set of buzzer controls for "You Dont Know Jack" on my arcade and made a tutorial that got passed around the community quite a bit. You've gone above any beyond with this ible! A little spit and polish and you could sell them!
10 years ago on Introduction
Pretty cool! Next project idea for you: hack the Duo Pop product to create a wireless version of your project. Toy hacking is fun!
10 years ago on Introduction
Nice tutorial - you could actually omit the pull-up resistors on the switches though, as the ATMega chip on the Arduino already has pull-ups on the ports. So you can just set them high as inputs!