Multiplayer Gameshow Buzzer - Teil 2 - Spielererweiterung und Updates

In the comments on the first post Multiplayer Game Show Buzzer Was asked how to extend the construction of 4 to 8 players. This question and other ideas for small updates have made me writing a second part. I use the dynamic memory management, so that the number of players can be chosen between 1 and (inclusive) 12 freely. I also show that the entrance pins is not necessarily in the set up() Initializing routine and also some gimmicks come to that the player can sweat something more. Here we go.

What we need




Nano V3 Atmega328 or Microcontroller Board with Atmega328p

up to 12



RGB WS2812B LED ring with 12 LEDs


Passive Buzzer Module KY-006


connection cable


Breadboard or Breadboard kit

circuit diagram

circuit diagram

Switching diagram to click


RGB LED ring



+ 5V









Button 1-12

D4 - D12

A0 - A2

Pin 1 each


Pin 2 each

The attentive reader will now notice that we do not use D13. This PIN should not be used as an input spin on Nano V3.0 with Atmega328 because there is the onboard LED with resistance. For the larger versions of the atmega328 that should work. Since I like challenges, we stay with the small version and pin number 13 sets a round. Since we have 12 LEDs available on the RGB LED ring, but now the official digital pins go to the tilation, we become the analog pins as digital inputs.

The structure otherwise corresponds to that Part 1. We only expand the buttons 5 to 12.


My new goal is to dynamically expand the buttons. This is of course limited as the PINs have to be initialized as outwards or inputs in the source code. This task can not be outsourced to the user. So we limit ourselves to a maximum of 12 players. If you turn on the microcontroller, I want to set first how many players will participate. The first button is mandatory. We need that for player setup mode. At the beginning you often press this button as players are there. For each player, another LED lights up on the ring. With the last player you want, the button is pressed longer so that the player setup is terminated. If you want to use all 12 buttons, you press until all LEDs light up. Then the setup is stopped automatically and it can start.

In the first version I had the player LED lit a few seconds after a button has been pressed. I thought that you can use this to limit the response time of a player after he has fuzzy. To put something "under pressure" to the player, I have now added a beep that is heard in seconds. If the response time has expired, you hear a long tone.

The source code

In the sketch I extended the maximum buttons to 12 and pin 4 of the microcontroller as DefaultButtonPin Are defined. The array uint32_t color [max_buttons]That contains the color values, I extended to 12. At this point, it is difficult to dynamically apply the memory. One could cancel the color values ​​randomly and then as I show it with the other arrays, dynamically expand. I saved that and set the colors.

The arrays for the entrance pins and the states of the buttons I have changed as follows:

 int *Button_pins = ZERO;
 int *Button_pins_temp = ZERO;
 boolean *Oldstate = ZERO;
 boolean *oldstate_temp = ZERO;
 boolean *NewState = ZERO;
 boolean *newstate_temp = ZERO;

Maybe now the question arises: What does he do?

Pointer, or pointers, are a book with seven seals for many. An array can be programmed in array certificate. That looks like this:

 int Button_pins[1] = 0;

As you already recognize, the number of items will be determined when declaring. But during programming, we do not even know how many buttons are used later and an array can not be expanded at runtime. We can only set the maximum number. Of course you could now also create an array with the 12 fields. But we want to make it a little more exciting, save memory and work dynamically. So we use the points of points. The definition with zero (which does not correspond to 0, but a zero pointer) should be done so that the pointer does not point to the emptiness and an indefinite state occurs. You can imagine that like a blind plug in the real world. An empty pipe is laid but not used yet and secured with a blind plug. Next Malloc () there are still Calloc ()where all values ​​are defined with 0 and REALLOC ()That we need later to enlarge the array.

I then added another sound C6 to the sound array. In the section I Game Configuration Called, the response time (now 5 seconds / 5000 ms), the Pieps interval of response time (now 1 second / 1000 ms) and the holding of the button during the setup (now 2 seconds / 2000 ms) are changed.

