Stoppable countdown timer[Airsoft Prop Bomb]

Hello everybody,

A year ago, I started a topic asking for help about a similar project. As of today, I couldn't manage myself to get this code running, so I'm back here asking for help again :blush:

I've changed a few things form the original project (no longer use of keyboard and LCD). The basic thing of this will be something like this: Once the Arduino is turned on, every 5 seconds a leed blinks and a beep sounds. If the button "A" is pressed, the bomb gets armed. Cool, I've got it til this point. When the button is pressed the device should start a countdown timer for X minutes, then go off(playing a long tone or something like that). To defuse the bomb before the time ends, the other team has to cut the right wires on the device, but if they cut any wrong wire, the "bomb" goes off instantly.

Here is the problem: I don't know how to make the timer stoppable.

Thanks to everybody XD

Controlled explosion/disrupter

Run wires from digital pins to Ground. Set the pinmode to INPUT_PULLUP. If the pin read HIGH the wire has been cut. Check the BAD wires first and if any read HIGH, explode. Then check the GOOD wire (or wires) and if it (or they all) read HIGH, disarm.

For fun, if they cut one BAD wire you can increase the countdown rate and only explode if they cut a second BAD wire. :slight_smile:

Hey again and thanks for the quick answer.

I got what you say, John, but I still don't know how to make the Arduino check the status of the pins through the countdown. At first I thought about using something with if and else if and a delay doing a loop, but then I realized that will go on a infinite bucle that won't stop... It will work if the timer could be set up as variant apart from the if loop, and then including time-check if clause inside the loop.

We can't see your code (this is the programming section) so any advice is going to be vague.

Oops, sorry.

Here you go:

int ledpin =  13; 
int armbutton = 12;
int ledpin2 = 11;
int rightwire = 01;
int badwire1 = 02;
int badwire2 = 03;
int badwire3 = 04;
int offrelay = 05;

void setup() 
{
pinMode(ledpin, OUTPUT);
pinMode(armbutton, INPUT);
pinMode(rightwire, INPUT_PULLUP);
pinMode(badwire1, INPUT_PULLUP);
pinMode(badwire2, INPUT_PULLUP);
pinMode(badwire3, INPUT_PULLUP);
pinMode(offrelay, OUTPUT);
}


