[Solved] Airsoft Domination Project

Similar project to some others in the forum, but just different enough. If you aren't familiar with the "Domination" game mode, two teams compete for holding a point (could be a fort, a stump, some moose poop, whatever) for the most amount of time.

This project is to count down the 60-minute game timer, while keeping track of how much time each team holds the point. In order to start their team's time, a player must press and release their team's button.

The code I have so far, for the most part, works as intended.

  1. I press Orange button to start the game. This starts the 60-minute countdown and actuates Orange relay to blink an external orange light (which only blinks before either team captures the point.. it's basically only so the players can find the box).

  2. I can press Blue button to start Blue timer counting up and the Blue relay to actuate an external blinking blue light. Orange relay gets set to LOW so the orange external light is turned off.

  3. I can press Green button to pause Blue timer, start Green timer counting up and the Green relay to actuate an external blinking green light. Blue relay gets set to LOW so the blue external light is turned off.

Up to this this point, everything works exactly how it needs to work. However, the next time I press Blue button, it resets Blue timer to 0 and starts counting up again. Everything else works as intended. Same applies to subsequent Green button use.

Goal:
I would very much like it to not reset the teams' respective timers, as that defeats the purpose of the project. :slightly_smiling_face:

Thanks in advance.


The project is on Wokwi: AI Domination Game - Wokwi ESP32, STM32, Arduino Simulator

Hardware:

  • Arduino Uno
  • I2C 16x2
  • Three momentary arcade buttons
  • Three relays

Code:

#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;

const unsigned long gameDuration = 3600000; // 60 minutes in milliseconds

bool gameTimerRunning = false;
bool blueTimerRunning = false;
bool greenTimerRunning = false;

bool blueButtonPressed = false;
bool greenButtonPressed = 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("GAME 60:00");
  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 = gameDuration - elapsedTime;

    // Calculate remaining game time
    int gameMinutes = remainingTime / 60000;
    int gameSeconds = (remainingTime / 1000) % 60;

    displayTime(gameMinutes, gameSeconds);

    // 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);
  }

    // 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 for game start (orange button press)
  if (orangeButtonState && !gameTimerRunning) {
    startGameTimer(currentTime);
  }



// Check blue team button
  if (blueButtonState && !blueTimerRunning && !blueButtonPressed && gameTimerRunning) {
    startBlueTimer(currentTime);
    blueTimerRunning = true;
    greenTimerRunning = false;
    blueButtonPressed = true;
  } else if (!blueButtonState && blueButtonPressed) {
    blueElapsedTime += currentTime - blueStartTime;
    blueButtonPressed = false;
  }

// Check green team button
  if (greenButtonState && !greenTimerRunning && !greenButtonPressed && gameTimerRunning) {
    startGreenTimer(currentTime);
    greenTimerRunning = true;
    blueTimerRunning = false;
    greenButtonPressed = true;
  } else if (!greenButtonState && greenButtonPressed) {
    greenElapsedTime += currentTime - greenStartTime;
    greenButtonPressed = false;
  }
  

//  if (greenTimerRunning && !greenButtonState) {
//    greenElapsedTime += currentTime - greenStartTime;
//  }
  
  
  
  
  // Check for game end
  if (gameTimerRunning && currentTime - gameStartTime >= gameDuration) {
    endGameTimer();
  }


  // Update blue timer if running
  if (blueTimerRunning) {
    unsigned long blueElapsedTime = currentTime - blueStartTime;
    int blueMinutes = blueElapsedTime / 60000;
    int blueSeconds = (blueElapsedTime / 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);
  }

  // Update green timer if running
  if (greenTimerRunning) {
    unsigned long greenElapsedTime = currentTime - greenStartTime;
    int greenMinutes = greenElapsedTime / 60000;
    int greenSeconds = (greenElapsedTime / 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);
  }
}

