SmartLock
1. DESCRIPCIÓN GENERAL
Para nuestro proyecto final de la asignatura, hemos decidido crear una alarma con cerradura inteligente. Habrá una alarma, la cual mediante un sensor de movimiento detectará si alguien ha entrado en la sala, y comenzará a pitar si es así. Dicha alarma se podrá desactivar mediante un chip RFID conectado a un teclado 4×4. Este último sistema, una vez pasado el chip, e introducido la contraseña correcta se abrirá una puerta y la alarma se desactivará automáticamente. Son dos sistemas independientes, unidos mediante dos placas ESP32 mediante ESP-NOW.
2. IMPLEMENTACIÓN
Para dicha implementación, hemos conectado el sistema de alarma con sensor de movimiento con el sistema de desactivación de alarma + puerta mediante dos ESP32.
2.1 Sistema de alarma con sensor de movimiento.
En cuanto al sistema de alarma, está formado por los siguientes materiales:
- 1 Protoboard
- Cables
- Sensor de humedad y temperatura
- Sensor ultrasónico de distancia
- Zumbador Buzzer
- Botón
- Pantalla TFT
- ESP32

Ilustración 1.- Sistema de alarma por fuera

Ilustración 2.- Sistema de alarma por dentro
Como se puede apreciar en la imagen (Ilustración 1.- Sistema de alarma por fuera), mediante una pantalla TFT, conectada al sensor de humedad y temperatura, mostrará la temperatura y humedad de la sala por defecto, cambiando cada 7 segundos, mostrando también, el estado de la alarma.
En el caso de conectar o desconectar la alarma mediante el otro sistema, aparecerá un mensaje de “Alarma activada” o “Alarma desactivada” respectivamente. Una vez el sensor ultrasónico de distancia detecta un obstáculo a menos de 15 centímetros de distancia, en el caso de estar la alarma en estado: activada, comenzará a sonar mediante el zumbador buzzer y la pantalla TFT mostrará el mensaje: “¡INTRUSO!
Si no detecta ningún obstáculo, en caso de estar la alarma en estado: activada, mostrará el mensaje: “VIGILANDO…” hasta que encuentre un obstáculo y mostrará los mensajes mencionados anteriormente.
Por último, cuando se desactive la alarma, se mostrará el mensaje: “ALARMA DESACTIVADA”.
Como se puede apreciar en la imagen (Ilustración 2.- Sistema de alarma por dentro), y se ha mencionado en los materiales utilizados, hay un botón, cuyo principal objetivo es poder activar o desactivar la alarma manualmente desde dentro de la sala, en caso de haber un error en la conexión con el otro sistema.
2.2 Sistema de desactivación de alarma mediante sistema RFID, servomotor y teclado matricial 4×4
En este sistema, se han utilizado los siguientes materiales:
- 2 protoboards
- LED
- Teclado Matricial 4×4
- SENSOR RFID (MODELO RC522)
- Servomotor
- Condensador
- Cables
- ESP32

Ilustración 3.- Sistema de desactivación de alarma por fuera

