#include <Wire.h> // Librería para comunicación I2C
#include <Adafruit_GFX.h> // Librería base para gráficos
#include <Adafruit_SSD1306.h> // Librería específica para la pantalla SSD1306
// --- Configuración de la pantalla OLED ---
#define SCREEN_WIDTH 128 // Ancho en píxeles
#define SCREEN_HEIGHT 64 // Alto en píxeles
#define OLED_ADDR 0x3C // Dirección I2C de la pantalla (verifica en Wokwi si es correcta para tu componente)
// Crea el objeto de la pantalla. El -1 indica que no se usa pin de Reset dedicado.
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// --- Pines para los sensores simulados (potenciómetros en WOKWI) ---
const int phPin = 34; // GPIO34 para pH (ADC1_CH6 en ESP32) - Pin solo de entrada
const int tdsPin = 35; // GPIO35 para TDS (ADC1_CH7 en ESP32) - Pin solo de entrada
// --- Variables para almacenar las lecturas ---
float pHValue; // Variable para almacenar el valor de pH (puede tener decimales)
int tdsValue; // Variable para almacenar el valor de TDS (generalmente entero en ppm)
void setup() {
// Iniciar comunicación Serial para depuración
Serial.begin(115200);
// *** AÑADIDO: Iniciar explícitamente la comunicación I2C ***
// Aunque display.begin a veces lo hace, es bueno ser explícito.
// Asegúrate que los pines SDA/SCL en Wokwi estén conectados a GPIO21/GPIO22 del ESP32.
Wire.begin();
// Inicializar la pantalla OLED
if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
Serial.println("Error al iniciar OLED. Verifica:");
Serial.println("- Cableado (SDA->21, SCL->22, VCC->3.3V, GND->GND)");
Serial.println("- Dirección I2C (0x3C en el código y en Wokwi)");
while(1); // Detener ejecución si falla la inicialización de la pantalla
}
// Configurar resolución del ADC a 12 bits (0-4095) para el ESP32
analogReadResolution(12);
// Mostrar mensaje inicial en la pantalla OLED
display.clearDisplay(); // Limpiar el buffer de la pantalla
display.setTextSize(1); // Tamaño de fuente pequeño
display.setTextColor(SSD1306_WHITE); // Color del texto (blanco sobre negro)
display.setCursor(0,0); // Posicionar cursor (columna 0, fila 0)
display.println(" Sistema de"); // Escribir texto
display.setCursor(0,15);
display.println("Monitoreo de Agua");
display.setCursor(0,35);
display.println(" Cargando...");
display.display(); // Enviar el buffer a la pantalla física/virtual
delay(2000); // Esperar 2 segundos
}
void loop() {
// 1. Leer valores de los "sensores" (potenciómetros en Wokwi)
// Lee el voltaje analógico en los pines y lo convierte a un valor digital (0-4095)
int phRaw = analogRead(phPin);
int tdsRaw = analogRead(tdsPin);
// 2. Convertir las lecturas crudas a valores "reales" (simulados)
// Mapea el rango del ADC (0-4095) a un rango deseado de pH (0.0 - 14.0)
pHValue = map(phRaw, 0, 4095, 0, 140) / 10.0;
// Mapea el rango del ADC (0-4095) a un rango deseado de TDS (0 - 1000 ppm)
tdsValue = map(tdsRaw, 0, 4095, 0, 1000);
// 3. Mostrar información en la pantalla OLED
display.clearDisplay(); // Limpiar pantalla para la nueva actualización
// Encabezado
display.setTextSize(1);
display.setCursor(0,0);
display.println("== CALIDAD DEL AGUA ==");
// Dibuja una línea horizontal debajo del encabezado
display.drawLine(0, 10, display.width()-1, 10, SSD1306_WHITE);
// Mostrar valor de pH
display.setCursor(0,15);
display.print("pH: ");
display.print(pHValue, 1); // Muestra el pH con 1 decimal
// Mostrar valor de TDS
display.setCursor(0,30);
display.print("TDS: ");
display.print(tdsValue);
display.println(" ppm"); // Añade " ppm" y salta de línea (aunque no hay más abajo)
// Indicador simple de estado basado en los valores
display.setCursor(0,45);
display.print("Estado: ");
// Lógica para determinar si el agua está en un rango aceptable
if(pHValue >= 6.5 && pHValue <= 7.5 && tdsValue < 800) {
display.println("OPTIMO"); // Si pH y TDS están bien
} else {
display.println("ALERTA"); // Si algo está fuera de rango
// Mostrar causa específica de la alerta (opcional)
display.setCursor(0,55); // Mover cursor a la última línea
if(pHValue < 6.5) display.println("pH muy bajo");
else if(pHValue > 7.5) display.println("pH muy alto");
else if(tdsValue >= 800) display.println("TDS elevado");
// Nota: Solo se mostrará la primera condición de alerta que se cumpla
}
// Enviar todo lo dibujado al display
display.display();
// 4. Enviar datos también al Monitor Serie para depuración
Serial.print("Lectura Raw pH: "); Serial.print(phRaw); // Útil para ver el valor crudo
Serial.print(" -> pH: "); Serial.print(pHValue, 1);
Serial.print(" | Lectura Raw TDS: "); Serial.print(tdsRaw); // Útil para ver el valor crudo
Serial.print(" -> TDS: "); Serial.print(tdsValue);
Serial.println(" ppm");
// Esperar 2 segundos antes de la siguiente lectura y actualización
delay(2000);
}