Controlar encendido y apagado de relay con tiempos variables

Muy buena noche para todos. Estoy haciendo un proyecto con arduino Uno y el shield de 4 Relays para controlar unas electro válvulas.
La idea esque tengo dos tuberías en paralelo y mientras una línea esté cerrada la otra tiene que estar abierta y la idea esque ese valor de apertura y cierre vaya cambiando, es decir, que primera abra una válvula 20 seg y luego de este tiempo la otra se abra los mismos 20 seg, pero luego cambié este valor a 35 seg por ejemplo y así sucesivamente con la idea que sea automático, es decir tener una lista con la cantidad de seg por ciclo y que se vaya realizando. Nunca he programado y he visto mil videos y probado usando VB y Data streamer pero no he podido, si alguien puede guarne sería excelente.

La solución a eso es tener una máquina de estados y configurar todo usando millis(). Si usas delay() no podrás hacerlo.

En Documentación tenemos buenos tutoriales de los dos temas. Maquinas de estados y 4 o 5 de millis().
Coloca en un array o matriz según te parezca, la valvula y su tiempo, y con eso podras armar un patron a seguir.
Ojo yo me lo estoy imaginando asi.
{20, 20, 35, etc}
Si siempre sera un grupo alternado al otro entonces vas cambiando sobre el que actuan los tiempos y solo será una maquina con los tiempos en que este en ON una cambio ON la otra cambio y asi.

Muchas gracias por lo que me dijiste @Surbyte pues con varios foros y demás hice un código que realmente sirve. Ahora, siento que si necesito luego ampliar el número de ciclos me saldría muy largo, intente hacerlo con un for y dentro el switch case pero me ha ido fatal, realmente ni siquiera sé si eso es posible hacerlo, pues le pongo como variavle i el tiempo que debe permanecer predndia o apagada pero el ciclo empieza a tomar los valores sin el orden que defini en un array.

const byte relay1 = 4;            //declaración de pines de relays
byte ciclo = 1;                   //Declarar el valor de la variable ciclo (case)
unsigned long previusMillis = 0;  // Funcion millis
unsigned long interval;

//AQUI  TIENES LOS TIEMPO DE DURACION DE CADA CICLO
unsigned long tiempo[] = { 4000, 6000, 8000 };

void setup() {  // Declarar los pines de salida indicadores y botones
  pinMode(relay1, OUTPUT);
  Serial.begin(9600);
}

void loop() {

  switch (ciclo) {
    case 1:  // verde encendido 1sg
      digitalWrite(relay1, HIGH);
      ciclo = 2;
      interval = tiempo[0];
      previusMillis = millis();
      Serial.print("predndido:");
      Serial.println(previusMillis);
      break;

    case 2:
      if (millis() - previusMillis >= interval) {
        digitalWrite(relay1, LOW);
        ciclo = 3;
        previusMillis = millis();
        interval = tiempo[0];
        Serial.print("apagado:");
        Serial.println(previusMillis);
      }
      break;

    case 3:
      if (millis() - previusMillis >= interval) {
        digitalWrite(relay1, HIGH);
        ciclo = 4;
        previusMillis = millis();
        interval = tiempo[1];
        Serial.print("predndido:");
        Serial.println(previusMillis);
      }
      break;

    case 4:
      if (millis() - previusMillis >= interval) {
        digitalWrite(relay1, LOW);
        ciclo = 5;
        previusMillis = millis();
        interval = tiempo[1];
        Serial.print("apagado:");
        Serial.println(previusMillis);
      }
      break;

    case 5:
      if (millis() - previusMillis >= interval) {
        digitalWrite(relay1, HIGH);
        ciclo = 6;
        previusMillis = millis();
        interval = tiempo[2];
        Serial.print("predndido:");
        Serial.println(previusMillis);
      }
      break;

    case 6:
      if (millis() - previusMillis >= interval) {
        digitalWrite(relay1, LOW);
        ciclo = 7;
        previusMillis = millis();
        interval = tiempo[2];
        Serial.print("apagado:");
        Serial.println(previusMillis);
      }
      break;

    case 7:
      if (millis() - previusMillis >= interval) {
        ciclo = 1;
      }
      break;
  }
}

ese es el código que sirve y a acontinuación lo que intente hacer desde mi ignoracia y no funcionó. No sé si haya otra manera de simplificar ese proceso.

const byte relay1=4;    //declaración de pines de relays 
byte ciclo=1;           //Declarar el valor de la variable ciclo (case)
unsigned long milisAnterior=0;       // Funcion millis
unsigned long intervalo;

//AQUI  TIENES LOS TIEMPO DE DURACION DE CADA CICLO
unsigned long tiempo[]={2000,5000,9000};

void setup() 
{                        // Declarar los pines de salida indicadores y botones
 pinMode(relay1,OUTPUT);
 Serial.begin(9600);
}

void loop()
{
 for(int i=0;i<=5;i++)
{
  switch(ciclo)
  {
    case 1:                        
     digitalWrite(relay1,HIGH);
     ciclo=2;
     milisAnterior=millis();
     intervalo=tiempo[i];
     Serial.print("Encendido:");
     Serial.println(i);
    break;
    case 2:
      if(millis() -milisAnterior>=intervalo)
      {
       digitalWrite(relay1,LOW); 
       ciclo=3;
       milisAnterior=millis();
       intervalo=tiempo[i];
       Serial.print("Apagado:");
       Serial.println(i);      
      }           
    break;
    case 2:
      if(millis() -milisAnterior>=intervalo)
      {
       ciclo=1;
      }
    break;
   }
  }   
}

