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;
}
}