Control de Extractor mediante control de tiempo

Pues integrado en un proyecto en el que estoy metido para controlar un invernadero, un tema que me esta causando problemas es la conexion y desconexion de el extractor cada X tiempo para renovar el aire. Con la iluminacion no hay problema, ya que puedo definir hora de inicio y hora de fin. Pero la extraccion al ser cada 15 minutos, no puedo definir tantisimas variables para ello. Alguien me aconseja algo?

 //control renovacion de aire
   if(estadoManual[2] == 2){
           
           if(estadoAutomatico[3] == 2){     // Si Extractor no esta encendido por ninguna funcion        automatica
            if(repeticiones == 0){
              minutoInicio = minutoActual;
              minutoFin = (minutoActual + 2);
              minutoVolatil = minutoInicio; 
            }
            if(repeticiones >= 1){
              minutoInicio = minutoVolatil + 2;
              minutoFin = minutoInicio + 2;
            }
 
           if(minutoInicio <= minutoActual && minutoFin >= minutoActual){
             digitalWrite(optoPins[4], HIGH);
             estadoAutomatico[3] == 1;     //Pongo estado en 1 para indicar que esta encendido en un panel
             estadoAutomatico[6] == 1;   // indico para otras funciones que se esta ejecutando una renovacion automatica
             repeticiones += 1;
             
           }
             else if(minutoFin >= minutoActual && temperatura < 27.00 ){
             digitalWrite(optoPins[4], LOW);
             estadoAutomatico[3] = 2;
             estadoAutomatico[6] = 2;

             repeticiones = 0;
             }
           }
           }

Este es un trozo del codigo que estoy probando (que no funciona) porque intento definir una especie de contador ir cambiando la hora de inicio y de fin respectivamente, pero asi no sirve y tmpoco se me ocurre nada por ahora ::slight_smile:

Sabes que dificil es meterme en tu cabeza e intentar entender tu porción de código con la leve explicación que has dado.

Deberías dar una mejor explicación, cuantos estados automáticos hay, que hacen, porque hablas de repeticiones.
Quienes pueden alterar dichos estados automáticos.

Viendo todo el código sería mas facíl. Incluso se puede simular y ver el comportamiento de esta parte.

Veo que no tienes ninguna impresión que te diga como va la cosa, intenta presentar en el monitor serial, estados parciales para ir entendiendo el comportamiento de la rutina.

haber si puedo explicarme un poco mejor, hay realmente dos estados. Activo o inactivo, apartir de hay hay dos formas de activarlos. Atraves de una web con botones se pueden activan manualmente y activados manualmente anulan las funciones automaticas. Y luego tambien esta la opcion automatica que es donde viene todo el grueso, se activan por temperatura MAX y por humedad MAX y se desactivan por Minimas(haciendo las correspondientes comprobaciones tanto para activacion como para desactivacion de que estado tenian). Por ejemplo si llegan a temperatura maxima pero ya estaban activos pues evidentemente no hace nada, y por el contrario si llegan a temperaturas minimas hacen la comprobacion de si en ese momento esta activo por temporizado, ya que en ese acaso no lo apagarian. Apartir de aqui que ese tema esta totalmente controlado, el problema que tengo, fuera aparte de logicas de programa, es que no soy capaz de programarle un temporizado cada 15 minutos. Porque hacerle un temporizado como tengo para la iluminacion es ponerle minuto de inicio y minuto de fin, pero cada 15 minutos seria un programa infinitamente largo. Entonces lo que necesito es encontrar una solucion para eso. Aunque sea cambiando totalmente el codigo expuesto que era solamente para que vierais hasta donde he llegado sin resultados jajajaj. Espero haberme expicado un poco mejor y si necesita alguien alguna informacion adicional que lo diga. Muchas gracias por responder surbyte

Hola.
La verdad es que sin poner tu código es difícil responderte concretamente, así que te responderé genéricamente.
Mi opinión es que la solución a tu problema pasa por transformar la hora a minutos. No sé si los quince minutos son en minutos fijos o desde la última activación (se haya producido por temporizado o manual o temperatura...).
En el primer caso, chequearíamos así:

if (minuto % 15 == 0) // va a ser verdadero en todas las horas en punto, y quince, y treinta, y cuarenta y cinco minutos.

