Paintball Match Timer - Newbie Needing Assistance!

Hello Everyone!

I'm a programming newbie and i've been working on this project for the past couple of days. I'm at the point where im developing a proof on concept to take into a larger scale in the future. I'd love some input as how to best execute this, as i'm figuring out my basic(and growing!) understanding of the arduino programming language isn't quite enough to knock this project out on my own. Any input or help would be greatly appreciated!!

Here is the application im using this in:

  • Paintball games start with a 10 second count down after both teams acknowledge they are ready.
  • After 10 seconds, a horn sounds and the game starts. The game lasts 5-minutes.
  • Each team has a button/buzzer at their start gate. if one team hits the other's buzzer within the 5-minute period, the game ends.

Here is what i want the program to do:

  • Each team has a buzzer/button at their start gate as usual.
  • Each team hits their own button to signify they are ready. (i do not want both teams to have to hit their buttons simultaneously).
  • Once the program detects both teams are ready, i want it to play 10 beeps(the 10 second start timer), sound a horn, and then i want it to start a 5-minute timer.(ideally this could be interrupted at any time, but not necessary)
  • During the 5-minute timer, i want any button press to stop the clock and reset back to the waiting state.(meaning the game is over, wait for the next game)
  • If the 5-minute timer expires without a button press, then the system resets. (waiting for both teams to ready-up again)

Some additional thoughts:

  • I have this rigged up, very roughly, using a bread board, some LEDs, and a piezo speaker.
  • The real world application will involve different parts obviously, but i'm not concerned about that quite yet.
  • I've put together a rough version of what i have so far. As you can see it's a very basic sketch, but it's stuck in a loop after the 10 second timer that i can't figure out how to get out of.

Your link does not work for me. It would be far better if you would post your code here as shown in the "how to use this forum-please read" sticky.

groundFungus:
Your link does not work for me. It would be far better if you would post your code here as shown in the "how to use this forum-please read" sticky.

Sure thing. Here it is below:

// constants won't change. They're used here to set pin numbers:
#define button1Pin 5
#define button2Pin 6   // the number of the pushbutton pin
#define greenledPin 8      // the number of the LED pin
#define lyellowledPin 9
#define ryellowledPin 10
#define buzzerPin 11

// variables will change:
int button1State = 0;         // variable for reading the pushbutton status
int button2State = 0;
int lastbutton1State = 0;
int lastbutton2State = 0;
int lyellowledpinstate = 0;
int ryellowledpinstate = 0;
int greenledpinstate= 0;
int state = 0;
int old = 0;

void setup() {
  // initialize the LED pins as an output:
  pinMode(greenledPin, OUTPUT);
  pinMode(lyellowledPin, OUTPUT);
  pinMode(ryellowledPin, OUTPUT);
  // initialize the pushbutton pins as an input:
  pinMode(button1Pin, INPUT);
  pinMode(button2Pin, INPUT);
  // Set LEDs to OFF.
  digitalWrite(lyellowledPin, LOW);
  digitalWrite(ryellowledPin, LOW);
  digitalWrite(greenledPin, LOW);
}

void loop() {
 
  
  // ************BUTTON ONE SET-UP**********
  // read the state of the pushbutton value.
  button1State = digitalRead(button1Pin);
  if (button1State != lastbutton1State){ 				//if button state has changed(was 0, now 1 or was  1, now 0)
    if (button1State == 1) { 							//if button state is 1
      delay(50);
      if(lyellowledpinstate==1) 						//if the left yellow LED is on, turn it off. 
        lyellowledpinstate=0;
      else lyellowledpinstate=1; 						//If it is off, turn it on.
    }
       lastbutton1State = button1State; 				//the previous button 1 state, is now the current button state
    }
    digitalWrite(lyellowledPin, lyellowledpinstate);

 
  
  // ************BUTTON TWO SET-UP**********
  // read the state of the pushbutton value.
    button2State = digitalRead(button2Pin);

  if (button2State != lastbutton2State){
    if (button2State == 0) {
      delay(50);
      if(ryellowledpinstate==1) ryellowledpinstate=0;
      else                      ryellowledpinstate=1;
    }
       lastbutton2State = button2State;
    }
    digitalWrite(ryellowledPin, ryellowledpinstate);

 
  
  // ************TRIGGER + COUNTDOWN SET-UP**********

    if ((lyellowledpinstate == 1) && (ryellowledpinstate == 1)) {
          delay(1000);
          digitalWrite (greenledPin, HIGH);
          tone (buzzerPin, 261, 100);
          delay(200);
          tone (buzzerPin, 261, 100);
          delay(200);
          tone (buzzerPin, 261, 100);
          delay(2000);
          tone (buzzerPin, 261, 250);
          delay(1000);
          tone (buzzerPin, 261, 250);
          delay(1000);
          tone (buzzerPin, 261, 250);
          delay(1000);
          tone (buzzerPin, 261, 250);
          delay(1000);
          tone (buzzerPin, 261, 250);
          delay(1000);
          tone (buzzerPin, 261, 250);
          delay(1000);
          tone (buzzerPin, 261, 250);
          delay(1000);
          tone (buzzerPin, 261, 250);
          delay(1000);
          tone (buzzerPin, 261, 250);
          delay(1000);
          tone (buzzerPin, 261, 250);
          delay(1000);
          tone (buzzerPin, 800, 2000);
          delay(3000);
          noTone(buzzerPin);
      }
      }

