Darts Scoreboard with Buzzer

Hey folks, I've managed to cobble together some code for a darts scoreboard i'm looking to build. Go easy on me, i'm a newbie!

I'm keen to see if I can add functionality for a piezo buzzer to make a "winning" melody whenever either players' score reaches zero.

Does anyone have any ideas?

Existing code attached.
Final_dartDisplay_3.ino (5.5 KB)

Please post your code here

In my experience the easiest way to tidy up the code and add the code tags is as follows

Start by tidying up your code by using Tools/Auto Format in the IDE to make it easier to read. Then use Edit/Copy for Forum and paste what was copied in a new reply. Code tags will have been added to the code to make it easy to read in the forum thus making it easier to provide help.

Thanks for the tip @UKHeliBob. Please see below which should hopefully help:

#include <TM1637Display.h>
#include <Keypad.h>

uint8_t curPlayer = 0;
uint8_t numOnDisplay1[4] = { 0, 0, 0, 0 };
uint8_t numOnDisplay2[4] = { 0, 0, 0, 0 };
boolean initialScoreSet = false;
int lastScore1 = 0;
int lastScore2 = 0;
int curScore1 = 0;
int curScore2 = 0;

#define BRIGHTNESS 5  //Any value 0-7
#define CLK_1 A2
#define DIO_1 2
#define CLK_2 3
#define DIO_2 4
#define KEYPAD_C1 5
#define KEYPAD_C2 6
#define KEYPAD_C3 7
#define KEYPAD_C4 8
#define KEYPAD_R1 9
#define KEYPAD_R2 10
#define KEYPAD_R3 13
#define KEYPAD_R4 12
#define PLAYER_LED_1 A0
#define PLAYER_LED_2 A1
const byte ROWS = 4;  // Four rows
const byte COLS = 4;  // Four columns
char keys[ROWS][COLS] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};
byte rowPins[ROWS] = { KEYPAD_R1, KEYPAD_R2, KEYPAD_R3, KEYPAD_R4 };
byte colPins[COLS] = { KEYPAD_C1, KEYPAD_C2, KEYPAD_C3, KEYPAD_C4 };
Keypad kpd = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
TM1637Display display1 = TM1637Display(CLK_1, DIO_1);
TM1637Display display2 = TM1637Display(CLK_2, DIO_2);

void setup() {
  Serial.begin(9600);
  display1.setBrightness(BRIGHTNESS);
  display2.setBrightness(BRIGHTNESS);
  display1.clear();
  display2.clear();
  pinMode(PLAYER_LED_1, OUTPUT);
  pinMode(PLAYER_LED_2, OUTPUT);
  digitalWrite(PLAYER_LED_1, HIGH);  //At startup player1's turn
  digitalWrite(PLAYER_LED_2, LOW);
  showScoreDisplay1();
  showScoreDisplay2();
}

void loop() {
  char key = kpd.getKey();
  if (key) {
    Serial.print("Keypad button pressed: ");
    Serial.println(key);
    handleKeyPress(key);
  }
  delay(10);
}
void handleKeyPress(char key) {
  switch (key) {
    case '*':
      break;
    case '#':
      break;
    case 'A':
      enterKeyPressed();
      break;
    case 'B':
      break;
    case 'C':
      undo();
      break;
    case 'D':
      //set initial score
      curPlayer = 0;
      initialScoreSet = false;
      clearStack1();
      clearStack2();
      break;
    case '0':
      pushStack(0);
      break;
    case '1':
      pushStack(1);
      break;
    case '2':
      pushStack(2);
      break;
    case '3':
      pushStack(3);
      break;
    case '4':
      pushStack(4);
      break;
    case '5':
      pushStack(5);
      break;
    case '6':
      pushStack(6);
      break;
    case '7':
      pushStack(7);
      break;
    case '8':
      pushStack(8);
      break;
    case '9':
      pushStack(9);
      break;
  }
  if (curPlayer == 0) {
    digitalWrite(PLAYER_LED_1, HIGH);
    digitalWrite(PLAYER_LED_2, LOW);
  } else {
    digitalWrite(PLAYER_LED_1, LOW);
    digitalWrite(PLAYER_LED_2, HIGH);
  }
}
void pushStack(uint8_t data) {
  if (curPlayer == 0) {
    numOnDisplay1[0] = numOnDisplay1[1];
    numOnDisplay1[1] = numOnDisplay1[2];
    numOnDisplay1[2] = numOnDisplay1[3];
    numOnDisplay1[3] = data;
    showDisplayArray1();
  }
  if (curPlayer == 1) {
    numOnDisplay2[0] = numOnDisplay2[1];
    numOnDisplay2[1] = numOnDisplay2[2];
    numOnDisplay2[2] = numOnDisplay2[3];
    numOnDisplay2[3] = data;
    showDisplayArray2();
  }
}