En el código 1, los tiempos 0..1..2 los usas tanto para ON como para OFF, no se si esa era la idea.
He simplificado un poco el código 1.

const byte relay1 = 4;            //declaración de pines de relays
byte ciclo = 1;                   //Declarar el valor de la variable ciclo (case)
unsigned long previusMillis = 0;  // Funcion millis
unsigned long interval;

//AQUI  TIENES LOS TIEMPO DE DURACION DE CADA CICLO
unsigned long tiempo[] = { 4000, 6000, 8000 };
byte index = 0;

void setup() {  // Declarar los pines de salida indicadores y botones
  pinMode(relay1, OUTPUT);
  Serial.begin(9600);
}

void loop() {

  switch (ciclo) {
    case 1:  // verde encendido 1sg
      digitalWrite(relay1, HIGH);
      interval = tiempo[index];
      Serial.print("Encendido :");
      previusMillis = millis();
      Serial.println(previusMillis);
      ciclo = 2;
      break;

    case 2:
      if (millis() - previusMillis >= interval) {
        digitalWrite(relay1, LOW);
        Serial.print("Apagado :");
        previusMillis = millis();
        Serial.println(previusMillis);
        ciclo = 3;
      }
      break;
    case 3:
      if (millis() - previusMillis >= interval) {
        ciclo = 1;
        if (index++>2) 
            index = 0;
      }
      break;
  }
}

Me salvaste la vida en serio, wow, es justo lo que quería, muchas gracias @Surbyte

Igualmente yo mejoraría la cosas con tiempos ON y OFF diferentes.
Te parece?
Dos maneras una mas cruda o dura que la segunda mas eficiente.
vamos por la 1ra.
Uso un vector o array para ON y otro para OFF igual que como esta pero los consulto en cada caso.
Ni siquiera cambio intervalo como variable. Lo ajusto a lo que necesito

unsigned long tiempoON[] = { 4000, 6000, 8000 };
unsigned long tiempoOFF[] = { 2000, 3000, 4000 };

y el loop cambiaría asi

void loop() {

  switch (ciclo) {
    case 1:  // verde encendido 1sg
      digitalWrite(relay1, HIGH);
      interval = tiempoON[index];  // cargo el tiempo ON que corresponda.
      Serial.print("Encendido :");
      previusMillis = millis();
      Serial.println(previusMillis);
      ciclo = 2;
      break;

    case 2:
      if (millis() - previusMillis >= interval) {  // este es el tiempoON correspondiente
        digitalWrite(relay1, LOW);
        Serial.print("Apagado :");
        interval = tiempoOFF[index];  // cargo el tiempo OFF que corresponda.
        previusMillis = millis();
        Serial.println(previusMillis);
        ciclo = 3;
      }
      break;
    case 3:
      if (millis() - previusMillis >= interval) { // este es el tiempoOFF correspondiente
        ciclo = 1;
        if (index++>2) 
            index = 0;
      }
      break;
  }
}

Las segunda manera seria una matriz, con los tiempos ON y OFF

unsigned long tiempo[][2] = { {4000, 2000},
                                                     {6000, 3000},
                                                     {8000, 4000}
                                                    };

y su acceso solo cambia en que cuando pides ON lo llamas asi

// ON de este modo
interval = tiempoON[index][0];
// OFF de este
interval = tiempoON[index][1];

Como verás es como jugar con diferentes maneras.
Todavia queda otra manera que es usando una estructura que aporta comodidad a la hora de entender con qué estas trabajando.

struct _tiempos {
      unsigned long tiempoON;
      unsigned long tiempoOFF;
};
// La definicion de los tiempos.
_tiempos tiempo[3] = { {4000, 2000},
                                          {6000, 3000},
                                          {8000, 4000}
                                        };

Asi quedaría todo con una estructura.

const byte relay1 = 4;            //declaración de pines de relays
byte ciclo = 1;                   //Declarar el valor de la variable ciclo (case)
unsigned long previusMillis = 0;  // Funcion millis
unsigned long interval;

//AQUI  TIENES LOS TIEMPO DE DURACION DE CADA CICLO
struct _tiempos {
      unsigned long tiempoON;
      unsigned long tiempoOFF;
};

_tiempos tiempo[3] = { {4000, 2000},
                       {6000, 3000},
                       {8000, 4000}
                     };
byte index = 0;

void setup() {  // Declarar los pines de salida indicadores y botones
  pinMode(relay1, OUTPUT);
  Serial.begin(9600);
}

void loop() {

  switch (ciclo) {
    case 1:  // verde encendido 1sg
      digitalWrite(relay1, HIGH);
      interval = tiempo[index].tiempoON;
      Serial.print("prendido:");
      previusMillis = millis();
      Serial.println(previusMillis);
      ciclo = 2;
      break;

    case 2:
      if (millis() - previusMillis >= interval) {
        digitalWrite(relay1, LOW);
        interval = tiempo[index].tiempoOFF;
        Serial.print("apagado:");
        previusMillis = millis();
        Serial.println(previusMillis);
        ciclo = 3;
      }
      break;
    case 3:
      if (millis() - previusMillis >= interval) {
        ciclo = 1;
        if (index++>2) 
            index = 0;
      }
      break;
  }
}