Incluso, si tienes un tiempo establecido de encendido (pongamos dos minutos):

if ((minuto % 15 >= 0) && (minuto % 15 <2))

En el segundo caso, inicialmente podrías hacer:

unsigned int minutoUltimaActivacion = hora*60+minuto;

Y para chequear si ha transcurrido el tiempo:

unsigned minutoActual = hora*60 + minuto;
if (minutoUltimaActivacion>minutoActual) { //habría que comprobar por si acaso hemos saltado de día
    minutoActual+=3600; // sumamos un día a la hora
}

if (minutoActual - minutoUltimaActivacion >= 15) {
// código a ejecutar
minutoUltimaActivacion=minutoActual; // reseteamos el contador
}

Vuelvo a insistir.
Tu explicacion mejora pero sin el código general luce como descolgada.

No hay forma de entender que estas haciendo.
Mi Eslogan "Sube tu código y agrega los enlaces de las librerías.", simplemente lo tomé de las Normas del foro.

//conexiones
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
//tiempo
#include <Time.h>
//sensor DHT
#include "DHT.h"
#define DHTPIN 5 
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);


String readString;
boolean leyendo;
unsigned long epoch;
int horas;
int minutos;
int segundos;
int dia;
int mes;
int anio;
unsigned int horaInicio = 0;
unsigned int horaFin = 0;
unsigned int horaActual = 0;
unsigned int minutoActual;
unsigned int minutoUltimaActivacion;  
byte estadoAutomatico[7] = {2, 0, 2, 2, 2, 2, 2};     // 0 no definido, 1 encendido, 2 apagado.  luz, periodo, int, ext, vent, riego, renovacion aire
byte estadoManual[5] = {2, 2, 2, 2, 2,};  // 1 encendido, 2 apagado. luz, int, ext, vent, riego
byte optoPins[5] = {66, 6, 7, 8, 9};   //66 reservado riego, 6 int, 7 luz, 8 vent, 9 ext.
float temperatura;
int humedad;

// Configuración de direccion MAC e IP.
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,108);

// Inicia las librerias Ethernet server.
EthernetServer server(1989);
unsigned int localPort = 8888;            //  Puerto local para escuchar UDP

//IPAddress timeServer(130, 206, 194, 254);       // time.nist.gov NTP server (fallback)
IPAddress timeServer(130,206,3,166);    // Red Iris Bilbao
//IPAddress timeServer(130,206,206,248);  // Red Iris Madrid
const int NTP_PACKET_SIZE= 48;   // La hora son los primeros 48 bytes del mensaje
byte packetBuffer[ NTP_PACKET_SIZE];  // buffer para los paquetes

EthernetUDP Udp;       // Una instancia de UDP para enviar y recibir mensajes

  
void setup() {
Serial.begin(9600);                  // Inicia el puerto serie.  
dht.begin();                         // Inicia el Sensor
Ethernet.begin(mac, ip);            // Inicia la conexión Ethernet y el servidor.
server.begin();                     // Inicia el servidor
Udp.begin(localPort);               
Serial.print("IP local del servidor ");
Serial.println(Ethernet.localIP());

//declaraciones de pins
digitalWrite(5, INPUT_PULLUP);      //pullup para cable señal de sensor dht
for (byte i = 0;i<5; i++){
 pinMode(optoPins[i], OUTPUT);
 digitalWrite(optoPins[i], LOW);
 } 

// encendido y apgado de led para ver que se resetea la placa.
digitalWrite (optoPins[0], HIGH);
delay(2000);
digitalWrite (optoPins[0], LOW);

//funciones para sincronizar y poner en hora el reloj de arduino
hora();
setTime(horas, minutos, segundos, dia, mes, anio);
      minutoUltimaActivacion = (horas*60+minutos);
}
 