void undo() {
  if (curPlayer == 0) {
    curPlayer = 1;
    curScore2 = lastScore2;
    showScoreDisplay2();
  } else {
    curPlayer = 0;
    curScore1 = lastScore1;
    showScoreDisplay1();
  }
}

void enterKeyPressed() {
  if (!initialScoreSet) {
    setInitScore();
  } else {
    updateScore();
  }
  clearStack1();
  clearStack2();
}
void updateScore() {
  if (curPlayer == 0) {
    int tempNum = (numOnDisplay1[0] * 1000) + (numOnDisplay1[1] * 100) + (numOnDisplay1[2] * 10) + (numOnDisplay1[3]);
    lastScore1 = curScore1;
    curScore1 -= tempNum;
    if (curScore1 < 0) { curScore1 = 0; }
    showScoreDisplay1();
    curPlayer = 1;
  } else {
    int tempNum = (numOnDisplay2[0] * 1000) + (numOnDisplay2[1] * 100) + (numOnDisplay2[2] * 10) + (numOnDisplay2[3]);
    lastScore2 = curScore2;
    curScore2 -= tempNum;
    if (curScore2 < 0) { curScore2 = 0; }
    showScoreDisplay2();
    curPlayer = 0;
  }
}
void setInitScore() {
  if (curPlayer == 0) {
    curScore1 = (numOnDisplay1[0] * 1000) + (numOnDisplay1[1] * 100) + (numOnDisplay1[2] * 10) + (numOnDisplay1[3]);
    Serial.println("Initial score set for player 1");
    showScoreDisplay1();
    curPlayer = 1;
  } else {
    curScore2 = (numOnDisplay2[0] * 1000) + (numOnDisplay2[1] * 100) + (numOnDisplay2[2] * 10) + (numOnDisplay2[3]);
    Serial.println("Initial score set for player 2");
    showScoreDisplay2();
    initialScoreSet = true;
    curPlayer = 0;
  }
}
void clearStack1() {
  numOnDisplay1[0] = 0;
  numOnDisplay1[1] = 0;
  numOnDisplay1[2] = 0;
  numOnDisplay1[3] = 0;
}
void clearStack2() {
  numOnDisplay2[0] = 0;
  numOnDisplay2[1] = 0;
  numOnDisplay2[2] = 0;
  numOnDisplay2[3] = 0;
}

void showScoreDisplay1() {
  display1.showNumberDec(curScore1, false);
  Serial.print("D1: ");
  Serial.println(curScore1);
}
void showScoreDisplay2() {
  display2.showNumberDec(curScore2, false);
  Serial.print("D2: ");
  Serial.println(curScore2);
}
void showDisplayArray1() {
  int num = (numOnDisplay1[0] * 1000) + (numOnDisplay1[1] * 100) + (numOnDisplay1[2] * 10) + (numOnDisplay1[3]);
  display1.showNumberDec(num, false);
  Serial.print("D1: ");
  Serial.println(num);
}
void showDisplayArray2() {
  int num = (numOnDisplay2[0] * 1000) + (numOnDisplay2[1] * 100) + (numOnDisplay2[2] * 10) + (numOnDisplay2[3]);
  display2.showNumberDec(num, false);
  Serial.print("D2: ");
  Serial.println(num);
}

Thank for posting using code tags. It really does make it easier to read and copy the code for examination

As to adding the buzzer, where in the sketch could you detect that a player score is exactly zero ?

Thanks. I guess the 2 places reaching zero could be defined would be either updateScore or both ShowScoreDisplay functions?

Again, I'm pretty new to all this so don't know the right answer. Missed school that day!

In the updateScore() function would be a good place

void updateScore()
{
    if (curPlayer == 0)
    {
        int tempNum = (numOnDisplay1[0] * 1000) + (numOnDisplay1[1] * 100) + (numOnDisplay1[2] * 10) + (numOnDisplay1[3]);
        lastScore1 = curScore1;
        curScore1 -= tempNum;       
        
        //activate the buzzer if curScore1 equals zero
        
        if (curScore1 < 0) { curScore1 = 0; }
        showScoreDisplay1();
        curPlayer = 1;
    }
    else
    {
        int tempNum = (numOnDisplay2[0] * 1000) + (numOnDisplay2[1] * 100) + (numOnDisplay2[2] * 10) + (numOnDisplay2[3]);
        lastScore2 = curScore2;
        curScore2 -= tempNum;

        //activate the buzzer if curScore2 equals zero

        if (curScore2 < 0) { curScore2 = 0; }
        showScoreDisplay2();
        curPlayer = 0;
    }
}

