Timing Sequence Project

Hi Everyone!,

I have attempted multiple trial and error using this tutorial but no luck so far..

Any help would be greatly appreciated.

Goal:
I want something to happen in a sequence after 1 sec, 2 sec, 45 sec, 60 sec and 5 mins.
Then stop sequence and exit out of sequence.

Problem:
Either the timer does not function or only timer 1 gets reset into a loop.. pretty much 1 sec gets typed over and over and I don't seem to find a solution.

Example:
// Enabled Sequence if Button Pressed:
void enabled_sequence()

if (Timer >= 1000UL)
{
Serial.print(F("\r\n Timer 1 sec"));
}

else if (Timer >= 2000UL)
{
Serial.print(F("\r\n Timer 2 sec"));
}

else if (Timer >= 45000UL)
{
Serial.print(F("\r\n Timer 45 sec"));
}

else if (Timer >= 60000UL)
{
Serial.print(F("\r\n Timer 1 min"));
}

else if (Timer >= 300000)
{
Serial.print(F("\r\n Timer 5 min"));
}
}

In addition, I'm not set on a straight millis and would not mind using a millis = counter to solve the multiple timers in the sequence but looking for a viable alternative. I think I'm close but not sure.. keep hitting a dead end.

/* Blink without Delay

  Turns on and off a light emitting diode (LED) connected to a digital
  pin, without using the delay() function.  This means that other code
  can run at the same time without being interrupted by the LED code.

  The circuit:
  * LED attached from pin 13 to ground.
  * Note: on most Arduinos, there is already an LED on the board
  that's attached to pin 13, so no hardware is needed for this example.

  created 2005
  by David A. Mellis
  modified 8 Feb 2010
  by Paul Stoffregen
  modified 11 Nov 2013
  by Scott Fitzgerald


  This example code is in the public domain.

  http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
  */

// constants won't change. Used here to set a pin number :
 const int ledPin =  13;      // the number of the LED pin

// Variables will change :
int ledState = LOW;             // ledState used to set the LED

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated

// constants won't change :
 const long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
   // set the digital pin as output:
   pinMode(ledPin, OUTPUT);
}

void loop() {
   // here is where you'd put code that needs to be running all the time.

   // check to see if it's time to blink the LED; that is, if the
   // difference between the current time and last time you blinked
   // the LED is bigger than the interval at which you want to
   // blink the LED.
   unsigned long currentMillis = millis();

   if (currentMillis - previousMillis >= interval) {
     // save the last time you blinked the LED
     previousMillis = currentMillis;

     // if the LED is off turn it on and vice-versa:
     if (ledState == LOW) {
       ledState = HIGH;
     } else {
       ledState = LOW;
     }

     // set the LED with the ledState of the variable:
     digitalWrite(ledPin, ledState);
   }
}

Hi,
You need to include complete code (SEE How to use Code Tags so we can see it!)

http://forum.arduino.cc/index.php/topic,148850.0.html

Hi Terry,

Code from the tutorial added above.

I see this as a starting point but does not have multiple timers within one sequence.

*Note: I do not want to use delay() because I would like to be able to stop the sequence and the delay function is junk in this type of application.

if (Timer >= 1000UL)
  { 
    Serial.print(F("\r\n Timer 1 sec")); 
  }

Well, this is true all the time after 1 second, isn't it?
You can modify it by using a flag to indicate the event is not valid anymore:

if ((Timer >= 1000UL) && (1secFlag == 0))
  { 
    Serial.print(F("\r\n Timer 1 sec")); 
    1secFlag = 1;
  }

Then when you go thru all of them, clear the flags and let it start over.
I'm assuming you have this at the start of loop:

