Aqui dejamos el codigo de Arduino IDE mas abajo se muestra el codigo explicado por partes:
Este es el codigo de la placa Arduino:
#include <DHT.h>
#define DHTPIN 3 // Pin del DHT11
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
const int ldrPin = A0; // Sensor de luz (LDR)
const int humedadSueloPin = A1; // Sensor de humedad del suelo
const int numLecturas = 10; // Número de lecturas para promediar el LDR
const int pumpPin = 7; // Bomba de agua conectada al pin 7
String incomingCommand = ""; // Buffer para almacenar comandos entrantes
// Función para promediar las lecturas del LDR
int obtenerValorLuzPromediado() {
int sumaLuz = 0;
for (int i = 0; i < numLecturas; i++) {
sumaLuz += analogRead(ldrPin);
delay(50); // Pequeño retardo para estabilizar la lectura
}
return sumaLuz / numLecturas;
}
void setup() {
Serial.begin(9600); // Comunicación Serial con el ESP8266
dht.begin();
pinMode(pumpPin, OUTPUT);
// Como el relé es activo en bajo, para apagar la bomba se debe poner HIGH.
digitalWrite(pumpPin, HIGH); // Asegura que la bomba esté apagada al inicio
Serial.println("Setup completado. Bomba apagada.");
}
void loop() {
// Procesar comandos entrantes con prefijo "$CMD:"
while (Serial.available() > 0) {
char c = Serial.read();
incomingCommand += c;
if (c == '\n') { // Fin de línea
if (incomingCommand.startsWith("$CMD:")) {
char cmd = incomingCommand.charAt(5);
if (cmd == '1') {
// Comando para encender la bomba: relé activo en bajo → pin LOW.
digitalWrite(pumpPin, LOW);
Serial.println("Bomba ENCENDIDA");
} else if (cmd == '0') {
// Comando para apagar la bomba: se pone HIGH.
digitalWrite(pumpPin, HIGH);
Serial.println("Bomba APAGADA");
}
}
incomingCommand = ""; // Limpiar buffer
}
}
// Lectura de sensores
float temp = dht.readTemperature(); // Temperatura en °C
float hum = dht.readHumidity(); // Humedad en %
int valorLuz = obtenerValorLuzPromediado();
// Invertimos el mapeo: a mayor luz (valorLuz bajo) se asigna un porcentaje alto.
int luz = map(valorLuz, 0, 1023, 100, 0);
luz = constrain(luz, 0, 100);
int humedadSuelo = analogRead(humedadSueloPin);
humedadSuelo = map(humedadSuelo, 1023, 300, 0, 100);
// Enviar datos de sensores en formato CSV: temp, hum, luz, humedadSuelo
Serial.print(temp); Serial.print(",");
Serial.print(hum); Serial.print(",");
Serial.print(luz); Serial.print(",");
Serial.println(humedadSuelo);
delay(2000); // Espera 2 segundos antes de la siguiente iteración
}
El programa del Arduino realiza las siguientes funciones:
Inicialización y Configuración:
Inicia la comunicación serial a 9600 baudios para intercambiar datos con el ESP8266.
Configura el sensor DHT11, el sensor LDR y el sensor de humedad del suelo.
Define el pin para la bomba (pin 7) y lo configura como salida. Como el relé es activo en bajo, se establece el pin en HIGH para mantener la bomba apagada al inicio.
Recepción de Comandos:
Escucha en el puerto serial mensajes que comienzan con el prefijo $CMD:.
Si se recibe $CMD:1, enciende la bomba (pone el pin 7 en LOW).
Si se recibe $CMD:0, apaga la bomba (pone el pin 7 en HIGH).
Lectura y Procesamiento de Sensores:
Lee la temperatura y humedad del DHT11.
Realiza múltiples lecturas del sensor LDR para promediar el valor y, mediante una transformación, convierte la lectura en un porcentaje (mayor luz equivale a un porcentaje mayor).
Mapea la lectura del sensor de humedad del suelo a un porcentaje.
Envío de Datos al ESP8266:
Al final de cada ciclo, el Arduino envía los valores de temperatura, humedad, luz y humedad del suelo en formato CSV (valores separados por comas) a través del puerto serial.
El ESP8266 recibe estos datos y los utiliza para mostrarlos en una página web.
Esta estructura permite que el sistema monitoree el ambiente y controle la bomba de agua, a la vez que actualiza constantemente la información mostrada en el servidor web del ESP8266:
#include <ESP8266WiFi.h>
const char* ssid = "antonio"; // Nombre de la red WiFi
const char* password = "palomino"; // Contraseña de la red WiFi
WiFiServer server(80);
String temp, hum, luz, suelo; // Variables para almacenar los datos de sensores
String pumpState = "Apagada"; // Estado de la bomba
unsigned long lastClientTime = 0;
const unsigned long timeoutInterval = 30000; // 30 segundos de inactividad
void setup() {
Serial.begin(9600); // Comunicación Serial con el Arduino
WiFi.begin(ssid, password);
Serial.println("Conectando a WiFi...");
pinMode(LED_BUILTIN, OUTPUT);
while (WiFi.status() != WL_CONNECTED) {
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}
digitalWrite(LED_BUILTIN, LOW);
Serial.println("\nConectado a WiFi");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
server.begin();
// Al iniciar, asegurar que la bomba esté apagada
pumpState = "Apagada";
Serial.print("$CMD:0\n");
lastClientTime = millis();
}
void loop() {
// Leer datos enviados por el Arduino (datos de sensores)
if (Serial.available()) {
String data = Serial.readStringUntil('\n');
int coma1 = data.indexOf(',');
int coma2 = data.indexOf(',', coma1 + 1);
int coma3 = data.indexOf(',', coma2 + 1);
temp = data.substring(0, coma1);
hum = data.substring(coma1 + 1, coma2);
luz = data.substring(coma2 + 1, coma3);
suelo = data.substring(coma3 + 1);
}
// Manejo de solicitudes web
WiFiClient client = server.available();
if (client) {
Serial.println("Cliente conectado.");
lastClientTime = millis();
String request = client.readStringUntil('\r');
client.flush();
Serial.println("Petición: " + request);
if (request.indexOf("/pump/on") != -1) {
pumpState = "Encendida";
Serial.print("$CMD:1\n"); // Comando para encender la bomba
} else if (request.indexOf("/pump/off") != -1) {
pumpState = "Apagada";
Serial.print("$CMD:0\n"); // Comando para apagar la bomba
}
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
client.println("<!DOCTYPE html>");
client.println("<html lang='es'>");
client.println("<head><meta charset='UTF-8'><meta name='viewport' content='width=device-width, initial-scale=1.0'><title>Datos del Invernadero</title></head>");
client.println("<body style='font-family:Arial, sans-serif; text-align:center;'>");
client.println("<h1>DATOS DEL INVERNADERO</h1>");
client.println("<h2>Temperatura: " + temp + " °C</h2>");
client.println("<h2>Humedad: " + hum + " %</h2>");
client.println("<h2>Luz: " + luz + " %</h2>");
client.println("<h2>Humedad del Suelo: " + suelo + " %</h2>");
client.println("<h2>Bomba: " + pumpState + "</h2>");
client.println("<br><a href='/pump/on'><button>Encender Bomba</button></a>");
client.println("<br><a href='/pump/off'><button>Apagar Bomba</button></a>");
client.println("</body></html>");
client.stop();
}
// Si no se ha conectado ningún cliente en timeoutInterval, forzar el apagado de la bomba
if (millis() - lastClientTime > timeoutInterval) {
if (pumpState != "Apagada") {
pumpState = "Apagada";
Serial.print("$CMD:0\n");
Serial.println("Timeout: Inactividad detectada, Bomba apagada.");
}
}
delay(10);
}
Configuración Inicial:
En el setup(), el ESP8266 se conecta a la red WiFi usando las credenciales proporcionadas. Durante este proceso, el LED integrado parpadea para indicar que se está intentando la conexión. Una vez conectado, se muestra la IP en el monitor serial y se inicia el servidor web en el puerto 80. Además, se envía un comando para asegurar que la bomba esté apagada al arrancar el sistema.
Recepción y Procesamiento de Datos del Arduino:
En el loop(), el ESP8266 escucha en el puerto serial para recibir datos de sensores enviados por el Arduino. Estos datos llegan en formato CSV y se dividen en variables correspondientes a temperatura, humedad, luz y humedad del suelo.
Servidor Web y Control de la Bomba:
El ESP8266 actúa como servidor web. Cuando un cliente (por ejemplo, un navegador) se conecta, se lee la solicitud HTTP. Dependiendo de la URL solicitada (/pump/on o /pump/off), se actualiza el estado de la bomba y se envía el comando correspondiente al Arduino a través del Serial.
La respuesta del servidor es una página web sencilla en HTML que muestra los datos actuales del invernadero y ofrece botones interactivos para controlar la bomba. Esto permite una interacción en tiempo real para encender o apagar la bomba de forma remota.
Gestión de Inactividad:
Si no se detecta actividad de ningún cliente en 30 segundos, el sistema forzará el apagado de la bomba para evitar que quede encendida accidentalmente.