Implementing a Millis Timer

I have a sketch to move 4 servos at random intervals, the sketch is working well but I want to be able to start the sketch with a push button and to end after a set time.

I have been using the following sketch with a LED which works fine but I don't know how to put a Button Activated Millis Timer into my Servo Sketch which already uses millis. I have tried putting the two together and I seem to be a long way from getting it to work; can someone advise on how I can go about it?

Button activated Millis Timer for LED

const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  12;      // the number of the LED pin
unsigned long off_time;

boolean ledState=false;

int buttonState = 0;         // variable for reading the pushbutton status


void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);      
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);   
  digitalWrite(ledPin, LOW); 

}

void loop(){
 
if ((ledState) && (millis()>=off_time)) /* is it on and is it later or equal to off_time */
{
    digitalWrite(ledPin,LOW);
    ledState = false;
}
else if (!ledState) /* is it off? */
{
    buttonState = digitalRead(buttonPin);
    if(buttonState == HIGH)
    {
        digitalWrite(ledPin, HIGH);
        ledState = true;
        off_time = millis() + 15000;
    }
}}

Servo Code to move servo's at random intervals.

#include <Servo.h>

Servo servo;                             
Servo servo2;
Servo servo3;                             
Servo servo4;

int pos = 0;                        
int pos2 =0;
int pos3 = 0;                        
int pos4 =0;

unsigned long timerVal;                // Variable to hold the timer for servo head                    
unsigned long timerVal2;
unsigned long timerVal3;                     
unsigned long timerVal4;

int countupdown = 1;                   // Variable to hold the positive or negative change in angle           
int countupdown2 = 2;
int countupdown3 = 3;                    
int countupdown4 = 4;

unsigned long previousMillis1; 
unsigned long previousMillis2; 
unsigned long previousMillis3; 
unsigned long previousMillis4; 

unsigned long randInterval1;
unsigned long randInterval2;
unsigned long randInterval3;
unsigned long randInterval4;

const int buttonPin = 2;                           // TAKEN FROM SKETCH: Button activated Millis Timer for LED
const int ledPin =  12;                            // TAKEN FROM SKETCH: Button activated Millis Timer for LED
unsigned long off_time;                            // TAKEN FROM SKETCH: Button activated Millis Timer for LED

boolean ledState=false;
int buttonState = 0; 


void setup() {

  servo.attach (8);                      
  servo2.attach (9);
  servo3.attach (10);                      
  servo4.attach (11);


  pinMode(ledPin, OUTPUT);                           // TAKEN FROM SKETCH: Button activated Millis Timer for LED   
  pinMode(buttonPin, INPUT);                         // TAKEN FROM SKETCH: Button activated Millis Timer for LED
  digitalWrite(ledPin, LOW);                         // TAKEN FROM SKETCH: Button activated Millis Timer for LED

  //randomSeed (analogRead (0)); 
}

