PROYECTO_04

ZKTeco

Control de Acceso Físico

Control de acceso para una escuela, con placa hecha en casa: quién entra lo decide el backend, no el lector.

TIPO
Hardware · Full Stack
ESTADO
EN PRODUCCIÓN
DIAGRAMAS
4
CAPTURAS
13
  • React
  • Vite
  • TailwindCSS
  • Java
  • Spring Boot
  • MySQL
  • Arduino / ESP32
  • C++
  • KiCad
  • Wiegand 26/34

01 Qué es

Control de acceso para una escuela, de punta a punta: una PCB propia con Arduino Nano que gobierna dos lectores Wiegand y dos chapas, un lector de tarjetas MIFARE ZKTeco PROID10BM en cada puerta, un backend en Spring Boot que decide quién entra y un panel web para dar de alta, dar de baja y bloquear alumnos, hospedado en el servidor de la propia escuela.

  • Placa pcb_control Rev A: 170 × 115 mm, 61 componentes THT, 42 redes, ERC y DRC en cero.
  • Dos lectores Wiegand 26/34 independientes, dos relés de puerta como contacto seco y dos botones de salida.
  • La placa no decide nada: lee la tarjeta, manda el ID por el puerto serie y abre solo cuando el backend le da la señal.
  • Backend en Spring Boot que valida si el alumno está activo o bloqueado, y panel web con alumnos, tarjetas, historial de accesos y estado.

02 La placa · Rev A

Diseñada en KiCad. Todo es de agujero pasante a propósito: nada de SMD, para que la placa entera se suelde con la misma técnica y el mismo cautín. Cuatro tornillos M3 en agujeros de 3.2 mm.

BloqueComponentesPara qué
CerebroArduino Nano v3 (A1)Lee los dos lectores por interrupción y maneja relés, botones, LED y buzzer
AlimentaciónPTC F1 1.1 A · Schottky SB340 D7 · buck MP1584 U1 · C1 100 µF · C2 10 µF12 V protegidos; 5 V para el Nano y los pull-ups
Entrada Wiegand ×2TVS P6KE6.8CA D1–D4 · C4–C7 1 nF · R3, R4, R7, R8 220 Ω · pull-ups R1, R2, R5, R6 2.2 kΩProtege el AVR y compra distancia de cable
Relés ×2SRD-12VDC-SL-C K1, K2 · BC337 Q1, Q2 · 1N4148 D5, D6 · snubber R17, R18 100 Ω + C10, C11 100 nF/250 VContacto seco COM/NC/NO hacia la chapa
Avisos del lectorULN2003A U2 · pull-ups R22–R25 4.7 kΩ sin poblarLED y buzzer de ambos lectores con un solo integrado
IndicadoresLED verde LED1 (PWR) · LED rojo LED2, LED3 (relé 1 y 2)Ninguno gasta un pin del Nano
BornerasMX126/DG126 paso 5.00 mm: J2, J3 7 vías · J4, J5 3 vías · J1, J6, J7 2 víasLectores, puertas, entrada 12 V y botones de salida

03 Cómo funciona

Alimentación

Los 12 V entran por J1, pasan por el PTC F1 (rearmable: al quitar la falla vuelve solo) y por el Schottky D7, que bloquea la polaridad invertida. Ese riel alimenta directo las bobinas de los relés, los dos lectores y la entrada del buck U1, que baja a 5 V para el Nano y los pull-ups: unos 40 mA en total.

La lectura Wiegand

Las líneas D0 y D1 del lector son colector abierto: en reposo ambas están en 5 V por los pull-ups de 2.2 kΩ. Para mandar un bit, el lector tira una a masa durante ~50 µs; pulso en D0 = bit 0, pulso en D1 = bit 1. Una tarjeta de 26 bits son 26 pulsos repartidos entre las dos líneas.

Cada línea recorre TVS → filtro de 1 nF → resistencia serie de 220 Ω → pin del Nano. Esa cadena es lo que compra la distancia: Wiegand no es diferencial y por eso es sensible al ruido.

