how to start and cancel delays

I'm working on a project where I need a "timeout" function. It is an interactive puzzle on a sloped surface, pieces have magnets embedded that trigger switches tied to the digital pins. If you finish the puzzle, an actuator drops a bar at the bottom of the puzzle and the pieces slide off into a bag, resetting the puzzle. I need a time out so that if someone walks away with out finishing the puzzle, the actuator will reset the board.
Let's say that every 5 minutes the board would reset. Any user input would restart the timer. At the end, the timer is paused until the first piece is put down again.

this (untested) fragment may give you an idea of how to do this.
calling the myDelay function instead of the usual Arduino delay will allow the sketch to check if the timeout has matured and reset needs to be called.

unsigned long  timeout =  5 * 60 *1000 * 60; // 5 minutes
unsigned long  startTime=0;

void myDelay( unsigned long val)
{
   while( val > 0)
   {
     if (millis() - startTime > timeout) 
         resetGame(); // function to reset the game 
     delay(1);
     val--;
   }     
}


// add this line to places in sketch that has user input
    startTime = millis();

The millis() function returns "now", where "now" is how long the Arduino has been running (since the last restart).

You could add a variable to record the last time an action of interest occurred, setting it the value returned by millis().

At the end of each pass through loop, also call millis() to see if the time between "now" and the last action of interest is greater than whatever interval you want (5 minutes).

If it is, invoke the reset function (whatever that means for your game).

If you need help implementing this idea, post your code.

OK, thanks for the input, I've plugged it in but it's still not there yet.
here is the code so far. I still need to implement rs232 for my video player control but one thing at a time!

/*
This code is for an interactive puzzle board.  The pieces are steps involved in a process
so they have to be placed in the right order.  As each piece is put down, a video
player will display an image related to that step.  At certain points, relays open, 
activating lights in cases containing displays about the process. The puzzle is on a 
sloped surface with a moveable ledge at the bottom supporting the pieces.  When someone
finishes the puzzle, an actuator swings the ledge down causing the pieces to slide down into
a bag.  The runonce statements prevent the program from continuing to send play commands.
A reset is needed in case someone does not finish the puzzle and walks away.  After
a specified time of inactivity, the ledge will swing down and reset the game.
Any activity would reset this timer.

To Do: Add rs232 language
written by John Peel
*/


// constants won't change. They're used here to 
// set pin numbers:
  const int buttonPin1 = 2; // the numbers of the pushbutton pin
  const int buttonPin2 = 3; 
  const int buttonPin3 = 4; 
  const int buttonPin4 = 5; 
  const int buttonPin5 = 6; 
  const int buttonPin6 = 7; 
  const int buttonPin7 = 8;
  const int buttonPin8 = 9;
  const int buttonPin9 = 10;  
  const int relay1 =  11; // the numbers of the relay pin
  const int relay2 =  12; 
  const int relay3 =  13;
  const int relay4 =  14;
  const int relay5 =  15;

// variables will change:

  int buttonState1 = 0;// variables for reading the pushbutton status
  int buttonState2 = 0;  
  int buttonState3 = 0;  
  int buttonState4 = 0;  
  int buttonState5 = 0;  
  int buttonState6 = 0;  
  int buttonState7 = 0;
  int buttonState8 = 0;
  int buttonState9 = 0;

// this is for the timeout counter
  unsigned long  timeout =  5 * 1000; // 5 seconds for testing
  unsigned long  startTime=0;

  bool run_once1 = false;
  bool run_once2 = false;
  bool run_once3 = false;
  bool run_once4 = false;
  bool run_once5 = false;
  bool run_once6 = false;
  bool run_once7 = false;
  bool run_once8 = false;
  bool run_once9 = false;

// functions below

void myDelay( unsigned long val)
{
   while( val > 0)
   {
     if (millis() - startTime > timeout)
         resetGame(); // function to reset the game
     delay(1);
     val--;
     }    
  }
void resetGame()
  {
    digitalWrite (relay3, HIGH);  //open actuator relay to drop ledge, 
    delay (2000); //time delay, we want to make sure all pieces have slid off the table
    digitalWrite (relay4,HIGH);  //Relays 4 and 5 switch the polarity to the actuator, closing it
    digitalWrite (relay5, HIGH);//
    delay (2000) ; // time for ledge to raise
    digitalWrite (relay3,LOW);// shut off power to the actuator
    digitalWrite (relay4,LOW);
    digitalWrite (relay5,LOW);
    digitalWrite (relay1,LOW);// shut off relays one and two, case lights
    digitalWrite (relay2,LOW);
    run_once1 = false;  //resets all the switches
    run_once2 = false;
    run_once3 = false;
    run_once4 = false;
    run_once5 = false;
    run_once6 = false;
    run_once7 = false;
    run_once8 = false;
    run_once9 = false;
    Serial.println  ("play intro loop");//send play command to roku:
  }
