Dispensador Automático de Agua con Monedas usando ESP32
Materiales Necesarios
-
1 × ESP32 (NodeMCU ESP32 o similar)
-
1 × Display LCD 16×2 con módulo I2C
-
2 × Botones pulsadores
-
1 × Sensor de monedas (lector de monedas de 5 unidades)
-
1 × Sensor de presencia (infrarrojo o ultrasonido)
-
1 × Bomba de agua DC 5-12V
-
1 × Relé para controlar la bomba de agua
-
1 × Depósito de agua
-
1 × Tubo para dispensar agua
-
1 × Recipiente para monedas
-
1 × Diodo LED (indicador de estado)
-
1 × Resistencia 220Ω para el LED
-
2 × Resistencias 10kΩ (opcional, para botones si no usa pull-up interno)
-
1 × Fuente de alimentación 12V para la bomba
-
1 × Regulador de voltaje 5V para el ESP32
-
Cables y protoboard
Construcción
1. Conexiones Eléctricas
LCD I2C:
-
SDA → GPIO 21 (ESP32)
-
SCL → GPIO 22 (ESP32)
-
VCC → 5V
-
GND → GND
Botones (con pull-up interno):
-
Botón 1L → GPIO 13
-
Botón 0.5L → GPIO 12
-
Ambos botones conectados también a GND
Sensor de Monedas:
-
Señal → GPIO 14
-
VCC → 5V
-
GND → GND
Sensor de Presencia:
-
Trig → GPIO 27 (si es ultrasonido)
-
Echo → GPIO 26 (si es ultrasonido)
-
VCC → 5V
-
GND → GND
-
(Si es IR, OUT → GPIO 27)
Bomba de Agua:
-
Control a través de relé
-
Relé IN → GPIO 33
-
VCC del relé → 5V
-
GND del relé → GND
LED Indicador:
-
Ánodo → GPIO 32 con resistencia 220Ω
-
Cátodo → GND
2. Montaje Mecánico
-
Instalar el depósito de agua en la parte superior
-
Colocar la bomba de agua cerca del depósito
-
Montar el tubo dispensador con el sensor de presencia
-
Instalar el lector de monedas en una ranura accesible
-
Fijar el display LCD en un lugar visible
-
Colocar los botones de selección de cantidad
Código Programa
#include <Wire.h> #include <LiquidCrystal_I2C.h> // Configuración del LCD LiquidCrystal_I2C lcd(0x27, 16, 2); // Dirección I2C 0x27, display 16x2 // Pines const int boton1L = 13; const int boton05L = 12; const int sensorMoneda = 14; const int sensorPresencia = 27; const int releBomba = 33; const int ledIndicador = 32; // Variables int credito = 0; bool recipientePresente = false; unsigned long tiempoDispensado = 0; bool dispensando = false; // Precios const int precio1L = 10; const int precio05L = 5; void setup() { Serial.begin(115200); // Inicializar LCD lcd.init(); lcd.backlight(); lcd.clear(); // Configurar pines pinMode(boton1L, INPUT_PULLUP); pinMode(boton05L, INPUT_PULLUP); pinMode(sensorMoneda, INPUT); pinMode(sensorPresencia, INPUT); pinMode(releBomba, OUTPUT); pinMode(ledIndicador, OUTPUT); digitalWrite(releBomba, LOW); // Asegurar que la bomba está apagada digitalWrite(ledIndicador, LOW); mostrarMensajeInicial(); } void loop() { // Leer sensor de presencia recipientePresente = digitalRead(sensorPresencia) == HIGH; // Detectar monedas if (digitalRead(sensorMoneda) == HIGH) { delay(50); // Debounce if (digitalRead(sensorMoneda) == HIGH) { credito += 5; lcd.clear(); lcd.setCursor(0, 0); lcd.print("Credito: "); lcd.print(credito); lcd.print(" unidades"); delay(1000); mostrarMenu(); } } // Verificar botones if (digitalRead(boton1L) == LOW && !dispensando) { dispensarAgua(1000, precio1L); // 1000 ml = 1L } if (digitalRead(boton05L) == LOW && !dispensando) { dispensarAgua(500, precio05L); // 500 ml = 0.5L } // Actualizar display si no está dispensando if (!dispensando && millis() % 5000 < 100) { mostrarMenu(); } // Controlar LED indicador digitalWrite(ledIndicador, recipientePresente); } void dispensarAgua(int cantidadML, int precio) { if (credito >= precio && recipientePresente) { credito -= precio; dispensando = true; lcd.clear(); lcd.setCursor(0, 0); lcd.print("Dispensando..."); lcd.setCursor(0, 1); lcd.print(cantidadML); lcd.print(" ml"); // Encender bomba digitalWrite(releBomba, HIGH); // Calcular tiempo de dispensado (ajustar según flujo de bomba) // Suponiendo 100 ml por segundo unsigned long tiempo = (cantidadML * 1000) / 100; tiempoDispensado = millis(); while (millis() - tiempoDispensado < tiempo) { // Verificar que el recipiente sigue presente if (digitalRead(sensorPresencia) == LOW) { break; // Detener si quitan el recipiente } delay(100); } // Apagar bomba digitalWrite(releBomba, LOW); lcd.clear(); lcd.setCursor(0, 0); lcd.print("Dispensado OK!"); lcd.setCursor(0, 1); lcd.print("Credito: "); lcd.print(credito); delay(2000); dispensando = false; mostrarMenu(); } else { lcd.clear(); if (!recipientePresente) { lcd.setCursor(0, 0); lcd.print("Coloque"); lcd.setCursor(0, 1); lcd.print("recipiente!"); } else { lcd.setCursor(0, 0); lcd.print("Credito"); lcd.setCursor(0, 1); lcd.print("insuficiente!"); } delay(2000); mostrarMenu(); } } void mostrarMenu() { lcd.clear(); lcd.setCursor(0, 0); lcd.print("1L:"); lcd.print(precio1L); lcd.print(" 0.5L:"); lcd.print(precio05L); lcd.setCursor(0, 1); lcd.print("Credito: "); lcd.print(credito); } void mostrarMensajeInicial() { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Dispensador"); lcd.setCursor(0, 1); lcd.print("de Agua"); delay(2000); mostrarMenu(); }
Ajustes y Calibración
-
Calibración del sensor de monedas: Ajustar la sensibilidad según las monedas de 5 unidades
-
Tiempo de dispensado: Ajustar el cálculo del tiempo según el flujo de tu bomba específica
-
Sensor de presencia: Calibrar la distancia de detección según la posición del recipiente
Funcionamiento
-
El usuario inserta monedas de 5 unidades
-
El crédito se acumula en el display
-
Selecciona la cantidad deseada (1L o 0.5L)
-
El sistema verifica que haya un recipiente colocado
-
Dispensa la cantidad seleccionada
-
Descuesta el monto correspondiente del crédito
Consideraciones de Seguridad
-
Implementar un timeout para devolver el crédito si no se usa
-
Incluir protección contra sobreflujo
-
Asegurar que la bomba se apaga automáticamente en caso de error
-
Usar materiales aptos para contacto con agua potable
Este proyecto proporciona una base completa para construir un dispensador automático de agua controlado por monedas usando ESP32.
