/*
###### Airsoft/Paintball Domination Game ######
Description:
No space for the batteries, so that was a bad design. Everything but the 6 LED lamps is powered
by a 5v USB battery bank. The LED lamps are powered by an airsoft 11.1v lipo.
To start a game, just press and release the "admin" button (the yellow/orange middle one that
doesn't illuminate. That immediately begins starts the game timer (which can be changed in the code).
The box blinks orange to indicate no team has held the point yet.
Blue team presses and releases the blue button and their time begins immediately, complete
with the blue flashing light. Green button does the same.
When the game timer runs out, the program looks at the two accrued times, and whichever
team has the most time, the box will rapidly blink that team's color LED lamps.
In the case of a tie, the box will rapidly blink the orange admin lights. And, of course,
The circuit:
Arduino Uno R3.
SunFounder IIC I2C 16x2.
3 momentary push buttons (two illuminate).
Three relays.
Six LED lamps in appropriate colors.
Translucent ammo can.
Created 21 September 2023
Modified 6 October 2023
* added "Press Start"
* LCD now shows HH:MM:SS
By BearsoftME
for Southern Aroostook Action Sports
SAASMaine.com
Any questions or comments, please email the author: [email protected]
Demo: https://www.youtube.com/watch?v=ft3u3nQDFkM
Partial Parts List:
The board is ELEGOO UNO: https://www.amazon.com/gp/product/B01EWOE0UU/
The display is a standard I2C: https://www.amazon.com/gp/product/B019K5X53O/
The relays: https://www.amazon.com/gp/product/B07BVXT1ZK/
The buttons: https://www.amazon.com/gp/product/B071CNX3CF/
The LEDs... pick your colors: https://www.amazon.com/gp/product/B07FXTGBBB/
The box is a clear ammo can-style box from Walmart.. find it in home improvement.
Instead of powering the LEDs via the relays with the 5v from the board, I used an airsoft 11.1v lipo.
I powered the ELEGOO with a USB power bank.
I used a "breadboard" and jumper wires to build mine, as I was pressed for time, but I would HIGHLY
recommend getting a breakout board. I'll be getting one this winter and rewiring my DOMBOX. It'll
make better and stronger connections: https://www.amazon.com/s?k=uno+breakout+board
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // Initialize the LCD
const int orangeButtonPin = 2; // Orange button pin
const int blueButtonPin = 3; // Blue team button pin
const int greenButtonPin = 4; // Green team button pin
const int orangeRelayPin = 5; // Orange relay pin
const int blueRelayPin = 6; // Blue team relay pin
const int greenRelayPin = 7; // Green team relay pin
unsigned long gameStartTime = 0;
unsigned long blueStartTime = 0;
unsigned long greenStartTime = 0;
unsigned long blueElapsedTime = 0;
unsigned long greenElapsedTime = 0;
unsigned long blueTime = 0;
unsigned long greenTime = 0;
unsigned long bluePausedTime = 0;
unsigned long greenPausedTime = 0;
const unsigned long gameDuration = 3600000; // in millieconds
bool gameTimerRunning = false;
bool blueTimerRunning = false;
bool greenTimerRunning = false;
bool blueButtonStatePrev = false;
bool greenButtonStatePrev = false;
void setup() {
lcd.init();
lcd.backlight();
pinMode(orangeButtonPin, INPUT_PULLUP);
pinMode(blueButtonPin, INPUT_PULLUP);
pinMode(greenButtonPin, INPUT_PULLUP);
pinMode(orangeRelayPin, OUTPUT);
pinMode(blueRelayPin, OUTPUT);
pinMode(greenRelayPin, OUTPUT);
lcd.setCursor(2, 0);
lcd.print("PRESS START");
lcd.setCursor(0, 1);
lcd.print("B 00:00 G 00:00");
}
void loop() {
bool orangeButtonState = digitalRead(orangeButtonPin) == LOW;
bool blueButtonState = digitalRead(blueButtonPin) == LOW;
bool greenButtonState = digitalRead(greenButtonPin) == LOW;
unsigned long currentTime = millis();
// Check if the game timer is running
if (gameTimerRunning) {
unsigned long elapsedTime = currentTime - gameStartTime;
unsigned long remainingTime = (elapsedTime <= gameDuration) ? (gameDuration - elapsedTime) : 0;
// Calculate remaining game time
int gameHours = remainingTime / 3600000; // Calculate hours (1 hour = 3600000 milliseconds)
int gameMinutes = (remainingTime % 3600000) / 60000; // Calculate minutes
int gameSeconds = (remainingTime / 1000) % 60; // Calculate seconds
displayTime(gameHours, gameMinutes, gameSeconds);
// Check if the game timer has reached its duration
if (remainingTime == 0) {
blueTimerRunning = false; // Stop the blue timer
greenTimerRunning = false; // Stop the green timer
gameTimerRunning = false; // Stop the game timer
displayWinner(); // Display the winner based on total time
}
// Blink orange relay if blue or green timers are not running
if (!blueTimerRunning && !greenTimerRunning) {
// Blink the orange relay (1 second on, 1 second off)
unsigned long orangeRelayTime = currentTime % 2000;
digitalWrite(orangeRelayPin, (orangeRelayTime < 1000));
} else {
// Turn off the orange relay when blue or green timers are running
digitalWrite(orangeRelayPin, LOW);
}
} else {
// Turn off the orange relay when the game timer is not running
digitalWrite(orangeRelayPin, LOW);
}
// Check for game start (orange button press)
if (orangeButtonState && !gameTimerRunning) {
startGameTimer(currentTime);
}
// Blink blue relay if blue timer is running
if (blueTimerRunning) {
// Blink blue relay (1 second on, 1 second off)
unsigned long blueRelayTime = currentTime % 2000;
digitalWrite(blueRelayPin, (blueRelayTime < 1000));
} else {
// Turn off the blue relay when green timer is running
digitalWrite(blueRelayPin, LOW);
}
// Blink green relay if green timer is running
if (greenTimerRunning) {
// Blink green relay (1 second on, 1 second off)
unsigned long greenRelayTime = currentTime % 2000;
digitalWrite(greenRelayPin, (greenRelayTime < 1000));
} else {
// Turn off the green relay when blue timer is running
digitalWrite(greenRelayPin, LOW);
}
// Check blue team button
if (blueButtonState && !blueButtonStatePrev && gameTimerRunning) {
// If blue timer is not running, start it or resume from where it was paused
if (!blueTimerRunning) {
if (blueStartTime == 0) {
// Start blue timer from 0
blueStartTime = currentTime;
} else {
// Resume blue timer from where it was paused
blueStartTime = currentTime - blueTime;
}
blueTimerRunning = true;
}
// If green timer was running, pause it and remember the elapsed time
if (greenTimerRunning) {
greenPausedTime += currentTime - greenStartTime;
greenTimerRunning = false;
}
}
// Check green team button
if (greenButtonState && !greenButtonStatePrev && gameTimerRunning) {
// If green timer is not running, start it or resume from where it was paused
if (!greenTimerRunning) {
if (greenStartTime == 0) {
// Start green timer from 0
greenStartTime = currentTime;
} else {
// Resume green timer from where it was paused
greenStartTime = currentTime - greenTime;
}
greenTimerRunning = true;
}
// If blue timer was running, pause it and remember the elapsed time
if (blueTimerRunning) {
bluePausedTime += currentTime - blueStartTime;
blueTimerRunning = false;
}
}
// Store the button states for the next iteration
blueButtonStatePrev = blueButtonState;
greenButtonStatePrev = greenButtonState;
// Update blue timer if running
if (blueTimerRunning) {
unsigned long blueElapsed = currentTime - blueStartTime;
int blueMinutes = blueElapsed / 60000;
int blueSeconds = (blueElapsed / 1000) % 60;
lcd.setCursor(0, 1);
lcd.print("B ");
if (blueMinutes < 10) {
lcd.print("0");
}
lcd.print(blueMinutes);
lcd.print(":");
if (blueSeconds < 10) {
lcd.print("0");
}
lcd.print(blueSeconds);
blueTime = blueElapsed;
}
// Update green timer if running
if (greenTimerRunning) {
unsigned long greenElapsed = currentTime - greenStartTime;
int greenMinutes = greenElapsed / 60000;
int greenSeconds = (greenElapsed / 1000) % 60;
lcd.setCursor(9, 1);
lcd.print("G ");
if (greenMinutes < 10) {
lcd.print("0");
}
lcd.print(greenMinutes);
lcd.print(":");
if (greenSeconds < 10) {
lcd.print("0");
}
lcd.print(greenSeconds);
greenTime = greenElapsed;
}
}
void displayTime(int hours, int minutes, int seconds) {
lcd.setCursor(1, 0);
lcd.print("GAME ");
lcd.setCursor(7, 0);
if (hours < 10) {
lcd.print("0");
}
lcd.print(hours);
lcd.print(":");
if (minutes < 10) {
lcd.print("0");
}
lcd.print(minutes);
lcd.print(":");
if (seconds < 10) {
lcd.print("0");
}
lcd.print(seconds);
}
void startGameTimer(unsigned long currentTime) {
gameTimerRunning = true;
gameStartTime = currentTime;
}
void displayWinner() {
int relay = 0;
lcd.setCursor(0, 0);
lcd.print(" "); // Clear the first line
if (blueTime > greenTime) {
lcd.setCursor(0, 0);
lcd.print("BLUE TEAM WINS!");
digitalWrite(orangeRelayPin, LOW);
digitalWrite(greenRelayPin, LOW);
// Blink blue relay
while (relay < 500) {
digitalWrite(blueRelayPin, LOW);
delay(125);
digitalWrite(blueRelayPin, HIGH);
delay(125);
relay ++;
}
} else if (greenTime > blueTime) {
lcd.setCursor(0, 0);
lcd.print("GREEN TEAM WINS!");
digitalWrite(blueRelayPin, LOW);
digitalWrite(orangeRelayPin, LOW);
// Blink green relay
while (relay < 500) {
digitalWrite(greenRelayPin, LOW);
delay(125);
digitalWrite(greenRelayPin, HIGH);
delay(125);
relay ++;
}
} else {
lcd.setCursor(2, 0);
lcd.print("IT'S A TIE!");
digitalWrite(blueRelayPin, LOW);
digitalWrite(greenRelayPin, LOW);
// Blink orange relay
while (relay < 500) {
digitalWrite(orangeRelayPin, LOW);
delay(125);
digitalWrite(orangeRelayPin, HIGH);
delay(125);
relay ++;
}
}
}