/*
Project: Tennis Scoreboard
Description: Use to keep score in a tennis match
In a real circuit add 330 ohm resistors on each segment
and transistors on each digit! (Wokwi doesn't care...)
The gray wires are digits, colored are the segments.
Creation date: 5/14/23
Author: AnonEngineering
License: https://en.wikipedia.org/wiki/Beerware
*/
#include <LiquidCrystal_I2C.h>
const char PLAYER_1_NAME[] = {"Otto Bounds "};
const char PLAYER_2_NAME[] = {"Dennis Ball "};
const int SET_PIN = 23;
const int GAME_PIN = 25;
const int POINT_PIN = 27;
const int PLAYER1_PIN = 31;
const int PLAYER2_PIN = 29;
// point scores
const uint8_t POINT_SCORES[4] = {15, 30, 40, 41};
// digit pins, 0 - 9
const uint8_t DIGIT_PINS[10] = {8, 9, 10, 11, 12, 3, 4, 5, 6, 7};
// segment pins, A - G
const uint8_t SEG_PINS[7] = {51, 49, 47, 45, 43, 53, 41};
// lookup table, which segments are on for each number,
// 10 numbers, 7 segments
const uint8_t NUM_SEGS[10][7] = {
{1, 1, 1, 1, 1, 1, 0}, /* 0 */
{0, 1, 1, 0, 0, 0, 0}, /* 1 */
{1, 1, 0, 1, 1, 0, 1}, /* 2 */
{1, 1, 1, 1, 0, 0, 1}, /* 3 */
{0, 1, 1, 0, 0, 1, 1}, /* 4 */
{1, 0, 1, 1, 0, 1, 1}, /* 5 */
{1, 0, 1, 1, 1, 1, 1}, /* 6 */
{1, 1, 1, 0, 0, 0, 0}, /* 7 */
{1, 1, 1, 1, 1, 1, 1}, /* 8 */
{1, 1, 1, 1, 0, 1, 1} /* 9 */
};
int currentPlayer = 0;
int sets[2] = {0, 0};
int games[2] = {0, 0};
int points[2] = {0, 0};
LiquidCrystal_I2C lcd(0x27, 16, 2);
void writeDigit(int digit, int number) {
// set up the segments
for (int segment = 0; segment < 7; segment++) {
digitalWrite(SEG_PINS[segment], NUM_SEGS[number][segment]);
}
// turn digit on
digitalWrite(DIGIT_PINS[digit], LOW);
// turn digit off
digitalWrite(DIGIT_PINS[digit], HIGH);
}
void checkSet() {
static int oldSetState = HIGH;
int setState = digitalRead(SET_PIN);
if (setState != oldSetState) {
if (setState == LOW) {
if (currentPlayer == 0) {
sets[0] = sets[0] + 1;
if (sets[0] > 9) sets[0] = 9;
} else {
sets[1] = sets[1] + 1;
if (sets[1] > 9) sets[1] = 9;
}
}
oldSetState = setState;
}
delay(20); // debounce
}
void checkGame() {
static int oldGameState = HIGH;
int gameState = digitalRead(GAME_PIN);
if (gameState != oldGameState) {
if (gameState == LOW) {
if (currentPlayer == 0) {
games[0] = games[0] + 1;
if (games[0] > 99) games[0] = 99;
} else {
games[1] = games[1] + 1;
if (games[1] > 99) games[1] = 99;
}
}
oldGameState = gameState;
}
delay(20); // debounce
}
void checkPoint() {
static int oldPointState = HIGH;
static int pointsTotalOne = 0;
static int pointsTotalTwo = 0;
int pointState = digitalRead(POINT_PIN);
if (pointState != oldPointState) {
if (pointState == LOW) {
if (currentPlayer == 0) {
points[0] = POINT_SCORES[pointsTotalOne];
pointsTotalOne++;
if (pointsTotalOne > 4) points[0] = 41;
} else {
points[1] = POINT_SCORES[pointsTotalTwo];
pointsTotalTwo++;
if (pointsTotalTwo > 4) points[1] = 41;
}
}
oldPointState = pointState;
}
delay(20); // debounce
}
void checkPlayer() {
if (digitalRead(PLAYER1_PIN) == LOW) currentPlayer = 0;
if (digitalRead(PLAYER2_PIN) == LOW) currentPlayer = 1;
}
void updateSet() {
writeDigit(0, sets[0]);
writeDigit(5, sets[1]);
}
void updateGame() {
int gameHi[2] = {0, 0};
int gameLo[2] = {0, 0};
gameHi[0] = (games[0] % 100) / 10; // tens
gameHi[1] = (games[1] % 100) / 10; // tens
gameLo[0] = games[0] % 10; // ones
gameLo[1] = games[1] % 10; // ones
writeDigit(1, gameHi[0]);
writeDigit(2, gameLo[0]);
writeDigit(6, gameHi[1]);
writeDigit(7, gameLo[1]);
}
void updatePoint() {
int pointHi[2] = {0, 0};
int pointLo[2] = {0, 0};
pointHi[0] = (points[0] % 100) / 10; // tens
pointHi[1] = (points[1] % 100) / 10; // tens
pointLo[0] = points[0] % 10; // ones
pointLo[1] = points[1] % 10; // ones
writeDigit(3, pointHi[0]);
writeDigit(4, pointLo[0]);
writeDigit(8, pointHi[1]);
writeDigit(9, pointLo[1]);
}
void updatePlayer() {
static int lastPlayer = -1;
if (currentPlayer != lastPlayer) {
lastPlayer = currentPlayer;
lcd.setCursor(15, 0);
lcd.print(' ');
lcd.setCursor(15, 1);
lcd.print(' ');
if (currentPlayer == 0) {
lcd.setCursor(15, 0);
} else {
lcd.setCursor(15, 1);
}
lcd.print("*");
}
}
void testDisplay() {
writeDigit(0, 0);
writeDigit(1, 1);
writeDigit(2, 2);
writeDigit(3, 3);
writeDigit(4, 4);
writeDigit(5, 5);
writeDigit(6, 6);
writeDigit(7, 7);
writeDigit(8, 8);
writeDigit(9, 9);
}
void setup() {
lcd.init();
pinMode(SET_PIN, INPUT_PULLUP);
pinMode(GAME_PIN, INPUT_PULLUP);
pinMode(POINT_PIN, INPUT_PULLUP);
pinMode(PLAYER1_PIN, INPUT_PULLUP);
pinMode(PLAYER2_PIN, INPUT_PULLUP);
for (int i = 0; i < 10; i++) {
pinMode(DIGIT_PINS[i], OUTPUT);
digitalWrite(DIGIT_PINS[i], HIGH);
}
for (int i = 0; i < 7; i++) {
pinMode(SEG_PINS[i], OUTPUT);
digitalWrite(SEG_PINS[i], LOW);
}
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print(PLAYER_1_NAME);
lcd.setCursor(0, 1);
lcd.print(PLAYER_2_NAME);
}
void loop() {
//testDisplay();
checkPlayer();
checkSet();
checkGame();
checkPoint();
updatePlayer();
updateSet();
updateGame();
updatePoint();
}
Players
Sets
Games
Points