// Código completo optimizado del sistema de seguridad Fabsafe con prioridad en parada de emergencia, reposo térmico y estructura modular // Full optimized code for Fabsafe safety system with emergency stop priority, thermal rest, and modular structure #include #include #include #include // Pines de hardware / Hardware Pins #define SDA_LCD 48 #define SCL_LCD 47 #define LCD_ADDRESS 0x27 #define BUZZER_PIN 2 #define BUTTON_PIN 5 #define RX_PIN 16 #define TX_PIN 15 #define LED_VERDE 19 #define LED_AMARILLO 20 #define LED_ROJO 21 #define RELAY_PIN 17 LiquidCrystal_I2C lcd(LCD_ADDRESS, 16, 2); HardwareSerial fingerSerial(1); Adafruit_Fingerprint finger(&fingerSerial); // Variables de estado / State Variables unsigned long tiempoInicioAcceso = 0; unsigned long ultimoCheck = 0; bool accesoActivo = false; bool enReposo = false; bool bloqueado = false; int intentosFallidos = 0; int intentosLectura = 0; const unsigned long tiempoAcceso = 10UL * 60 * 1000; // 10 minutos / minutes const unsigned long intervaloLectura = 100; // 100ms para lectura de emergencia unsigned long tiempoBloqueoInicio = 0; unsigned long tiempoAnteriorLCD = 0; void setup() { Serial.begin(115200); inicializarHardware(); mostrarLCDScroll("Fabsafe - Safety first, always. Keep your hands safe."); iniciarSensor(); } void loop() { unsigned long ahora = millis(); if (digitalRead(BUTTON_PIN) == HIGH && !bloqueado) { activarBloqueoSeguridad("Emergencia!"); return; } if (bloqueado) { if (ahora - tiempoBloqueoInicio >= 30000) { desbloquearSistema(); } return; } if (enReposo) { lcd.noBacklight(); mostrarLCD("Modo reposo", "Pulsa EMG para salir"); return; } if (accesoActivo) { manejarAccesoActivo(); return; } if (intentosLectura >= 5) { finger.LEDcontrol(false); enReposo = true; intentosLectura = 0; return; } if (ahora - ultimoCheck >= intervaloLectura) { ultimoCheck = ahora; leerHuellaProceso(); } } void inicializarHardware() { pinMode(BUZZER_PIN, OUTPUT); pinMode(BUTTON_PIN, INPUT); pinMode(LED_VERDE, OUTPUT); pinMode(LED_AMARILLO, OUTPUT); pinMode(LED_ROJO, OUTPUT); pinMode(RELAY_PIN, OUTPUT); digitalWrite(LED_VERDE, LOW); digitalWrite(LED_AMARILLO, HIGH); digitalWrite(LED_ROJO, LOW); digitalWrite(RELAY_PIN, LOW); Wire.begin(SDA_LCD, SCL_LCD); lcd.init(); lcd.backlight(); tone(BUZZER_PIN, 600, 300); delay(150); tone(BUZZER_PIN, 800, 300); delay(300); } void iniciarSensor() { fingerSerial.begin(57600, SERIAL_8N1, RX_PIN, TX_PIN); finger.begin(57600); for (int i = 0; i < 10; i++) { if (finger.verifyPassword()) { finger.LEDcontrol(false); mostrarLCD("Listo para usar", ""); delay(2000); return; } delay(500); } mostrarLCD("ERROR sensor", "Apagar sistema!"); tone(BUZZER_PIN, 300, 500); while (true); } void leerHuellaProceso() { mostrarLCD("Intento lectura", "Intento " + String(intentosLectura + 1)); delay(4000); tone(BUZZER_PIN, 900, 100); finger.LEDcontrol(true); delay(1000); int r = finger.getImage(); if (r == FINGERPRINT_OK && finger.image2Tz() == FINGERPRINT_OK && finger.fingerSearch() == FINGERPRINT_OK) { accesoConcedido(finger.fingerID); } else if (r == FINGERPRINT_OK) { intentosFallidos++; mostrarLCD("Huella incorrecta", "Intento " + String(intentosFallidos)); tone(BUZZER_PIN, 400, 400); delay(1500); if (intentosFallidos >= 3) { activarBloqueoSeguridad("3 Fallos!"); } } finger.LEDcontrol(false); intentosLectura++; } void accesoConcedido(int id) { mostrarLCD("Huella OK", "ID: " + String(id)); tone(BUZZER_PIN, 1000, 300); digitalWrite(LED_VERDE, HIGH); digitalWrite(LED_AMARILLO, LOW); digitalWrite(RELAY_PIN, HIGH); accesoActivo = true; tiempoInicioAcceso = millis(); intentosFallidos = 0; intentosLectura = 0; delay(1000); } void manejarAccesoActivo() { unsigned long ahora = millis(); unsigned long restante = tiempoAcceso - (ahora - tiempoInicioAcceso); if (restante <= 0) { desactivarAcceso(); return; } if (restante <= 10000 && ahora % 1000 < 200) { tone(BUZZER_PIN, 1000, 100); } if (ahora - tiempoAnteriorLCD > 1000) { tiempoAnteriorLCD = ahora; mostrarLCD("Maquina activa", "Tiempo: " + String(restante / 1000) + "s"); } } void desactivarAcceso() { accesoActivo = false; digitalWrite(RELAY_PIN, LOW); digitalWrite(LED_VERDE, LOW); digitalWrite(LED_AMARILLO, HIGH); mostrarLCD("Tiempo finalizado", "Reingrese huella"); delay(3000); } void activarBloqueoSeguridad(const String& motivo) { digitalWrite(RELAY_PIN, LOW); // Apagar relay primero / Turn off relay first mostrarLCD(motivo, "BLOQUEADO"); for (int i = 0; i < 5; i++) { tone(BUZZER_PIN, 500, 300); delay(400); } digitalWrite(LED_VERDE, LOW); digitalWrite(LED_ROJO, HIGH); digitalWrite(LED_AMARILLO, HIGH); finger.LEDcontrol(false); accesoActivo = false; bloqueado = true; tiempoBloqueoInicio = millis(); } void desbloquearSistema() { bloqueado = false; mostrarLCD("Listo para usar", "..."); intentosFallidos = 0; intentosLectura = 0; enReposo = false; accesoActivo = false; digitalWrite(RELAY_PIN, LOW); digitalWrite(LED_VERDE, LOW); digitalWrite(LED_ROJO, LOW); digitalWrite(LED_AMARILLO, HIGH); finger.LEDcontrol(false); lcd.backlight(); } void mostrarLCD(const String& l1, const String& l2) { lcd.clear(); lcd.setCursor(0, 0); lcd.print(l1); lcd.setCursor(0, 1); lcd.print(l2); } void mostrarLCDScroll(const String& msg) { lcd.clear(); for (int i = 0; i < msg.length(); i++) { lcd.clear(); lcd.setCursor(0, 0); lcd.print(msg.substring(i, i + 16)); delay(300); } }