Acesso
← Voltar ao Índice de Manuais🔩Engenharia & Firmware

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:

  • Validação Descentralizada (Offline-First): O acionamento da trava de catraca/relé não depende de resposta da internet. O ESP32 valida a assinatura do cartão localmente e libera o fluxo imediatamente.
  • Resiliência de Energia e Horário: Uso obrigatório de um módulo de relógio de precisão RTC DS3231 com bateria para manter a data/hora exata dos acessos mesmo durante quedas conjuntas de luz e Wi-Fi.
  • Armazenamento Local temporário: Buffer circular na memória Flash interna (LittleFS ou SPIFFS) para acumular milhares de acessos e despachar em lotes assíncronos.
  • Segurança de Hardware: Compilação do firmware com Flash Encryption e Secure Boot ativados para impedir a extração física da Chave A e da API Key por dump de memória.

  • 2. Componentes de Hardware Necessários (BOM - Bill of Materials)

    ComponenteModelo / Especificação RecomendadaFunção
    MicrocontroladorESP32-WROOM-32 (NodeMCU / DevKit v1)Processamento, Wi-Fi 802.11 b/g/n e armazenamento local
    Leitor NFCMódulo PN532 (Comunicação SPI ou I2C)Leitura e autenticação do Setor 1 dos cartões Mifare / DESFire
    Relógio RTCMódulo RTC DS3231 (I2C) + Bateria CR2032Manutenção da data e hora em tempo real sem servidor NTP
    AtuadorMódulo Relé 5V de 1 Canal (Optoacoplado)Acionamento do solenoide/eletroímã da catraca ou fechadura
    Sinalização SonoraBuzzer 5V AtivoBip sonoro (Entrada autorizada, Recusada, Erro de sincronismo)
    Sinalização VisualLED Bicolor (Verde / Vermelho) ou Neopixel WS2812BFeedback visual de liberação ou bloqueio
    AlimentaçãoFonte Chaveada 12V 2A + Regulador Step-Down 5V/3AAlimentaçã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 PN532Pino ESP32Descrição
    VCC5VAlimentação principal
    GNDGNDTerra comum
    SCKGPIO 18 (VSPI SCK)Clock SPI
    MISOGPIO 19 (VSPI MISO)Master In Slave Out
    MOSIGPIO 23 (VSPI MOSI)Master Out Slave In
    SS / SSGPIO 5 (VSPI SS)Chip Select do PN532

    3.2 Conexão do Relógio RTC DS3231 (Interface I2C)

    Pino RTC DS3231Pino ESP32Descrição
    VCC3.3V / 5VAlimentação lógica
    GNDGNDTerra comum
    SDAGPIO 21 (I2C SDA)Dados I2C
    SCLGPIO 22 (I2C SCL)Clock I2C

    3.3 Conexão dos Atuadores e Periféricos (GPIOs)

    ComponentePino ESP32Estado AtivoDescrição
    Módulo Relé (Catraca)GPIO 26LOW / HIGH (depende da placa)Pulso de 200 ms para acionar a trava
    BuzzerGPIO 27HIGHEmite bips de status
    LED Verde (Sucesso)GPIO 12HIGHSinaliza acesso liberado
    LED Vermelho (Bloqueado)GPIO 14HIGHSinaliza 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.

    SetorBlocoConteúdoAcesso / Permissão
    Setor 0Bloco 0, 1, 2UID do Cartão de FábricaLeitura Pública
    Setor 1Bloco 4uuidCampus (String UUID v4 de 36 caracteres em UTF-8)Protegido pela Chave A da instituição
    Setor 1Bloco 7Trailer de Segurança (Chave A / Bits de Acesso / Chave B)Gravável apenas por gravadores autorizados

    Algoritmo de Validação no ESP32:

  • Detectar aproximação do cartão via PN532.
  • Identificar se o cartão é Mifare Classic (SAK = 0x08 ou 0x18).
  • Tentar autenticação no Bloco 4 (Setor 1) usando a Chave A.
  • Se a autenticação falhar $\rightarrow$ Negar acesso imediatamente (Acionar Buzzer em Tom Grave 3x + LED Vermelho).
  • Se a autenticação passar $\rightarrow$ Ler os 36 bytes do uuidCampus.
  • Verificar se o uuidCampus está na Lista Negra de Bloqueios (armazenada em memória RAM/Flash).
  • Se estiver bloqueado $\rightarrow$ Negar acesso.
  • Se estiver válido $\rightarrow$ Liberar Acesso (Pulso de 200ms no Relé + Bip Curto + LED Verde) e gravar no buffer offline.

  • 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

  • URL: POST https://seu-dominio.com/api/hardware/sync
  • Headers Obrigatórios:
  • Content-Type: application/json
  • x-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."
    }
  • Se o código HTTP for 200 OK, o ESP32 deve apagar os registros despachados do buffer LittleFS.
  • Se o código HTTP for 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.

    © 2026 Acesso — Acesso permitido, identidade preservada.