// ════════════════════════════════════════════════════════
// BASURERO INTELIGENTE - VERSIÓN SIMPLIFICADA WOKWI
// Esta versión usa un enfoque más directo para Wokwi
// ════════════════════════════════════════════════════════
#include <WiFi.h>
#include <HTTPClient.h>
// ═══════ WIFI ═══════
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// ═══════ GOOGLE SHEETS ═══════
const char* googleScriptURL = "https://script.google.com/macros/s/AKfycbw4oAm9OyeJTQODA1a5wxWOiRKyQHzJx-9Q-jwlv3f4ETy6kATLW6J1XL14Go6rfEBg2A/exec";
// ═══════ DISPOSITIVO ═══════
String dispositivoID = "";
// ═══════ SENSOR ULTRASÓNICO ═══════
const int trigPin = 18;
const int echoPin = 19;
// ═══════ LEDS ═══════
#define LED_VERDE 27
#define LED_AMARILLO 26
#define LED_ROJO 25
// ═══════ CONFIGURACIÓN BASURERO ═══════
const float ALTURA_BOTE = 61.0;
const float UMBRAL_LLENO = 20.0;
const float UMBRAL_MEDIO = 45.0;
int lecturaNum = 0;
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("\n╔══════════════════════════════════════╗");
Serial.println("║ BASURERO INTELIGENTE - WOKWI ║");
Serial.println("╚══════════════════════════════════════╝\n");
pinMode(LED_VERDE, OUTPUT);
pinMode(LED_AMARILLO, OUTPUT);
pinMode(LED_ROJO, OUTPUT);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
obtenerID();
conectarWiFi();
Serial.println("\n✅ SISTEMA LISTO\n");
delay(2000);
}
void loop() {
lecturaNum++;
Serial.println("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
Serial.println("📊 LECTURA #" + String(lecturaNum));
float distanciaSensor = medirDistancia();
if (distanciaSensor < 0) {
Serial.println("❌ Error en sensor");
delay(5000);
return;
}
float nivelOcupadoCM = ALTURA_BOTE - distanciaSensor;
if (nivelOcupadoCM < 0) nivelOcupadoCM = 0;
if (nivelOcupadoCM > ALTURA_BOTE) nivelOcupadoCM = ALTURA_BOTE;
float porcentajeOcupado = (nivelOcupadoCM / ALTURA_BOTE) * 100.0;
String estado = determinarEstado(distanciaSensor);
Serial.println("\n📋 DATOS:");
Serial.println(" 📏 Distancia: " + String(distanciaSensor, 1) + " cm");
Serial.println(" 📊 Nivel: " + String(nivelOcupadoCM, 1) + " cm");
Serial.println(" 📈 Ocupado: " + String(porcentajeOcupado, 1) + "%");
Serial.println(" 🚦 Estado: " + estado);
mostrarEstadoLED(estado);
// Enviar datos
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\n📤 Enviando datos...");
if (enviarDatos(nivelOcupadoCM, porcentajeOcupado, estado)) {
Serial.println("✅ ¡Datos enviados exitosamente!");
parpadearLED(LED_VERDE, 2);
} else {
Serial.println("❌ Error al enviar");
parpadearLED(LED_ROJO, 2);
}
} else {
Serial.println("❌ WiFi desconectado");
}
Serial.println("\n⏳ Próxima lectura en 10s\n");
delay(10000);
}
// ════════════════════════════════════════════════════════
// FUNCIONES
// ════════════════════════════════════════════════════════
void obtenerID() {
uint8_t mac[6];
WiFi.macAddress(mac);
char macStr[18];
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
dispositivoID = String(macStr);
Serial.println("🔑 ID: " + dispositivoID);
}
void conectarWiFi() {
Serial.println("🌐 Conectando WiFi...");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
int intentos = 0;
while (WiFi.status() != WL_CONNECTED && intentos < 20) {
delay(500);
Serial.print(".");
intentos++;
}
Serial.println();
if (WiFi.status() == WL_CONNECTED) {
Serial.println("✅ WiFi conectado");
Serial.println(" IP: " + WiFi.localIP().toString());
} else {
Serial.println("❌ Error WiFi");
}
}
float medirDistancia() {
long suma = 0;
int validas = 0;
for (int i = 0; i < 5; i++) {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH, 30000);
if (duration > 0) {
suma += duration;
validas++;
}
delay(30);
}
if (validas > 0) {
float distancia = (suma / (float)validas) * 0.034 / 2.0;
if (distancia > ALTURA_BOTE) return ALTURA_BOTE;
if (distancia < 2) return 2;
return distancia;
}
return -1.0;
}
String determinarEstado(float distancia) {
if (distancia < UMBRAL_LLENO) return "LLENO";
if (distancia < UMBRAL_MEDIO) return "MEDIO";
return "VACIO";
}
// ════════════════════════════════════════════════════════
// ENVÍO SIMPLIFICADO PARA WOKWI
// ════════════════════════════════════════════════════════
bool enviarDatos(float nivel, float ocupado, String estado) {
HTTPClient http;
// Construir URL
String url = String(googleScriptURL);
url += "?dispositivo=" + dispositivoID;
url += "&nivel=" + String(nivel, 2);
url += "&ocupado=" + String(ocupado, 2);
url += "&estado=" + estado;
// Codificar los dos puntos de la MAC
url.replace(":", "%3A");
Serial.println(" URL: " + url);
// Configurar HTTP
http.begin(url);
http.setTimeout(15000);
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
// Enviar petición
int httpCode = http.GET();
String respuesta = http.getString();
Serial.println(" HTTP: " + String(httpCode));
if (respuesta.length() > 0 && respuesta.length() < 200) {
Serial.println(" Respuesta: " + respuesta);
}
http.end();
// Considerar éxito si:
// - Código 200 (OK)
// - Código 302 (Redirección de Google)
// - Respuesta contiene "success"
if (httpCode == 200 || httpCode == 302) {
return true;
}
if (respuesta.indexOf("success") >= 0) {
return true;
}
return false;
}
// ════════════════════════════════════════════════════════
// LEDs
// ════════════════════════════════════════════════════════
void mostrarEstadoLED(String estado) {
digitalWrite(LED_VERDE, LOW);
digitalWrite(LED_AMARILLO, LOW);
digitalWrite(LED_ROJO, LOW);
if (estado == "VACIO") {
digitalWrite(LED_VERDE, HIGH);
} else if (estado == "MEDIO") {
digitalWrite(LED_AMARILLO, HIGH);
} else {
digitalWrite(LED_ROJO, HIGH);
}
}
void parpadearLED(int pin, int veces) {
for (int i = 0; i < veces; i++) {
digitalWrite(pin, HIGH);
delay(150);
digitalWrite(pin, LOW);
delay(150);
}
}