Ilustración 4.- Sistema de desactivación de alarma por dentro
Para nuestro proyecto, decidimos hacer dos sistemas por separado, y unirlo mediante dos placas ESP32, con ESP-NOW. Esto lo que hace es unirlos mediante una red interna utilizando una de las placas como emisor (Sistema de desactivación) y una de receptor (Sistema de activación). Esta conexión se realiza mediante la dirección física (MAC) de los dispositivos, sin necesidad de una red WIFI externa.
Para el sistema de desactivación de alarma, como se puede apreciar en la imagen (Ilustración 3.- Sistema de desactivación de alarma por fuera), hemos decidido utilizar un sensor RFID, el cual al pasar la tarjeta correspondiente, activará el teclado matricial 4×4.
El teclado matricial 4×4 consta de 3 principales funcionalidades:
- Escribir bien la contraseña à Cuando el usuario escribe bien la contraseña (2222), le deberá dar al botón enviar (esquina inferior derecha), lo cual enviará una señal al servomotor, que abrirá la puerta, y mediante la conexión con el ESP-NOW, desactivará la alarma.
- Escribir mal la contraseña à Cuando el usuario escribe mal una contraseña, al dar al botón de enviar, la luz LED colocada en la parte superior de la puerta, parpadeará repetidamente, indicando que la contraseña introducida es errónea. La puerta no se abrirá, y, por lo tanto, la alarma se mantendrá activa.
- Borrado de contraseña à Si el usuario, tras pasar el chip RFID, se da cuenta que se ha equivocado de contraseña, antes de enviarla, tiene la opción de borrado de contraseña. Tras escribir algún número erróneo, al pulsar sobre la tecla inferior izquierda de teclado, la contraseña se borrará por completo, pudiéndola escribir de nuevo, sin tener que pasar el chip RFID de vuelta.
Cabe destacar que el teclado matricial está también conectado con la luz LED superior de la puerta, por lo que, al pulsar una tecla, la luz LED parpadeará.
En el caso de pasar un CHIP que no es el correcto por el sensor RFID, la luz parpadeará repetidamente, como hace al introducir una contraseña equivocada.
3. PASOS DADOS
Para poder empezar con nuestro proyecto, lo primero de todo era buscar una idea que nos gustase a todos los integrantes del grupo, y, que a la par, viésemos interesante para mostrarla al resto de la clase. En un principio queríamos hacer que dos sistemas se conectasen entre sí mediante las ESP-32 (al igual que en nuestro proyecto), para poder comunicarse sin necesidad de WIFI o ninguna fuente de energía externa. Esta idea vino debido al apagón nacional que sufrimos recientemente.
Tras comentarlo con el profesor, vimos que no era algo visual para presentar como proyecto, ya que era mucho más software que hardware. Como nuestra idea era utilizar los ESP-32 que conectasen entre sí, decidimos hacer un sistema grande, que estuviese dividido en dos sistemas pequeños, llegando así a nuestro proyecto final, el sistema SmartLock, de activación y desactivación de alarma.
Para realizar el sistema de activación y desactivación de alarma, decidimos dividir el proyecto en 2, realizarlo por separado, y finalmente unir ambas partes, añadiendo por último la lógica del ESP-NOW, para culminar el proyecto, los tres juntos.
4. REPARTO DE TAREAS
En cuanto al reparto de tareas, no fue un problema para nosotros, ya que todos los miembros del grupo estuvimos de acuerdo desde un principio en que quiso hacer cada uno.
- Ángel Molinero Caja: Ideación y planteamiento del proyecto, lógica y conexiones del sistema de alarma, conexión final mediante ESP-32.
- Jorge Castellano Bajo: Ideación y planteamiento del proyecto, memoria ejecutiva, montaje de vídeos y elementos multimedia, conexión final mediante ESP-32.
- Pedro González Martín: Ideación y planteamiento del proyecto, lógica y conexiones del sistema de desactivación de alarma, conexión final mediante ESP-32.
Como se puede apreciar en el vídeo de presentación, todos los integrantes participamos en él.
5. MATERIAL UTILIZADO Y COSTES
A continuación, podemos apreciar todos los materiales utilizados, escribiendo únicamente los costes de los materiales que hemos tenido que comprar, sin tener en cuenta los otorgados por la universidad.

