Showmaster - Buttons, Buzzer and WS2812B RGB LEDs

This little craft project shows how you can turn your game night with friends into a little game show. It is suitable, for example, for question rounds in which the player who "buzzes" the answer first gets points. You probably know the principle from television. Let's go.

What we need

Quantity Componenent
1 Nano V3 ATMega328 or Microcontroller Board with ATmega328P
4 Push button
1 RGB WS2812B LED ring with 12 LEDs
1 Passive buzzer module KY-006
several Jumper wires
1 Breadboard oder Breadboard Kit


Circuit diagram

First, we connect all components as can be seen on the following circuit diagram:

Circuit diagram

Microcontroller buzzer
D2 (Signal
GND -
  RGB LED ring
D3 IN
+ 5V Vcc
GND GND
  Button 1-4
D4, D5, D6, D7 Pin 1 each
GND Pin 2 each


You can choose any components as pushbuttons to bridge the contact between GND and the respective digital input.

We will use the internal pull-up resistors, so this is possible. We just have to make sure later that the inputs are active low then.

I used a passive buzzer module. The difference to the active buzzer is that no rectangular signal must be generated there. Bernd Albrecht is in his Blog post "We bring you the flute tones" addressed the use of these modules.

Expose

My goal is to be able to press four different buttons and then have each one display a different color on the LED ring. In addition, the buzzer module should emit a matching sound. First I connected the LED ring and installed the appropriate library called "Adafruit Neopixel". It brings the example sketch "buttoncycler", which we can use well as a base. Instead of the RGB ring you can also use four SMD RGB modules. Then the library is omitted, but the RGB pins have to be connected individually. This means that 4 x 3 pins would be necessary. The buttons are each connected to one of four additional digital pins and GND. With this we would have the hardware complete.

construction

For the buzzer we can install the library "Tone". This makes it very easy to elicit the module tones. Here we can operate on the sample chain "Tonetest".

The source code

From the example sketches I wrote a program that queries the four buttons one after the other. If one of them is pressed, the corresponding LED lights up for 5 seconds and a sound is heard briefly.

To test the function of the components right at the beginning of the program, I added a start animation that lights up the LEDs in the player colors and sounds the buzzer.

Here is the source code:
 * MultiplayerGameshowBuzzer 
  * fuer vier Spieler mit Farben und Toenen
  * fuer AZ-Delivery.de
  *  
  * Funktion:
  * Spieler können je einen Taster betaetigen
  * Spielerfarbe leuchtet auf und Buzzer-Sound erklingt
  *  
  * Verwendete Hardware:
  *   - ATmega328p Mikrocontroller
  *   - Passives Buzzer Module
  *   - Neopixelring mit 12 RGB LEDs
  *   - 4 Taster
  *  
  * Verwendete Bibliotheken:
  *   - Adafruit_NeoPixel.h
  *   - Tone.h
  *  
  * Beispielquelle aus der Adafruit_NeoPixel.h: buttoncycler
  *  
  ***************************************************
  * @filename   :   buttoncycler.ino
  * @brief     :   neopixel demo
  * @author     :   Adafruit
  *
  * Copyright (C) Adafruit

  ****************************************************
  *
  * Pinout:
  *  
  *     Neopixel Ring   |     Mikrocontroller
  * ------------------------------------
  *     VCC                 |     5V oder 3.3V
  *     GND                 |     GND
  *     IN                     |     D2
  *        
  *        
  * Beispielquelle aus der Tone.h: ToneTest

  ***************************************************
  * @filename   :   ToneTest.ino
  * @brief     :   Tone demo
  * @author     :  
  *
  * https://code.google.com/archive/p/rogue-code/wikis/ToneLibraryDocumentation.wiki
  ***************************************************
  *
  * Pinout:
  *  
  *     Active Buzzer Module   |     Mikrocontroller
  * ------------------------------------------------
  *     GND                             |     GND
  *     IN                                 |     D2
  *
  *
  */

 
 #include <Adafruit_NeoPixel.h>
 #include <Tone.h>
 #define PIXEL_PIN   2  // Digital IO pin connected to the NeoPixels.
 #define BUZZER_PIN   3
 #define PIXEL_COUNT 12  // Number of NeoPixels
 #define MAX_BUTTONS 4
 
 /***************************
   * NEOPIXEL
  */
 // Declare our NeoPixel strip object:
 Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
 // Argument 1 = Number of pixels in NeoPixel strip
 // Argument 2 = Arduino pin number (most are valid)
 // Argument 3 = Pixel type flags, add together as needed:
 //   NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
 //   NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
 //   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
 //   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
 //   NEO_RGBW   Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
 int LED_number[MAX_BUTTONS] = {7, 10, 1, 4};                  // Neopixel-Nummer der Spieler
 uint32_t color[MAX_BUTTONS] = { strip.Color(255, 0, 0),       // Spielerfarben
                                 strip.Color(0, 255, 0),
                                 strip.Color(0, 0, 255),
                                 strip.Color(255, 0, 255)};
 /***************************
  * BUTTONS
  */
 int BUTTON_PIN[MAX_BUTTONS] = {4, 5, 6, 7};                   // Button Pin Nummern          
 boolean oldState[MAX_BUTTONS] = {HIGH, HIGH, HIGH, HIGH};    
 boolean newState[MAX_BUTTONS] = {HIGH, HIGH, HIGH, HIGH};
 int button_count = 0;

 
 /***************************
  * TONES
  */
 int notes[] = { NOTE_C3,
                 NOTE_C4,
                 NOTE_D4,
                 NOTE_E4,
                 NOTE_F4};
 Tone buzzer;
 
 void setup() {
   pinMode(BUTTON_PIN[0], INPUT_PULLUP);
   pinMode(BUTTON_PIN[1], INPUT_PULLUP);
   pinMode(BUTTON_PIN[2], INPUT_PULLUP);
   pinMode(BUTTON_PIN[3], INPUT_PULLUP);
   buzzer.begin(BUZZER_PIN);
   strip.begin();
   strip.show();
   startAnimation();
 }

 
 void loop() {
   newState[button_count] = digitalRead(BUTTON_PIN[button_count]);
   
   if((newState[button_count] == LOW) && (oldState[button_count] == HIGH)) {
     // Short delay to debounce button.
     delay(20);
     // Check if button is still low after debounce.
     newState[button_count] = digitalRead(BUTTON_PIN[button_count]);
     if(newState[button_count] == LOW) {      // Yes, still low
       strip.setPixelColor(LED_number[button_count], color[button_count]);
       strip.show();
       buzzer.play(notes[0], 500);
       delay(5000);
       strip.setPixelColor(LED_number[button_count], strip.Color(  0,   0,   0));
       strip.show();
    }
  }
   // Set the last-read button state to the old state.
   oldState[button_count] = newState[button_count];
   button_count++;
   if (button_count > MAX_BUTTONS-1) {
     button_count = 0;
  }
 }
 
 void startAnimation() {
   int i = 0;
   int colorCount = 0;
   int delayTime = 35;
 
   // Farbkreise mit Spielerfarben
   while (colorCount < MAX_BUTTONS) {
     buzzer.play(notes[colorCount+1], 200);
     for (i = 0; i < PIXEL_COUNT; i++) {
       strip.setPixelColor(i, color[colorCount]);
       strip.show();
       delay(delayTime);
    }
     colorCount++;
  }
   
   colorCount = 0;
 
   // Alle Pixel aus
   for (i = 0; i < PIXEL_COUNT; i++) {
     strip.setPixelColor(i, strip.Color(  0,   0,   0));
     strip.show();
     delay(delayTime);
  }
 
   // Spieler-Pixel
   for (i = 0; i < MAX_BUTTONS; i++) {
     strip.setPixelColor(LED_number[i], color[i]);
     strip.show();
     buzzer.play(notes[i+1], 200);
     delay(500);
  }
 
   delay(1000);
   
   for (i = 0; i < PIXEL_COUNT; i++) {
     strip.setPixelColor(i, strip.Color(  0,   0,   0));
     strip.show();
  }
 }

Quellcode als Download

To run through the buttons and LEDs in the program faster and with less source code, I used arrays. The following line contains the LED number in the RGB LED ring:

 int LED_number[MAX_BUTTONS] = {7, 10, 1, 4};

The LED with the number 0 is on 5 o'clock, so on the bottom right. This is due to the fact that I soldered a pin strip, with which I could plug the ring on the plug-in board.

The player colors are defined with the following line:

 uint32_t color[Max_buttons] = { strip.Color(255, 0, 0),       // player colors
                                 strip.Color(0, 255, 0),
                                 strip.Color(0, 0, 255),
                                 strip.Color(255, 0, 255)};

The function Color () From the Neopixel library produces a 32-bit value. I have summarized four values ​​in a group.

The pins for the buttons and their states are written in the arrays as follows:

 int BUTTON_PIN[MAX_BUTTONS] = {4, 5, 6, 7};                   // Button Pin Nummern          
 boolean oldState[MAX_BUTTONS] = {HIGH, HIGH, HIGH, HIGH};    
 boolean newState[MAX_BUTTONS] = {HIGH, HIGH, HIGH, HIGH};

With the array it is now possible with DigitalRead With the help of a loop, to query the four pins one after the other. The arrays Oldstate [] and NewState [] Used to check if a button has been pressed and released again. Otherwise we would hold down the button and thereby trigger the buzz several times. Theoretically we would not have to do that because I have inserted a pause when a button is pressed.

The sounds for the buzzer can also be written to an array. I set C3 as a sound that sounds when a button is pressed. The other sounds serve only for the starting animation.

in the set up() The pullup resistors must be activated at the input pins:
 void setup() {
   pinMode(BUTTON_PIN[0], INPUT_PULLUP);
   pinMode(BUTTON_PIN[1], INPUT_PULLUP);
   pinMode(BUTTON_PIN[2], INPUT_PULLUP);
   pinMode(BUTTON_PIN[3], INPUT_PULLUP);
   buzzer.begin(BUZZER_PIN);
   strip.begin();
   strip.show();
   startAnimation();
 }

For this they are initialized with INPUT_PULLUP. The buzzer needs the begin() function, so does the RGB LED ring. The show() function switches the LEDs off here. It is always needed to show the set color on the desired LED. The values are first loaded into memory and then displayed on the LEDs.

I start the start animation here after the initialization. With two loops, the pixels are passed through and displayed with the previously set colors. After that they are switched off and the player LEDs are switched on again one by one. The buzzer then sounds for this.

Player colors

Here we already see the advantage of the arrays. With the loops you can iterate over them very easily.

The loop() function has also become relatively short as a result. Since here the microcontroller runs in an endless loop anyway, we don't need to create an extra loop. We query the button pins and count up the index of the array with each pass. When one of the buttons is pressed, the conditional query takes effect and the appropriate LED lights up. The button pins, the LED numbers and the player colors use the same index in their arrays. This way you can access the values in all arrays with one counter. This shortens the source code immensely.

Conclusion

You have seen how we can connect push button, buzzer and RGB LED ring to an ATmega328 microcontroller and build a game show buzzer for four players. I hope you can use it to spice up your game night a bit. Have fun with tinkering.

Buzzer test

Andreas Wolter
For AZ-Deliver blog
For arduinoProjects for beginners

3 comments

Andreas Wolter

Andreas Wolter

@Buttgereit: Danke für den Hinweis. Wurde korrigiert.
@Klaus: Ja das lässt sich soweit erweiter, wie es digitale Eingänge für die Taster gibt.
Ich werde in Kürze ein Update dazu schreiben und den Quellcode verlinken.

Buttgereit

Buttgereit

Fritzing -Verdrahtung und Verbindungstabelle stimmen nicht überein:D2 an Buzzer S-Kontakt, D3 an LED Ring In

Klaus

Klaus

Hallo
super Projekt – kann man das auch auf 8 Spieler erweitern ?

Danke

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