#include <LiquidCrystal_I2C.h>
#define I2C_ADDR 0x27 // Dirección típica del módulo I2C del LCD
#define LCD_COLUMNS 16
#define LCD_ROWS 2
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_ROWS);
// Pines (ajústalos si conectas a otros)
const int pinServo = 9; // D9: señal del servo (PWM)
const int pinLed = 8; // D8: LED
const int pinBtn = 7; // D7: botón (INPUT_PULLUP)
const int minPulseWidth = 500; // µs, servo 0°
const int maxPulseWidth = 2400; // µs, servo 180°
bool puertaAbierta = false;
void setup() {
Serial.begin(115200);
pinMode(pinServo, OUTPUT);
pinMode(pinLed, OUTPUT);
pinMode(pinBtn, INPUT_PULLUP); // botón a GND
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Puerta cerrada");
// Arrancamos con puerta cerrada (servo en 0° y LED apagado)
moverServo(0);
digitalWrite(pinLed, LOW);
}
void loop() {
// Botón activo cuando se pulsa (LOW por INPUT_PULLUP)
if (digitalRead(pinBtn) == LOW) {
// Pequeño anti-rebote
delay(50);
if (digitalRead(pinBtn) == LOW) {
puertaAbierta = !puertaAbierta; // alternar estado
if (puertaAbierta) {
moverServo(90); // ángulo "abierto"
digitalWrite(pinLed, HIGH);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Ta abierta");
} else {
moverServo(0); // ángulo "cerrado"
digitalWrite(pinLed, LOW);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Ta cerrada");
}
// esperar a que sueltes el botón (para no leer muchas veces)
while (digitalRead(pinBtn) == LOW) {
delay(10);
}
}
}
}
// PWM manual para el servo (basado en ejemplo de Wokwi STM32)
void moverServo(int angulo) {
int pulseWidth = map(angulo, 0, 180, minPulseWidth, maxPulseWidth);
// Generar unos cuantos pulsos para que el servo se posicione
for (int i = 0; i < 50; i++) { // ~1 segundo (50 * 20 ms)
digitalWrite(pinServo, HIGH);
delayMicroseconds(pulseWidth);
digitalWrite(pinServo, LOW);
delay(20 - pulseWidth / 1000); // periodo total ~20 ms
}
}