in the set up() Then the arrays are provided with storage space and connected to the pointers that I have previously declared:

   Button_pins = (Int *)malloc(Player_count*(sizeof(int)));
   Oldstate = (boolean*)malloc(Player_count*(sizeof(boolean)));
   NewState = (boolean*)malloc(Player_count*(sizeof(boolean)));
   Button_pins[0] = DefaultButtonPin;

The function Malloc () Reserved memory in the specified size and returns a pointer to this memory location. With the assignment Button_pins Our array is linked to this memory location. The variable Player_count Contains the value 1. The function contains the value Sizeof (int) Returns the size of an integer, so we reserve 1 x 2 bytes. We would have Player_count As usual with 0 can be started, no memory could be reserved because 0 x remains just 0. Although we can use this counter several times, but you need to take care of later when we use the variable as an index for the array, because there we start counting with 0.

The array Button_pins Quasi is the list that contains the entrance spin for each player. So I can assign the PINs to all players from 0 to 11 and later iterate via this list. Player 0 contains the DefaultButtonPin 4.

After the starting animation I have not changed, the LED of the first player is turned on:

   strip.SetpixelColor(Player_count - 1, color[Player_count - 1]);;

I have renounced this time to set the offset so that the upper LED is assigned to the first player. That would be a little more expensive.

In the Loop () Now have to be distinguished between the player setup and normal game mode. That makes the variable setup. At program start, we are in the player setup, the first LED lights up and the first button is already initialized as input. If the button is pressed, the arrays become with REALLOC () Extended.

Note: Malloc (), Calloc () and REALLOC () should only be used for such microcontrollers, as the program memory is fragmented and at some point to the tilt. Since we limit here to 12 players, that should not be a problem.

With the extension of the PIN array, the respective PIN is initialized as input. You can not only do that set up()but also in the program at all times. Something tricky is now when using the small Nano V3 ATMEGA328, since pin 13 should not be initialized as input and to be used with buttons. With the following trick and another variable, we can enter the pins in the PIN array as we need it:

 // Pin 13 overpring
 IF (Player_count < 10) {
     pin_number = DefaultButtonPin + (Player_count - 1);
 Else {
     pin_number = DefaultButtonPin + (Player_count);

Player No. 9 has the pin D12. Until then, it remains in the order calculated with the help of the defaultButtonPin and the player number. Pin 4 is already available in the array at position 0. Pin 5 to 12 are entered here successively. Thereafter, with pin 14 (A0) is continued. When the maximum number of players is entered, the array looks like this:














Pin code













If you now iterate over the field number, you always get the right entrance point, which we do for DigitalRead In the main loop need. The arrays Oldstate and NewState are equally expanded. If one uses another microcontroller, you can comment out or adjust this small algorithm.

If the maximum number of players is reached, the player set is ended, the LEDs turned off and the gameshow can begin.

If you want to keep the number of players lower, the button should remain pressed and the player setup is stopped after the preselected time. For this we take ButtonPress_Time = Millis (); The start time at pressing the button. Below then the query follows:

   // Hold hold for finishing the player setup
   IF (setup && (NewState[Button_count] == Low) && (Oldstate[Button_count] == Low)) {
     IF (millis() - ButtonPress_Time >= ButtonLongpress_Time) {
       setup = false;
       for (int I = 0; I < Pixel_count; I++) {
         strip.SetpixelColor(I, strip.Color(  0,   0,   0));;

At this point is checked whether the input spin Low was, Low is and if the program is still in setup is located. If so, it is checked whether the time has been pressed for holding. If so, the player setup is also finished here.

The entire source code you will find here as a download.


Really dynamic (so flexible in the number of players) is only conditionally possible. The array for the colors could still be filled automatically. Otherwise it depends on which microcontroller is used and how many input pins are available. With a few adjustments you can extend the number as desired. With 12 players you are already fine. One would have to replace the RGB ring, so that more LEDs are available.

Have fun decay

Andreas Wolter

For AZ-Delivery Blog

For arduinoProjects for beginners

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. Install ESP32 now from the board manager
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP programming via WLAN