/* Quiz Buzzer ----- ------ v.03.5 Behaviours: * Startup, flash lights, reds then greens. Detect plugged in buzzers? Start 'newgame' * When any red button pressed: All green lights come on then off twice and on third time, 'winner' LED comes on only. Any addtional presses counted for 2 seconds. Red buttons switch off either when pressed or after 5 seconds. (Current: 1 second.) * Short press selects 'next fastest' until all chosen. Then resets. (Not implimented) * 'reset' for held 2 seconds, switches off all green LEDs, flashes red buttons twice, then all red on. Game reset. (Current: Reset on press) Bonus: * 'Dice' mode, 'reset' held down for 5 seconds while in 'armed' mode. Starts after 5 seconds of hold-down, runs sequence: 1324 until button release. (Impliment: Current '1234') * 'Handicap', 'reset' held while power up = half second 'bias' towards buzzer 1 (Not implimented) * 'Drinking' game. Countdown timer then reaction. Any untouched buzzers 'win'. If all pressed, fastest 'wins'. */ // Where are all my IO pins and hardware. #define BUTOFFSET 14 #define REDOFFSET 10 #define GREOFFSET 6 #define RESBUT 2 #define RESLED 3 #define BUZZ 4 // Global data byte gamemode=1; // 1 = dice, 2 = quiz, 3 = drinking byte special=0; // Latches 'startup' modes. 0 = normal, 1 = handicap, 2 = drinking. byte gamereset=1; // 1 = just reset (off if any red button pressed) byte resetting=0; // Break out of counter loop. byte playing=0; // 1 = timer started (Off after 5 seconds) byte winner=0; // If winner is chosen. And who. (Also used for nasty hacks, so make sure it's reset before useing) unsigned long buztime[4]; // Button timer data. 32 bits (4 bytes). Battery will run out before this overflows. byte buzcon[] = {false,false,false,false}; // Buzzers connected. void setup() { /* gamereset=1; // 1 = just reset (off if any red button pressed) resetting=0; // Break out of counter loop. playing=0; // 1 = timer started (Off after 5 seconds) winner=0; // If winner is chosen. And who. int time[4] = 0xffff; // All buttons start out with highest value */ // initialize serial: Serial.begin(9600); // This needs to be tidied up. pinMode(10, OUTPUT); pinMode(11, OUTPUT); pinMode(12, OUTPUT); pinMode(13, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); pinMode(8, OUTPUT); pinMode(9, OUTPUT); pinMode(14, INPUT); pinMode(15, INPUT); pinMode(16, INPUT); pinMode(17, INPUT); pinMode(RESLED, OUTPUT); pinMode(BUZZ, OUTPUT); pinMode(RESBUT, INPUT_PULLUP); // Detect startup conditons to set special modes. digitalWrite(RESLED, HIGH); delay(200); digitalWrite(RESLED, LOW); if(digitalRead(RESBUT)==LOW){ pinMode(GREOFFSET, INPUT_PULLUP); pinMode(GREOFFSET+3, INPUT_PULLUP); if (digitalRead(GREOFFSET)==LOW) { // Drinking game mode special=2; delay(200); digitalWrite(RESLED, HIGH); delay(200); digitalWrite(RESLED, LOW); } } else if (digitalRead(GREOFFSET+3)==LOW) { special=1; } pinMode(GREOFFSET, INPUT); pinMode(GREOFFSET, OUTPUT); Serial.print("Special:"); Serial.println(special); // Finish getting things ready and set up vars randomSeed(analogRead(4)); resetgame(); } void loop() // start main loop { unsigned long checkMillis; unsigned long resetMillis; while(digitalRead(RESBUT)==LOW) {delay(10);} // Wait for reset button to be released. digitalWrite(RESLED, HIGH); if(special==2) { gamemode=3; } else { gamemode=2; } // Enables 'drinking' mode. while(gamereset){ // Every 500mS, check if any new buzzers have been connected. // This code needs 'reset game and flash lights if new connected' mode. // Right now, it just enables each buzzer. Important for drinking game and dice modes. if(millis()-checkMillis >= 500 ) { checkMillis = millis(); buttonDetect(); if(gamemode==2) { // If quiz, acknolage plug in. for(byte i=0; i<4; i++) { if(buzcon[i]) { redLED(i, HIGH); } else { redLED(i, LOW); } } } } // Quiz mode - start on any red-button. // Ignore button presses in other modes. if(gamemode==2) { for(byte i=0; i<4; i++) { if(buzcon[i]) { if(digitalRead(i+14)==HIGH){ buztime[i] = millis(); gamereset=0; playing=1; redLED(i, LOW); Serial.print("But:"); Serial.print(i); Serial.print("."); Serial.print(buztime[i]); Serial.print(" "); } } } } // Drinking - start on reset // Ignore quick presses in quiz mode. // Start dice if pressed down for 2 seconds. resetMillis = millis(); if(digitalRead(RESBUT)==LOW){ delay(10); while(gamereset==1) { if(digitalRead(RESBUT)==HIGH){ // Button let go quickly. (Needs to have no effect in triva mode) if(gamemode==3) { // Only work in drinking game mode. gamereset=0; playing=1; } else { playing=5; // Escape, but not playing. Nasty hack part 1 gamereset=0; } } if(millis()-resetMillis >= 2000 ) { // Button held down for 2 seconds gamemode=1; // Dice mode gamereset=0; } } } // Made it unreset if in quiz mode. - Nasty hack part 2 if(playing==5) { gamereset=1; playing=0; } } // End of reset loop. // Game now running. Display what is happening and lets get on with it! Serial.print("Mode:"); Serial.print(gamemode); Serial.print("!"); if(gamemode==2) { digitalWrite(BUZZ, HIGH); } // Start buzzing in quizz mode digitalWrite(RESLED, LOW); // And reset LED off! // Drinking game logic // Flash random number of times then.. if(gamemode==3) { Serial.print("Count:"); for(byte i=random(3, 20); i>0; i--) { Serial.print(i); Serial.print("."); delay(1500); digitalWrite(RESLED, HIGH); delay(200); digitalWrite(RESLED, LOW); } Serial.print("!"); // Light up red buttons. Timer starting! for(byte i=0; i<4; i++) { if(buzcon[i]) { redLED(i, HIGH); } else { redLED(i, LOW); } } } // Do all the button timer stuff. Drinking and Quiz. if(gamemode>1) { checkMillis = millis(); while(playing) { playing=0; for(byte i=0; i<4; i++) { if(buzcon[i]) { if(buztime[i]==0xffffffff){ playing=1; if(digitalRead(i+14)==HIGH){ buztime[i] = millis(); redLED(i, LOW); Serial.print(i); Serial.print("."); Serial.print(buztime[i]); Serial.print(" "); } } } } if(millis()-checkMillis >= 500 ) { // Timeout value playing=0; winner=1; // Quick reuse for buzzer trigger. Serial.print("Time "); } } // End playing // Nasty hack. If everyone presses buttons, buzz a bit. if(winner!=1){ delay(500); } winner=0; // Make sure things are how we left it. digitalWrite(BUZZ, LOW); // Buzzer off // Red lights off! for(byte i=0; i<4; i++) { redLED(i, LOW); } // Pretty flashing before we give up the answer for(byte q=0; q<4; q++) { for(byte i=0; i<4; i++) { greenLED(i, HIGH); } delay(100); for(byte i=0; i<4; i++) { greenLED(i, LOW); } delay(400); } // Choose winner. Valid for all modes. winner=0; // Have to start somewhere. for(byte i=0; i<4; i++) { // Go through all four buzzers. // greenLED(winner,LOW); if(buztime[i]= 10000 ) { gamereset=0; Serial.print("T"); } } resetgame(); Serial.println(" RESET"); } // End loop() /* ----- What did this do? What was it for? Why is it here? ---- --- Old code that I have no idea what it was for! -- Serial.print("Press: "); for(byte i=0; i<4; i++) { if(buzcon[i]) { redLED(i, HIGH); Serial.print(i); if(digitalRead(i+14)==HIGH){ Serial.print(".H "); greenLED(i, HIGH); } else { greenLED(i, LOW); Serial.print(".L "); } } else { redLED(i, LOW); } } Serial.println(""); */ // delay(50); // waits for a second // for(byte i=0; i<4; i++) { // redLED(i, LOW); // sets the LED off // greenLED(i,LOW); // } // delay(50); // -------------- FUCTIONS ----------- // Control red LEDS void redLED(byte ipin,byte istate){ digitalWrite(ipin+REDOFFSET, istate); } // Control green LEDs void greenLED(byte ipin,byte istate){ digitalWrite(ipin+GREOFFSET, istate); } // Detect what buttons are plugged in. void buttonDetect(){ Serial.print("Det:"); for(byte i=0; i<4; i++) { // digitalWrite(i+ioffset, LOW); pinMode(i+GREOFFSET, INPUT_PULLUP); //Serial.print(i); if (digitalRead(i+GREOFFSET)==LOW) { Serial.print("T"); buzcon[i]=true; } else { Serial.print("F"); buzcon[i]=false; } pinMode(i+GREOFFSET, INPUT); pinMode(i+GREOFFSET, OUTPUT); } Serial.println(". "); } // Put everything back where you left it. Including lights off. // And all timers reset. Lets play again! void resetgame() { for(byte i=0; i<4; i++) { buztime[i] = 0xffffffff; // All buttons start out with highest value buzcon[0] = false; redLED(i,LOW); greenLED(i,HIGH); // What is with this? Needed? } resetting=0; // Break out of counter loop. playing=0; // 1 = timer started (Off after 5 seconds) winner=0; // No more winner gamereset=1; // Ready to go again. } /* -------------------------- OLD PSUDOCODE EXAMPLE STUFF ------------------------- --- ORIGINAL IDEAS - FOR LOGIC FLOW REFRENCE ONLY ------- if(playing & timer()=5sec) { playing = 0; timer(off); redledoff(all); } // Stops 'play' mode. Allows for resetting. All lights off. if buttondown() not restting=1 { // If any button is pressed down. Unless resetting. if red buttons() { // Any of the red buttons down if(reset) { // And game is ready to go. reset = 0 playing =1 // Start game starttimer() // And timer. } if(playing) { // If someone has pressed a button winner = 1; for each button{ If time(button) = 0xffff { // And button hasn't been 'counted' yet time(button)=timer; // Save counts for each timer. redledoff(button); // Switch off red button LED } } } if resetbutton() & playing = 0 { if(winner) { // Show next winner. time(winner) = 0xffff; // Give old winener max time. winner=0; // No more winner, so have to rerun the check! } if(resettimer = 2sec { resetting=1; } // trigger reset if(resettimer = 5sec & reset=1) { // Run 'dice'. else { // No button pressed. resetresettimer(); } if ( reset=0 AND winner=0 ) { // If there isn't one and at least one button has been pressed(reset=0);, find and show winner winner=1; // Have to start somewhere. for button 1 to 4 { // Go through all the buttons. if(time(winner) less time(button) ) { winner = button); // Find the lowest. } if(timer(winner)=0xffff) { // No 'real' winners left. newgame(); // Restat game again! else { displaywinner(winner); // Flash lights and show who won! } ------------------- END EXAMPLE PSUDOCODE ---------------- */