Especificação Técnica de Engenharia e Prototipagem de Hardware (ESP32) — Sistema Acesso
Documento de Engenharia de Hardware & Firmware
Versão da Especificação: 1.0.0
Destinatários: Equipe de Prototipagem, Desenvolvedores de Firmware e Engenharia de Hardware
Sistema Alvo: Acesso — Plataforma de Controle de Frequência e Ocupação
1. Visão Geral do Protótipo
O dispositivo de hardware é uma unidade autônoma de controle de acesso (totem / leitor de catraca) baseada no microcontrolador ESP32. Sua função é efetuar a leitura e validação local criptográfica de cartões NFC Mifare em tempo real (< 200 ms) e descarregar os acessos acumulados via rede Wi-Fi para o servidor central através do endpoint REST B2B (POST /api/hardware/sync).
Principais Diretrizes da Arquitetura:
LittleFS ou SPIFFS) para acumular milhares de acessos e despachar em lotes assíncronos.Chave A e da API Key por dump de memória.2. Componentes de Hardware Necessários (BOM - Bill of Materials)
| Componente | Modelo / Especificação Recomendada | Função |
|---|---|---|
| Microcontrolador | ESP32-WROOM-32 (NodeMCU / DevKit v1) | Processamento, Wi-Fi 802.11 b/g/n e armazenamento local |
| Leitor NFC | Módulo PN532 (Comunicação SPI ou I2C) | Leitura e autenticação do Setor 1 dos cartões Mifare / DESFire |
| Relógio RTC | Módulo RTC DS3231 (I2C) + Bateria CR2032 | Manutenção da data e hora em tempo real sem servidor NTP |
| Atuador | Módulo Relé 5V de 1 Canal (Optoacoplado) | Acionamento do solenoide/eletroímã da catraca ou fechadura |
| Sinalização Sonora | Buzzer 5V Ativo | Bip sonoro (Entrada autorizada, Recusada, Erro de sincronismo) |
| Sinalização Visual | LED Bicolor (Verde / Vermelho) ou Neopixel WS2812B | Feedback visual de liberação ou bloqueio |
| Alimentação | Fonte Chaveada 12V 2A + Regulador Step-Down 5V/3A | Alimentação estável para ESP32, relé e solenoide |
3. Esquemático de Ligação dos Pinos (Pinout ESP32)
3.1 Conexão do Leitor NFC PN532 (Interface SPI)
Nota: Certifique-se de ajustar a chave seletora DIP do módulo PN532 para o modo SPI (Channel 1: OFF, Channel 2: ON).| Pino PN532 | Pino ESP32 | Descrição |
|---|---|---|
| VCC | 5V | Alimentação principal |
| GND | GND | Terra comum |
| SCK | GPIO 18 (VSPI SCK) | Clock SPI |
| MISO | GPIO 19 (VSPI MISO) | Master In Slave Out |
| MOSI | GPIO 23 (VSPI MOSI) | Master Out Slave In |
| SS / SS | GPIO 5 (VSPI SS) | Chip Select do PN532 |
3.2 Conexão do Relógio RTC DS3231 (Interface I2C)
| Pino RTC DS3231 | Pino ESP32 | Descrição |
|---|---|---|
| VCC | 3.3V / 5V | Alimentação lógica |
| GND | GND | Terra comum |
| SDA | GPIO 21 (I2C SDA) | Dados I2C |
| SCL | GPIO 22 (I2C SCL) | Clock I2C |
3.3 Conexão dos Atuadores e Periféricos (GPIOs)
| Componente | Pino ESP32 | Estado Ativo | Descrição |
|---|---|---|---|
| Módulo Relé (Catraca) | GPIO 26 | LOW / HIGH (depende da placa) | Pulso de 200 ms para acionar a trava |
| Buzzer | GPIO 27 | HIGH | Emite bips de status |
| LED Verde (Sucesso) | GPIO 12 | HIGH | Sinaliza acesso liberado |
| LED Vermelho (Bloqueado) | GPIO 14 | HIGH | Sinaliza cartão recusado / bloqueado |
4. Estrutura de Leitura do Cartão Mifare Classic 1K
O firmware deve efetuar a autenticação local do Setor 1 do cartão Mifare utilizando a Chave A privada configurada na instituição.
| Setor | Bloco | Conteúdo | Acesso / Permissão |
|---|---|---|---|
| Setor 0 | Bloco 0, 1, 2 | UID do Cartão de Fábrica | Leitura Pública |
| Setor 1 | Bloco 4 | uuidCampus (String UUID v4 de 36 caracteres em UTF-8) | Protegido pela Chave A da instituição |
| Setor 1 | Bloco 7 | Trailer de Segurança (Chave A / Bits de Acesso / Chave B) | Gravável apenas por gravadores autorizados |
Algoritmo de Validação no ESP32:
SAK = 0x08 ou 0x18).uuidCampus.uuidCampus está na Lista Negra de Bloqueios (armazenada em memória RAM/Flash).5. Protocolo de Comunicação REST B2B (Lote de Acessos)
A cada 60 segundos (ou quando o buffer atingir 10 registros), o ESP32 deve enviar o lote de acessos acumulados para o servidor HTTP/HTTPS.
5.1 Endpoint de Sincronização
POST https://seu-dominio.com/api/hardware/syncContent-Type: application/jsonx-api-key: <API_KEY_DO_DISPOSITIVO> (ou Authorization: Bearer <API_KEY_DO_DISPOSITIVO>)5.2 Formato do Payload (JSON Request)
{
"acessos": [
{
"uuidCampus": "550e8400-e29b-41d4-a716-446655440000",
"sentido": "entrada",
"timestampAcesso": "2026-08-06T08:23:15.000Z"
},
{
"uuidCampus": "550e8400-e29b-41d4-a716-446655440001",
"sentido": "saida",
"timestampAcesso": "2026-08-06T08:24:02.000Z"
}
]
}uuidCampus: Código UUID lido do Setor 1 do cartão.sentido: "entrada" ou "saida" (configurado no firmware de acordo com o lado do leitor).timestampAcesso: Data e hora capturadas do RTC DS3231 no exato instante do toque do cartão, formatadas em ISO 8601 UTC.5.3 Resposta do Servidor (JSON Response)
{
"inseridos": 2,
"ignorados": 0,
"mensagem": "Sincronização concluída com sucesso."
}200 OK, o ESP32 deve apagar os registros despachados do buffer LittleFS.401 Unauthorized, a API Key é inválida. O ESP32 deve manter o buffer e tentar novamente em 60s, emitindo alerta visual.6. Fluxograma de Máquina de Estados do Firmware (State Machine)
┌──────────────────────────────┐
│ BOOT DO ESP32 │
└──────────────┬───────────────┘
│
┌──────────────▼───────────────┐
│ Inicializar SPI (PN532), │
│ I2C (RTC), LittleFS e Wi-Fi │
└──────────────┬───────────────┘
│
┌──────────────▼───────────────┐
│ LOOP PRINCIPAL (Main Loop) │
└──────────────┬───────────────┘
│
┌────────────────────┴────────────────────┐
│ │
┌──────▼─────────────────────┐ ┌───────────▼─────────────────────┐
│ Evento: Cartão Encostado │ │ Temporizador: 60s ou Buffer Cheio│
└──────┬─────────────────────┘ └───────────┬─────────────────────┘
│ │
┌──────▼─────────────────────┐ ┌───────────▼─────────────────────┐
│ 1. Ler RTC (Timestamp) │ │ 1. Tem Wi-Fi conectado? │
│ 2. Autenticar Setor 1 │ │ 2. Ler lotes do LittleFS │
│ 3. Validar Chave A │ │ 3. Enviar POST /api/hardware/sync│
└──────┬─────────────────────┘ └───────────┬─────────────────────┘
│ │
┌─────┴─────────────┐ ┌─────┴─────────────┐
│ Chave A Válida? │ │ HTTP Status 200? │
└─────┬───────────┬─┘ └─────┬───────────┬─┘
│ Sim │ Não │ Sim │ Não
┌──────▼─────┐ ┌───▼───────────┐ ┌─────▼─────┐ ┌───▼───────────┐
│Acionar Relé│ │Bip Erro │ │Limpar Lote│ │Manter no │
│(200ms) │ │LED Vermelho │ │do LittleFS│ │LittleFS │
│Gravar no │ └───────────────┘ └───────────┘ └───────────────┘
│LittleFS │
└────────────┘7. Exemplo de Código Base em C++ (Arduino Framework / ESP32)
Este código fornece a estrutura pronta para ser compilada no VS Code com a extensão PlatformIO ou Arduino IDE:
#include <WiFi.h>
#include <HTTPClient.h>
#include <SPI.h>
#include <Adafruit_PN532.h>
#include <Wire.h>
#include <RTClib.h>
#include <LittleFS.h>
#include <ArduinoJson.h>
// Configurações da Rede e API
const char* WIFI_SSID = "SUA_REDE_WIFI";
const char* WIFI_PASS = "SUA_SENHA_WIFI";
const char* API_URL = "https://seu-dominio.com/api/hardware/sync";
const char* API_KEY = "SUA_API_KEY_DO_DISPOSITIVO";
// Configurações de Pinos
#define PN532_SS 5
#define RELE_PIN 26
#define BUZZER_PIN 27
#define LED_GREEN 12
#define LED_RED 14
// Chave A Institucional (6 Bytes)
uint8_t keyA[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; // Substituir pela chave da instituição
Adafruit_PN532 nfc(PN532_SS);
RTC_DS3231 rtc;
void setup() {
Serial.begin(115200);
pinMode(RELE_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_RED, OUTPUT);
digitalWrite(RELE_PIN, LOW);
// Inicializa LittleFS
if (!LittleFS.begin(true)) {
Serial.println("Erro ao inicializar LittleFS!");
}
// Inicializa RTC
if (!rtc.begin()) {
Serial.println("RTC não encontrado!");
}
// Inicializa PN532
nfc.begin();
uint32_t versiondata = nfc.getFirmwareVersion();
if (!versiondata) {
Serial.println("Placa PN532 não encontrada!");
} else {
nfc.SAMConfig();
Serial.println("PN532 Inicializado com sucesso.");
}
// Conecta ao Wi-Fi
WiFi.begin(WIFI_SSID, WIFI_PASS);
}
void bipSucesso() {
digitalWrite(LED_GREEN, HIGH);
digitalWrite(BUZZER_PIN, HIGH);
delay(150);
digitalWrite(BUZZER_PIN, LOW);
delay(100);
digitalWrite(LED_GREEN, LOW);
}
void bipErro() {
digitalWrite(LED_RED, HIGH);
digitalWrite(BUZZER_PIN, HIGH);
delay(100);
digitalWrite(BUZZER_PIN, LOW);
delay(100);
digitalWrite(BUZZER_PIN, HIGH);
delay(100);
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(LED_RED, LOW);
}
void acionarCatraca() {
digitalWrite(RELE_PIN, HIGH);
delay(200); // Pulso de 200 ms
digitalWrite(RELE_PIN, LOW);
}
void loop() {
uint8_t success;
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };
uint8_t uidLength;
// Leitura do leitor NFC
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 100);
if (success) {
// Autentica o Setor 1 (Bloco 4) com a Chave A
uint8_t authenticated = nfc.mifareclassic_AuthenticateBlock(uid, uidLength, 4, 0, keyA);
if (authenticated) {
uint8_t data[16];
uint8_t readSuccess = nfc.mifareclassic_ReadDataBlock(4, data);
if (readSuccess) {
// Converte o UUID lido
char uuidBuf[37];
memcpy(uuidBuf, data, 16);
uuidBuf[36] = '\0';
DateTime now = rtc.now();
Serial.print("Cartão Autorizado: ");
Serial.println(uuidBuf);
// Libera catraca imediatamente
bipSucesso();
acionarCatraca();
// TODO: Salvar registro no LittleFS para despacho assíncrono em lote
} else {
bipErro();
}
} else {
Serial.println("Falha na autenticação da Chave A!");
bipErro();
}
}
delay(200);
}8. Considerações Finais e Entrega
Este manual fornece todos os parâmetros de comunicação, layout de cartões, conexões físicas e lógica do firmware para que a equipe desenvolva o hardware com padrão industrial e prontidão de produção.