La apertura y la salida

Cuando el backend autoriza, el Nano pone D6 en alto, R9 mete ~4.3 mA a la base de Q1, el transistor satura y conecta el negativo de la bobina a masa. R10 (10 kΩ) mantiene la base a masa mientras el Nano arranca: sin ella el pin flota y el relé podría dispararse solo al encender. D5 absorbe el pico inverso de la bobina.

J4 y J5 entregan COM/NC/NO como contacto seco: el relé es solo un interruptor y la corriente de la cerradura no pasa por la placa. El snubber RC (R17 + C10) puentea COM–NO para que el arco no pegue los contactos; se eligió RC y no diodo porque no tiene polaridad y funciona igual con carga DC o AC.

LEDs de la placa, LED y buzzer del lector

Tres LEDs y ninguno gasta un pin del Nano. LED1 (verde, PWR) cuelga del riel de 5 V: si enciende, el buck funciona. LED2 y LED3 (rojos) van del +12 V a la bobina del relé por R20 y R21: encienden justo cuando el transistor satura, así que indican el accionamiento real y no lo que el firmware cree. Si el LED de relé enciende y la puerta no abre, el problema está del relé para afuera; si no enciende, del transistor para adentro. Parte el diagnóstico en dos.

El LED y el buzzer del lector son colector abierto: hay que tirarlos a masa. En vez de cuatro transistores con sus resistencias va un ULN2003A (U2), que trae siete drivers con las resistencias de base y los diodos de clamp ya dentro; se usan cuatro canales. Los controla el Nano por A0–A3 y no por D10–D13 por una razón concreta: D13 lleva el LED de la placa Nano y el bootloader lo parpadea en cada arranque, así que el lector pitaría en cada reset.

04 Borneras

Familia MX126 / DG126, paso 5.00 mm, taladro 1.3 mm y pad de Ø2.8 mm. J2 y J3 están giradas 180° para que la boca del cable mire al borde, así que el pin 1 queda a la derecha: la serigrafía está rotulada pad por pad y se lee MALLA · BUZZ · LED · D1 · D0 · GND · 12V de izquierda a derecha. Hazle caso a la serigrafía, no al número de pin.

BorneraUsoPines
J2 / J3Lector 1 y 2 · 7 vías12V · GND · D0 · D1 · LED · BUZZ · MALLA
J4 / J5Puerta 1 y 2 · contacto seco · 3 víasCOM · NC · NO
J1Entrada 12 V · 2 vías+12V · GND
J6 / J7Botón de salida 1 y 2 · 2 víasBTN · GND

05 Pinout del Nano

El Nano solo tiene dos interrupciones por hardware y aquí hacen falta cuatro líneas Wiegand. El lector 1 se queda con INT0/INT1; el lector 2 va por pin-change interrupt. Por eso el firmware no puede ser el ejemplo básico de dos líneas.

PinFunciónRedNota
D2 · D3Lector 1 · D0 / D1W1_D0 · W1_D1INT0 / INT1, hardware
D4 · D5Lector 2 · D0 / D1W2_D0 · W2_D1PCINT20 / PCINT21
D6 · D7Relé 1 / 2REL1_CTRL · REL2_CTRLalto = abre
D8 · D9Botón de salida 1 / 2BTN1 · BTN2bajo = pulsado
A0 · A1LED / buzzer lector 1RDR1_LED_C · RDR1_BEEP_C→ ULN2003A I1 / I2
A2 · A3LED / buzzer lector 2RDR2_LED_C · RDR2_BEEP_C→ ULN2003A I3 / I4
+5VEntrada de 5 V+5Vdesde el buck; el USB del Nano va al servidor y su Schottky evita que se retroalimente
VINSin conectar—a propósito: se alimenta por el pin de 5 V

Quedan libres D10–D13 y A4–A7: sitio para sensores de puerta, un RTC o almacenar tarjetas por I²C.