void setup()
  {
  // initialize the relay pin as an output:
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
  pinMode(relay4, OUTPUT);
  pinMode(relay5, OUTPUT);
  
  // initialize the pushbutton pins as an input:
  pinMode(buttonPin1, INPUT); 
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
  pinMode(buttonPin4, INPUT);
  pinMode(buttonPin5, INPUT);
  pinMode(buttonPin6, INPUT);
  pinMode(buttonPin7, INPUT);
  pinMode(buttonPin8, INPUT);
  pinMode(buttonPin9, INPUT);

  Serial.begin(9600); // set up Serial library at 9600 bps    
       
  Serial.println  ("play intro loop");// send play command to roku: 
  } 



void loop()
  {
  // read the state of the pushbutton value:
  buttonState1 = digitalRead(buttonPin1);
  buttonState2 = digitalRead(buttonPin2);
  buttonState3 = digitalRead(buttonPin3);
  buttonState4 = digitalRead(buttonPin4);
  buttonState5 = digitalRead(buttonPin5);
  buttonState6 = digitalRead(buttonPin6);
  buttonState7 = digitalRead(buttonPin7);
  buttonState8 = digitalRead(buttonPin8);
  buttonState9 = digitalRead(buttonPin9);
 

      // check if pussle piece is on the board.  each piece corresponds to a button pin.
      // pieces have to be placed in order, 1 through 9.  checks if one is there but the others are not and so on
  { 
    if
     (buttonState1 == HIGH&&buttonState2==LOW &&buttonState3==LOW &&buttonState4==LOW &&buttonState5==LOW &&buttonState6==LOW &&buttonState7==LOW &&buttonState8==LOW &&
      buttonState9==LOW  && !run_once1) 
    {
      myDelay;
      run_once1 = true;      
      Serial.println  ("play file one");// send play command to roku:
      startTime = millis();
    }
 
    else if (buttonState1 == HIGH&&buttonState2==HIGH&&buttonState3==LOW &&buttonState4==LOW &&buttonState5==LOW &&buttonState6==LOW &&buttonState7==LOW &&buttonState8==LOW &&
      buttonState9==LOW  && !run_once2 )
    { 
      myDelay; 
      run_once2 = true;
      startTime = millis();    
      Serial.println  ("play file two");// send play command to roku:
    }
    
    else if (buttonState1== HIGH&&buttonState2==HIGH&&buttonState3== HIGH&&buttonState4==LOW &&buttonState5==LOW &&buttonState6==LOW &&buttonState7==LOW &&buttonState8==LOW &&
      buttonState9==LOW && !run_once3)
    { 
      myDelay;    
      run_once3 = true;        
      Serial.println  ("play file three");// send play command to roku:
      startTime = millis();
    }
    
    else if (buttonState1== HIGH&&buttonState2==HIGH&&buttonState3== HIGH&&buttonState4== HIGH&&buttonState5==LOW &&buttonState6==LOW &&buttonState7==LOW &&buttonState8==LOW &&buttonState9 ==LOW && !run_once4)
    { 
      myDelay;  
      run_once4 = true;        
      Serial.println  ("play file four");// send play command to roku:
      startTime = millis();
    }
    
    else if (buttonState1== HIGH&&buttonState2==HIGH&&buttonState3== HIGH&&buttonState4== HIGH&&buttonState5== HIGH&&buttonState6-buttonState9 ==LOW && !run_once5)
    { 
      myDelay;  
      run_once5 = true;    
      Serial.println  ("play file five");// send play command to roku:
      digitalWrite (relay1,HIGH);
      startTime = millis();
    }
    
    else if (buttonState1== HIGH&&buttonState2==HIGH&&buttonState3== HIGH&&buttonState4== HIGH&&buttonState5==HIGH&&buttonState6== HIGH&&buttonState7==LOW &&buttonState8==LOW &&buttonState9 ==LOW && !run_once6 )
    { 
      myDelay;  
      run_once6 = true;     
      Serial.println  ("play file six");// send play command to roku:
      startTime = millis();
    }
    
    else if (buttonState1 == HIGH&&buttonState2==HIGH&&buttonState3== HIGH&&buttonState4== HIGH&&buttonState5==HIGH&&buttonState6== HIGH&&buttonState7== HIGH&&buttonState8 == LOW &&buttonState9 ==LOW && !run_once7 )
    { 
      myDelay;   
      run_once7 = true;    
      Serial.println  ("play file seven");// send play command to roku:
      startTime = millis();
    }
    
    else if (buttonState1== HIGH&&buttonState2==HIGH&&buttonState3== HIGH&&buttonState4== HIGH&&buttonState5==HIGH&&buttonState6== HIGH&&buttonState7== HIGH&&buttonState8== HIGH&&buttonState9==LOW && !run_once8 )
    {  
      run_once8 = true;
      Serial.println  ("play file eight");// send play command to roku:
      digitalWrite (relay2, HIGH);
      startTime = millis();
    }
    
    else if (buttonState1== HIGH&&buttonState2==HIGH&&buttonState3== HIGH&&buttonState4== HIGH&&buttonState5==HIGH&&buttonState6== HIGH&&buttonState7== HIGH&&buttonState8== HIGH&&buttonState9== HIGH && !run_once9)
    {   
      run_once9 = true;     
      Serial.println  ("play file nine");// send play command to roku:
      delay (6000);  //what ever the length of the final video is plus a few seconds
      resetGame ();   
    }
   }
 }
    
   

  /code]