void loop(){
Timer = millis();

I think I'd use an array or two myself, something like this:

// 1 sec, 2 sec, 45 sec, 60 sec and 5 mins.
unsigned long timeArray[] = {1000UL, 2000UL, 45000UL, 60000UL, 300000UL,};

int dataArray[] = {1,2,45,60,300,};
byte arrayIndex = 0;

void loop(){
currentTime = millis();
  if (currentTime >= timeArray[arrayIndex]){
  Serial.print("Time elapsed (sec) = ");
  Serial.println (dataArray[arrayIndex]);
  arrayIndex = arrayIndex +1;
    if (arrayIndex == 4){
    arrayIndex = 0;
    }
  }
}

Hi CrossRoads,

  1. I have been working on my code but something seems to be wrong with my flags and they are not working for some operator error (me). However, the timer part works awesome!
// Libraries:
#include <Servo.h>
#include <SPI.h>
#include <USB.h>
#include <XBOXRECV.h>

// Xbox Control:
USB Usb; // USBHub Hub1(&Usb); Some dongles have a hub inside and try this is your dongle isn't working.
XBOXRECV Xbox(&Usb);

// Define Variables & Objects:
int start;                // Device On Switch.
int back;                 // Device Off Switch.

// Relay Activates or Deactivates Device:
#define relay 4 

// Set Clock:
unsigned long CurrentTime, SetTime; 

// Set Timers: 
int Timer1 = 0; 
int Timer2 = 5000; 
int Timer3 = 45000;
int Timer4 = 60000; 
int Timer5 = 300000; 

// Timer Flags: 
int TimerFlag1 = 1; 
int TimerFlag2 = 1; 
int TimerFlag3 = 1 
int TimerFlag4 = 1; 
int TimerFlag5 = 1; 



// Setup Robot USB, XBOX Hub with Controller:
void setup()
{
  Serial.begin(9600);
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection.
  if (Usb.Init() == -1)
  {
    Serial.print(F("\r\nOSC did not start"));
    while (1); //halt
  }
  Serial.print(F("\r\n Primary System Engaged"));

  // Relay Pin: 
  pinMode(relay, OUTPUT); 
  digitalWrite(relay,LOW);        

}



// Loop USB, Xbox Hub with Controller:
void loop()
{
  Usb.Task();
  if (Xbox.Xbox360Connected[0])
  {
    enabled_xbox(); 
    enabled_control();
    enabled_device(); 
  }

  else
  {
    Serial.print(F("\r\n Robot Control Disconnected"));

    disabled_xbox(); 
    disabled_control(); 
    disabled_device(); 
  }
}



// Primary Run Routine For Xbox Values:
void enabled_xbox()
{
  Usb.Task();
  if (Xbox.Xbox360Connected[0])
  {
    start = Xbox.getButtonClick(START);         // Define Start Button.
    back = Xbox.getButtonClick(BACK);           // Define BACK Button.
  }
}



// Disables Xbox Values():
void disabled_xbox()
{
}



// Primary Run Routine For Xbox Control:
void enabled_control()
{
  Usb.Task();
  if (Xbox.Xbox360Connected[0])
  {

    //  Start Lights:
    else if (start)
    {
      Serial.print(F("\r\n Start Button"));
      Serial.print(F("\r\n Device On Switch")); 

      SetTime = CurrentTime; 
      
      // Timer Flags: 
      int TimerFlag1 = 0; 
      int TimerFlag2 = 0; 
      int TimerFlag3 = 0; 
      int TimerFlag4 = 0; 
      int TimerFlag5 = 0; 
    }

    //  Stop Lights:
    else if (back)
    {
      Serial.print(F("\r\n Back Button"));
      Serial.print(F("\r\n Device Off Switch")); 
      
      // Timer Flags: 
      int TimerFlag1 = 1; 
      int TimerFlag2 = 1; 
      int TimerFlag3 = 1; 
      int TimerFlag4 = 1; 
      int TimerFlag5 = 1; 
    }

    else
    {
      disabled_control();
    }
  }
}



// Disables control:
void disabled_control()
{
}



// Enabled Device if Start Button Pressed:
void enabled_device()
{
  // Timing Sequence at 1 sec, 2 sec, 45 sec, 60 sec and 5 mins.
  // Press Start Button to reset sequence or Back Button to stop sequence. 

  // Time:
  CurrentTime = millis(); 
  Serial.println(CurrentTime); 
  Serial.println(SetTime); 
     
  if ((CurrentTime - SetTime >= Timer1) && (TimerFlag1 == 0))
  { 
    Serial.print(F("\r\n Timer Start")); 
    // dosomething();  
    TimerFlag1 = 1; 
    Serial.println(TimerFlag1);
  }
  
  else if ((CurrentTime - SetTime >= Timer2) && (TimerFlag2 == 0))
  { 
    Serial.print(F("\r\n Timer 5 sec")); 
    // dosomething(); 
    TimerFlag2 = 1; 
    Serial.println(TimerFlag2);
  }
    
  else if ((CurrentTime - SetTime >= Timer3) && (TimerFlag3 == 0))
  { 
    Serial.print(F("\r\n Timer 45 sec")); 
    // dosomething():
    TimerFlag3 = 1; 
    Serial.println(TimerFlag3);
  }
      
  else if ((CurrentTime - SetTime >= Timer4) && (TimerFlag4 == 0))
  { 
    Serial.print(F("\r\n Timer 1 min")); 
    digitalWrite(relay,HIGH); 
    TimerFlag4 = 1; 
    Serial.println(TimerFlag4);
  }

  else if ((CurrentTime - SetTime >= Timer5) && (TimerFlag5 == 0))
  { 
    Serial.print(F("\r\n Timer 5 min")); 
    digitalWrite(relay,LOW); 
    TimerFlag5 = 1; 
    Serial.println(TimerFlag5);
  } 
  else 
  { 
  }
}



// Disables Device if Back Button Pressed:
void disabled_device()
{ 
  // Turn Off Device:
  digitalWrite(relay,LOW); 
}
  1. The array idea is cool and would love to play around with it but could not figure out how to throw commands out within the array. This just allows me to shoot the timer with no functions to activate on the timer.

Example: 1000UL and enable_motor1, 2000UL and enable_motor2, ect.;

// 1 sec, 2 sec, 45 sec, 60 sec and 5 mins.
unsigned long timeArray[] = {1000UL, 2000UL, 45000UL, 60000UL, 300000UL,};

int dataArray[] = {1,2,45,60,300,};
byte arrayIndex = 0;

void loop(){
currentTime = millis();
  if (currentTime >= timeArray[arrayIndex]){
  Serial.print("Time elapsed (sec) = ");
  Serial.println (dataArray[arrayIndex]);
  arrayIndex = arrayIndex +1;
    if (arrayIndex == 4){
    arrayIndex = 0;
    }
  }
}

Have a look at how millis() is used for timing in Several Things at a Time. It is an extended example of BWoD.

...R

I think that's basically what code example 1 does Robin2.
I think the way CurrenTime and SetTime are declared in functions vs being global might be causing some issue, or perhaps they need to be declared as volatile.
Too many functions for me, I'd rather inline all the code, make all the variables global. I find it easier to follow the program flow in these little embedded sketches that way vs jumping all over the place trying to find the functions and see what is going on. But I'm a hardware designer, not software engineer, so I don't mind being overruled on that.

In this case, SetTime is always 0. I would set it = to millis() in when the xbox got connected, otherwise, if it takes a few seconds to connect, the first couple time periods might be missed.

Hi R and CrossRoads,

Thanks for the feedback. I found that helpful for testing and have seen that already as well as a few other examples. However, they do not use a counter in the same method I'm needing it for. I need to learn how to properly use flags in my example because I need flags and the timer to create an activation cycle on command. I do not want this always running in a loop and want to call it using start and stop button on the controller. My code above shows this but I think something is missing for the flag1-5.

*The timing works and I'm printing values of mils and everything works except for the flags calling to start sequence, stop sequence and reset sequence.

*CrossRoads,

  1. I'm new and will look up volatile :);

  2. most of my variables are global and can you give me an example of a change or global you are talking about?; and

  3. I think my purpose of "SetTime is always 0. I would set it = to millis() when xbox connected", was not clear. The point of calling it at start button is so I can call when to create a set point and be different than millis.... If I use millis() when xbox connected, the counter sequence will start as soon as the xbox controller is connected and is the same as all these other examples setting the sequence to turn on automatic with the Arduino being turned on. Although, I think it would be cooler to be able to call timers with a controller (just my opinion).

Example:
millis = 10000
press start button = SetTime and will make SetTime lock at 10000.
about 10 secs later...

millis = 20000 and SetTime = 10000
20000 - 10000 = 10000 to activate if statement.

All is working fine.. I'm having a flag error as stated above.

-Eddie

mcgeheeiv:
3) I think my purpose of "SetTime is always 0. I would set it = to millis() when xbox connected", was not clear. The point of calling it at start button is so I can call when to create a set point and be different than millis.... If I use millis() when xbox connected, the counter sequence will start as soon as the xbox controller is connected and is the same as all these other examples setting the sequence to turn on automatic with the Arduino being turned on. Although, I think it would be cooler to be able to call timers with a controller (just my opinion).