06 Firmware

control_acceso.ino compila para arduino:avr:nano sin avisos: 6.5 KB de flash (21 %) y 324 B de RAM. Lee ambos lectores por interrupción y arma la trama bit a bit; cierra la lectura tras 25 ms de silencio; acepta 26 y 34 bits y valida las dos paridades antes de mandar nada. No guarda tarjetas: el ID sale por el USB del Nano, como puerto serie a 115200, hacia el servidor de la escuela, y es el backend quien decide.

  • Manda CARD con el número de lector y el ID; si el backend responde OPEN, abre el relé 3 s sin bloquear el bucle, con un pitido largo y LED verde; si responde DENY o la trama viene mal, tres pitidos cortos.
  • Botones de salida con antirrebote de 30 ms.
  • El ID es (facility << 16) | número, igual para Wiegand 26 y 34: los dos formatos se aplastan al mismo ID de 32 bits, que es el que se guarda en el servidor al dar de alta al alumno.
  • El backend registra cada lectura, autorizada o no, en el historial de accesos.
  • El vector PCINT2 cubre todo el puerto D, así que la rutina compara con el estado anterior para quedarse solo con los flancos de bajada de PD4 y PD5.
> CARD 1 00A1B2C3    # Nano → backend: lector 1 leyó este ID
> OPEN 1             # backend → Nano: alumno activo, abre el relé 1 tres segundos
> DENY 1             # backend → Nano: bloqueado o desconocido, tres pitidos
> BTN 2              # Nano → backend: botón de salida 2, solo para el historial

07 Resiliencia

Un control de acceso vive dentro de una caja, sin nadie mirándolo, y tiene que seguir funcionando. Estas son las decisiones tomadas con eso en mente, no por elegancia.

Si…Entonces
el firmware se cuelgaUn watchdog de 2 s reinicia el Nano, y lo primero que hace setup() es apagar los dos relés: si el reset ocurrió con una puerta abierta, no se queda abierta
el lector no es de 26 bitsSe aceptan Wiegand 26 y 34 con sus paridades; el registro de bits es de 64 bits porque una trama de 34 no cabe en 32
hay ruido en el cableUna trama que no tenga exactamente 26 o 34 bits se descarta sola; el contador sigue subiendo pasado el límite para que una ráfaga quede con un n imposible en vez de parecerse a una tarjeta
el backend no contesta o el USB se desconectaLa placa sigue alimentada por el buck, no por el USB. La puerta no abre: sin OPEN no hay apertura y el intento queda con tres pitidos. Los botones de salida siguen funcionando porque son locales a la placa
hay que dar de alta o bloquear un alumnoSe hace en el panel, sin tocar la placa: el ID de la tarjeta se captura pasándola por el lector y el cambio aplica en la siguiente lectura
la placa lleva 49 días encendidamillis() desborda; todas las esperas usan resta sin signo, que sobrevive al desbordamiento, y no hay un solo delay(): relés, LEDs y pitidos son máquinas de estado

08 Verificación y riesgos

Lo comprobado y lo no comprobado, separado a propósito. Que el ERC pase no significa que el circuito funcione: durante el diseño, un error grave (base y colector del BC337 invertidos) sobrevivió a un ERC perfectamente limpio. Solo apareció al leer la netlist red por red y preguntarle a KiCad el orden real de las patas del transistor.

VerificadoCómo
ERC: 0 errores, 0 avisosReglas eléctricas del esquemático con --severity-all
Netlist: 42 redesExportada y leída red por red: base en Q1.2, colector en Q1.1, bobina en K1.2, común en K1.1
Huellas: 61 de 61Cada huella contrastada contra su .kicad_mod real, pin a pad
DRC: 0 violacionesReglas de diseño de la placa
Polaridad de LED y buzzer del lectorContra la documentación de HID, referencia del sector: se activan a masa, 0–12 V / 100 mA, dentro de spec del ULN2003A