void displayTime(int minutes, int seconds) {
  lcd.setCursor(6, 0);
  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 endGameTimer() {
  gameTimerRunning = false;
  lcd.setCursor(6, 0);
  lcd.print("GAME OVER");
}

void startBlueTimer(unsigned long startTime) {
  blueTimerRunning = true;
  blueStartTime = startTime;
}

void startGreenTimer(unsigned long startTime) {
  greenTimerRunning = true;
  greenStartTime = startTime;
}

UPDATE

I got the code to operate the buttons and pauses and no resets as needed.

Now the timer end is giving me problems. Instead of the game timer stopping at zero (and pausing whatever count up timer is running), the LCD displays "GAME 6046:47" and keeps counting down. Whichever count up timer is counting up continues to count up.

I need everything to just stop when the game timer hits 0.

#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;

const unsigned long gameDuration = 10000; // 3600000 = 60 minutes in milliseconds

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("GAME 60:00");
  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 = gameDuration - elapsedTime;

    // Calculate remaining game time
    int gameMinutes = remainingTime / 60000;
    int gameSeconds = (remainingTime / 1000) % 60;

    displayTime(gameMinutes, gameSeconds);

    // 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) {  // && !greenTimerRunning
    if (blueTimerRunning) {
      // Blue timer was running, pause it
      blueElapsedTime += currentTime - blueStartTime;
      blueTimerRunning = false;
    } else {
      // Blue timer was paused, start it
      blueStartTime = currentTime;
      blueTimerRunning = true;
      // If green timer was running, pause it
      if (greenTimerRunning) {
        greenElapsedTime += currentTime - greenStartTime;
        greenTimerRunning = false;
      }
    }
  }

  // Check green team button
  if (greenButtonState && !greenButtonStatePrev) {  // && !blueTimerRunning
    if (greenTimerRunning) {
      // Green timer was running, pause it
      greenElapsedTime += currentTime - greenStartTime;
      greenTimerRunning = false;
    } else {
      // Green timer was paused, start it
      greenStartTime = currentTime;
      greenTimerRunning = true;
      // If blue timer was running, pause it
      if (blueTimerRunning) {
        blueElapsedTime += 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 = blueElapsedTime + (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);
  }

  // Update green timer if running
  if (greenTimerRunning) {
    unsigned long greenElapsed = greenElapsedTime + (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);
  }

}

void displayTime(int minutes, int seconds) {
  lcd.setCursor(6, 0);
  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 endGameTimer() {
  gameTimerRunning = false;
  lcd.setCursor(6, 0);
  lcd.print("GAME OVER");
}

Just to summarize your requirements, are you essentially trying to create an Arduino based chess clock?

If you search for Arduino Chess Clock using your favourite search engine, there are a few examples out there that might be a good starting point, if not a solution, for your project.

Thanks for the reply!

I've already tried that, but that solution hasn't worked for me; there are simply too many moving parts to try to wrangle in.

I'm pretty attached to my current mostly-working code, since I've spent roughly 90 hours working on it.

There has got to be a simple way to just stop everything when the game timer hits 0. If I can make that happen, then I'll worry about doing team time comparisons and declaring a winner based on who accrued the most time.

Ideally an endgame LCD would look like this:

BLUE TEAM WINS!
B 17:42   G 16:12

or

GREEN TEAM WINS!
B 07:13  G 42:08

As it is right now, when the game timer reaches zero, it's like it starts over at a ridiculously high number, and whichever count up time is running doesn't stop. The first line (game timer that counts backwards from 60 minutes) reads

  GAME  6046:47 

and counts down from there.

Everything stops as it's supposed to now with the game timer reaching 0. Finding the right combination of code to get the sketch to declare a winner has me stumped now.

As written, the code declares the winner based on who presses their button first, not the accrued time they've earned. To solve this problem, I attempted to introduce global variables (blueTotalTime and greenTotalTime), then continuously full them with the values created while their respective timers are counting up. It seems super redundant to me, but programming ain't my thing, despite taking three semesters of university-level programming (python, C++, and FORTRAN, if you can believe it).

My code is below, and I'm stepping away from the project today, at least the programming side of it. I need to work on making the hardware pretty.

#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 blueTotalTime = 0; // Global variable to store blue team's total time
unsigned long greenTotalTime = 0; // Global variable to store green team's total time

const unsigned long gameDuration = 10000; // 10 minutes in milliseconds

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("GAME 10:00"); // Adjusted to 10 minutes
  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 gameMinutes = remainingTime / 60000;
    int gameSeconds = (remainingTime / 1000) % 60;

    displayTime(gameMinutes, gameSeconds);

    // 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);
    }

    // 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
    }
  } 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) {  // && !greenTimerRunning
    if (blueTimerRunning) {
      // Blue timer was running, pause it
      blueElapsedTime += currentTime - blueStartTime;
      blueTimerRunning = true;
    } else {
      // Blue timer was paused, start it
      blueStartTime = currentTime;
      blueTimerRunning = true;
      // If green timer was running, pause it
      if (greenTimerRunning) {
        greenElapsedTime += currentTime - greenStartTime;
        greenTimerRunning = false;
      }
    }
  }

  // Check green team button
  if (greenButtonState && !greenButtonStatePrev && gameTimerRunning) {  // && !blueTimerRunning
    if (greenTimerRunning) {
      // Green timer was running, pause it
      greenElapsedTime += currentTime - greenStartTime;
      greenTimerRunning = true;
    } else {
      // Green timer was paused, start it
      greenStartTime = currentTime;
      greenTimerRunning = true;
      // If blue timer was running, pause it
      if (blueTimerRunning) {
        blueElapsedTime += 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);

    // Filling Blue Game End Variable
    blueTotalTime = blueElapsedTime;
  }

  // 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);

    // Filling Green Game End Variable
    greenTotalTime = greenElapsedTime;
  }
}

