Problema de delay con boton - simulacion sistema de riego

Mi programa es una simulación de un sistema de riego, a tales horas, ciertos días, se activa y se muestra con unos leds y una pantalla TFT que aun no configuro. El detalle es que contamos con 2 climas, verano e invierno.
En este caso verano seria "clima = 1" e invierno "clima = 2". Dichas variables cambian con un botón, el detalle es que, a la hora de hacer la comunicación debe de ser con un delay de 1000ms para que podamos ver el tiempo "tal cual es", pero al usar ese delay el boton reacciona a veces si, a veces no. En cambio si quito ese delay y uso uno meno, de unos 200 segundos como se ve en el código. Funciona perfectamente, el botón atiende mi pulsación cada que lo pulso.

Mi pregunta es, hay alguna forma de hacer que, por ejemplo, el loop del botón tenga un delay de 200 y el loop de los print 1000? O saben de alguna manera de corregir este problema, gracias!

#include <Wire.h>  //Incluimos Libreria I2C //Siempre que utilicemos I2C se necesitara esta libreria + la del dispositivo.
#include <RTClib.h>  //Libreria del RTC DS1307

RTC_DS1307 rtc;     //Genera instancia "rtc" de la clase RTC_DS1307

int ledNort = 3;
int ledSouth = 4;
int ledEast = 5;
int ledWest = 6;
int btClima = 12;

//Variables de tiempo
int dia;
int clima = 1;
unsigned int hora;
unsigned int minu;
unsigned int sec;

// Bloque de inicializacion de parametros
void setup ()
{
  Serial.begin(9600);
  Wire.begin();        //Inicializa la clase I2C
  rtc.begin();         //Inicializa el objeto "rtc"
  pinMode(ledNort, OUTPUT);
  pinMode(ledSouth, OUTPUT);
  pinMode(ledWest, OUTPUT);
  pinMode(ledEast, OUTPUT);
  delay(1000);
  pinMode(btClima, INPUT_PULLUP);

  //rtc.adjust(DateTime(__DATE__, __TIME__));   //Para programar el dispositivo (Toma fecha y hora de la ultima compilación)
  rtc.adjust(DateTime(21, 10, 11, 4, 59, 55));   //Año, mes, dia, hora, minuto, segundo        //Con este vamos a asignar la hora donde iniciaremos el regado
  
  if (! rtc.isrunning()) {
    Serial.println("El RTC NO esta operando!");
  
  // rtc.adjust(DateTime(__DATE__, __TIME__)); //Esta linea establece la fecha y hora
  }                                            // del archivo de compilacion de este sketch

}

void loop () 
{
    //Control del clima
    if(digitalRead(btClima) == LOW and clima == 1)
    {
      clima = 2;
      delay(200);
      rtc.adjust(DateTime(21, 10, 10, 17, 59, 55));
      digitalWrite(ledNort, LOW);
      digitalWrite(ledSouth, LOW);
      digitalWrite(ledEast, LOW);
      digitalWrite(ledWest, LOW);
    }
    if(digitalRead(btClima) == LOW and clima == 2)
    {
      clima = 1;
      delay(200);
      rtc.adjust(DateTime(21, 10, 11, 4, 59, 55));
      digitalWrite(ledNort, LOW);
      digitalWrite(ledSouth, LOW);
      digitalWrite(ledEast, LOW);
      digitalWrite(ledWest, LOW);
    }
    
    DateTime now = rtc.now();  //Genera variable "now" del tipo estructura DateTime
                               //y lo iguala a la variable now del RTC
    
    Serial.print(now.year(), DEC);
    Serial.print('-');
    Serial.print(now.month(), DEC);
    Serial.print('-');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.print('-');
    Serial.print(now.dayOfWeek(), DEC);
    Serial.println();
    Serial.println(clima);
    //delay(1000);
    
    dia = now.dayOfWeek();
    
    hora = now.hour();
    minu = now.minute();
    sec = now.second();

    //Control del riego VERANO - Escala 1:3    
    if(clima == 1)
    {
      if (dia == 1 or dia == 3 or dia == 6)
      {
        if (hora == 5 and minu == 0 and sec == 0)
        {
          digitalWrite(ledNort, HIGH);
        }
        else if (hora == 5 and minu == 0 and sec == 5)
        {
          digitalWrite(ledNort, LOW);
          digitalWrite(ledSouth, HIGH);
        }
        else if (hora == 5 and minu == 0 and sec == 15)
        {
          digitalWrite(ledSouth, LOW);
          digitalWrite(ledEast, HIGH);
        }
        else if (hora == 5 and minu == 0 and sec == 20)
        {
          digitalWrite(ledEast, LOW);
          digitalWrite(ledWest, HIGH);
        }
        else if (hora == 5 and minu == 0 and sec == 30)
        {
          digitalWrite(ledWest, LOW);
        }
      }
    }

    //Control del riego INVIERNO - Escala 1:5 
    if(clima == 2)
    {
      if (dia == 0)
      {
        if (hora == 18 and minu == 0 and sec == 0)
        {
          digitalWrite(ledNort, HIGH);
        }
        else if (hora == 18 and minu == 0 and sec == 6)
        {
          digitalWrite(ledNort, LOW);
          digitalWrite(ledSouth, HIGH);
        }
        else if (hora == 5 and minu == 0 and sec == 18)
        {
          digitalWrite(ledSouth, LOW);
          digitalWrite(ledEast, HIGH);
        }
        else if (hora == 5 and minu == 0 and sec == 24)
        {
          digitalWrite(ledEast, LOW);
          digitalWrite(ledWest, HIGH);
        }
        else if (hora == 5 and minu == 0 and sec == 36)
        {
          digitalWrite(ledWest, LOW);
        }
      }
    }
}

No tengo un ejemplo en español, pero necesitas investigar usando millis() para multitarea.

Hay un proyecto en Proyectos, que tiene resuelto gran parte de lo que preguntas. Dale una leida al Acuario, aunque se trate de otra cosa, el manejo de las estaciones es similar.

Espero no haberte malentendido, pero no existe la multitarea en Arduino, si en un ESP32 (doble nucleo) corriendo FreeRTOS pero en general solo puedes implementar una máquina de estados en un Arduino.
Y no veo la necesidad por ahora de usar millis() en lo que esta usando.

1 Like

Prácticamente todas las tareas múltiples, excepto el soporte de hardware específico, son inherentemente tareas únicas de recursos compartidos de tiempo compartido. Esto se logra fácilmente con las limitaciones de Arduino, incluso los AVR, mediante el uso de millis() para permitir que múltiples tareas compartan los recursos del procesador.

Consulte el diagrama de flujo del programa de cualquier programa cronometrado millis() y compárelo con un esquema multitarea CISC y señale las diferencias fundamentales.

Pero es una discusión de otro hilo. No es multitarea. Es una tarea secuencial ejecutada a tiempos diferentes sin bloqueo como provoca delay().
Si quieres para no desvirtuar este hilo abre uno y debatimos cada uno su postura con el tema.
Igualmente te entiendo y tal vez sea un tema semantico sobre que entiende cada uno por tarea.