// Se importan las librerias necesarias
#include <Arduino.h>
#include <NewPing.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include <ESP32Time.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
// Definiendo y construyendo el objeto de la pantalla
// Direccion, columnas, filas
LiquidCrystal_I2C lcd_1(0x27,16,2);
// Definiendo y construyendo el objeto NewPing y sus variables
int trigg = 5;
int echo = 18;
int maxDist = 400;
NewPing ultraSens_1(trigg, echo, maxDist);
float dist_uS1 = 0.0;
String uS1_Stat = "";
// Definiendo el pin para inidcar la transmision de datos y el simbolico de 5 segundos
int led_escrit = 13;
int led_lect = 2;
// Realizando la conexion a internet
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// Definiendo variables relacionadas al timepo
ESP32Time rtc;
const long offset = -6 * 60 * 60;
String timeStamp = "";
// Definiendo la URL del Firebase
String fireURL="https://tec2022-2a1dd-default-rtdb.firebaseio.com/Actividad 3/.json";
/*
Se definen el intervalo en el que se va a cambiar de escritura a lectura, este intervalo es
de 5 segundos, por lo que el arduino va a mandar datos por 5 segundos y eschucara durante
los otros 5
*/
int intervalo_escrit = 5000;
// Se define un bloqueo de escritura
bool bloqEscrit = false;
// Se almacena un acomulado de la duracion de la ejecucion de los eventos
unsigned long tiempoAnterior_modo = 0;
// Se asigna una variable de control para intercambiar entre el modo de lectura y de escritura
bool lectura = false;
// Se asigna una variable para guardar la simbolizacion del delay
bool check_delay = false;
void setup(){
// Se incia la comunicacion serial
Serial.begin(115200);
// Llamar a la funcion de conexion wifi
initWiFi();
// Se definen los modos de trabajo de los pines
pinMode(led_lect, OUTPUT);
pinMode(led_escrit, OUTPUT);
// Establecer el estado inicial de los leds
digitalWrite(led_lect, LOW);
digitalWrite(led_escrit, LOW);
// Se inicia la conexion con el servidor de tiepo
configTime(offset, 3600, "mx.pool.ntp.org");
// Una vez obtenida la conexion, se actualiza el reloj interno del ESP32
struct tm timeinfo;
if (getLocalTime(&timeinfo)){
rtc.setTimeStruct(timeinfo);
}
// Iniciando la comunicacion con la pantalla
lcd_1.init();
}
void loop(){
// Apagar el led simbolizador del envio de datos
digitalWrite(led_escrit, LOW);
// Se obtiene la distancia
dist_uS1 = ultraSens_1.ping_cm();
// Se guarda el tiempo en el que se tomo la medicion
timeStamp = rtc.getTime("%Y-%m-%e @ %T");
// Se manda llamar la funcion para evaluar distancia
uS1_Stat = uS_Eval(dist_uS1);
// Se imprime la informacion en la pantalla
printDatos_uS("uS_1: ", String(dist_uS1), " cm", uS1_Stat);
// Se mandan los datos a la base de Firebase
if (modeCheck(intervalo_escrit)) {
httpSend(fireURL, timeStamp, "ultraSens_1", uS1_Stat, String(dist_uS1));
}
}
// Funcion para imprimir datos locales al LCD
void printDatos_uS(String id, String info1, String unidad, String info2) {
String join = "";
// Limpiar el LCD antes de mostrar la info
lcd_1.clear();
// Imprimir Datos
join = id + info1 + unidad;
lcd_1.setCursor(0, 0);
lcd_1.print(join);
lcd_1.setCursor(0, 1);
lcd_1.print(info2);
}
// Funcion para obtener la lectura y estatus del sensor ultrasonico
String uS_Eval(int dist_uS) {
// Se evalua la distancia
String uS_Stat = "";
if (dist_uS >= 0.0 && dist_uS <= 25.0) uS_Stat = "Zona de Riesgo";
else if (dist_uS >= 25.1 && dist_uS <= 100.0) uS_Stat = "Zona Segura";
else uS_Stat = "Fuera de Rango";
return uS_Stat;
}
// Funcion para realizar la conexion a internet mediante WiFi
void initWiFi() {
// Se establece el modo de conexion del ESP32 como una estacion
WiFi.mode(WIFI_STA);
// Se incializa el objeto WiFi y se le indica a donde conectarse
WiFi.begin(ssid, password);
// Se indica que se encuentra realizando la conexion a internet
Serial.print("Connecting to WiFi ..");
// Se espera hasta que la bandera de conexion sea verdadera
while (WiFi.status() != WL_CONNECTED) {
// SI no nos hemos conectado se indica la espera en el monitor serial
Serial.print('.');
// Se esperan 500 ms para volver a checar la conexion
delay(500);
}
// Se imprime la direccion IP de conexion para simbolizar la conexion existosa
Serial.println(WiFi.localIP());
}
// Funcion que nos va a permitir realizar el envio de datos a Firebase
void httpSend(String url, String stamp, String sensID, String stat, String val){
// Se prende el led de escritura
digitalWrite(led_escrit, HIGH);
// Se crea un objeto HTTP
HTTPClient fireClient;
// Se incializa el objeto creado con el URL de Firebase
fireClient.begin(url);
fireClient.addHeader("Content-Type", "application/json");
// Se incia la creacion del json a mandar
// Se define una variable donde guardar el Json
String send;
// Se crea un objeto json con un tamaño 128 (ArduinoJson Asistant)
StaticJsonDocument<128> json;
// Se crea un objeto json anidado, el primer elemento es el timestamp
JsonObject entry = json.createNestedObject(stamp);
// Dentro del time stamp se envia el ID, status y valor del sensor
entry["ID Sensor"] = sensID;
entry["Status"] = stat;
entry["Valor"] = val;
// Se inicia la serializacion o conversion de los datos al formato json
// se serializa el objeto json y se guarda el resultado en el String send
serializeJson(json, send);
// Se hace un patch al firebase, mandando como payload el json serializado
fireClient.PATCH(send);
// Se crea una variable en la que se visualiza lo enviado al Firebase
String payload = fireClient.getString();
// Se imprime lo mandado al firebase
Serial.println(payload);
}
// Funcion para checar si el Arduino esta en modo de escritura, el default al
// prender el arduino es que la lectura este activadda
bool modeCheck(int intervalo) {
// Primero se va a tomar el timepo actual del arduino y se va a guardar en una variable
// de tipo unsigned long debido a que estamos trabajando con tiempo (el timepo esta en ms)
unsigned long tiempoActual = millis();
// Una vez que se tomo el timepo actual se va a checar si ya se cumplio el intervalo
if (tiempoActual - tiempoAnterior_modo >= intervalo_escrit) {
// Si el timepo actual es mayor al intervalo se guarda el timepo actual como el tiempo
// anterior
tiempoAnterior_modo = tiempoActual;
// Se checa si el bloqueo de escritura esta activo
if (bloqEscrit == false) {
// Si no esta activo, se activa el bloqueo
bloqEscrit = true;
}
else {
// Si estaba activo, se desactiva
bloqEscrit = false;
}
}
// Se regresa el estado del bloqueo
return bloqEscrit;
}