DIAGRAMAS

−0.4 V 12 V 5 V J1 · 12 V fuente externa F1 · PTC 1.1 A rearmable D7 · SB340 bloquea polaridad invertida Riel ~11.6 V C1 100 µF Bobinas K1 · K2 y los dos lectores U1 · MP1584 buck 12 V → 5 V Arduino Nano + pull-ups · ~40 mA LED1 · PWR si enciende, el buck funciona
01 Alimentación: 12 V protegidos, 5 V para el cerebro
W1_D0 Lector ZKTeco D0 = bit 0 · D1 = bit 1 J2 · 7 vías malla solo aquí a masa D1 · P6KE6.8CA TVS bidireccional C4 · 1 nF filtro de línea R3 · 220 Ω serie al AVR R1 · 2.2 kΩ a 5 V pull-up: reposo en alto D2 · INT0 flanco de bajada lector 2: mismo camino hacia D4 · PCINT20
02 Un bit Wiegand: del lector al pin
BOBINA CIERRA NO Nano · D6 alto = abre · 3 s R9 · 1 kΩ ~4.3 mA a la base Q1 · BC337 satura: bobina a masa K1 · SRD-12VDC D5 absorbe el pico inverso J4 · COM / NC / NO contacto seco R10 · 10 kΩ base a masa mientras arranca LED2 · rojo en paralelo a la bobina Cerradura 12 V fuente propia · snubber RC LED encendido y puerta cerrada → del relé para afueraLED apagado → del transistor para adentro
03 Abrir la puerta sin que la corriente pase por la placa
ID USB OPEN 1 DENY 1 Interrupción arma la trama bit a bit 26 o 34 bits + paridades tras 25 ms de silencio Serie 115200 CARD 1 00A1B2C3 Backend Spring Boot ¿activo o bloqueado? Relé 3 s pitido largo · LED verde Denegada tres pitidos cortos Ruido n imposible, no parece tarjeta Historial cada lectura, pase o no
04 La placa lee, el servidor decide

01 04

01 Alimentación: 12 V protegidos, 5 V para el cerebro
−0.4 V 12 V 5 V J1 · 12 V fuente externa F1 · PTC 1.1 A rearmable D7 · SB340 bloquea polaridad invertida Riel ~11.6 V C1 100 µF Bobinas K1 · K2 y los dos lectores U1 · MP1584 buck 12 V → 5 V Arduino Nano + pull-ups · ~40 mA LED1 · PWR si enciende, el buck funciona

el Schottky cuesta ~0.4 V y el riel queda en ~11.6 V · el relé engancha a ~9 V · el Nano se alimenta por su pin de 5 V y VIN queda al aire

CAPTURAS

Esquemático de la placa pcb_control Rev A en KiCad: Nano, dos entradas Wiegand con TVS y filtros, dos relés con BC337 y snubber, ULN2003A y borneras
Esquemático · Rev A
Lector de tarjetas MIFARE ZKTeco PROID10BM utilizado en el control de acceso
Lector ZKTeco PROID10BM
Lector ZKTeco instalado junto a la puerta de acceso
Instalación en sitio
Diseño de la PCB propia con Arduino y relé para la chapa eléctrica
Diseño de la PCB
Vista del ruteo de pistas de la placa de control de acceso
Ruteo de pistas
Vista 3D de la placa con los conectores y las fuentes step-down
Vista 3D de la placa
Vista 3D de la placa por el reverso, con la serigrafía de las borneras del lector
Serigrafía de borneras
Pantalla de inicio de sesión del panel web de control de acceso
Acceso al panel
Listado de alumnos registrados en el panel de administración
Alumnos registrados
Formulario de alta de alumno y asignación de tarjeta
Alta de alumno
Registro histórico de accesos con fecha y hora
Historial de accesos
Panel de administración mostrando el estado de los alumnos
Estado de alumnos
Vista de configuración del sistema de control de acceso
Configuración

01 01