void displayTime(int minutes, int seconds) {
  lcd.setCursor(6, 0);
  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
  
  unsigned long blueElapsed = blueElapsedTime + blueTotalTime;
  unsigned long greenElapsed = greenElapsedTime + greenTotalTime;

  if (blueTotalTime > greenTotalTime) {
    lcd.setCursor(0, 0);
    lcd.print("BLUE TEAM WINS!");
  // Blink blue relay  
        while (relay < 500) {  
          digitalWrite(blueRelayPin, LOW);
          delay(250);
          digitalWrite(blueRelayPin, HIGH);
          delay(250);
        relay ++;
        }

  } else if (greenTotalTime > blueTotalTime) {
    lcd.setCursor(0, 0);
    lcd.print("GREEN TEAM WINS!");
  // Blink green relay 
        while (relay < 500) {
          digitalWrite(greenRelayPin, LOW);
          delay(250);
          digitalWrite(greenRelayPin, HIGH);
          delay(250);  
        relay ++;  
        }

  } else {
    lcd.setCursor(3, 0);
    lcd.print("IT'S A TIE!");
  // Blink orange relay
        while (relay < 500) {  
          digitalWrite(orangeRelayPin, LOW);
          delay(250);
          digitalWrite(orangeRelayPin, HIGH);
          delay(250);
        relay ++;    
        }
  }
}

It's alive! :troll:

Every time I got something to work, something else would break. Since I'm a "shotgun programmer", I'm not exactly sure how I got the box to work with the code I have, but that's pretty typical for me.

Here's a quick video demo: https://www.youtube.com/watch?v=ft3u3nQDFkM

The project is saved on Wokwi: AI Domination Game - Wokwi ESP32, STM32, Arduino Simulator

Here's the final code that works exactly as it needs to:

#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 = 10000; // 10 minutes in milliseconds

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("GAME 10:00"); // Adjusted to 10 minutes
  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 gameMinutes = remainingTime / 60000;
    int gameSeconds = (remainingTime / 1000) % 60;

    displayTime(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 minutes, int seconds) {
  lcd.setCursor(6, 0);
  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 ++;    
        }
  }
}

1 Like

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