My brain can't make any sense of that.

Can you explain it more clearly?

...R

mcgeheeiv:
Hi Everyone!,

I have attempted multiple trial and error using this tutorial but no luck so far..

https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay

Any help would be greatly appreciated.

Goal:
I want something to happen in a sequence after 1 sec, 2 sec, 45 sec, 60 sec and 5 mins.
Then stop sequence and exit out of sequence.

Problem:
Either the timer does not function or only timer 1 gets reset into a loop.. pretty much 1 sec gets typed over and over and I don't seem to find a solution.

Example:
// Enabled Sequence if Button Pressed:
void enabled_sequence()

if (Timer >= 1000UL)
{
Serial.print(F("\r\n Timer 1 sec"));
}

else if (Timer >= 2000UL)
{
Serial.print(F("\r\n Timer 2 sec"));
}

else if (Timer >= 45000UL)
{
Serial.print(F("\r\n Timer 45 sec"));
}

else if (Timer >= 60000UL)
{
Serial.print(F("\r\n Timer 1 min"));
}

else if (Timer >= 300000)
{
Serial.print(F("\r\n Timer 5 min"));
}
}

Try reversing the sequence of your if-statements, checking for the biggest value first, then the second biggest and so on.

:slight_smile:

R,

For 3), CrossRoads said that I should change millis() to when xbox connected but this defeats the whole purpose of the controller with start and stop buttons. If I did the above, my Arduino would startup, instantly turn the xbox controller on and the timer would start. I want to be able to start millis() when I push the start button and most of my code does work, however the Flag parts below do not work. I only need to figure out why the flags are not working.