Not sure what is wrong with your current code, but your description calls for what is known as a finitestate machine (FSM).

The below can act as a framework that you can extend and modify (e.g. more states if needed)

Your program can be in a few states
wait for both teams to be ready
countdown
play
finished

So the code first defines those states and sets the startup state.

Next the code defines two button pins, one for each team.

In setup, the code enables the internal pull-ups for the buttons; this will prevent floating inputs which might be the cause of your current problem.

In loop(), the code checks the current state and takes action based on that.
In WAIT_READY it reads the buttons, sets a flag if a button was pressed and checks if both buttons were pressed at some stage. If the latter is the case, the code will set the currentState to COUNT_DOWN and the next iteration of loop() that case will be executed.

Once the COUNT_DOWN state has finished, the 5 minute timer is started by setting the current time and next currentState is set to PLAY.

And so on

enum STATES
{
  WAIT_READY,
  COUNT_DOWN,
  PLAY,
  FINISHED,
};

STATES currentState = WAIT_READY;

const byte team1ButtonPin = 5;
const byte team2ButtonPin = 6;

void setup()
{
  // button to be wired between pin and GND
  pinMode(team1ButtonPin, INPUT_PULLUP);
  pinMode(team2ButtonPin, INPUT_PULLUP);
}


void loop()
{
  static bool team1Ready = false;
  static bool team2Ready = false;
  static unsigned long startTime;

  switch (currentState)
  {
    case WAIT_READY:
      if (digitalRead(team1ButtonPin) == LOW)
      {
        team1Ready = true;
      }
      if (digitalRead(team2ButtonPin) == LOW)
      {
        team2Ready = true;
      }

      // if both teams ready
      if (team1Ready == true && team2Ready == true)
      {
        // go to next state
        currentState = COUNT_DOWN;
      }
      break;
    case COUNT_DOWN:
      // beep 10 times
      for (uint8_t cnt = 0; cnt < 10; cnt++)
      {
        ...
        ...
      }
      // setup timer
      startTime = millis();
      // go to next state
      currentState = PLAY;
      break;
    case PLAY:
      if (millis() - startTime >= 300000UL)
      {
        currentState = FINISHED;
      }
      if(digitalRead(team1ButtonPin) == LOW)
      {
        // winner is team 2
        ...
        ...
        currentState = FINISHED;
      }
      if(digitalRead(team2ButtonPin) == LOW)
      {
        // winner is team 1
        ...
        ...
        currentState = FINISHED;
      }
      break;
    case FINISHED:
      // cleanup for next game
      team1Ready = false;
      team2Ready = false;

      // back to beginning
      currentState = WAIT_READY;
      break;
  }
}

I've omitted anything related to leds, buzzers etc.

Note that buttons need to be wired between pin and GND (as indicated in the code).

Agreed, finite state machine is what you need. Sterretje just gave you a very good framework already to build upon. A finite state machine is a very flexible way of programming such things, and allows for relatively easy changes to your program later.

Also note you don't need to do state checking or even debouncing on your buttons as it's just the first contact that counts. That makes the button reading that much easier.

#define button1Pin 5
#define button2Pin 6   // the number of the pushbutton pin

So, you have 2 buttons. There is NOT a clue here what they are for.

From your description, I count 4 switches - two at the starting point, one for each team, and 2 at the ending points, one for each team.

teamOneStartPin, teamTwoStartPin, teamOneEndPin, teamTwoEndPin would be names I'd use, and then when I read from them, I'd know EXACTLY what to expect.

#define lyellowledPin 9
#define ryellowledPin 10

Hmmm. l for lazy and r for rambunctious? Nothing in your project description mentions left and right, so right off the bat, I'm lost, and can make no sense of the rest of your code.

Using abbreviated/cryptic naming may seem like it's saving work today but it can be a trap. A real benefit of using descriptive names as @PaulS suggests is it makes the program self-documenting - which will be a big help six months from now if you have to modify or add something.