/* 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
*/
// Plantagotchi para ESP32 con algoritmo de emociones mejorado y datos simplificados en pantalla OLED
#include <myimages.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>
#define DHTPIN 4
#define DHTTYPE DHT11
#define SOIL_PIN 34
#define LDR_PIN 35
#define LIGHT_RELAY 25
#define FAN_RELAY 26
#define PUMP_RELAY 27
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// Pines I2C para la pantalla OLED
#define OLED_SDA 21
#define OLED_SCL 22
// WiFi y MQTT
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "broker.hivemq.com";
WiFiClient espClient;
PubSubClient client(espClient);
DHT dht(DHTPIN, DHTTYPE);
TwoWire OLEDWire = TwoWire(0);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &OLEDWire, -1);
void setup_wifi() {
delay(10);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
}
void reconnect() {
while (!client.connected()) {
if (client.connect("PlantagotchiClient")) {
client.subscribe("plantagotchi/pump");
client.subscribe("plantagotchi/ledlight");
} else {
delay(5000);
}
}
}
void callback(char* topic, byte* message, unsigned int length) {
String msg;
for (int i = 0; i < length; i++) {
msg += (char)message[i];
}
if (String(topic) == "plantagotchi/pump") {
digitalWrite(PUMP_RELAY, msg == "ON" ? HIGH : LOW);
display.print(PUMP_RELAY, msg == "ON" ? " Agua ON " : " Agua OFF");
}
if (String(topic) == "plantagotchi/ledlight") {
digitalWrite(LIGHT_RELAY, msg == "ON" ? HIGH : LOW);
display.print(LIGHT_RELAY, msg == "ON" ? " Luz ON " : " Luz OFF");
}
}
String getEmotionText(float temp, float hum, int soil, int light) {
if (soil < 30 && temp > 32 && hum < 40 && light > 1000) return "CRITICO";
if (soil < 35 && hum < 45) return "SECO";
if (temp > 32 && hum < 50 && soil > 40) return "CALOR";
if (light < 400 && hum > 60) return "OSCURA";
if (soil > 60 && temp >= 22 && temp <= 28 && light > 800 && hum > 50) return "FELIZ";
return "NORMAL";
}
void showDataOnDisplay(float temp, float hum, int soil, int light, String emotion) {
display.clearDisplay();
// Parte superior: emoción
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println(emotion);
// Parte inferior: datos simplificados
display.setTextSize(1);
display.setCursor(0, 36);
display.print("T:"); display.print((int)temp); display.print("C ");
display.print("H:"); display.print((int)hum); display.println("%");
display.setCursor(0, 48);
display.print("S:"); display.print(soil); display.print("% ");
display.print("L:"); display.println(light);
display.print(temp > 30 ? "aire ON " : "aire OFF");
display.display();
}
void setup() {
pinMode(FAN_RELAY, OUTPUT);
pinMode(PUMP_RELAY, OUTPUT);
pinMode(LIGHT_RELAY, OUTPUT);
digitalWrite(FAN_RELAY, LOW);
digitalWrite(PUMP_RELAY, LOW);
digitalWrite(LIGHT_RELAY, LOW);
Serial.begin(115200);
dht.begin();
OLEDWire.begin(OLED_SDA, OLED_SCL);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) reconnect();
client.loop();
float temp = random(100, 500) / 10.0; // dht.readTemperature();
float hum = random(0, 999) / 10.0; // dht.readHumidity();
int soil = random(0, 1000) / 10.0; // analogRead(SOIL_PIN) / 40.95;
int light = random(0, 1000000) / 10.0; // analogRead(LDR_PIN);
client.publish("plantagotchi/temp", String(temp).c_str());
client.publish("plantagotchi/hum", String(hum).c_str());
client.publish("plantagotchi/soil", String(soil).c_str());
client.publish("plantagotchi/light", String(light).c_str());
digitalWrite(FAN_RELAY, temp > 30 ? HIGH : LOW);
String emotion = getEmotionText(temp, hum, soil, light);
showDataOnDisplay(temp, hum, soil, light, emotion);
delay(5000);
}