// Timer Flags: 
int TimerFlag1 = 1; 
int TimerFlag2 = 1; 
int TimerFlag3 = 1 
int TimerFlag4 = 1; 
int TimerFlag5 = 1; 


// Primary Run Routine For Xbox Control:
void enabled_control()
{
  Usb.Task();
  if (Xbox.Xbox360Connected[0])
  {

    //  Start Lights:
    else if (start)
    {
      Serial.print(F("\r\n Start Button"));
      Serial.print(F("\r\n Device On Switch")); 

      SetTime = CurrentTime; 
      
      // Timer Flags: 
      int TimerFlag1 = 0; 
      int TimerFlag2 = 0; 
      int TimerFlag3 = 0; 
      int TimerFlag4 = 0; 
      int TimerFlag5 = 0; 
    }

    //  Stop Lights:
    else if (back)
    {
      Serial.print(F("\r\n Back Button"));
      Serial.print(F("\r\n Device Off Switch")); 
      
      // Timer Flags: 
      int TimerFlag1 = 1; 
      int TimerFlag2 = 1; 
      int TimerFlag3 = 1; 
      int TimerFlag4 = 1; 
      int TimerFlag5 = 1; 
    }

    else
    {
      disabled_control();
    }
  }
}



// Disables control:
void disabled_control()
{
}



// Enabled Device if Start Button Pressed:
void enabled_device()
{
  // Timing Sequence at 1 sec, 2 sec, 45 sec, 60 sec and 5 mins.
  // Press Start Button to reset sequence or Back Button to stop sequence. 

  // Time:
  CurrentTime = millis(); 
  Serial.println(CurrentTime); 
  Serial.println(SetTime); 
     
  if ((CurrentTime - SetTime >= Timer1) && (TimerFlag1 == 0))
  { 
    Serial.print(F("\r\n Timer Start")); 
    // dosomething();  
    TimerFlag1 = 1; 
    Serial.println(TimerFlag1);
  }
  
  else if ((CurrentTime - SetTime >= Timer2) && (TimerFlag2 == 0))
  { 
    Serial.print(F("\r\n Timer 5 sec")); 
    // dosomething(); 
    TimerFlag2 = 1; 
    Serial.println(TimerFlag2);
  }
    
  else if ((CurrentTime - SetTime >= Timer3) && (TimerFlag3 == 0))
  { 
    Serial.print(F("\r\n Timer 45 sec")); 
    // dosomething():
    TimerFlag3 = 1; 
    Serial.println(TimerFlag3);
  }
      
  else if ((CurrentTime - SetTime >= Timer4) && (TimerFlag4 == 0))
  { 
    Serial.print(F("\r\n Timer 1 min")); 
    digitalWrite(relay,HIGH); 
    TimerFlag4 = 1; 
    Serial.println(TimerFlag4);
  }

  else if ((CurrentTime - SetTime >= Timer5) && (TimerFlag5 == 0))
  { 
    Serial.print(F("\r\n Timer 5 min")); 
    digitalWrite(relay,LOW); 
    TimerFlag5 = 1; 
    Serial.println(TimerFlag5);
  } 
  else 
  { 
  }
}



