Quiz show buzzers

I am wondering if its possible to monitor 4 buttons at the same time and then print the order to a small lcd screen? The only part that i can't figure out is if its possible to monitor the pins at once. Any help would be much appreciated. Thank you.

It is possible to input multiple digital input pins in one read operation using direct port access: Arduino Reference - Arduino Reference

However the Arduino is fast enough that you can read 4 digital input pins in a small tight loop such that you would like never notice a difference with humans doing the button pushing. The problem with using direct port manipulation is that you lose a little code portability if someone else's board uses a different processor chip, say a 328 Vs a Mega 1280. The Arduino core library 'abstracts' the I/O pin assignments such that pins are not dependent on what model processor you are using.

Lefty

Depends on how you code it i guess.

Take for example this code section of code for a Simon game. This uses a very basic rutien for checking the buttons.

void input() { //Function for allowing user input and checking input against the generated array

 for (int x=0; x <= turn;){ //Statement controlled by turn count
   input1 = digitalRead(switch1);
   input2 = digitalRead(switch2);
   input3 = digitalRead(switch3);
   input4 = digitalRead(switch4);

   if (input1 == HIGH){ //Checking for button push
     digitalWrite(led1, HIGH);
     delay(200);
     digitalWrite(led1, LOW);
     inputArray[x] = 1;
     delay(50);
     Serial.print(" ");
     Serial.print(1);
     if (inputArray[x] != randomArray[x]) { //Checks value input by user and checks it against
       fail();                              //the value in the same spot on the generated array
     }                                      //The fail function is called if it does not match
     x++;
   }

   if (input2 == HIGH){
     digitalWrite(led2, HIGH);
     delay(200);
     digitalWrite(led2, LOW);
     inputArray[x] = 2;
     delay(50);
     Serial.print(" ");
     Serial.print(2);
     if (inputArray[x] != randomArray[x]) {
       fail();
     }
     x++;

   }

   if (input3 == HIGH){
     digitalWrite(led3, HIGH);
     delay(200);
     digitalWrite(led3, LOW);
     inputArray[x] = 3;
     delay(50);
     Serial.print(" ");
     Serial.print(3);
     if (inputArray[x] != randomArray[x]) {
       fail();
     }
     x++;

   }

   if (input4 == HIGH){

     digitalWrite(led4, HIGH);
     delay(200);
     digitalWrite(led4, LOW);
     inputArray[x] = 4;
     delay(50);
     Serial.print(" ");
     Serial.print(4);
     if (inputArray[x] != randomArray[x]) {
       fail();
     }
     x++;

   }
  }
 delay(500);
 turn++; //Increments the turn count, also the last action before starting the output function over again
}

Because each button is checked in turn. A tie will always go to the button that is first in line. So button 4 will always loose a tie.

A tie will always go to the button that is first in line. So button 4 will always loose a tie.

In theory, but with a tight loop using simple digital input reads, there should be less then millisec resolution and such ties would be rare and not noticeable by the contestants I'm sure. Keep it simple first and then worry about how accurate the tie breaking is. :wink:

Lefty

A simple and reasonably fair way to break ties is to select the winner randomly.

But I agree with retroleft. Get it working first.

You could use an analog pin with various resistances for each button - this way a tie will always be properly acknowledged.

You could use an analog pin

How long does a conversion take?

What do you mean conversion?

From the time analogRead is called until it returns. The longer it takes, the more likely it is for a tie to occur.

Using a port read, the "check for button" loop can be done in less than 16 clock cycles. For a tie to occur, two people would have to click within 1 millionth of a second of each other.

I'm not saying your idea is bad. It certainly has merits. With your idea, it just may be more likely for a tie to occur.

I suspect that unless you're putting together the set for a new £1m quiz show - it doesn't matter. How about varying the order the buttons are read? then one controller doesn't have a permanent advantage.

I like all the ideas. So far it seems like the easiest is to have the buttons hooked up to one input with different resistances for each. Would just need to read one input. It would be nice to keep the order of who pushed just incase the first person doesn't know the answer.

How about varying the order the buttons are read? then one controller doesn't have a permanent advantage.

If all that happens in the main loop is that the inputs are looked at then there is no permanent advantage for any button. This is because the time taken to go from the last button in the list to the first is little more than from the first to the second. As the bulk of the time is spent in the digitalRead function all buttons have an equal chance.
Do an experiment, wire all the inputs to the same button, a permanent tie, and see how many times the first button on the list is called.

It would be nice to keep the order of who pushed

This means you have to keep looking at the buttons even when one has been pressed.