6. PROBLEMAS Y SOLUCIONES ENCONTRADAS
- MUESTRA DE DATOS EN LA PANTALLA TFT: Al cambiar cada 7 segundos lo que aparece en la pantalla TFT, tuvimos que agregar un sistema de refresco, que pusiese la pantalla TFT completamente azul durante un corto periodo de tiempo, para que así no se solapase el texto de muestra de temperatura y humedad, con el texto del estado de la alarma.
- Inestabilidad por consumo de energía : Cuando comenzamos a hacer pruebas, nos dimos cuenta que un montón de elementos no funcionaban correctamente cuando tocaban, tras muchos cambios y pruebas, nos dimos cuenta que al conectar los sistemas a nuestro portátil, no les llegaba la suficiente potencia, por lo que teníamos que conectarlo a un enchufe a tierra con más potencia.
- Conflicto de pines y cableado e inestabilidad de conexión: Muchas veces, debido al transporte de los materiales, una vez ya estaba montada parte del proyecto, tuvimos que comprobar de nuevo que todas las conexiones estuviesen perfectamente enganchadas, ya que en muchas ocasiones aparecían cables sueltos. A parte, uno de los teclados empezó a dar fallos, por lo que tuvimos que cambiarlo a mitad de la realización del proyecto.
- Conexión ESP-NOW: Al ser las placas ESP-32 algo totalmente nuevo para nosotros, tuvimos que informarnos acerca de su uso. Esto lo hicimos mediante la lectura de varios foros y visualización de vídeos explicativos.
7. CÓDIGO
Código Alarma
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <SPI.h>
#include <DHT.h>
// pantalla TFT-ST7789
#define TFT_CS 10
#define TFT_DC 9
#define TFT_RST 8
// sensor temp y humedad
#define DHTPIN 2
#define DHTTYPE DHT11
#define BUZZER 3
// sensor ultrasonico
#define TRIG_PIN 6
#define ECHO_PIN 7
#define BOTON_PIN A0
#define PIN_REMOTO_ESP32 A1
// Inicialización de objetos
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
DHT dht(DHTPIN, DHTTYPE);
// variables estado alarma
bool alarmaActiva = false;
bool intrusoDetectado = false;
bool mostrarSensor = true; // controla que pantalla se ve
unsigned long ultimoCambio = 0; // temporizador cambio de pantalla
const unsigned long intervaloCambio = 7000; // cambiar pantalla cada 7seg
// variables para evitar lecturas falsas
bool alarmaCambioPendiente = false; // botón físico
bool senalRemotaPendiente = false; // señal del ESP32
// funcion para escribir texto centrado
void mostrarTextoCentrado(const char* texto, int y, int size, uint16_t color) {
int16_t x1, y1;
uint16_t w, h;
tft.setTextSize(size);
tft.getTextBounds(texto, 0, 0, &x1, &y1, &w, &h);
int16_t x = (tft.width() – w) / 2 – x1;
tft.setCursor(x, y);
tft.setTextColor(color, ST77XX_BLUE);
tft.print(texto);
}
// funcion para leer la distancia del sensor ultrasónico
long leerDistanciaCm() {
digitalWrite(TRIG_PIN, LOW); delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duracion = pulseIn(ECHO_PIN, HIGH, 30000);
if (duracion == 0) return 999;
return duracion * 0.034 / 2;
}
// funcion para mostrar datos meteorologicos
void mostrarPantallaSensor() {
float temp = dht.readTemperature();
float hum = dht.readHumidity();
tft.fillScreen(ST77XX_BLUE);
if (isnan(temp) || isnan(hum)) {
mostrarTextoCentrado(«Error sensor», 150, 3, ST77XX_RED);
return;
}
mostrarTextoCentrado(«Panel de Control», 10, 2, ST77XX_WHITE);
mostrarTextoCentrado(«Sistema Alarma», 35, 2, ST77XX_WHITE);
mostrarTextoCentrado(«Temp / Humedad», 90, 2, ST77XX_WHITE);
mostrarTextoCentrado((String(temp, 1) + » C»).c_str(), 140, 3, ST77XX_CYAN);
mostrarTextoCentrado((String(hum, 1) + » %»).c_str(), 190, 3, ST77XX_GREEN);
}
// funcion para mostrar estado de alarma
void mostrarPantallaAlarma() {
tft.fillScreen(ST77XX_BLUE);
mostrarTextoCentrado(«Panel de Control», 10, 2, ST77XX_WHITE);
mostrarTextoCentrado(«Sistema Alarma», 35, 2, ST77XX_WHITE);
if (alarmaActiva) {
mostrarTextoCentrado(«ALARMA», 100, 4, ST77XX_RED);
mostrarTextoCentrado(«ACTIVADA», 160, 3, ST77XX_RED);
if (intrusoDetectado) mostrarTextoCentrado(«¡INTRUSO!», 210, 3, ST77XX_RED);
else mostrarTextoCentrado(«VIGILANDO…», 210, 3, ST77XX_YELLOW);
} else {
mostrarTextoCentrado(«ALARMA», 100, 4, ST77XX_GREEN);
mostrarTextoCentrado(«DESACTIVADA», 160, 3, ST77XX_GREEN);
}
}
void actualizarPantalla() {
if (mostrarSensor) mostrarPantallaSensor();
else mostrarPantallaAlarma();
}
void alternarAlarma() {
alarmaActiva = !alarmaActiva;
if (alarmaActiva) {
tone(BUZZER, 1000, 200);
} else {
noTone(BUZZER);
intrusoDetectado = false;
}
mostrarSensor = false;
actualizarPantalla(); // muestra el estado de la alarma
ultimoCambio = millis(); // guarda el tiempo trascurrido
}
// revisar señal del boton
void revisarBoton() {
if (digitalRead(BOTON_PIN) == LOW) { // cuando se pulsa la señal es low
if (!alarmaCambioPendiente) {
alternarAlarma();
alarmaCambioPendiente = true; // para evitar varios cambios de estado en una pulsacion
delay(50);
}
} else {
alarmaCambioPendiente = false;
}
}
// revisa señal del ESP32
void revisarSenalRemota() {
if (digitalRead(PIN_REMOTO_ESP32) == HIGH) {
if (!senalRemotaPendiente) {
alternarAlarma();
senalRemotaPendiente = true;
}
} else {
senalRemotaPendiente = false;
}
}
void setup() {
dht.begin();
pinMode(BUZZER, OUTPUT);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(BOTON_PIN, INPUT_PULLUP);
pinMode(PIN_REMOTO_ESP32, INPUT);
tft.init(240, 320, SPI_MODE0);
tft.setRotation(1);
tft.fillScreen(ST77XX_BLUE);
actualizarPantalla();
}
void loop() {
revisarBoton();
revisarSenalRemota();
if (alarmaActiva) {
long distancia = leerDistanciaCm();
// si el objeto esta a menos de 15cm se activa la alarma
if (distancia > 0 && distancia < 15) {
if (!intrusoDetectado) {
intrusoDetectado = true;
if (mostrarSensor) {
mostrarSensor = false;
ultimoCambio = millis();
}
mostrarPantallaAlarma();
}
tone(BUZZER, 3000);
} else {
if (intrusoDetectado) {
intrusoDetectado = false;
noTone(BUZZER);
if (!mostrarSensor) mostrarPantallaAlarma();
}
}
} else {
noTone(BUZZER);
}
// rotación datos pantalla
if (millis() – ultimoCambio > intervaloCambio) {
mostrarSensor = !mostrarSensor;
actualizarPantalla();
ultimoCambio = millis();
}
delay(50);
}
Código ESP32 Receptor
#include <esp_now.h>
#include <WiFi.h>
#define PIN_SALIDA_A_ARDUINO 15
typedef struct struct_mensaje {
bool puertaAbierta;
} struct_mensaje;
struct_mensaje mensajeRecibido;
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
memcpy(&mensajeRecibido, incomingData, sizeof(mensajeRecibido));
if (mensajeRecibido.puertaAbierta) {
digitalWrite(PIN_SALIDA_A_ARDUINO, HIGH);
Serial.println(«PUERTA ABIERTA»);
} else {
digitalWrite(PIN_SALIDA_A_ARDUINO, LOW);
Serial.println(«PUERTA CERRADA»);
}
}
void setup() {
Serial.begin(115200);
pinMode(PIN_SALIDA_A_ARDUINO, OUTPUT);
digitalWrite(PIN_SALIDA_A_ARDUINO, LOW);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println(«Error ESP-NOW»);
return;
}
esp_now_register_recv_cb((esp_now_recv_cb_t)OnDataRecv);
}
void loop() {
}
Código Puerta, Cerradura y ESP32 Emisor
#include <SPI.h>
#include <MFRC522.h>
#include <Keypad.h>
#include <ESP32Servo.h>
//esp-now
#include <esp_now.h>
#include <WiFi.h>
//RFID
#define SS_PIN 5
#define RST_PIN 22
MFRC522 rfid(SS_PIN, RST_PIN);
String UID_MAESTRO = «60 E8 BD 4F»;
//SERVOMOTOR
Servo miServo;
#define SERVO_PIN 4
int posCerrado = 90;
int posAbierto = 0;
//LED
#define LED_PIN 2
//TECLADO
const byte FILAS = 4;
const byte COLUMNAS = 4;
char keys[FILAS][COLUMNAS] = {
{‘1′,’2′,’3′,’A’},
{‘4′,’5′,’6′,’B’},
{‘7′,’8′,’9′,’C’},
{‘*’,’0′,’#’,’D’}
};
byte pinesFilas[FILAS] = {33, 32, 25, 26};
byte pinesColumnas[COLUMNAS] = {27, 14, 12, 13};
Keypad teclado = Keypad(makeKeymap(keys), pinesFilas, pinesColumnas, FILAS, COLUMNAS);
//SISTEMA
String claveSecreta = «2222»;
String inputPIN = «»;
bool esperandoPIN = false;
unsigned long tiempoInicioPIN = 0;
//ESP_NOW
uint8_t mac_destino[] = {0x88, 0x57, 0x21, 0xB1,0xB8,0x74};
typedef struct struct_mensaje {
bool puertaAbierta; // open/close
}struct_mensaje;
struct_mensaje mensaje;
esp_now_peer_info_t peerInfo;
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print(«\r\nEstado del envio: «);
Serial.println(status == ESP_NOW_SEND_SUCCESS ? «Entregado Exitosamente» : «Fallo en envio»);
}
void setup() {
Serial.begin(115200);
//logica esp-now
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println(«Error inicializando ESP-NOW»);
return;
}
esp_now_register_send_cb((esp_now_send_cb_t)OnDataSent);
memcpy(peerInfo.peer_addr, mac_destino, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK){
Serial.println(«Error al añadir el otro ESP32»);
return;
}
//iniciar RFID
SPI.begin();
rfid.PCD_Init();
//iniciar Servo
miServo.setPeriodHertz(50); // Frecuencia estándar servos
miServo.attach(SERVO_PIN, 500, 2400);
//iniciar LED
pinMode(LED_PIN, OUTPUT);
cerrarPuerta();
Serial.println(«Estado: CERRADO»);
Serial.println(«Acerque su tarjeta»);
}
void loop() {
//esperando tarjeta
if (!esperandoPIN) {
if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
String uidLeido = «»;
for (byte i = 0; i < rfid.uid.size; i++) {
uidLeido += String(rfid.uid.uidByte[i] < 0x10 ? » 0″ : » «);
uidLeido += String(rfid.uid.uidByte[i], HEX);
}
uidLeido.toUpperCase();
uidLeido.trim();
Serial.print(«Tarjeta detectada»);
// tarjeta coorecta
if (uidLeido == UID_MAESTRO) {
Serial.println(«TARJETA CORRECTA»);
Serial.println(«Ingrese PIN en el teclado y pulse ‘#'»);
//parpadeo led caso correcto
digitalWrite(LED_PIN, LOW); delay(100); digitalWrite(LED_PIN, HIGH);
//modo essperando PIN
esperandoPIN = true;
tiempoInicioPIN = millis();
inputPIN = «»;
} else {
Serial.println(«TARJETA NO AUTORIZADA»);
parpadeoError();
}
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
}
}
//ESPERANDO PIN
else {
char tecla = teclado.getKey();
if (tecla) {
// Parpadeo luz al pulsar una tecla
digitalWrite(LED_PIN, LOW); delay(50); digitalWrite(LED_PIN, HIGH);
if (tecla == ‘D’) {
Serial.println(«\nVerificando PIN…»);
if (inputPIN == claveSecreta) {
abrirPuerta();
} else {
Serial.println(«INCORRECTOO»);
parpadeoError();
cerrarPuerta();
}
}
else if (tecla == ‘*’) { //nos permite borrar
inputPIN = «»;
Serial.println(«PIN borrado, empiece de nuevo»);
}
else {
inputPIN += tecla;
Serial.print(«*»); // Muestra asteriscos en el monitor al escribir en le teclado
}
}
}
}
void cerrarPuerta() {
esperandoPIN = false;
inputPIN = «»;
miServo.write(posCerrado);
digitalWrite(LED_PIN, HIGH); // enciende el led cuando la puerta está cerrada
enviarSenal(false);
}
void abrirPuerta() {
Serial.println(«¡ACCESO CONCEDIDO!»);
Serial.println(«ABRIENDO PUERTA»);
miServo.write(posAbierto);
digitalWrite(LED_PIN, LOW); //apagado el led mientras puerta abierta
enviarSenal(true);
delay(5000);
Serial.println(«Cerrando puerta automáticamente…»);
cerrarPuerta();
}
void parpadeoError() { //3 parpadeos si se falla el pin
for(int i=0; i<3; i++){
digitalWrite(LED_PIN, LOW); delay(100);
digitalWrite(LED_PIN, HIGH); delay(100);
}
}
void enviarSenal(bool estaAbierto) {
mensaje.puertaAbierta = estaAbierto;
esp_err_t result = esp_now_send(mac_destino, (uint8_t *) &mensaje, sizeof(mensaje));
if (result == ESP_OK) {
Serial.print(«Enviado estado: «);
Serial.println(estaAbierto ? «TRUE (Abierto)» : «FALSE (Cerrado)»);
} else {
Serial.println(«Error enviando señal»);
}
}
8. CASOS DE USO
Mediante los casos de uso podremos ver las principales acciones que es capaz de realizar nuestro sistema. Casos de uso:
- Mostrar por pantalla TFT: El sistema cambiará cada 7 segundos el contenido mostrado en la pantalla TFT. El cambio será entre el estado de la alarma (activada/desactivada) y la temperatura y humedad de la sala.
- Activar / desactivar alarma mediante botón: El sistema de activación de alarma tiene un control manual, mediante un botón, para activar y desactivar la alarma desde dentro cuando sea necesario.
- Detectar intruso: Cuando el sensor ultrasónico de movimiento detecta un objeto a menos de 15 cm de distancia, mediante el buzzer introducido en el sistema, el sistema de alarma comenzará a emitir un pitido de alerta.
- Pasar chip RFID: Para poder comenzar a escribir en el teclado matricial, se deberá pasar la placa RFID correspondiente. Una vez pasada, se podrá comenzar a escribir en el teclado.
- Escribir contraseña: Tras pasar el chip RFID, se podrá comenzar a escribir en el teclado matricial
- Fallar contraseña: Al enviar una contraseña incorrecta, la luz LED de la parte superior de la puerta parpadeará, indicando el error.
- Borrar contraseña: Si ha habido una equivocación de escriturade contraseña, el sistema permite borrar la contraseña, pudiendo así escribirla de nuevo, sin necesidad de volver a pasar el chip.
- Acertar contraseña: El usuario escribirá la contraseña correctamente, abriéndose así la puerta mediante el servomotor y desactivando la alarma.
- Abrir puerta: Tras escribir correctamente la contraseña, la puerta se abrirá automáticamente mediante un servomotor.
- Cerrar puerta: Tras 5 segundos abierta, la puerta se cerrará automáticamente.
- Desactivar alarma mediante contraseña: Una vez escrita la contraseña y abierta la puerta, el sistema desactivará la alarma, pudiendo pasar por el sensor de movimiento sin que este emita ruido por el buzzer.
9. BIBLIOGRAFÍA
- Naylamp Mechatronics. (s.f.). Tutorial módulo Lector RFID RC522. https://naylampmechatronics.com/blog/22_tutorial-modulo-lector-rfid-rc522.html
- Llamas, L. (s.f.). Configuración Básica de ESP-NOW con ESP32. Luis Llamas. https://www.luisllamas.es/como-usar-esp-now-en-esp32/