Linear Actuator controlled by SEEED Studio Relay Shield using Millis function

Hi and thanks as always for taking the time to help me out. My new Halloween project is a Tombstone that raises in the air for 50 seconds, then lowers back, with a green LED spotlight shining on it. I currently have the following program that works:

/*

Manual Linear Actuator Control using an Arduino and 
This demo shows how to do basic manual control of a large linear
actuator using an Arduino. The first button extends
the actuator and the second retracts the actuator.
 
 
 * SEEED Relay #1-  Digital Pin 7
 * SEEED Relay #3 - Digital Pin 5
 * SEEED Relay #4 - Digital Pin 4 
 

 */

// constants won't change. They're used here to set pin numbers:
const int relay3Pin =  5;      // the number of the Relay3pin
const int relay4Pin =  4;      // the number of the Relay4pin
const int relay7Pin=   7;      // the number of the Relay7pin


void setup() { 
  
  
  //start serial connection
  Serial.begin(9600);  
  
  // initialize the relay pin as an output:
  pinMode(relay3Pin, OUTPUT);    
  pinMode(relay4Pin, OUTPUT);    
  pinMode(relay7Pin, OUTPUT);
}

void loop(){
    
    // turn relay3 on:    
    digitalWrite(relay3Pin, HIGH); 
    delay(15000); //activate for 15 seconds
  
 
    // turn relay3 off:
    digitalWrite(relay3Pin, LOW); 
    delay(50000);//deactivate for 50 seconds
  
  
    
    // turn relay4 on:    
    digitalWrite(relay4Pin, HIGH);
    delay(15000);//activate for 15 seconds 
  
 
    // turn relay4 off:
    digitalWrite(relay4Pin, LOW);
    delay(50000);//deactivate for 50 seconds 


    //turn relay1 on:
    digitalWrite(relay7Pin, HIGH);
    delay(15000);//activate for 15 seconds

    //turn relay1 off:
    digitalWrite(relay7Pin, LOW);
    delay(50000);//deactivate for 50 seconds
  
}

However, using the DELAY function is, of course, stopping the program, resulting in:
Tombstone raises, stops for delay.
Tombstone lowers. stops for delay.
THEN light bulb comes on.

What I would like to get to is:
-Tombstone starts to raise- takes 15 seconds to fully extend
-LED Light bulb comes on showing tombstone raising in air
-Have Tombstone and LED stay raised (Linear Actuator needs to be OFF during this time) for 50 seconds
-Tombstone starts to lower (takes 15 seconds to lower), would like LED light bulb to be off during this time while prop resets.
-Tombstone remains lowered (Linear Actuator needs to be OFF during this time) for 50 seconds.

So knowing I could not use the DELAY function, I started attempting to do Millis. My first attempt go the bulb on, but the relays were clicking rapidly,so I quickly shut it off to keep it from being damaged. I then went a little more into SeveralThingsAtTheSameTimeRev1.ino, but I have hit a wall. Two main problems:

  • The linear actuator takes a defined period of 15 seconds (15000 Milliseconds) to travel up and down. If I don’t shut if off, it continues to grind away and make noise and strain. So I need to have it stop/kill power to it while it is idle up in the air and lowered. So I’m defining a fixed period of 50 seconds, but when I define that in millis I’m getting the following fatal error:
    comparison between signed and unsigned integer expressions

which means that I’m mixing defined and undefined time. But Relay3 that controls the raising of the linear actuator must be off before Relay4 can start lowering- which brings me to question #2:

In Millis, can I move relay3 ending time so it will then start relay 4? Or does relay3 need to be timed to end at a certain time, then relay 4 begin at another specifinc time? Is there any easier way of building in a delay in Millis function?

Here is my current code. No, it does not compile due to the integer expression error. Thank you for taking time out of your day to look this over and point me in the right direction.

// Linear Actuator Tombstone using an Arduino UNO and SEEED relay shield using raising relay(Relay3Pin), lowering relay, (relay4Pin) and a 12v LED Light Bulb (relay7Pin)

//=======
// ----CONSTANTS (won't change)

const int relay3Pin = 5;      // the pin number for relay to raising the linear actuator
const int relay4Pin = 4;     // the pin number for relay to lower the linear actuator
const int relay7Pin = 7;     // the pin number for relay to turn on the LED Light Bulb

