tengo este circuito que se encarga de monitorear la habitacion de una villa.
los sensores se encargan de monitorizar la entrada principal, la entrada de la cochera y detectar si hay un auto estacionado. además de tener el estado A) disponible, B)ocupado (se ingresa un importe), C) limpieza y D)mantenimiento. en cada estado se muestra la hora e inicia un cronometro para medir el tiempo de cada estado. todos estos datos los mando a una base de datos en Firebase.
la duda que tengo es que cada vez que ingreso el estado B) ocupado, se reinicia el programa o simplemente no me responden las teclas.
me gustaría saber si alguien me puede ayudar con este problema o si tiene algunas recomendaciones para el código
aquí esta el código
// Librerías
#include <ESP8266WiFi.h>
#include <FirebaseArduino.h>
#include <Keypad_I2C.h>
#include <Keypad.h>
#include "RTClib.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Pantalla LCD
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Se define el RTC
RTC_DS3231 rtc;
// Dirección I2C del teclado
#define I2CADDR 0x20
// Sensores Ultrasonicos
#define TRIG1 D3
#define ECO1 D4
#define TRIG2 D5
#define ECO2 D6
#define TRIG3 D7
#define ECO3 D8
#define DISTANCE_THRESHOLD 50
// Configuración del WiFi
#define WIFI_SSID ""
#define WIFI_PASSWORD ""
// Configuración de Firebase
#define FIREBASE_HOST "mark07-95cca-default-rtdb.firebaseio.com"
#define FIREBASE_AUTH "AyIeJd111qfPmoAMLXYQOHnYv3UD3vnc1KkRUbNh"
// Definición de los días para el RTC
char daysOfTheWeek[7][12] = {"Domingo", "Lunes", "Martes", "Miercoles", "Jueves", "viernes", "Sabado"};
// Configuración del teclado
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
// Conexión de las filas y columnas del teclado
byte rowPins[ROWS] = {3, 2, 1, 0};
byte colPins[COLS] = {7, 6, 5, 4};
// Inicialización del teclado I2C
Keypad_I2C kpd(makeKeymap(keys), rowPins, colPins, ROWS, COLS, I2CADDR, PCF8574);
unsigned long tiempoInicio = 0; // Variable para almacenar el tiempo de inicio del cronómetro
bool cronometroActivo = false; // Variable para indicar si el cronómetro está activo
String estadoActual = "Desconocido"; // Variable para almacenar el estado actual
String cantidadActual = ""; // Variable para almacenar la cantidad actual
unsigned long tiempoUltimaActualizacion = 0; // Variable para almacenar el tiempo de la última actualización
const unsigned long intervaloActualizacion = 1000; // Intervalo de actualización de pantalla en milisegundos
unsigned long tiempoUltimaLecturaSensores = 0; // Variable para controlar la lectura de los sensores
const unsigned long intervaloLecturaSensores = 60000; // Intervalo de lectura de sensores en milisegundos (1 minuto)
unsigned long tiempoUltimaActualizacionFirebase = 0; // Variable para controlar la actualización periódica a Firebase
const unsigned long intervaloActualizacionFirebase = 180000; // Intervalo de actualización a Firebase en milisegundos (3 minutos)
void setup() {
// Inicialización de conexión WiFi
Serial.begin(9600);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
lcd.setCursor(0, 1);
lcd.print(".");
}
Serial.println("Conectado al WiFi");
lcd.println("Conectado al WiFi");
// Configuración de Firebase
Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
// Entrada y salida de sensores ultrasonicos
pinMode(TRIG1, OUTPUT);
pinMode(ECO1, INPUT);
pinMode(TRIG2, OUTPUT);
pinMode(ECO2, INPUT);
pinMode(TRIG3, OUTPUT);
pinMode(ECO3, INPUT);
Wire.begin(); // Inicia la comunicación I2C
kpd.begin(makeKeymap(keys)); // Inicia el teclado
rtc.begin(); // Inicia el RTC
rtc.adjust(DateTime(__DATE__, __TIME__)); // Se establece la hora dada por la computadora
lcd.init(); // Inicia la pantalla LCD
lcd.backlight(); // Enciende la retroiluminación
lcd.setCursor(0, 0); // Establece el cursor en la posición inicial
lcd.print("BIENVENIDOS"); // Mensaje inicial
lcd.setCursor(0, 1);
lcd.print("SELECCIONE EL ESTADO");
delay(2000); // Se agrega una duración de 2 segundos
lcd.clear(); // Se limpia la pantalla
mostrarMenu();
}
void mostrarMenu() { // Muestra los estados disponibles
lcd.setCursor(0, 0);
lcd.print("A= Disponible");
lcd.setCursor(0, 1);
lcd.print("B= Ocupado");
lcd.setCursor(0, 2);
lcd.print("C= Limpieza");
lcd.setCursor(0, 3);
lcd.print("D= Mantenimiento");
}
void loop() {
// Verificar el estado de la conexión WiFi
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Desconectado del WiFi. Intentando reconectar...");
WiFi.disconnect();
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
// Esperar hasta que se conecte al WiFi
while (WiFi.status() != WL_CONNECTED) {
delay(500); // Asegúrate de que esto no cause un bloqueo largo
Serial.print(".");
}
Serial.println();
Serial.println("Reconectado al WiFi");
}
// Configuración del teclado
char key = kpd.getKey();
if (key) {
lcd.clear();
lcd.setCursor(0, 1);
switch (key) {
case 'A':
estadoActual = "Disponible";
lcd.print("Estado: Disponible");
iniciarCronometro();
Firebase.pushString("/estado", estadoActual);
break;
case 'B':
estadoActual = "Ocupado";
lcd.print("Estado: Ocupado");
ingresarCantidad();
iniciarCronometro();
Firebase.pushString("/estado", estadoActual);
break;
case 'C':
estadoActual = "Limpieza";
lcd.print("Estado: Limpieza");
iniciarCronometro();
Firebase.pushString("/estado", estadoActual);
break;
case 'D':
estadoActual = "Mantenimiento";
lcd.print("Estado: Mantenimiento");
iniciarCronometro();
Firebase.pushString("/estado", estadoActual);
break;
case '*':
mostrarMenu();
break;
}
delay(1000); // Para dar tiempo a ver el estado antes de iniciar el cronómetro
}
unsigned long tiempoActual = millis();
if (tiempoActual - tiempoUltimaActualizacion >= intervaloActualizacion) {
if (cronometroActivo) {
actualizarLCD();
}
tiempoUltimaActualizacion = tiempoActual;
}
if (tiempoActual - tiempoUltimaLecturaSensores >= intervaloLecturaSensores) {
leerSensoresDistancia();
tiempoUltimaLecturaSensores = tiempoActual;
}
if (tiempoActual - tiempoUltimaActualizacionFirebase >= intervaloActualizacionFirebase) {
actualizarFirebase();
tiempoUltimaActualizacionFirebase = tiempoActual;
}
cronos(); // Actualizar la hora en el LCD y Firebase periódicamente
}
// Función para actualizar el LCD con la información del estado y el cronómetro
void actualizarLCD() {
lcd.setCursor(0, 0);
Serial.print(estadoActual);
if (cronometroActivo) {
unsigned long tiempoTranscurrido = millis() - tiempoInicio;
lcd.setCursor(0, 10);
lcd.print("Tiempo: ");
lcd.print(tiempoTranscurrido / 3600000); // Horas
lcd.print(":");
lcd.print((tiempoTranscurrido / 60000) % 60); // Minutos
lcd.print(":");
lcd.print((tiempoTranscurrido / 1000) % 60); // Segundos
}
}
void ingresarCantidad() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Ingrese cantidad:");
String cantidad = "";
char key;
unsigned long tiempoInicio = millis(); // Tiempo inicial para controlar el timeout
while (true) {
key = kpd.getKey();
if (key) {
if (isdigit(key)) {
cantidad += key;
lcd.setCursor(0, 1);
lcd.print(cantidad);
tiempoInicio = millis(); // Reiniciar el tiempo de timeout cuando se recibe un dígito
} else if (key == '#') {
cantidadActual = cantidad; // Guardar la cantidad actual ingresada
Firebase.pushString("/Cantidad", cantidadActual); // Actualizar en Firebase
break; // Finalizar entrada al presionar #
} else if (key == '*') {
if (cantidad.length() > 0) {
cantidad.remove(cantidad.length() - 1); // Borrar último carácter
lcd.setCursor(0, 1);
lcd.print(cantidad);
lcd.print(" "); // Borrar el carácter visualmente en la pantalla
}
tiempoInicio = millis(); // Reiniciar el tiempo de timeout cuando se borra un dígito
}
}
// Verificar el timeout después de 10 segundos sin entrada
if (millis() - tiempoInicio > 10000) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Timeout! Saliendo...");
delay(2000);
lcd.clear();
mostrarMenu();
return; // Salir de la función si hay timeout
}
}
}
void iniciarCronometro() {
tiempoInicio = millis(); // Guardar el tiempo de inicio
cronometroActivo = true; // Activar el cronómetro
}
void cronos() { // Hora
DateTime now = rtc.now();
lcd.setCursor(0, 0);
lcd.print("Hora: ");
lcd.print(now.hour(), DEC);
lcd.print(':');
lcd.print(now.minute(), DEC);
lcd.print(':');
lcd.print(now.second(), DEC);
lcd.setCursor(0, 1);
lcd.print(daysOfTheWeek[now.dayOfTheWeek()]);
lcd.print(", ");
lcd.print(now.day(), DEC);
lcd.print('/');
lcd.print(now.month(), DEC);
lcd.print('/');
lcd.print(now.year(), DEC);
delay(1000); // Hace una pausa de un segundo
Firebase.pushString("/Hora", String(now.hour()) + ":" + String(now.minute())); // Envía la hora a Firebase
}
void leerSensoresDistancia() { // Sensor Ultrasonico
// Configuración del sensor 1
long duracion1, distancia1;
digitalWrite(TRIG1, LOW);
delayMicroseconds(2);
digitalWrite(TRIG1, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG1, LOW);
duracion1 = pulseIn(ECO1, HIGH);
distancia1 = duracion1 * 0.034 / 2;
// Configuración del sensor 2
long duracion2, distancia2;
digitalWrite(TRIG2, LOW);
delayMicroseconds(2);
digitalWrite(TRIG2, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG2, LOW);
duracion2 = pulseIn(ECO2, HIGH);
distancia2 = duracion2 * 0.034 / 2;
// Configuración del sensor 3
long duracion3, distancia3;
digitalWrite(TRIG3, LOW);
delayMicroseconds(2);
digitalWrite(TRIG3, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG3, LOW);
duracion3 = pulseIn(ECO3, HIGH);
distancia3 = duracion3 * 0.034 / 2;
// Envío de datos a Firebase
Firebase.pushInt("/distancia1", distancia1);
Firebase.pushInt("/distancia2", distancia2);
Firebase.pushInt("/distancia3", distancia3);
// Imprimir distancias en el monitor serie
Serial.print("Distancia 1: ");
Serial.print(distancia1);
Serial.println(" cm");
Serial.print("Distancia 2: ");
Serial.print(distancia2);
Serial.println(" cm");
Serial.print("Distancia 3: ");
Serial.print(distancia3);
Serial.println(" cm");
// Activar el buzzer si la distancia es menor que el umbral
if (distancia1 < DISTANCE_THRESHOLD || distancia2 < DISTANCE_THRESHOLD || distancia3 < DISTANCE_THRESHOLD) {
tone(5, 1000); // Activa el buzzer en el pin D1 con una frecuencia de 1000 Hz
} else {
noTone(5); // Apaga el buzzer si no hay objeto cercano
}
}
void actualizarFirebase() {
DateTime now = rtc.now();
String hora = String(now.hour()) + ":" + String(now.minute());
// Actualizar todos los datos en Firebase
Firebase.pushString("/Hora", hora);
Firebase.pushString("/estado", estadoActual);
Firebase.pushString("/Cantidad", cantidadActual);
// Los estados de los sensores se actualizan en leerSensoresDistancia
Serial.println("Datos actualizados en Firebase");
}