Agreed with Grumpy Mike. The digital method has no inherent advantage of one person versus another, and it's easy to find out the order that people buzz in. One microsecond is plenty of resolution for all but the most high-stakes million-dollar-prize situations.

Separately, I would advise against using different resistance per switch. First, it will need to be calibrated for a given power source. (I have a shield that uses this scheme for a joystick, and only works when given 5V USB, not 9V battery power.) It's also a lot harder to add more switches in the future.

// the pins connected to each button; expandable
byte buttonPins[5] = { 3, 4, 5, 6, 9 };
byte alreadyPressed[5];
byte orderPressed[5];

#define countof(x) ((sizeof(x)/sizeof(*(x)))

// set up buttons with internal tie-up resistors
void setupButtons() {
    for (byte i = 0; i < countof(buttonPins); i++) {
        digitalWrite(buttonPins[i], HIGH);
        pinMode(buttonPins[i], INPUT);
        alreadyPressed[i] = 0xFF;
        orderPressed[i] = 0xFF;
    }
}

// wait for everyone to release their button (HIGH) for at least 100ms
void waitForFairStart(int duration = 100, int timeout = 5000) {
    setupButtons();
    int cycles = 0;
    int failures = 0;
    while (cycles < duration && failures < timeout) {
        delay(1);
        byte i;
        for (i = 0; i < countof(buttonPins); i++) {
           if (digitalRead(buttonPins[i]) == LOW)
               break;
        }
        if (i >= countof(buttonPins))
            count++;
        else
            count = 0, failures++;
    }
}

// wait for the first to press their button (LOW)
byte waitForFirstHit(int timeout = 5000) {
    setupButtons();
    long start = millis();
    long offset = (start+timeout < start)? timeout*2 : 0;
    while (millis()+offset < start+timeout+offset)
        for (byte i = 0; i < countof(buttonPins); i++)
           if (digitalRead(buttonPins[i]) == LOW)
               return i;
    return 0xFF;
}

// wait to get order of button presses within timeout
// orderPressed[0] is index of first button pressed, and so on
//
byte waitForAllHits(int timeout = 5000) {
    setupButtons();
    byte next = 0;
    long start = millis();
    long offset = (start+timeout < start)? timeout*2 : 0;
    while (next < countof(buttonPins) &&
           millis()+offset < start+timeout+offset) {
        for (byte i = 0; i < countof(buttonPins); i++) {
            if (alreadyPressed[i] == 0xFF)
                if (digitalRead(buttonPins[i]) == LOW) {
                    orderPressed[next] = i;
                    alreadyPressed[next] = i;
                    next++;
                }
            }
        }
    }
    return next;
}

Hi guys,
I am a new user of the Arduino, and among my first projects is a 6 user quiz buzzer I hope to develop.

After a couple of days of brain racking the plan I have thought of, is to use the 6 analog input pins as buzzer inputs and have the output from the digital output pins in the form of a 6 digit number. This will be fed to six 7 segment displays, numbered first, second, third and so on (which indicates the positions). Each of them will indicate a number between 1 and 6, indicating the person who came in that position. So overall, we'll have complete information about who pressed when.

Now, since I am a total Arduino noob, just want to know if this can be done or am I missing something. I ask this cause I have not gone much farther than blinking an LED on my Arduino till now! :smiley:

After a couple of days of brain racking the plan I have thought of, is to use the 6 analog input pins as buzzer inputs

Might want to give this more though, then. Why would you use an analog pin to read an on/off switch state?

is to use the 6 analog input pins as buzzer inputs

I wouldn't do this, because it would be hard to convince a knowledgable contestant that this was fair.
To read the analogue inputs takes a finite amount of time, because there is only one shared A/D converter.
Use digital inputs instead, and use direct port manipulation to read them.

@PaulS and Groove - first of all thanks for the prompt replies. Secondly, I stand corrected. A big blunder by me. But one of the reasons I thought of it, is that the number of digital outputs available are few...

You can, however, use the analogue inputs as digital inputs.

Thanks for the tip. :slight_smile:

Okay, did some quick calulations and the largest output will be 654321. Which requires 20 digital output lines. So I decided why not simplify the design and consider only the first four buzzer presses. In this case the maximum output would be 6543. Which requires only 13 digital lines. DO ABLE i guess! :slight_smile:

Okay, did some quick calulations and the largest output will be 654321. Which requires 20 digital output lines. So I decided why not simplify the design and consider only the first four buzzer presses. In this case the maximum output would be 6543. Which requires only 13 digital lines. DO ABLE i guess!

If there are only 4 outputs, wouldn't the largest then be 4321?

What does the largest output value have to do with the numbers of pins required?