/*
Proyecto: Sistema de Monitoreo Agrícola con ESP32
SMART AGRO
Autor: [Ramiro Lopera]
Fecha: [2025]
Descripción:
- Mide temperatura y humedad ambiental DHT22/11 O simulados)
- Controla 2 dispositivos via MQTT: broker.emqx.io - broker.hivemq.com - mosquitto
- Muestra información en pantalla OLED
- Publica datos a broker MQTT
- Actualización en tiempo real de la interfaz gráfica
- Lectura de sensores cada N segundos
- Actualización del contador cada N segundos
Hardware requerido:
- ESP32
- Pantalla OLED SSD1306 128x64
- Sensor DHT11
- 2 Módulos Relay
- Conexión WiFi
Diagrama de conexiones:
DHT11:
- VCC -> 3.3V
- GND -> GND
- DATA -> Pin ?
OLED:
- SDA -> GPIO 21
- SCL -> GPIO 22
Dispositivos:
- Relay1 -> Pin 26
- Servo1 -> Pin 27
*/
#include <myimages.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#include <stdlib.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <ESP32Servo.h>
// Configuración OLED
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Configuración del DHT11
#define DHTPIN 32
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
// Configuración de los dispositivos
const int RelayPin1 = 25;
const int ServoPin1 = 33;
// vinculo la librería del servo
Servo servo;
// Configuración WiFi
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// Configuración MQTT
const char* mqtt_server = "broker.hivemq.com"; // broker.emqx.io - broker.hivemq.com
const char* tempTopic = "rlopera/AGRO/matera/temperatura";
const char* humeTopic = "rlopera/AGRO/matera/humedad";
const char* contTopic = "rlopera/AGRO/ingresos/contador";
const char* Relay1Topic = "rlopera/AGRO/riegojardin/relay";
const char* Servo1Topic = "rlopera/AGRO/puertagaraje/servo";
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
int contador = 0;
float temperatura = 0;
float humedad = 0;
// Define las variables de actualización de la pantalla y el sensor
unsigned long lastDisplayUpdate = 0;
unsigned long lastSensorUpdate = 0;
// rutina para conectarse a la red WiFi
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Conectando a ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi conectado");
Serial.println("Dirección IP: ");
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* message, unsigned int length) {
Serial.print(topic);
String msg;
for (int i = 0; i < length; i++) {
msg += (char)message[i];
}
Serial.println(" Mensaje: " + msg);
// Control del Relay1
if (String(topic) == Relay1Topic) {
if (msg == "ON") {
digitalWrite(RelayPin1, HIGH);
Serial.println(" - Relay 1 ON");
} else if (msg == "OFF") {
digitalWrite(RelayPin1, LOW);
Serial.println(" - Relay 1 OFF");
}
}
// Control del Servo1
if (String(topic) == Servo1Topic) {
if (msg == "ON") {
digitalWrite(ServoPin1, HIGH);
servo.write(0);
Serial.println(" - Servo 1 ON");
} else if (msg == "OFF") {
digitalWrite(ServoPin1, LOW);
servo.write(90);
Serial.println(" - Servo 1 OFF");
}
}
}
void reconnect() {
while (!client.connected()) {
Serial.print("Conectando al servidor MQTT...");
if (client.connect("clientId-AGRORamiro123")) {
Serial.println("Conectado");
// Suscribirse a los tópicos para controlar los Dispositivos
client.subscribe(Relay1Topic);
client.subscribe(Servo1Topic);
} else {
Serial.print("Fallo, rc=");
Serial.print(client.state());
Serial.println(" Intentando de nuevo en 5 segundos...");
delay(5000);
}
}
}
void setup() {
// Configuración serial
Serial.begin(115200);
// Configuración de los dispositivos
pinMode(RelayPin1, OUTPUT);
// pinMode(ServoPin1, OUTPUT);
digitalWrite(RelayPin1, LOW); // se establecen los dispositivos apagados
digitalWrite(ServoPin1, LOW);
// Configuración del sensor DHT11
dht.begin();
// Mapeamos el servo para PWM
servo.attach(ServoPin1, 500, 2400);
// Configuración de la pantalla OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("No se encuentra la pantalla OLED"));
while (true)
;
}
// display.setRotation(2); //180 grados
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print("Conectando WiFi...");
display.display();
// Conectar a WiFi
setup_wifi();
// Configurar MQTT
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
// Mostrar en la pantalla OLED
display.clearDisplay();
display.setCursor(0, 0);
display.print("Conectado a WiFi");
display.display();
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
unsigned long now = millis();
// Actualización de pantalla (frecuente)
if (now - lastDisplayUpdate > 200) { // Actualizar cada 200 ms (ajustable)
lastDisplayUpdate = now;
// Obtener información de la red WiFi
int32_t rssi = WiFi.RSSI();
IPAddress ip = WiFi.localIP();
// Mostrar los datos en la pantalla OLED
display.clearDisplay();
display.setTextSize(1);
display.drawRoundRect(0, 0, 128, 64, 5, WHITE);
display.drawBitmap(2, 0, DataTemp, 10, 20, 1);
display.drawBitmap(75, 0, DataHum, 10, 20, 1);
display.setCursor(12, 2);
display.setTextSize(2);
display.print(temperatura, 1);
display.setTextSize(1);
display.print((char)247);
display.print("C");
display.setCursor(85, 2);
display.setTextSize(2);
display.print(humedad, 0);
display.setTextSize(2);
display.print("%");
display.setCursor(2, 20);
display.setTextSize(1);
display.print(ip);
display.setCursor(100, 20);
display.print(contador);
display.setCursor(5, 28);
display.print(ssid);
display.print("(");
display.print(rssi);
display.print(")");
String Relay1State = digitalRead(RelayPin1) ? "ON" : "OFF";
String Servo1State = digitalRead(ServoPin1) ? "ON" : "OFF";
// Serial.println("===");Serial.println(digitalRead(ServoPin1));Serial.println("===");
if (Relay1State == "ON") { display.drawBitmap(5, 42, riego_on, 15, 20, SSD1306_WHITE); }
if (Relay1State == "OFF") { display.drawBitmap(5, 42, riego_off, 15, 20, SSD1306_WHITE); }
if (Servo1State == "ON") { display.drawBitmap(25, 42, puerta_on, 15, 20, SSD1306_WHITE); }
if (Servo1State == "OFF") { display.drawBitmap(25, 42, puerta_off, 15, 20, SSD1306_WHITE); }
display.display();
}
// Actualización de sensor y envío MQTT (cada 10 segundos)
if (now - lastSensorUpdate > 10000) {
lastSensorUpdate = now;
contador++;
temperatura = random(200, 500) / 10.00; // dht.readTemperature(); //
humedad = random(10, 999) / 10.00; // dht.readHumidity(); //
char tempString[8];
dtostrf(temperatura, 1, 2, tempString);
client.publish(tempTopic, tempString);
char humeString[8];
dtostrf(humedad, 1, 2, humeString);
client.publish(humeTopic, humeString);
char contString[8];
itoa(contador, contString, 10);
client.publish(contTopic, contString);
Serial.print("Temp: ");
Serial.print(temperatura);
Serial.print(" °C, Hum: ");
Serial.print(humedad);
Serial.print(" %, Count: ");
Serial.println(contador);
}
}
/*
Documentación del Proyecto
📋 Descripción General
Sistema IoT para monitoreo agrícola que incluye:
Lectura de temperatura y humedad ambiental
Control remoto de dispositivos mediante relay y servo
Visualización en tiempo real en pantalla OLED
Comunicación mediante protocolo MQTT
🛠 Hardware Requerido
Componente Especificaciones
Microcontrolador ESP32
Pantalla OLED SSD1306 128x64 (I2C)
Sensor DHT11 (Temperatura/Humedad)
Relays 1 módulos de 5V
Servos 1 módulos de 5V
Alimentación DC
/proyecto-agricola
├── /include
│ └── myimages.h # Bitmaps personalizados
├── proyecto-agricola.ino # Código principal
*/