void loop()
{

  if ((ledState) && (millis()>=off_time))            // TAKEN FROM SKETCH: Button activated Millis Timer for LED
  {                                                  // TAKEN FROM SKETCH: Button activated Millis Timer for LED
    digitalWrite(ledPin,LOW);                        // TAKEN FROM SKETCH: Button activated Millis Timer for LED
    ledState = false;                                // TAKEN FROM SKETCH: Button activated Millis Timer for LED
  }                                                  // TAKEN FROM SKETCH: Button activated Millis Timer for LED
  else if (!ledState) /* is it off? */               // TAKEN FROM SKETCH: Button activated Millis Timer for LED
  {                                                  // TAKEN FROM SKETCH: Button activated Millis Timer for LED
    buttonState = digitalRead(buttonPin);            // TAKEN FROM SKETCH: Button activated Millis Timer for LED
    if(buttonState == HIGH)                          // TAKEN FROM SKETCH: Button activated Millis Timer for LED
    {                                                // TAKEN FROM SKETCH: Button activated Millis Timer for LED
      digitalWrite(ledPin, HIGH);                    // TAKEN FROM SKETCH: Button activated Millis Timer for LED


      if ((timerVal + randInterval1) <= millis()) {     // SERVO LOOP STARTS
        randInterval1 = random (15, 600);
        servo.write(pos);                 // move head servo
        pos = pos + countupdown;     // increment or decrement value depending on countupdown value
        if (pos == 120) {                // If pos reaches this position, change 
          countupdown = -20;                   // directon by making countupdown negative
        } 
        if (pos == 60) {                 // If pos reaches this position, change direction 
          countupdown = 20;                    // making countupdown positive
        }
        timerVal = millis();                 // Reset the timer
      }

      if ((timerVal2 + randInterval2) <= millis()) {     // Timer loop
        randInterval2 = random (15, 1000);
        servo2.write(pos);                 // move head servo
        pos2 = pos2 + countupdown2;     // increment or decrement value depending on countupdown value
        if (pos2 == 120) {                // If pos reaches this position, change 
          countupdown2 = -20;                   // directon by making countupdown negative
        } 
        if (pos2 == 60) {                 // If pos reaches this position, change direction 
          countupdown2 = 20;                    // making countupdown positive
        }
        timerVal2 = millis();                 // Reset the timer
      }

      if ((timerVal3 + randInterval3) <= millis()) {     // Timer loop
        randInterval3 = random (15, 1000);
        servo3.write(pos);                 // move head servo
        pos3 = pos3 + countupdown3;     // increment or decrement value depending on countupdown value
        if (pos3 == 120) {                // If pos reaches this position, change 
          countupdown3 = -20;                   // directon by making countupdown negative
        } 
        if (pos3 == 60) {                 // If pos reaches this position, change direction 
          countupdown3 = 20;                    // making countupdown positive
        }
        timerVal3 = millis();                 // Reset the timer
      }

      if ((timerVal4 + randInterval4) <= millis()) {     // Timer loop
        randInterval4 = random (15, 1000);
        servo4.write(pos);                 // move head servo
        pos4 = pos4 + countupdown4;     // increment or decrement value depending on countupdown value
        if (pos4 == 120) {                // If pos reaches this position, change 
          countupdown4 = -20;                   // directon by making countupdown negative
        } 
        if (pos4 == 60) {                 // If pos reaches this position, change direction 
          countupdown4 = 20;                    // making countupdown positive
        }
        timerVal4 = millis();                 // Reset the timer

        ledState = true;                             // TAKEN FROM SKETCH: Button activated Millis Timer for LED
        off_time = millis() + 15000;                 // TAKEN FROM SKETCH: Button activated Millis Timer for LED
      }
    }
  }
}

This is NOT, contrary to what you seem to expect, the homework hotline. You can't just "put two programs together". You need to define the requirements for a program, and then borrow the bits and pieces of the two programs that perform the actions that you want, to achieve the desired result. Notice what that statement starts with.

Notice what that statement starts with.

No Paul; I don't what statement your referring to? And No I don't want you or anyone else to put the codes together for me; how am I going learn anything that way? What I am after is a pointer in the right direction and both sketches were posted to give an idea of where I am at.

