El sistema que presentamos es una solución completa de control de acceso basada en tecnología de reconocimiento de huellas dactilares, implementada en una plataforma ESP32. Este proyecto combina hardware y software para crear un sistema de seguridad fiable y versátil que puede ser utilizado en hogares, oficinas, laboratorios o cualquier espacio que requiera un control de acceso seguro.
Componentes principales del sistema:
1. Reconocimiento biométrico: Utiliza un sensor de huellas dactilares para identificar a los usuarios autorizados de manera rápida y precisa.
2. Notificaciones remotas: Implementa comunicación con Telegram para enviar alertas y registros de acceso en tiempo real.
3. Control físico: Mediante un servomotor que puede activar mecanismos de apertura como cerraduras eléctricas o pestillos.
4. Interfaz de usuario: A través del puerto serie, permite gestionar usuarios, registrar nuevas huellas y configurar el sistema.
5. Registro de actividad: Captura y almacena la información de cada acceso con marca de tiempo precisa gracias a la sincronización NTP.
Este sistema proporciona una alternativa segura a los métodos tradicionales de control de acceso como llaves o tarjetas, que pueden ser perdidas, robadas o duplicadas. La autenticación biométrica garantiza que solo las personas registradas puedan obtener acceso, mientras que las notificaciones instantáneas mantienen informados a los administradores sobre la actividad del sistema.
El código está diseñado para ser flexible y fácilmente adaptable a diferentes necesidades y configuraciones de hardware, permitiendo expandir sus funcionalidades según los requerimientos específicos de cada implementación.
Tal vez pueda interesarte proyectos en arduino, pic, robótica, telecomunicaciones, suscribete en http://www.youtube.com/user/carlosvolt?sub_confirmation=1 mucho videos con código fuentes completos y diagramas
Componentes electrónicos
Un Esp32
Características del módulo ESP32-T
Conectividad
El módulo ESP32 dispone de todas las variantes del WiFi:
- 802.11 b/g/n/e/i/n
- Wi-Fi Direct (P2P), P2P Discovery, P2P Group Owner mode and P2P Power Management
Esta versión nueva incluye la conectividad mediante Bluethoot de bajo consumo
- Bluetooth v4.2 BR/EDR and BLE
- BLE Beacon
Además, puede comunicarse mediante los protocoles SPI, I2C, UART, MAC Ethernet, Host SD
Prestaciones del microcontrolador
La CPU está formado por un SoC modelo Tensilica LX6 con las siguientes características y memoria
- Doble núcleo de 32 bits con velocidad de 160MHz
- Memoria ROM de 448 kBytes
- Memoria SRAM de 520kBytes
Dispne de 48 Pines
- 18 ADC de 12 bits
- 2 DAC de 8 bits
- 10 pines sensores de contacto
- 16 PWM
- 20 Entradas/salidas digitales
Alimentación y modos de consumo
Para un correcto funcionamiento del ESP32 es necesario subministrar un voltaje de entre 2,8V y 3,6V. La energía que consume depende del modo de funcionamiento. Contiene un modo, el Ultra Low Power Solution (ULP), en que se continúan realizando tareas básicas (ADC, RTC…) en el modo Sleep.
Módulo fingerprint Open Smart
Descargar Manual –> R308-fingerprint-module-user-manual_English
Buzzer
Pines hembra
Pines macho
PCB
Descargar archivo gerber –> Esp32_fingerprint_PCB
Crear Bot en Telegram
En telegram buscamos BotFather
Escribimos /start y nos aparecerá algo similar a esto
Escribimos /newbot
Nos apareceré el nombre del bot, y inventamos un nombre para nuestro bot, debe tener el formato «usuario_bot»
Obtendremos un token que vamos a usar en el código fuente
Ahora buscaremos IDBot, y lo iniciamos
Escribimos /getid y nos entregará el user_id que debemos colocar en el código fuente
Código Fuente
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 |
#include <Arduino.h> #include <WiFi.h> #include <WiFiClientSecure.h> #include <UniversalTelegramBot.h> #include <ArduinoJson.h> #include <Adafruit_Fingerprint.h> #include <ESP32Servo.h> #include "time.h" // Configuración WiFi const char* redWifi = "Tu_red_wifi"; const char* contrasenaWifi = "Tu_clave_wifi"; // Configuración Telegram #define TOKEN_BOT "Tu_token" // Obtener de BotFather #define ID_CHAT "Tu_id_chat" // ID del chat o grupo donde enviar notificaciones // Configuración del sensor de huellas (usando hardware UART2) #define HUELLA_RX 16 // Conectar al TX del sensor #define HUELLA_TX 17 // Conectar al RX del sensor Adafruit_Fingerprint sensorHuella = Adafruit_Fingerprint(&Serial2); // Definición de pines #define PIN_BUZZER 23 #define PIN_SERVO 15 // Pin para el servo SG90 // Cliente seguro y bot de Telegram WiFiClientSecure cliente_seguro; UniversalTelegramBot bot(TOKEN_BOT, cliente_seguro); // Configuración del servo Servo servoPuerta; int posicionServoCerrado = 0; // Posición inicial (cerrado) int posicionServoAbierto = 90; // Posición abierta (90 grados) // Configuración NTP para obtener la hora const char* servidorNTP = "pool.ntp.org"; const long compensacionGMT_seg = -10800; // UTC-3 const int compensacionVerano_seg = 0; // Sin horario de verano // Estructura para almacenar los usuarios struct Usuario { uint8_t id; String nombre; }; // Array con los usuarios registrados (hasta 5) Usuario usuarios[] = { {1, "Usuario 1"}, {2, "Usuario 2"}, {3, "Usuario 3"}, {4, "Usuario 4"}, {5, "Usuario 5"} }; const int numUsuarios = 5; // Variables para el sistema de registro de huellas String comandoSerial = ""; boolean modoRegistro = false; int nuevoID = 0; void setup() { Serial.begin(115200); delay(1000); Serial.println("Iniciando sistema de huellas dactilares con notificación por Telegram y control de servo"); // Configurar pin del buzzer como salida pinMode(PIN_BUZZER, OUTPUT); digitalWrite(PIN_BUZZER, LOW); // Asegurar que el buzzer está apagado al inicio // Configurar servo ESP32PWM::allocateTimer(0); servoPuerta.setPeriodHertz(50); // Frecuencia estándar para servos servoPuerta.attach(PIN_SERVO, 500, 2400); // Valores min/max para SG90 // Mover el servo a la posición inicial servoPuerta.write(posicionServoCerrado); // Notificar inicio del sistema con un breve sonido del buzzer sonarBuzzer(100); // Beep corto de 100ms al iniciar delay(100); sonarBuzzer(100); // Inicializar sensor de huellas Serial2.begin(57600, SERIAL_8N1, HUELLA_RX, HUELLA_TX); if (!sensorHuella.verifyPassword()) { Serial.println("No se encontró el sensor de huellas dactilares"); while (1) { delay(1); } } Serial.println("Sensor de huellas dactilares encontrado!"); Serial.print("Capacidad del sensor: "); Serial.println(sensorHuella.capacity); // Conectar a WiFi WiFi.begin(redWifi, contrasenaWifi); Serial.print("Conectando a WiFi"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(); Serial.println("Conectado a WiFi"); Serial.print("Dirección IP: "); Serial.println(WiFi.localIP()); // Configurar certificados para Telegram (necesario desde 2023) cliente_seguro.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Configurar servidor NTP configTime(compensacionGMT_seg, compensacionVerano_seg, servidorNTP); // Notificar inicio del sistema String mensajeInicio = "Sistema de huellas iniciado!!!"; bot.sendMessage(ID_CHAT, mensajeInicio, "Markdown"); // Mostrar comandos disponibles Serial.println("\nComandos disponibles:"); Serial.println("- enroll ID : Registra una nueva huella con el ID especificado"); Serial.println("- list : Muestra los usuarios registrados"); Serial.println("- delete ID : Elimina la huella con el ID especificado"); Serial.println("- help : Muestra esta ayuda"); } void loop() { // Leer comandos seriales para registro de huellas if (Serial.available()) { char c = Serial.read(); if (c == '\n') { procesarComandoSerial(comandoSerial); comandoSerial = ""; } else { comandoSerial += c; } } // Si estamos en modo de registro, no verificamos huellas existentes if (modoRegistro) { if (nuevoID > 0) { int resultado = registrarHuella(nuevoID); if (resultado == 0) { // Registro exitoso sonarBuzzer(100); delay(100); sonarBuzzer(100); delay(100); sonarBuzzer(100); String mensaje = "✅ Nueva huella registrada\n"; mensaje += "👤 ID #" + String(nuevoID) + "\n"; mensaje += "🕒 " + obtenerHoraFormateada(); bot.sendMessage(ID_CHAT, mensaje, "Markdown"); } modoRegistro = false; nuevoID = 0; } return; } // Verificar si hay una huella en el sensor int idHuella = obtenerIDHuella(); if (idHuella != -1) { Serial.print("Huella detectada con ID #"); Serial.println(idHuella); servoPuerta.write(posicionServoAbierto); // Hacer sonar el buzzer al detectar una huella válida sonarBuzzer(200); // Beep de 200ms // Buscar el usuario correspondiente a la huella String nombreUsuario = "Usuario desconocido"; for (int i = 0; i < numUsuarios; i++) { if (usuarios[i].id == idHuella) { nombreUsuario = usuarios[i].nombre; break; } } // Obtener la hora actual String horaActual = obtenerHoraFormateada(); // Enviar notificación de Telegram String mensaje = "✅ Acceso autorizado\n"; mensaje += "👤 *" + nombreUsuario + "*\n"; mensaje += "🕒 " + horaActual; bot.sendMessage(ID_CHAT, mensaje, "Markdown"); Serial.println("Notificación enviada a Telegram: " + mensaje); // Abrir el mecanismo (mover el servo) Serial.println("Abriendo mecanismo..."); //servoPuerta.write(posicionServoAbierto); // Esperar 5 segundos delay(5000); // Cerrar el mecanismo (volver el servo a posición inicial) Serial.println("Cerrando mecanismo..."); servoPuerta.write(posicionServoCerrado); // Esperar un tiempo para evitar múltiples detecciones del mismo dedo delay(1000); } delay(50); // Pequeña pausa entre escaneos } // Función para hacer sonar el buzzer void sonarBuzzer(int duracion) { digitalWrite(PIN_BUZZER, HIGH); delay(duracion); digitalWrite(PIN_BUZZER, LOW); } // Función para procesar comandos del puerto serial void procesarComandoSerial(String comando) { comando.trim(); if (comando.startsWith("enroll ")) { // Comando formato: "enroll 6" para registrar huella con ID 6 nuevoID = comando.substring(7).toInt(); if (nuevoID > 0 && nuevoID <= 127) { // La mayoría de sensores soportan hasta 127 huellas modoRegistro = true; Serial.println("Iniciando registro de nueva huella con ID #" + String(nuevoID)); Serial.println("Siga las instrucciones..."); } else { Serial.println("ID inválido. Use un número entre 1 y 127."); } } else if (comando == "list") { // Listar usuarios registrados Serial.println("Usuarios registrados:"); for (int i = 0; i < numUsuarios; i++) { Serial.println("ID #" + String(usuarios[i].id) + ": " + usuarios[i].nombre); } // También podemos verificar cuáles IDs están ocupados en el sensor Serial.println("\nComprobando huellas almacenadas en el sensor..."); for (int i = 1; i <= 10; i++) { // Comprobar primeros 10 IDs (ajusta según necesidad) uint8_t p = sensorHuella.loadModel(i); if (p == FINGERPRINT_OK) { Serial.println("ID #" + String(i) + ": Huella encontrada"); } } } else if (comando == "delete") { Serial.println("Para eliminar una huella, use: delete ID"); Serial.println("Ejemplo: delete 5"); } else if (comando.startsWith("delete ")) { int id = comando.substring(7).toInt(); if (id > 0) { if (sensorHuella.deleteModel(id) == FINGERPRINT_OK) { Serial.println("Huella con ID #" + String(id) + " eliminada correctamente"); } else { Serial.println("Error al eliminar huella"); } } } else if (comando.startsWith("servo ")) { // Comando para probar el servo: "servo 45" para mover a 45 grados int pos = comando.substring(6).toInt(); if (pos >= 0 && pos <= 180) { Serial.println("Moviendo servo a posición: " + String(pos)); servoPuerta.write(pos); } else { Serial.println("Posición inválida. Use un valor entre 0 y 180."); } } else if (comando == "help") { Serial.println("Comandos disponibles:"); Serial.println("- enroll ID : Registra una nueva huella con el ID especificado"); Serial.println("- list : Muestra los usuarios registrados"); Serial.println("- delete ID : Elimina la huella con el ID especificado"); Serial.println("- servo POS : Mueve el servo a la posición especificada (0-180)"); Serial.println("- help : Muestra esta ayuda"); } else { Serial.println("Comando no reconocido. Escriba 'help' para ver los comandos disponibles."); } } // Función para obtener la ID de la huella detectada int obtenerIDHuella() { uint8_t p = sensorHuella.getImage(); if (p != FINGERPRINT_OK) return -1; p = sensorHuella.image2Tz(); if (p != FINGERPRINT_OK) return -1; p = sensorHuella.fingerFastSearch(); if (p != FINGERPRINT_OK) return -1; return sensorHuella.fingerID; } // Función para obtener la hora formateada String obtenerHoraFormateada() { struct tm timeinfo; if (!getLocalTime(&timeinfo)) { Serial.println("Error al obtener la hora"); return "Hora no disponible"; } char cadenaHora[30]; strftime(cadenaHora, sizeof(cadenaHora), "%d/%m/%Y %H:%M:%S", &timeinfo); return String(cadenaHora); } // Función para el registro de nuevas huellas int registrarHuella(uint8_t id) { int p = -1; Serial.println("Esperando dedo para registrar con ID #" + String(id)); while (p != FINGERPRINT_OK) { p = sensorHuella.getImage(); switch (p) { case FINGERPRINT_OK: Serial.println("Imagen tomada"); break; case FINGERPRINT_NOFINGER: Serial.print("."); delay(100); break; default: Serial.println("Error en la captura de imagen"); return p; } } p = sensorHuella.image2Tz(1); if (p != FINGERPRINT_OK) { Serial.println("Error al convertir la imagen"); return p; } Serial.println("Retire el dedo"); delay(2000); p = 0; while (p != FINGERPRINT_NOFINGER) { p = sensorHuella.getImage(); } Serial.println("Coloque el mismo dedo nuevamente"); p = -1; while (p != FINGERPRINT_OK) { p = sensorHuella.getImage(); delay(100); } p = sensorHuella.image2Tz(2); if (p != FINGERPRINT_OK) { Serial.println("Error al convertir la segunda imagen"); return p; } Serial.println("Creando modelo para ID #" + String(id)); p = sensorHuella.createModel(); if (p != FINGERPRINT_OK) { Serial.println("Error al crear el modelo"); return p; } p = sensorHuella.storeModel(id); if (p != FINGERPRINT_OK) { Serial.println("Error al guardar el modelo"); return p; } Serial.println("¡Huella guardada con éxito!"); return 0; } |
Descargar Librería –> Universal-Arduino-Telegram-Bot-master
Tal vez pueda interesarte proyectos en arduino, pic, robótica, telecomunicaciones, suscribete en http://www.youtube.com/user/carlosvolt?sub_confirmation=1 mucho videos con código fuentes completos y diagramas
VIDEO RECOMENDADO