/*--------------------------------------------------------------------------------------------------------------------
---------------- CODIGO CON 4 RELES, RTC DS Y BOTONES FUNCIONANDO ---------02/12/2023---------
-------------------------- CON EL RELE DE GOTEO PLANTAS FUNCIONANDO ---------------------------------
-------------------------- CON EL REGAR AHORA FUNCIONANDO CON FOR ( CON DELAY()) ----------------------
-------------------------- DIAS QUE DEBE REGAR PATIO Y GOTEO FUNCIONANDO ---------------------
--------------------- CON 2 SESIONES PARA REIEGO PATIO Y CON LED PRENDIDO CUANDO RIEGA
-cambie el pin del boton detener riego del 3 al 7 para que el 3 me quede libre paa un futuro servo
y cambien el pin del relay 11 al 13 por si uso otro servo
*/
/*
CODIGO DE RIEGO
NOVIEMBRE 2023
1 RTC
4 RELAY
4 ELECTROVALVULAS DE 12V
4 BOTONES
1 LED
1 RELAY GOTEO PLANTAS
*/
#include <Wire.h>
#include <RTClib.h>
//********************************* BLOQUE ASIGNACION DE VARIABLES *********************************
//********************************* BLOQUE ASIGNACION DE VARIABLES *********************************
//********************************* BLOQUE ASIGNACION DE VARIABLES *********************************
//**** CAMBIRLOS POR EL DS QUE YO TENGO *********
RTC_DS1307 rtc; // crea objeto del tipo RTC
DateTime fecha;
//------------------------------------------- BLOQUE RELES -----------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ACA SE ESTABLECE EL RIEGO AUTOMATICO <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ACA SE ESTABLECE EL RIEGO AUTOMATICO <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ACA SE ESTABLECE EL RIEGO AUTOMATICO <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
DateTime fechaYHoraDePrueba = DateTime(2023, 12, 3, 19, 29, 55);
//------------------------------------- BLOQUE RELES DE PATIO ------------------------------
// establezco en que pin esta cada rele de riego de patio
const int relayPins[] = {8, 9, 10, 13};
const int numRelays = 4;
//----------------------------------------------------------------
// Si esta ACTIVADO o DESSACTIVADO el riego del patio
bool riegoPatioActivado = true;
// Variable para especificar "Que días de la semana se va a regar el patio"
//(0=domingo, 1=lunes, 2=martes,3=miercoles,4=jueves, 5=viernes,6=sabado )
int diasRiegoPatio[] = {0, 1, 3, 4 }; // ajustar esto según tus necesidades
//--- SESIONES POR DIAS ---
// hora y minuto que empieza a regar la Sesion 1 y si esta activada
bool sesion_1_activada = true;
int horaQueEmpieza_Patio_sesion_1 = 19;
int minutoQueEmpieza_Patio_sesion_1 = 30;
// hora y minuto que empieza a regar la Sesion 2 y si esta activada
bool sesion_2_activada = true;
int horaQueEmpieza_Patio_sesion_2 = 19;
int minutoQueEmpieza_Patio_sesion_2 = 36;
// cada regador riega X cantidad de minutos cada uno (ejemplo: 1 es 1 minuto por cada uno)
int minutosRigaCadaUno = 1;
// cada rele debera esperar los segundos que se coloque (ejemplo: 1 es 1 segundo por cada uno)
int esperaEntreReles = 3;
//---------------------------------- BLOQUE RELES DE GOTEO PLANTAS -------------------------
// establezco en que pin esta el rele de goteo plantas
int rele_12 = 12;
//----------------------------------------------------------------
// Si esta ACTIVADO o DESSACTIVADO el riego de goteo plantas
bool riegoPorGoteoActivado = true;
// Variable para especificar "Que días de la semana se van a regar las plantas con goteo"
//(0=domingo, 1=lunes, 2=martes,3=miercoles,4=jueves, 5=viernes,6=sabado )
int diasRiegoGoteo[] = {0, 2, 4, 6 }; // ajustar esto según tus necesidades
// hora y minuto que empieza a regar
int horaQueEmpieza_Goteo = 20;
int minutoQueEmpieza_Goteo = 30;
// riega X cantidad de minutos cada uno (ejemplo: 1 es 1 minuto)
int minutosRiga_Goteo = 1;
//------------------------------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FIN DE ESTABLECE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FIN DE ESTABLECE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FIN DE ESTABLECE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// variables int
unsigned long esperaDelay = esperaEntreReles * 1000UL;
int minInicioRele_1;
int minFinRele_1 ;
int minInicioRele_2;
int minFinRele_2 ;
int minInicioRele_3 ;
int minFinRele_3 ;
int minInicioRele_4 ;
int minFinRele_4 ;
int minInicioRele_12;
int minFinRele_12 ;
//----------------------------- BLOQUE ASIGNACION VARIABLES BOOLEANAS ------------------------------
// bool regarPatioNormal = true;
// bool regarGoteoNormal = true;
bool riegoHoyCancelado = false;
bool eventoInicioRele_1 = true;
bool eventoFinRele_1 = true;
bool eventoInicioRele_2 = true;
bool eventoFinRele_2 = true;
bool eventoInicioRele_3 = true;
bool eventoFinRele_3 = true;
bool eventoInicioRele_4 = true;
bool eventoFinRele_4 = true;
bool eventoInicioRele_Plantas = true;
bool eventoFinRele_Plantas = true;
// bandera para que el bloque loop ejecute una sola vez
bool banderaEstaRegando = true;
bool banderaRiegoPatioSesion_2 = true;
//-------------------------------------------------------------------------------------------
//------------------------------------- BLOQUE BOTONES Y LED-------------------------------------
int pinButton_DetenerRiegoActual = 7;
int pinButton_RegarAhora = 4;
int pinButton_NoRiegoHoy = 5;
int pinButton_ReanudarRiegoDeHoy = 6;
int pinLed = 2;
int retardoDelay = 250;
//--------------------------------------------------------------------------------------
//*************************************** BLOQUE SETUP ***********************************
//*************************************** BLOQUE SETUP ***********************************
//*************************************** BLOQUE SETUP ***********************************
void setup () {
// inicializa comunicacion serie a 9600 bps
Serial.begin(9600);
//--------------- SETUP ------- CONTROLA QUE EL MODULO RTC SE CONECTE ---------------
if (! rtc.begin()) { // si falla la inicializacion del modulo RTC
Serial.println("Modulo RTC no encontrado !"); // muestra mensaje de error
while (1); // bucle infinito que detiene ejecucion del programa
}
//----------------------------------------------------------------------
// **** linea para prueba ****
rtc.adjust(fechaYHoraDePrueba);
//**** ESTA LINEA HAY QUE COMENTARLA UNA VEZ QUE EL RTC SE HALLA SINCRONIZADO CON LA HORA DE LA PC
// rtc.adjust(DateTime(__DATE__, __TIME__)); // funcion que permite establecer fecha y horario
// al momento de la compilacion. Comentar esta linea
// y volver a subir para normal operacion
//------------------- SETUP ----------------- INICIALIZO RELES PATIO ------------------------------
// Set relay pins as OUTPUT
for (int i = 0; i < numRelays; i++) {
pinMode(relayPins[i], OUTPUT);
digitalWrite(relayPins[i], LOW); // Initialize relays to OFF
}
//------------------- SETUP -------------- INICIALIZO RELES GOTEO PLANTAS -------------------------
pinMode(rele_12, OUTPUT);
digitalWrite(rele_12, LOW);
//-------------------- SETUP ------------------- BLOQUE BOTONES --------------------------
pinMode(pinButton_DetenerRiegoActual, INPUT_PULLUP);
pinMode(pinButton_RegarAhora, INPUT_PULLUP);
pinMode(pinButton_NoRiegoHoy, INPUT_PULLUP);
pinMode(pinButton_ReanudarRiegoDeHoy, INPUT_PULLUP);
pinMode(pinLed, OUTPUT);
digitalWrite(pinLed, LOW);
}
//-----------------------------------------------------------------------------------------
//************************************ FIN BLOQUE SETUP ***************************************
//*************************************** BLOQUE LOOP ***************************************
//*************************************** BLOQUE LOOP ***************************************
//*************************************** BLOQUE LOOP ***************************************
void loop () {
fecha = rtc.now(); // funcion que devuelve fecha y horario en formato DateTime y asigna a variable fecha
//--------------------------------------- BLOQUE RELES PATIO ------ LOOP ---------------------------------
/*
este if es para que entre solo cuando sea 1 minuto antes de la hora y minutos fijados
asi no esta preguntando en los 4 if los mismo
*/
if (esDiaDeRiegoPatio(fecha) && (riegoPatioActivado == true) && (riegoHoyCancelado == false)){
// Sesion 1
if ( (sesion_1_activada == true)
&& (fecha.hour() == horaQueEmpieza_Patio_sesion_1)
&& ((fecha.minute() >= (minutoQueEmpieza_Patio_sesion_1))
&& (fecha.minute() <= ( minutoQueEmpieza_Patio_sesion_1 + (minutosRigaCadaUno * (numRelays + 1))) )))
{
regarPatio(horaQueEmpieza_Patio_sesion_1, minutoQueEmpieza_Patio_sesion_1 );
}
// Sesion 2
if ( (sesion_2_activada == true)
&& (fecha.hour() == horaQueEmpieza_Patio_sesion_2)
&& ((fecha.minute() >= (minutoQueEmpieza_Patio_sesion_2))
&& (fecha.minute() <= ( minutoQueEmpieza_Patio_sesion_2 + (minutosRigaCadaUno * (numRelays + 1))) )))
{
// esta bandera es porque la sesion 1 las desactiva cuando termia y para que el loop entre una sola vez
if (banderaRiegoPatioSesion_2 == true){
eventosInicioYFinRelesPatio_a_true();
Serial.println("Activo los eventos de riego patio para la Sesion 2");
banderaRiegoPatioSesion_2= false;
}
regarPatio(horaQueEmpieza_Patio_sesion_2, minutoQueEmpieza_Patio_sesion_2 );
}
}
//--------------------------------------- BLOQUE RELES GOTEO PLANTAS ----- LOOP ---------------------------------
/*
este if es para que entre solo cuando sea 1 minuto antes de la hora y minutos fijados
asi no esta preguntando en los 4 if los mismo
*/
if ((esDiaDeRiegoGoteo(fecha))
&& (fecha.hour() == horaQueEmpieza_Goteo)
&& ((fecha.minute() >= (minutoQueEmpieza_Goteo)) && (fecha.minute() <= ( minutoQueEmpieza_Goteo + (minutosRiga_Goteo * 2)) ))
&& (riegoHoyCancelado == false)
&& (riegoPorGoteoActivado == true))
{
regarPlantasGoteo();
}
//-------------------------------------------- FIN BLOQUE RELES --------------- LOOP ----------------------------
//--------------------------------------------- BLOQUE BOTONES---------------- LOOP -----------------------
//------------------------------------- BOTON 1: Detener el Riego Actual -------------
if (digitalRead(pinButton_DetenerRiegoActual) == 0){
detenerRiegoActualAhora();
}
//------------------------------------------BOTON 2: Regar Ahora ---------------------
if (digitalRead(pinButton_RegarAhora) == 0){
if ( (esDiaDeRiegoPatio(fecha))
&& (fecha.hour() == horaQueEmpieza_Patio_sesion_1)
&& ((fecha.minute() >= (minutoQueEmpieza_Patio_sesion_1 - (minutosRigaCadaUno * (numRelays + 1)))) && (fecha.minute() <= ( minutoQueEmpieza_Patio_sesion_1 + (minutosRigaCadaUno * (numRelays + 1))) ))){
Serial.println("Orden: Regar Ahora NO ACEPTADA El Riego Programado del Patio (Sesion 1) esta proximo");
}else if ( (esDiaDeRiegoPatio(fecha))
&& (fecha.hour() == horaQueEmpieza_Patio_sesion_2)
&& ((fecha.minute() >= (minutoQueEmpieza_Patio_sesion_2 - (minutosRigaCadaUno * (numRelays + 1)))) && (fecha.minute() <= ( minutoQueEmpieza_Patio_sesion_2 + (minutosRigaCadaUno * (numRelays + 1))) ))){
Serial.println("Orden: Regar Ahora NO ACEPTADA El Riego Programado del Patio (Sesion 2) esta proximo");
}else if( (esDiaDeRiegoGoteo(fecha))
&& ( (fecha.hour() == horaQueEmpieza_Goteo)
&& ((fecha.minute() >= (minutoQueEmpieza_Goteo - (minutosRigaCadaUno * 2))) && (fecha.minute() <= ( minutoQueEmpieza_Goteo + (minutosRiga_Goteo * 2)) )))){
Serial.println("Orden: Regar Ahora NO ACEPTADA El Riego Programado de Goteo esta proximo");
}else{
regarAhora();
}
}
//-------------------------------------- BOTON 3: No Riege Hoy -------------------------
if (digitalRead(pinButton_NoRiegoHoy) == 0){
noRiegoHoy();
}
//-------------------------------------BOTON 4: Reanudar Riego Programado para Hoy ------
if (digitalRead(pinButton_ReanudarRiegoDeHoy) == 0){
reanudarRiegoProgramado();
}
//---------------------------------- FIN BLOQUE BOTONES ---------------- LOOP ------------------
//**** ESTAS LINEA HAY QUE COMENTARLAS, SOLO SIRVEN PARA SI QUIERO VER QUE PASA CON EL RTC
//imprimirRelojParaVerConfiguracion();
//------------------------------ RESTABLECER VARIABLES -------------- LOOP ---------------------
// dentro del procedimiento, si son las = 3 de la mañana y minutos = 0 restablece valor de todo
restablecerVariables();
//---------------------------------------------------------------------------------------
}
//************************************ FIN BLOQUE LOOP ***************************************
//************************************ PROCEDIMIENTOS ******************************************
//************************************ PROCEDIMIENTOS ******************************************
//************************************ PROCEDIMIENTOS ******************************************
//------------------------- FUNCION para verificar si hoy es un día de riego Patio----------------------
bool esDiaDeRiegoPatio(DateTime fecha) {
// Obtiene el día de la semana (0=domingo, 1=lunes, 2=martes, ..., 7=domingo)
int diaDeLaSemana = fecha.dayOfTheWeek();
// Verifica si el día de la semana está en la lista de días de riego
for (int i = 0; i < (sizeof(diasRiegoPatio) / sizeof(diasRiegoPatio[0])); i++) {
if (diaDeLaSemana == diasRiegoPatio[i]) {
return true; // Hoy es un día de riego
}
}
return false; // Hoy no es un día de riego
}
//------------------------- FUNCION para verificar si hoy es un día de riego Patio----------------------
bool esDiaDeRiegoGoteo(DateTime fecha) {
// Obtiene el día de la semana (0=domingo, 1=lunes, 2=martes, ..)
int diaDeLaSemana = fecha.dayOfTheWeek();
// Verifica si el día de la semana está en la lista de días de riego
for (int i = 0; i < (sizeof(diasRiegoGoteo) / sizeof(diasRiegoGoteo[0])); i++) {
if (diaDeLaSemana == diasRiegoGoteo[i]) {
return true; // Hoy es un día de riego
}
}
return false; // Hoy no es un día de riego
}
//------------------------------- PROCEDIMIENTO REGAR PLANTAS GOTEO -------------------------------
void regarPlantasGoteo(){
minInicioRele_12 = minutoQueEmpieza_Goteo;
minFinRele_12 = (minInicioRele_12 + minutosRiga_Goteo ) ;
controlarReleProgramado(rele_12, eventoInicioRele_Plantas, eventoFinRele_Plantas, horaQueEmpieza_Goteo, minInicioRele_12, minFinRele_12);
}
//------------------------------- PROCEDIMIENTO REGAR PATIO -------------------------------
void regarPatio(int horaQueEmpieza_Patio_Prm, int minutoQueEmpieza_Patio_Prm ){
minInicioRele_1 = minutoQueEmpieza_Patio_Prm;
minFinRele_1 = (minInicioRele_1 + minutosRigaCadaUno );
minInicioRele_2 = (minFinRele_1);
minFinRele_2 = (minInicioRele_2 + minutosRigaCadaUno );
minInicioRele_3 = (minFinRele_2);
minFinRele_3 = (minInicioRele_3 + minutosRigaCadaUno );
minInicioRele_4 = (minFinRele_3);
minFinRele_4 = (minInicioRele_4 + minutosRigaCadaUno);
cartelEstaRegando();
controlarReleProgramado(relayPins[0], eventoInicioRele_1, eventoFinRele_1, horaQueEmpieza_Patio_Prm, minInicioRele_1, minFinRele_1);
controlarReleProgramado(relayPins[1], eventoInicioRele_2, eventoFinRele_2, horaQueEmpieza_Patio_Prm, minInicioRele_2, minFinRele_2 );
controlarReleProgramado(relayPins[2], eventoInicioRele_3, eventoFinRele_3, horaQueEmpieza_Patio_Prm, minInicioRele_3, minFinRele_3);
controlarReleProgramado(relayPins[3], eventoInicioRele_4, eventoFinRele_4, horaQueEmpieza_Patio_Prm, minInicioRele_4, minFinRele_4);
}
//----------------------------- PROCEDIMIENTO CONTROLAR RELE PROGRAMADO -------------------------
void controlarReleProgramado(int pinRele, bool &eventoInicio, bool &eventoFin, int horaQueEmpiezaPrm, int minInicioRelePrm, int minFinRelePrm) {
if (fecha.hour() == horaQueEmpiezaPrm && fecha.minute() == minInicioRelePrm) {
if (eventoInicio == true) {
digitalWrite(pinRele, HIGH);
digitalWrite(pinLed, HIGH);
Serial.println("Rele PIN: " + String(pinRele) + " Encendido" );
eventoInicio = false;
}
}
if (fecha.hour() == horaQueEmpiezaPrm && fecha.minute() == minFinRelePrm) {
if (eventoFin == true) {
digitalWrite(pinRele, LOW);
digitalWrite(pinLed, LOW);
Serial.println("Rele PIN: " + String(pinRele) + " Apagado" );
eventoFin = false;
delay(esperaDelay);
}
}
}
//------------------------- PROCEDIMIENTO - REGAR AHORA PATIO------------------------
void regarAhora() {
unsigned long milisegundosCadaUno = minutosRigaCadaUno * 60UL * 1000UL;
Serial.println("Se apretó el Botón Regar Ahora");
Serial.println("Orden: Regar Ahora ACEPTADA");
parpadearLed();
cartelEstaRegando();
unsigned long startTime = millis();
for (int i = 0; i < numRelays; i++) {
// Enciende el rele actual
digitalWrite(relayPins[i], HIGH);
digitalWrite(pinLed, HIGH);
Serial.println("Rele PIN: " + String(relayPins[i]) + " Encendido");
// Espera el tiempo establecido para el riego
while (millis() - startTime < (i + 1) * milisegundosCadaUno) {
// Verifica si se presionó el botón de detener riego actual
if (digitalRead(pinButton_DetenerRiegoActual) == 0) {
detenerRiegoActualAhora();
return;
}
}
// Apaga el rele actual
digitalWrite(relayPins[i], LOW);
digitalWrite(pinLed, LOW);
Serial.println("Rele PIN: " + String(relayPins[i]) + " Apagado");
// Espera el tiempo de espera entre reles
delay(esperaDelay);
}
}
//-------------------------- PROCEDIMIENTO - PARPADEAR LED ------------------------
void parpadearLed(){
int cont;
cont = 1;
while(cont <= 7){
digitalWrite(pinLed, HIGH);
delay(retardoDelay);
digitalWrite(pinLed, LOW);
delay(retardoDelay);
cont++;
}
cont = 1;
digitalWrite(pinLed, LOW);
}
//-------------------------- PROCEDIMIENTO - DETENER RIEGO ACTUAL ------------------------
void detenerRiegoActualAhora(){
Serial.println("Se apreto el Boton Detener el Riego Actual");
digitalWrite(relayPins[0], LOW);
digitalWrite(relayPins[1], LOW);
digitalWrite(relayPins[2], LOW);
digitalWrite(relayPins[3], LOW);
digitalWrite(rele_12, LOW);
Serial.println("Orden: Detener Riego Actual ACEPTADA");
parpadearLed();
}
//------------------------- PROCEDIMIENTO - NO REGAR HOY ------------------------
void noRiegoHoy(){
Serial.println("Se apreto el Boton No Riego Hoy");
Serial.println("Orden: No Regar Hoy ACEPTADA");
parpadearLed();
detenerRiegoActualAhora();
riegoHoyCancelado = true;
}
//-------------------------- PROCEDIMIENTO - REANUDAR RIEGO PROGRAMADO ------------------------
void reanudarRiegoProgramado(){
Serial.println("Se apreto el Boton Reanudar Riego de Hoy");
eventosTrue();
Serial.println("Orden: Reanudar Riego Programado para Hoy ACEPTADA");
parpadearLed();
}
//------------- PROCEDIMIENTO - RESTABLECER VARIABLES A LA MADRUGADA -------------
void restablecerVariables(){
// si son las = 3 de la mañana y minutos = 0 restablece valor de todo
if ( fecha.hour() == 3 && fecha.minute() == 0 )
eventosTrue();
}
//------------- PROCEDIMIENTO - CARTEL ESTA REGANDO ------------------------------
void cartelEstaRegando(){
if (banderaEstaRegando){
Serial.println("Esta Regando!!! ");
banderaEstaRegando= false;
}
}
//-------------------------------------PROCEDIMIENTO EVENTOS TRUE---------------------------------------------------
void eventosTrue(){
eventosInicioYFinRelesPatio_a_true();
eventoInicioRele_Plantas = true;
eventoFinRele_Plantas = true;
riegoHoyCancelado = false;
banderaEstaRegando = true;
banderaRiegoPatioSesion_2 = true;
}
//---------------------------------------------------------------------------------------------
void eventosInicioYFinRelesPatio_a_true(){
eventoInicioRele_1 = true;
eventoFinRele_1 = true;
eventoInicioRele_2 = true;
eventoFinRele_2 = true;
eventoInicioRele_3 = true;
eventoFinRele_3 = true;
eventoInicioRele_4 = true;
eventoFinRele_4 = true;
banderaEstaRegando = true;
}
//------------------------------ PROCEDIMIENTO IMPRIMIR RTC --------------------------------------------------------
void imprimirRelojParaVerConfiguracion(){
Serial.print(fecha.day()); // funcion que obtiene el dia de la fecha completa
Serial.print("/");
Serial.print(fecha.month()); // funcion que obtiene el mes de la fecha completa
Serial.print("/");
Serial.print(fecha.year()); // funcion que obtiene el año de la fecha completa
Serial.print(" ");
Serial.print(fecha.hour()); // funcion que obtiene la hora de la fecha completa
Serial.print(":");
Serial.print(fecha.minute()); // funcion que obtiene los minutos de la fecha completa
Serial.print(":");
Serial.println(fecha.second()); // funcion que obtiene los segundos de la fecha completa
delay(1000);
}
//---------------------------------------------------------------------------------------
//************************************** FIN BLOQUE PROCEDIMIENTOS ***************************************