void loop() 
{

 Notarmed: 
  if (armbutton == HIGH)
  {
    goto Armed;
  }
  else
  {
    goto Notarmed;
  }
 
 Armed: 
 
 if (digitalRead(badwire1 == HIGH) || digitalRead(badwire2 == HIGH) || digitalRead(badwire3 == HIGH))
 {
   goto Kaboom;
 }
 else if (digitalRead(rightwire == HIGH)
 {
   goto Defused;
 }
 else if (MISSINGTIMER == 0)
 {
   goto Kaboom;
 }
 else 
 {
   digitalWrite(ledpin, HIGH)
   tone(8, 440, 50)
   delay(950)
   digitalWrite(ledpin, LOW)
   goto Armed;
 }
 
 Kaboom:
digitalWrite(offrelay, HIGH)
delay(5000)
  goto Notarmed;

 Defused:
 digitalWrite{ledpin2, HIGH)
 delay(50)
 tone(8, 440, 1000)
 delay(1950)
 digitalWrite(ledpin2, LOW)

}

Don't use goto. Ever.

Never.

 if (armbutton == HIGH)

You've give armbutton the value 12 - that's never going to work.

int offrelay = 05;

Why octal?

AWOL:
Never.

Like ever.

(digitalRead(badwire1 == HIGH)

You need to pay more attention to where you put your parentheses.

Edit: Reading further, it occurs to me that you haven't even got this to compile yet.

I know that goto it's not the right way, but was the only one I knew...

How can I do the same thing the right way? Declaring separate functions and using void? Sorry for my ignorance :blush:

Writing fails corrected code:

int ledpin =  13; 
int armbutton = 6;
int ledpin2 = 11;
int rightwire = 1;
int badwire1 = 2;
int badwire2 = 3;
int badwire3 = 4;
int offrelay = 5;

void setup() 
{
pinMode(ledpin, OUTPUT);
pinMode(armbutton, INPUT);
pinMode(rightwire, INPUT_PULLUP);
pinMode(badwire1, INPUT_PULLUP);
pinMode(badwire2, INPUT_PULLUP);
pinMode(badwire3, INPUT_PULLUP);
pinMode(offrelay, OUTPUT);
}


void loop() 
{

 Notarmed: 
  if (armbutton == HIGH)
  {
    goto Armed;
  }
  else
  {
    goto Notarmed;
  }
  Kaboom:
 digitalWrite(offrelay, HIGH);
 delay(5000);
  goto Notarmed;

 Armed: 
 
if (digitalRead(badwire1 == HIGH) || digitalRead(badwire2 == HIGH) || digitalRead(badwire3 == HIGH))
 {
   goto Kaboom;
 }
else if (digitalRead(rightwire == HIGH))
 {
   goto Defused;
 }
else if (MISSINGTIMER == 0)
 {
   goto Kaboom;
 }
 else 
 {
   digitalWrite(ledpin, HIGH);
   tone(8, 440, 50);
   delay(950);
   digitalWrite(ledpin, LOW);
   goto Armed;
 }
 

 Defused:
 digitalWrite(ledpin2, HIGH);
 delay(50);
 tone(8, 440, 1000);
 delay(1950);
 digitalWrite(ledpin2, LOW);

 }

Thanks for your replies.

Fixerized:
How can I do the same thing the right way? Declaring separate functions and using void? Sorry for my ignorance :blush:

State machine. Here is an example of one:

// Keeps track of the time that we last changed states
unsigned long lastStateChangeTime;
// Continue the sequence for as many states as you need
enum State { STATE_0, STATE_1, STATE_2, STATE_3 } myState;
// Call this function to set the appropriate state and update our lastStateChangeTime variable
void setStateTo(State new_state);

// Displays, in binary, which state it is in using two LEDs.
const int stateLED0 = 4;
const int stateLED1 = 5;

void setup()
{
  Serial.begin(115200);
  Serial.println("begin - Starting in state 0");
  pinMode(stateLED0, OUTPUT);
  pinMode(stateLED1, OUTPUT);
}

void loop()
{
  unsigned long timeSinceChange = timeSinceLastStateChange();
  switch (myState)
  {
    case STATE_0:
      // OUTPUTS:
      digitalWrite(stateLED0, LOW);
      digitalWrite(stateLED1, LOW);
      // INPUTS:
      if (timeSinceChange >= 2000)
      {
        Serial.println("It's been two seconds, moving to state 1");
        setStateTo(STATE_1);
      }
      break;
    case STATE_1:
      // OUTPUTS:
      digitalWrite(stateLED0, HIGH);
      digitalWrite(stateLED1, LOW);
      // INPUTS:
      if (timeSinceChange >= 5000)
      {
        Serial.println("It's been five seconds, moving to state 2");
        setStateTo(STATE_1);
      }
      break;
    case STATE_2:
      // OUTPUTS:
      digitalWrite(stateLED0, LOW);
      digitalWrite(stateLED1, HIGH);
      // INPUTS:
      if (timeSinceChange >= 4000)
      {
        Serial.println("It's been four seconds, moving to state 3");
        setStateTo(STATE_3);
      }
      break;
    case STATE_3:
      // OUTPUTS:
      digitalWrite(stateLED0, HIGH);
      digitalWrite(stateLED1, HIGH);
      // INPUTS:
      if (timeSinceChange >= 8000)
      {
        Serial.println("It's been eight seconds, moving to state 0");
        setStateTo(STATE_0);
      }
      break;
    default:
      setStateTo(STATE_0);
      break;
  }
}

// Call this function to set the appropriate state and update our lastStateChangeTime variable
void setStateTo(State new_state)
{
  myState = new_state;
  lastStateChangeTime = millis();
}

// helper function to determine if it has been interval time since the last state change
unsigned long timeSinceLastStateChange()
{
  return (millis() - lastStateChangeTime);
}
  if (armbutton == HIGH)

Again, 12 is never going to equal 1

digitalRead(badwire1 == HIGH)

Again, that's always going to read just one pin, and not the one it seems you expect.

Oops, great fail again, I got you wrong... Sorry if any inconvenience.

int ledpin =  13; 
int armbutton = 12;
int ledpin2 = 11;
int rightwire = 1;
int badwire1 = 2;
int badwire2 = 3;
int badwire3 = 4;
int offrelay = 5;

void setup() 
{
pinMode(ledpin, OUTPUT);
pinMode(armbutton, INPUT);
pinMode(rightwire, INPUT_PULLUP);
pinMode(badwire1, INPUT_PULLUP);
pinMode(badwire2, INPUT_PULLUP);
pinMode(badwire3, INPUT_PULLUP);
pinMode(offrelay, OUTPUT);
}


void loop() 
{

 Notarmed: 
  if (digitalRead(armbutton) == HIGH)
  {
    goto Armed;
  }
  else
  {
    goto Notarmed;
  }
  Kaboom:
 digitalWrite(offrelay, HIGH);
 delay(5000);
  goto Notarmed;

 Armed: 
 
if (digitalRead(badwire1) == HIGH || digitalRead(badwire2) == HIGH || digitalRead(badwire3) == HIGH)
 {
   goto Kaboom;
 }
else if (digitalRead(rightwire) == HIGH)
 {
   goto Defused;
 }
else if (MISSINGTIMER == 0)
 {
   goto Kaboom;
 }
 else 
 {
   digitalWrite(ledpin, HIGH);
   tone(8, 440, 50);
   delay(950);
   digitalWrite(ledpin, LOW);
   goto Armed;
 }
 

 Defused:
 digitalWrite(ledpin2, HIGH);
 delay(50);
 tone(8, 440, 1000);
 delay(1950);
 digitalWrite(ledpin2, LOW);

 }

I hope it's better now... :blush:

EDIT: Compiling gives back this:

CodePropA.ino: In function 'void loop()':
CodePropA:49: error: 'MISSINGTIMER' was not declared in this scope

'MISSINGTIMER' was not declared in this scope

That's because it isn't declared at all, anywhere

int MISSINGTIMER?

I know that it isn't declared, but I dont know how to code a proper timer, that was my main problem at the start of the topic.

Fixerized:
I know that it isn't declared, but I dont know how to code a proper timer, that was my main problem at the start of the topic.

It may look attractive to just put it a placeholder variable until you can get a "proper timer" variable, but the reality is that you'll have to structure your code properly first. The state machine example I posted is a good start and includes an example of keeping track of time.

Thanks, Arrch. I've looking at it for a while, but I don't think I totally understand how it works. I'll investigate about it and I'll let you know in this post when I get a better code.

Thanks everybody who helped.

Finite state machines are a simple, yet very powerful concept. Essentially, you are working with inputs, outputs and states. The program has a current state, and this determines its output (Moore FSM). The inputs determine what the next state will be. The analogy that they taught us in school was that of a vending machine. In a vending machine, the inserted coins act as the input. The amount of money deposited is the bases for the state, and the output is the the soft drink. When a coin is deposited (it receives an input), it determines which coin it received and moves to the next state. The states could be labeled something like this:

enum State { NO_MONEY, GOT_5_CENTS, GOT_10_CENTS, GOT_15_CENTS, GOT_20_CENTS, GOT_25_CENTS } state;

With each coin deposited, the state will change based on how much money has been deposited (its current state) and what coin was deposited (its current input). Say the soda costs 25 cents. Once it gets to the GOT_25_CENTS state, it spits out a soda (the output).

For a more comprehensive explanation, see the Wiki article: Finite-state machine - Wikipedia