You could add a function to sound the buzzer and call it from updateScore() but what do you want to do afterwards ?

Ideal world would be for the buzzer to sound playing a melody to signal game end.

So after that I could add something in to press a button and start a new game right?

The buzzer could do whatever you want it to as long as it is capable of doing it. Have you got a buzzer ?

Note that there are 2 distinct types. One buzzes at a fixed frequency when a voltage is applied to its terminals. This is known as an active buzzer. The other type, known as a passive buzzer, needs a signal of the required frequency to be applied to its terminals in order to make a noise

As to extra actions after a win, such as zeroing the scores and maybe playing a start-up tune, it might be better if you restructured your program somewhat so that most functions, such as updateScore() are called from loop() and returned a value indicating a win. Reacting to a win in loop() would then make it easier to play the winning tune and reset the sketch. As the sketch is currently written by having loop() call a function that calls a function etc it is more difficult to unwind out of the multi level function calls to get back to the start following a win

Thanks again.

I do have a little piezo buzzer. Unsure if passive or active.

Put 5V across it. Does it buzz ?

I wouldn't call it a buzz but definitely made a noise lol

If it did anything except click then it is an active buzzer and you cannot change its note using software

ok will have a play around with some parts that i have.

looks like i have both types lol.

Have a look at the Tone library and its examples

Just ran this one from examples and was greeted with Jingle Bells:

/*
   Created by ArduinoGetStarted.com

   This example code is in the public domain

   Tutorial page: https://arduinogetstarted.com/library/arduino-melody-example
   Library References: https://arduinogetstarted.com/tutorials/arduino-buzzer-library

   This example uses a piezo buzzer:
   + plays a melody once on background each time a button is pressed
   + stops playing a melody when another button is pressed
   + without using delay() function, this is a non-blocking example
*/

#include <ezBuzzer.h>  // ezBuzzer library

const int START_BUTTON_PIN = 7;
const int STOP_BUTTON_PIN = 8;
const int BUZZER_PIN = 3;

int lastStartButtonState = HIGH;  // the previous state from the input pin
int lastStopButtonState = HIGH;   // the previous state from the input pin

ezBuzzer buzzer(BUZZER_PIN);  // create ezBuzzer object that attach to a pin;

// notes in the melody:
int melody[] = {
  NOTE_E5, NOTE_E5, NOTE_E5,
  NOTE_E5, NOTE_E5, NOTE_E5,
  NOTE_E5, NOTE_G5, NOTE_C5, NOTE_D5,
  NOTE_E5,
  NOTE_F5, NOTE_F5, NOTE_F5, NOTE_F5,
  NOTE_F5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5,
  NOTE_E5, NOTE_D5, NOTE_D5, NOTE_E5,
  NOTE_D5, NOTE_G5
};

// note durations: 4 = quarter note, 8 = eighth note, etc, also called tempo:
int noteDurations[] = {
  8, 8, 4,
  8, 8, 4,
  8, 8, 8, 8,
  2,
  8, 8, 8, 8,
  8, 8, 8, 16, 16,
  8, 8, 8, 8,
  4, 4
};

void setup() {
  Serial.begin(9600);
  pinMode(START_BUTTON_PIN, INPUT_PULLUP);
  pinMode(STOP_BUTTON_PIN, INPUT_PULLUP);
}

void loop() {
  buzzer.loop();  // MUST call the buzzer.loop() function in loop()

  int startButtonState = digitalRead(START_BUTTON_PIN);
  int stopButtonState = digitalRead(STOP_BUTTON_PIN);

  if (lastStartButtonState == HIGH && startButtonState == LOW) {
    Serial.println("The START button is pressed");
    if (buzzer.getState() == BUZZER_IDLE) {
      int length = sizeof(noteDurations) / sizeof(int);
      buzzer.playMelody(melody, noteDurations, length);  // playing
    }
  }

  if (lastStopButtonState == HIGH && stopButtonState == LOW) {
    Serial.println("The STOP button is pressed");
    if (buzzer.getState() != BUZZER_IDLE) {
      buzzer.stop();  // stop
    }
  }

  lastStartButtonState = startButtonState;
  lastStopButtonState = stopButtonState;
}
1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.