Dispensador de mascotas programable con menú LCD
Vamos a transformar el proyecto del dispensador para que en vez de un relevador + motor uses un servomotor (por ejemplo, SG90 o MG996R). El servo es ideal porque puede mover una compuerta o palanca que deje caer la comida en el momento programado.
Materiales
- ESP32 DevKit v1
- LCD 16×2 con interfaz I2C
- 3 botones (Arriba, Abajo, OK)
- Servomotor (SG90 para cargas pequeñas, MG996R si necesitas más torque)
- Fuente de alimentación adecuada (el servo requiere corriente estable, mejor usar fuente externa de 5V)
- Opcional: RTC DS3231 para mantener la hora precisa
Conexiones
- LCD I2C: igual que antes (SDA → GPIO21, SCL → GPIO22).
- Botones: GPIO32, GPIO33, GPIO25 con
INPUT_PULLUP. - Servo:
- Señal: GPIO26
- VCC: 5V (fuente externa si es servo grande)
- GND: común con ESP32
Lógica
- El menú en la LCD permite programar horas de alimentación.
- A la hora programada, el ESP32 mueve el servo a un ángulo que abre la compuerta del dispensador, espera unos segundos y regresa a la posición inicial.
- Puedes ajustar el ángulo de apertura y cierre según tu mecanismo.
Código de ejemplo (Arduino IDE)
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h>
#include <RTClib.h> // Opcional si usas DS3231
LiquidCrystal_I2C lcd(0x27, 16, 2);
RTC_DS3231 rtc;
Servo servo;
const int BTN_UP = 32;
const int BTN_DOWN = 33;
const int BTN_OK = 25;
const int SERVO_PIN = 26;
struct FeedTime {
int hour;
int minute;
bool enabled;
bool ranToday;
};
FeedTime feed1 = {8, 0, true, false};
FeedTime feed2 = {18, 0, true, false};
int openAngle = 90; // ángulo de apertura
int closeAngle = 0; // ángulo de reposo
int dispenseSeconds = 3;
void setup() {
Wire.begin();
lcd.init();
lcd.backlight();
pinMode(BTN_UP, INPUT_PULLUP);
pinMode(BTN_DOWN, INPUT_PULLUP);
pinMode(BTN_OK, INPUT_PULLUP);
servo.attach(SERVO_PIN);
servo.write(closeAngle);
if (!rtc.begin()) {
lcd.setCursor(0,0); lcd.print("Sin RTC");
} else {
if (rtc.lostPower()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
}
}
void triggerServo() {
servo.write(openAngle);
delay(dispenseSeconds * 1000);
servo.write(closeAngle);
}
void loop() {
DateTime now = rtc.now();
int h = now.hour();
int m = now.minute();
// Mostrar hora
lcd.setCursor(0,0);
lcd.print("Hora ");
lcd.print(h); lcd.print(":"); lcd.print(m);
// Checar horarios
if (feed1.enabled && h == feed1.hour && m == feed1.minute && !feed1.ranToday) {
triggerServo();
feed1.ranToday = true;
}
if (feed2.enabled && h == feed2.hour && m == feed2.minute && !feed2.ranToday) {
triggerServo();
feed2.ranToday = true;
}
// Reset flags a medianoche
if (h == 0 && m == 0) {
feed1.ranToday = false;
feed2.ranToday = false;
}
delay(1000);
}
Diferencias clave respecto a la versión con relevador
| Con relevador + motor | Con servomotor |
|---|---|
| Activa un motor externo (más potencia) | Mueve directamente una compuerta/palanca |
| Requiere fuente separada para motor | Servo puede alimentarse con 5V estable |
| Control binario (ON/OFF) | Control preciso de ángulo (0–180°) |
| Ideal para dispensadores grandes | Ideal para dispensadores pequeños/medianos |