const int relay3Pininterval = 50000; // the number of milliseconds to wait to raise Linear Actuator
const int relay4Pininterval = 50000; // the number of milliseconds to wait to lower Linear Actuator
const int relay7Pininterval = 65000; // the number of milliseconds for LED Light Bulb to turn off

const int relay3PinDuration = 15000; //  the number of milliseconds to raise Linear Actuator
const int relay4PinDuration = 15000; //  the number of milliseconds to lower Linear Actuator
const int relay7PinDuration = 65000; //  the number of milliseconds for Linear Actuator to stay on





//------- VARIABLES (will change)

byte relay3PinState = LOW;             // used to record whether the relay3Pin is on or off
byte relay4PinState = LOW;           //   LOW = off
byte relay7PinState = LOW;


unsigned long currentMillis = 0;    // stores the value of millis() in each iteration of loop()
unsigned long previousrelay3PinMillis = 0;   // will store last time relay were updated
unsigned long previousrelay4PinMillis = 0;
unsigned long previousrelay7PinMillis = 0;

//========

void setup() {

 Serial.begin(9600);
 Serial.println("Starting LinearActuatorwithMillis");  // so we know what sketch is running
 
     // set the relay pins as output:
 pinMode(relay3Pin, OUTPUT);
 pinMode(relay4Pin, OUTPUT);
 pinMode(relay7Pin, OUTPUT);
 
 
}

//=======

void loop() {

     // Notice that none of the action happens in loop() apart from reading millis()
     //   it just calls the functions that have the action code

 currentMillis = millis();   // capture the latest value of millis()
                             //   this is equivalent to noting the time from a clock
                             //   use the same time for all relays to keep them synchronized
 


}

//========

void updaterelay3PinState() {

 if (relay3PinState == LOW) {
         // if the relay3 is off, we must wait for the interval to expire before turning it on
   if (currentMillis - previousrelay3PinMillis >= relay3Pininterval) {
         // time is up, so change the state to HIGH
      relay3PinState = HIGH;
         // and save the time when we made the change
      previousrelay3PinMillis += relay3Pininterval;
         // NOTE: The previous line could alternatively be
         //              previousrelay3PinMillis = currentMillis
         //        which is the style used in the BlinkWithoutDelay example sketch
         //        Adding on the interval is a better way to ensure that succesive periods are identical

   }
 }
 else {  // i.e. if relay3Pin is HIGH
 
         // if the Led is on, we must wait for the duration to expire before turning it off
   if (currentMillis - previousrelay3PinMillis >= relay3PinDuration) {
         // time is up, so change the state to LOW
      relay3PinState = LOW;
         // and save the time when we made the change
      previousrelay3PinMillis += relay3PinDuration;
   }
 }
}

//=======

void updaterelay4PinState() {

 if (relay4PinState == LOW) {
   if (currentMillis - previousrelay4PinMillis >= relay4Pininterval) {
      relay4PinState = HIGH;
      previousrelay4PinMillis += relay4Pininterval;
   }
 }
 else {
   if (currentMillis - previousrelay4PinMillis >= relay4PinDuration) {
      relay4PinState = LOW;
      previousrelay4PinMillis += relay4PinDuration;
   }
 }    
}

//=======

void updaterelay7PinState() {

 if (relay7PinState == LOW) {
   if (currentMillis - previousrelay7PinMillis >= relay7Pininterval) {
      relay7PinState = HIGH;
      previousrelay7PinMillis += relay7Pininterval;
   }
 }
 else {
   if (currentMillis - previousrelay7PinMillis >= relay7PinDuration) {
      relay7Pin = LOW;
      previousrelay7PinMillis += relay7PinDuration;
   }
 }    
}

//========

void switchLeds() {
     // this is the code that actually switches the relays on and off

 digitalWrite(relay3Pin, relay3PinState);
 digitalWrite(relay4Pin, relay4PinState);
 digitalWrite(relay7Pin, relay7PinState);
 ;
}

//=====END