A few things.

One)

 bool run_once1 = false;
 bool run_once2 = false;
 bool run_once3 = false;
 bool run_once4 = false;
 bool run_once5 = false;
 bool run_once6 = false;
 bool run_once7 = false;
 bool run_once8 = false;
 bool run_once9 = false;

You really need to learn about arrays. :slight_smile:

Two) This declares a function that takes one argument, and returns nothing:

void myDelay( unsigned long val)

This:

     myDelay;

is syntactically valid. But it is not a call to the function. The function was evaluated. It is defined, so myDelay is non-zero. However, it does nothing. If you want to call the function you need one of these ( and one of these ). In between them, you need to put a value.

Third)

   else if (buttonState1 == HIGH&&buttonState2==HIGH&&buttonState3==LOW &&buttonState4==LOW &&buttonState5==LOW &&buttonState6==LOW &&buttonState7==LOW &&buttonState8==LOW &&
     buttonState9==LOW  && !run_once2 )

Doesn't your computer have a carriage return? A space bar?

It's called code. Not cryptic_not_meant_to_be_read_by_humans_text. Take pity on us old programmers, and make the code easy to read. Any time there are 10 conditional comparisons in an if test, there is almost certainly a better way.

Fourth (and final))

but it's still not there yet.

Doesn't work, eh? You need to be just the tiniest bit clearer as to what the problem is,

There is some code in this thread that my help you convert your sketch to use arrays: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1272300608

So noted,
I'm clearly no programmer, just a beginner trying to work this out.
You should have seen the code before I cleaned it up.
All kidding aside, I do appreciate your input.
Point by Point,
My background is more copy and paste than starting from scratch.
I'm looking at taking some classes to help. I'll look at arrays. Thanks
Number two was cut and paste from the first post.
What value would I put in to start the function, myDelay (1) ?
Third Clearly there is a better way to write this. I stuck with what worked but know it is a mess.
And Four, The timer function doesn't work as written certainly because of the code errors you identified in your second point.
Thanks for looking

To mem

I'll look it over this evening.
Thanks

What value would I put in to start the function, myDelay (1) ?

You would call the function using:

myDelay(1);

The idea, though, was not to force a delay in the game. The idea was to check if an extended period of time had elapsed since the last activity.

The function name should be ResetOnIdle (or something like that), taking no arguments. It should be called at the end of loop, not in every if block that gets executed. It should not call delay. It should not have a while loop in it. It should reset the game only if a game is in progress.

bool gameInProgress = false;

void ResetOnIdle()
{
    if (millis() - startTime > timeout && gameInProgress)
    {
        resetGame(); // function to reset the game
        gameInProgress = false;
    }
}

gameInProgress needs to be set to true somewhere in loop.

Of course.
My only programming background is with AMX equipment for AV equipment control using similar language. I've use showbusy=true statements to do the same type of thing there.
Thanks. I'll implement and update later today.

The function works beautifully.

Thanks for your help. I'll post the final code when it is finished.

Is there a possibility of using a Watch Dog Timer. This is the perfect case for it