The Servo sketch (without the // TAKEN FROM SKETCH: Button activated Millis Timer for LED parts) I have put together works well but I don't have the knowledge or ability at the moment to add a switch to run it for a specified time. I have now worked out that the button and timer need to go at the beginning of my servo sketch and not spread out through out it.

Paul if your going to reply again can you be a bit more helpful; go on why not surprise me!

Have a read of this:-
http://www.thebox.myzen.co.uk/Tutorial/Merging_Code.html

No Paul; I don't what statement your referring to?

I'm referring to this one:
You need to define ...

Thanks Grumpy_Mike for the link; it enabled me to reassess what I was doing and realise I was missing some code to start the Servo part of the loop, without this it was never going to work:

if (ledState == true)

Here is my updated code:

#include <Servo.h>
Servo servo;                             
Servo servo2;
Servo servo3;                             
Servo servo4;

int pos = 0;                        
int pos2 =0;
int pos3 = 0;                        
int pos4 =0;

unsigned long timerVal;                    // Variable to hold the timer for servo head                    
unsigned long timerVal2;
unsigned long timerVal3;                     
unsigned long timerVal4;

int countupdown = 1;                       // Variable to hold the positive or negative change in angle           
int countupdown2 = 2;
int countupdown3 = 3;                    
int countupdown4 = 4;

unsigned long previousMillis1; 
unsigned long previousMillis2; 
unsigned long previousMillis3; 
unsigned long previousMillis4; 
unsigned long previousMillis5; 

unsigned long randInterval1;
unsigned long randInterval2;
unsigned long randInterval3;
unsigned long randInterval4;
unsigned long randInterval5;


const int buttonPin = 2;                 // the number of the pushbutton pin
const int ledPin =  13;                  // the number of the LED pin
unsigned long off_time;

boolean ledState=false;

int buttonState = 0;                     // variable for reading the pushbutton status


void setup() {

  servo.attach (8);                      
  servo2.attach (9);
  servo3.attach (10);                      
  servo4.attach (11);

  pinMode(ledPin, OUTPUT);  
  pinMode(buttonPin, INPUT);   
  digitalWrite(ledPin, LOW); 
}

void loop(){

  if ((ledState) && (millis()>=off_time))  
  {
    digitalWrite(ledPin,LOW);
    ledState = false;
  }

  {
    buttonState = digitalRead(buttonPin);
    if(buttonState == HIGH)
    {
      digitalWrite(ledPin, HIGH);
      ledState = true;
      off_time = millis() + 30000;
    }
  }
  if (ledState == true)
  {
    if ((timerVal + randInterval1) <= millis()) {       // Timer loop
      randInterval1 = random (15, 600);
      servo.write(pos);                                 // move head servo
      pos = pos + countupdown;                          // increment or decrement value depending on countupdown value
      if (pos == 120) {                                 // If pos reaches this position, change 
        countupdown = -20;                              // directon by making countupdown negative
      } 
      if (pos == 60) {                                 // If pos reaches this position, change direction 
        countupdown = 20;                              // making countupdown positive
      }
      timerVal = millis();                               
    }
    if ((timerVal2 + randInterval2) <= millis()) {       
      randInterval2 = random (15, 1000);
      servo2.write(pos);                               
      pos2 = pos2 + countupdown2;    
      if (pos2 == 120) {                
        countupdown2 = -20;                  
      } 
      if (pos2 == 60) {                 
        countupdown2 = 20;                   
      }
      timerVal2 = millis();                 
    }

    if ((timerVal3 + randInterval3) <= millis()) {     
      randInterval3 = random (15, 1000);
      servo3.write(pos);                 
      pos3 = pos3 + countupdown3;     
      if (pos3 == 120) {                
        countupdown3 = -20;                   
      } 
      if (pos3 == 60) {                
        countupdown3 = 20;                    
      }
      timerVal3 = millis();                 
    }

    if ((timerVal4 + randInterval4) <= millis()) {    
      randInterval4 = random (15, 1000);
      servo4.write(pos);                
      pos4 = pos4 + countupdown4;     
      if (pos4 == 120) {                
        countupdown4 = -20;                   
      } 
      if (pos4 == 60) {                 
        countupdown4 = 20;                    
      }
      timerVal4 = millis();                 
    }
  }
}

This sketch is working well now apart from one thing. When the Arduino is turned on the servos move to 90 degrees which is good, as it is in the range of their allowed movement. However when the button is pressed for the first time after arduino is powered up all the servos move to 0 degrees and very slowly 1 step at a time move back to the lowest degree of their programmed range (about 60 degrees) and then start moving as in the loop. They only move to 0 degrees on the first go, every time after that when the button is pushed to start the loop they behave fine.

This seems to be a problem with millis as I have found that with other servo millis sketches the servos move to 0 degrees on start up. I was thinking of using a relay but that won't work unless the switch is pressed before the relay turns on the servo power. Even if I set the servo position to 90 degrees in Setup the servos still move to 0 degrees the very first time the loop is run.

If they are moving to 0 degrees they are going to get damaged. A clumsy way to do it might be to have two power switches, one for arduino and one for the servo power and for the arduino to be turned on first, the button pressed to run the sketch and then the servo power to be turned on once the sketch has run for the first time. I'd like to fit a relay to the servo power but that won't solve the problem as even if the servos are positioned correctly in Setup they will still move out of range on the first time the loop is run.

Any ideas on a solution?

Have a read of this:-
http://www.thebox.myzen.co.uk/Tutorial/Merging_Code.html

Why GrumpyMike should be changed to NiceMike

Hi, About Merging code: Mike's explanation is good and detailed. I have one that's a little different in that it copies one piece at at time from the two sketches you want to combine, into a template. If you want, take a look at it HERE:

You should look at the initiation of the pos and countuodown variables.

I have had a look at the int countupdown = 1; and the int pos = 0; but neither of these seem to solve the problem of the servo moving to position 0 the very first time the loop is run.

I'm thinking of putting in a loop counter and if the loop has been run more than once for the servo power then to be turned on.

void loop()
push button
If loop count less than 1 just run loop
If loop count more than 1 then turn on servo relay and run loop

Any other ideas?

try this:

int Pos = 60;
int countupdown = 20;
int pos2 = 60;
int countupdown2 = 20:
//and so on

How about trying this: In setup, write the servo position with servo.write(pos); to where you want them to be, in Startup. THEN do the attach statements.