// Disables Device if Back Button Pressed:
void disabled_device()
{ 
  // Turn Off Device:
  digitalWrite(relay,LOW); 
}

You create many duplicate local variables. Hint: remove the excess "int"s.

mcgeheeiv:
I want to be able to start millis() when I push the start button

I'm still not sure if I fully understand. One does not normally "start" millis(). That happens automatically when the Arduino is powered up. The normal thing is to save the value of millis() when something happens - such as pressing a button.

however the Flag parts below do not work. I only need to figure out why the flags are not working.

As @DrDietrich has said this is probably due to the fact that you are creating local versions of the variables as well as global versions.. When you put "int" before the variable name the compiler creates a new variable.

...R

Hi Everyone!,

I solved this issue and how do I close the post? Although, I do have one more question about arrays (see below).

Full code is above and here are the very minor changes to fix it.

2 Errors for those that may see this in the future and want to solve a similar problem..

Error 1) On the Flags, the variable high and low did not work for some reason and above my experience level but I found that using a counter worked.
Example: Current time = millis() and SetTime = when you want to start the clock. Say the timer millis() is at 10000 and you hit SetTime, the SetTime will now be 10000. If you want a function to act in 10 sec = 10000 millis, the millis time will now be at 20000 - 10000 for the locked set time = 10000 for the 10 sec. The flag error was that the 0 and 1 for on/off did not work for some reason but the counter method worked fine to simulate an array. counter 1 = step 1, counter 2 = step 2, ect.

if ((CurrentTime - SetTime >= Timer1) && (CounterFlag == 1))

Error 2) is that my times used as int went too high and you need to use long Timer1 = 300000. This will allow you use very high numbers because 300000 = 5 mins.

*** Now for my final question...I would like to know how to use functions within the array and not just send a array bit. ***

Example: 1000UL and enable_motor1();, 2000UL and enable_motor2, ect.;
or how can I get it to work?

// 1 sec, 2 sec, 45 sec, 60 sec and 5 mins.
unsigned long timeArray[] = {1000UL, 2000UL, 45000UL, 60000UL, 300000UL,};

int dataArray[] = {1,2,45,60,300,};
byte arrayIndex = 0;

void loop(){
currentTime = millis();
  if (currentTime >= timeArray[arrayIndex]){
  Serial.print("Time elapsed (sec) = ");
  Serial.println (dataArray[arrayIndex]);
  arrayIndex = arrayIndex +1;
    if (arrayIndex == 4){
    arrayIndex = 0;
    }
  }
}

mcgeheeiv:
you need to use long Timer1 = 300000.

All variables associated with millis() should be created as unsigned long.

Example: 1000UL and enable_motor1();, 2000UL and enable_motor2, ect.;
or how can I get it to work?

Sorry, I don't mean to be unkind but I have no idea what that means.

Keeo in mind that this project is in your brain full time. It is only in my brain for 2 or 3 minutes once a day.

...R

Hi R,

Thanks for the feedback and my apologies for not making my question more clear. I'm still very new to coding but learning fast. It looks like I can't add functions directly to arrays (my ignorance for not knowing how arrays work) but I used an if statement to call the function, when the array event activates :).

If all questions have been answered, go back to your initial post (dunno if really required), and edit the subject line to include RESOLVED.

mcgeheeiv:
but I used an if statement to call the function, when the array event activates

What do you mean by an "array event"? In my mind an array is a collection of data that just sits there silently.

...R