void loop() {
  //Lectura de sensor dht
      humedad = dht.readHumidity();
      temperatura = dht.readTemperature();
  //lectura de hora via servidor  
      hora();
      horaActual = horas;
      minutoActual = (horas*60 + minutos);
      
      Serial.println(minutoActual);
      Serial.println("XXXXXXXX");
      Serial.println(minutoUltimaActivacion);
  
  //control renovacion de aire
  
   if(estadoManual[2] == 2 && minutos % 15 == 0){           // va a ser verdadero en todas las horas en punto, y quince, y treinta, y cuarenta y cinco minutos.
           if (minutoUltimaActivacion > minutoActual) {    //habría que comprobar por si acaso hemos saltado de día
           minutoActual+=3600;                             // sumamos un día a la hora
            }
            if (minutoActual - minutoUltimaActivacion >= 15) {
              digitalWrite(optoPins[4], HIGH);
             estadoAutomatico[3] == 1;
             estadoAutomatico[6] == 1;
              minutoUltimaActivacion=minutoActual; // reseteamos el contador
              }
             else if((minutoActual - minutoUltimaActivacion >= 30) && temperatura < 27.00 ){
             digitalWrite(optoPins[4], LOW);
             estadoAutomatico[3] = 2;
             estadoAutomatico[6] = 2;
             }
           }
           
  
  delay(1000);
  /*
  //control de humedad en vegetativo
  
  if( estadoAutomatico[6] == 2 && estadoAutomatico[1] == 1 && estadoAutomatico[3] == 2 && humedad >= 85){
           estadoAutomatico[3] = 1;
           digitalWrite(optoPins[4], HIGH);   
         }
      if (humedad >= 95 && estadoAutomatico[3] == 1){
            estadoAutomatico[2] = 1;
            digitalWrite(optoPins[1], HIGH);
         } 
      if ( humedad <= 80 && estadoAutomatico[2] == 1){
        if(estadoManual[1] == 2){
         digitalWrite(optoPins[1], LOW);
         estadoAutomatico[2] = 2;
         }
        }
      if(humedad <= 75 && estadoAutomatico[3] == 1 && estadoAutomatico[6] == 2 && temperatura <= 23.00){
        if(estadoManual[2] == 2){
         digitalWrite(optoPins[4], LOW);
         estadoAutomatico[3] = 2;
         }
       } 
          //seguridad en cultivo
       if(estadoAutomatico[1] == 1 && humedad <= 70){
         if(estadoManual[1] == 2 && estadoManual[2] == 2){
         digitalWrite(optoPins[4], LOW);
         digitalWrite(optoPins[1], LOW);
         estadoAutomatico[2] = 2;
         estadoAutomatico[3] = 2;
         }
        // digitalWrite(LedErrorHumedad, HIGH);
       }else {
         // digitalWrite(LedErrorHumedad, LOW);
       }
         
   //control de humedad en floracion
   if( estadoAutomatico[6] == 2 && estadoAutomatico[1] == 2 && estadoAutomatico[3] == 2 && humedad >= 45){
           estadoManual[2] = 1;
           digitalWrite(optoPins[4], HIGH);   
         }
      if (humedad >= 55 && estadoAutomatico[3] == 1){
            estadoManual[1] = 1;
            digitalWrite(optoPins[1], HIGH);
         } 
      if ( humedad <= 45 && estadoAutomatico[2] == 1){
        if(estadoManual[1] == 2){
         digitalWrite(optoPins[1], LOW);
         estadoAutomatico[2] = 2;
         }
        }
      if(humedad <= 35 && estadoAutomatico[3] == 1 && estadoAutomatico[6] == 2 && temperatura <= 23.00){
        if(estadoManual[2] == 2){
         digitalWrite(optoPins[4], LOW);
         estadoAutomatico[3] = 2;
         }
       } 
          //seguridad en cultivo
       if(estadoAutomatico[1] == 2 && humedad <= 30){
         if(estadoManual[1] == 2 && estadoManual[2] == 2){
         digitalWrite(optoPins[4], LOW);
         digitalWrite(optoPins[1], LOW);
         estadoAutomatico[2] = 2;
         estadoAutomatico[3] = 2;
         }
        // digitalWrite(LedErrorHumedad, HIGH);
       }else {
         // digitalWrite(LedErrorHumedad, LOW);
       }
   
  
  /* //control de temperatura
      if(temperatura >= 25.00 && estadoAutomatico[3] == 2){      
           estadoAutomatico[3] = 1;
           digitalWrite(optoPins[4], HIGH); 
         }
      if (temperatura >= 27.00 && estadoAutomatico[3] == 1){
            estadoAutomatico[2] = 1;
            digitalWrite(optoPins[1], HIGH);
         } 
      if ( temperatura <= 25.00 && estadoAutomatico[2] == 1){
        if(estadoManual[1] == 2){
         digitalWrite(optoPins[1], LOW);
         estadoAutomatico[2] = 2;
        }
       }
      if(temperatura <= 20.00 && estadoAutomatico[3] == 1 && estadoAutomatico[6] == 2){
        if(estadoManual[2] == 2){
         digitalWrite(optoPins[4], LOW);
         estadoAutomatico[3] = 2;
         }
       }
       // seguridad en cultivo
       if(temperatura <= 18.00 ){
         if(estadoManual[1] == 2 && estadoManual[2] == 2)
         {
         digitalWrite(optoPins[4], LOW);
         digitalWrite(optoPins[1], LOW);
         estadoAutomatico[2] = 2;
         estadoAutomatico[3] = 2;
         }
        // digitalWrite(LedErrorTemperatura, HIGH);
       }else {
         // digitalWrite(LedErrorTemperatura, LOW);
       }
*/

//control de luz
if(estadoAutomatico[1] == 2){
           horaInicio = 1260;   // En minuto las 21 horas para inicio
           horaFin = 780;      // las 13 horas del dia siguiente para fin 
           
           if(horaInicio <= horaActual && (horaFin + 3600) >= horaActual){
             digitalWrite (optoPins[2], HIGH);
             estadoAutomatico[0] = 1;
           }
             else{
             digitalWrite (optoPins[2], LOW);
             estadoAutomatico[0] = 2;
             }
           }

  if(estadoAutomatico[1] == 1){
           horaInicio = 1380;// las 23 horas para inicio
           horaFin = 660;// las 11 horas del dia siguiente para fin
           
           if(horaInicio <= horaActual && (horaFin + 3600)>= horaActual){
             digitalWrite (optoPins[2], HIGH);
             estadoAutomatico[0] = 1;
           }
                 else{
             digitalWrite (optoPins[2], LOW);
             estadoAutomatico[0] = 2;
           }
        }

he puesto solo parte del codigo obviando el control via web porque me excedia los caracteres maximos :disappointed_relieved: .
los enlaces de las librerias es un poco mas costoso porque estan recopiladas de todas partes. Si alguien lo necesitara los buscaria todos.
La zona de control automatico por humedad y/o temperatura esta toda comentada para que no interfiera mientras hago pruebas con el control por temporizado (que esta en pruebas de codigo aplicando lo que me propuso el compañero) Gracias a todos

Bueno despues de poner en practica el ejemplo de codigo de "noter", así ha quedado el codigo final para el temporizado cada 15 minutos de la extraccion. Muchisimas gracias por la ayuda y lo dejo aqui integro por si a alguien mas le hiciera falta. Eres un genio noter :grinning: y surbyte, muchisimas gracias por las respuestas y la ayuda que desinteresadamente ofreces y que seguramente, en futuros proyectos o en este cuando le implemente alguna mejora, necesitaré. Un saludo amigos

unsigned int minutoActual;
unsigned int minutoUltimaActivacion;
unsigned int minutoDesactivacion; 

void setup(){
minutoUltimaActivacion = 0; // numero a 0 para que empiece la extraccion al encender el                      arduino y ya comience el ciclo automatico
}
void loop(){
horas ()  // funcion propia para sacar la hora de servidor udp
minutoActual = (horas*60 + minutos);

if(estadoManual[2] == 2){           // va a ser verdadero en todas las horas en punto, y quince, y treinta, y cuarenta y cinco minutos.
           if (minutoUltimaActivacion > minutoActual) {    //habría que comprobar por si acaso hemos saltado de día
           minutoActual+=3600;                             // sumamos un día a la hora
            }
            if (minutoActual - minutoUltimaActivacion >= 30) {
              digitalWrite(optoPins[4], HIGH);
             estadoAutomatico[3] = 1;
             estadoAutomatico[6] = 1;
              minutoUltimaActivacion=minutoActual; // reseteamos el contador
              minutoDesactivacion = minutoActual + 15;
              }
             else if(minutoActual == minutoDesactivacion && temperatura < 27.00 ){
             digitalWrite(optoPins[4], LOW);
             estadoAutomatico[3] = 2;
             estadoAutomatico[6] = 2;
             }
}
           }