I have attached a picture of the project, and here is the link to the SEEED studio relay:
http://wiki.seeedstudio.com/Relay_Shield_v3/
and to the linear actuator from ServoCity: [https://www.servocity.com/hda12-50](https://www.servocity.com/hda12- 50) . My linear actuator doesn’t have any potentiometer/positioning wires, its just a regular hot and neutral 2 wire.

following fatal error: comparison between signed and unsigned integer expressions

which means that I'm mixing defined and undefined time.

Those are just warnings and will not prevent compilation. you are comparing unsigned long data type to int data type which is a signed data type. Make the relay pin intervals and durations unsigned int or better yet, unsigned long as they deal with time.

Here is where the error is:

else
   {
      if (currentMillis - previousrelay7PinMillis >= relay7PinDuration)
      {
         relay7Pin = LOW; // can't change the value of a constant
         previousrelay7PinMillis += relay7PinDuration;
      }

You are trying to change the value of a constant (const int relay7Pin = 7; )

SOLVED! Thank you groundFungus! Once I got playing around with if/else commands some more, I changed the whole program to a state machine like program. I built it off the Nonblocking/Blocking example, so ignore the "Heartbeat" LED on pin13, it just looked kinda cool so I left it in there. Thanks again! Here is the new working code for anyone interested.

[code/ Linear Actuator Tombstone with Arduino Uno with a SEEED Studio Relay with a Raising Relay, A Lowering Relay, and a 12V LED Bulb to shine on tombstone during raising process.

const byte pin5 = 5;  //Linear Actuator Lowering Relay #3
const byte pin4 = 4;  //Linear Actuator Raising Relay #4
const byte LED = 7;   //LED Bulb on Relay #1 
const byte heartBeat = 13;

boolean blockingFlag = true;

unsigned long Millis13;
unsigned long lastMillis;
unsigned long wait = 3000;

enum States {
  StateStart, State2, State3, State4, State5, 
};
States mState = StateStart;

void setup()
{
  pinMode(heartBeat, OUTPUT);

  pinMode(pin5, OUTPUT);
  pinMode(pin4, OUTPUT);
  pinMode(LED, OUTPUT);

  delay(3000);

} //END of setup()


void loop()
{
  //**********************************
  //some code to check for blocking sketches
  if (millis() - Millis13 >= 200)
  {
    digitalWrite(heartBeat, !digitalRead(heartBeat)); //toggle D13
    Millis13 = millis(); //re-initalize
  }


  //********************************** BWD being used here
  if (millis() - lastMillis >= wait)
  {
    nonBlockingMethod();
  }

  
} //END of loop()



// ******************* Functions *******************

void nonBlockingMethod()
{
  switch (mState)
  {
    //***************************    
    case StateStart:
      {
        digitalWrite(pin5, HIGH);    // Raising Relay for Linear Actuator raises for 15 seconds
        digitalWrite(LED,HIGH);      // LED Bulb comes on
        wait = 15000;                  // wait for 15 seconds
        lastMillis = millis();
        mState = State2;
      }
      break;

    //***************************
    case State2:
      {
        digitalWrite(pin5, LOW);    // Raising Relay turns off, Linear Actuator remains raised
        digitalWrite(LED,HIGH);     //turn on LED Bulb
        wait = 50000;                  // wait for 50 seconds
        lastMillis = millis();
        mState = State3;
      }
      break;

    //***************************
    case State3:
      {
        digitalWrite(pin4, HIGH);     // Lowering Relay for Linear Actuator lowers for 15 seconds
        digitalWrite(LED, LOW);       //LED Bulb Turns off
        wait = 15000;                 // wait for 15 seconds
        lastMillis = millis();
        mState = State4;
      }
      break;

    //***************************    //LEDs OFF
    case State4:
      {
        digitalWrite(pin4, LOW);     // Lowering Relay for Linear Actuator remains off for 50 seconds
        digitalWrite(LED, LOW);      //LED Bulb remains off
        wait = 50000;                  // wait for 50 seconds
        lastMillis = millis();
        mState = State5;
      }
      break;

     
    //***************************
    case State5:
      {
        blockingFlag = true;
        wait = 3000;                 // wait for 3000ms
        mState = StateStart;
      }

      break;

    //***************************
    default:
      {
      }
      break;

  } //END of switch case

} //END of nonBlockingMethod()

// ************** END of sketch ****************
 ]