#include <Arduino.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <LiquidCrystal_I2C.h>
#include <DHTesp.h>
#include <ESP32Servo.h>
// Objetos
LiquidCrystal_I2C lcd(0x27, 16, 2);
DHTesp dhtSensor;
WiFiClient espClient;
PubSubClient mqttClient(espClient);
Servo valvula;
// WiFi
String wifiSSID = "Wokwi-GUEST";
String wifiPassword = "";
// ThingsBoard
const char* tbHost = "demo.thingsboard.io";
const char* tbToken = "e0yERgaw67VU6MULPrjT"; // NUEVO TOKEN
const int tbPort = 1883;
// Pines
const int DHT_PIN = 15;
const int SOIL_SENSOR_PIN = 34;
const int RELAY_PIN = 17;
const int SERVO_PIN = 16;
bool riegoActivo = false;
// Conectar WiFi
void connectWifi() {
WiFi.begin(wifiSSID.c_str(), wifiPassword.c_str());
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
}
// Conectar MQTT
void connectMQTT() {
mqttClient.setServer(tbHost, tbPort);
while (!mqttClient.connected()) {
mqttClient.connect("ESP32Client", tbToken, NULL);
delay(500);
}
}
// Enviar datos a ThingsBoard (incluyendo estado de riego)
void sendDataToThingsBoard(String temperature, String humidity, String soilMoisture, bool riego) {
String estadoRiego = riego ? "true" : "false";
String payload = "{\"temperature\":" + temperature +
",\"humidity\":" + humidity +
",\"soil_moisture\":" + soilMoisture +
",\"riego\":" + estadoRiego + "}";
mqttClient.publish("v1/devices/me/telemetry", payload.c_str());
}
void setup() {
Serial.begin(115200);
connectWifi();
connectMQTT();
dhtSensor.setup(DHT_PIN, DHTesp::DHT22);
lcd.init();
lcd.backlight();
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW);
valvula.attach(SERVO_PIN);
valvula.write(0); // válvula cerrada
}
void loop() {
if (!mqttClient.connected()) {
connectMQTT();
}
mqttClient.loop();
TempAndHumidity data = dhtSensor.getTempAndHumidity();
String temp = String(data.temperature, 2);
String hum = String(data.humidity, 1);
int soilValue = analogRead(SOIL_SENSOR_PIN);
int soilPercent = map(soilValue, 0, 4095, 0, 100);
soilPercent = constrain(soilPercent, 0, 100);
String soil = String(soilPercent);
// Control automático del riego
if (soilPercent < 40) {
digitalWrite(RELAY_PIN, HIGH); // Encender bomba
valvula.write(90); // Abrir válvula
riegoActivo = true;
} else if (soilPercent > 60) {
digitalWrite(RELAY_PIN, LOW); // Apagar bomba
valvula.write(0); // Cerrar válvula
riegoActivo = false;
}
// Mostrar en LCD
lcd.clear();
if (riegoActivo) {
lcd.setCursor(0, 0);
lcd.print("* RIEGO ACTIVADO *");
lcd.setCursor(0, 1);
lcd.print("Suelo: " + soil + "%");
} else {
lcd.setCursor(0, 0);
lcd.print("T:" + temp + "C H:" + hum + "%");
lcd.setCursor(0, 1);
lcd.print("Suelo: " + soil + "%");
}
// Imprimir en consola
Serial.println("Temp: " + temp + "°C");
Serial.println("Humidity: " + hum + "%");
Serial.println("Soil moisture: " + soil + "%");
Serial.println(riegoActivo ? "Estado: RIEGO ACTIVADO" : "Estado: RIEGO DESACTIVADO");
Serial.println("---");
// Enviar telemetría a ThingsBoard
sendDataToThingsBoard(temp, hum, soil, riegoActivo);
delay(2000);
}