Análise de Implementação: ESP32-CAM DIY

Especificação Técnica baseada no firmware e mapeamento de hardware do projeto

Módulos OV2640 / OV3660

1. Arquitetura Estrutural do Firmware

O firmware fornecido divide-se de forma modular para otimizar o processamento assíncrono de streaming de vídeo e comandos de controlo da câmara dentro do ecossistema do ESP32.

Ficheiros Core analisados:

  • CameraWebServer_2.ino: Ponto de entrada do sistema. Inicializa a comunicação Série a 115200 Baud, configura os parâmetros do barramento da câmara, gere a ligação à rede Wi-Fi configurada (TP-LINK_552E) e levanta as instâncias do servidor.
  • app_httpd.cpp: Camada lógica do servidor HTTP. Implementa os URIs responsáveis pelo processamento do fluxo de vídeo em tempo real (MJPEG) e os endpoints para captura estática de frames (JPEG/BMP).
  • board_config.h: Centraliza as diretivas do pré-processador para a escolha do perfil de hardware apropriado, garantindo portabilidade entre sensores.

2. Mapeamento Físico de Hardware (Pinos AI-Thinker)

A correspondência geométrica e eletrónica entre o SoC ESP32 e o sensor CMOS baseia-se no perfil embutido no ficheiro CameraWebServer_2.ino que substitui de forma estável o ficheiro dinâmico camera_pins.h para o modelo AI-Thinker.

O barramento de dados paralelo de 8-bits da câmara (D0-D7), os sinais de sincronismo (VSYNC, HREF, PCLK) e o barramento de controlo SCCB/I2C estão distribuídos da seguinte forma:

Barramento de Dados: D0=5, D1=18, D2=19, D3=21, D4=36, D5=39, D6=34, D7=35
Frequência de Clock (XCLK): GPIO 0 (20 MHz)
Pixel Clock (PCLK): GPIO 22
Sincronismo Vertical (VSYNC): GPIO 25
Sincronismo Horizontal (HREF): GPIO 23
Controlo I2C (SSCB): SDA=GPIO 26, SCL=GPIO 27
Power Down (PWDN): GPIO 32
Particularidade Crítica do Sensor OV3660:
O código nativo do CameraWebServer_2.ino possui uma rotina de validação de hardware que verifica o ID do sensor de imagem. Caso seja detetado o sensor OV3660, o firmware executa uma inversão vertical de hardware automática (s->set_vflip(s, 1)) e reajusta as curvas de saturação e brilho para compensar a ótica nativa deste modelo DIY.

3. Tabela de Partições e Alocação de Memória

Para conseguir gerir fluxos de vídeo de alta resolução (UXGA) sem estourar a memória RAM estática interna do chip (DRAM), a tabela de partições do módulo (especificada em partitions.csv) foi desenhada sob uma arquitetura customizada:

# Estrutura extraída do partitions.csv
# Name,   Type,  SubType, Offset,   Size
nvs,      data,  nvs,     0x9000,   0x5000
otadata,  data,  ota,     0xe000,   0x2000
app0,     app,   ota_0,   0x10000,  0x3c0000
fr,       data,        ,  0x3d0000, 0x20000
coredump, data,  coredump,0x3f0000, 0x10000

O firmware está alocado na partição app0 com um espaço expandido massivo de 3.75 MB (0x3c0000 bytes), permitindo o armazenamento de bibliotecas pesadas de processamento gráfico e suporte ao stack de Wi-Fi e Bluetooth simultâneos.

No arranque, o firmware valida se a PSRAM externa está ativa. Se detetada, ele aloca 2 buffers de fotogramas (config.fb_count = 2) em alta resolução; caso contrário, limita o buffer à memória interna DRAM em resolução reduzida (SVGA) para mitigar erros de falta de memória.

4. O Motor do Servidor Web (app_httpd.cpp)

O tráfego de streaming de vídeo gerado no ficheiro app_httpd.cpp baseia-se no protocolo de transmissão assíncrona multipartes sobre HTTP. O servidor não envia um ficheiro de vídeo convencional, mas sim um fluxo contínuo de ficheiros binários JPEG independentes delimitados por um boundary.

Mapeamento de URIs do Servidor:

  • / (Porta 80): Serve a interface gráfica web embutida em formato GZIP comprimido obtida a partir do array binário de camera_index.h.
  • /stream (Porta 81): Inicia o loop infinito que captura o frame do sensor (esp_camera_fb_get()) e despacha-o imediatamente para o cliente web com o cabeçalho Content-Type: image/jpeg, limpando o buffer logo a seguir.
  • /capture: Captura um único frame estático de alta resolução.

Mecanismo de Controlo do Flash LED por PWM:

A rotina setupLedFlash() do teu ficheiro app_httpd.cpp faz uso do periférico LEDC (Controlo de LED por hardware do ESP32). Configurado com uma frequência de 5000 Hz e resolução de 8 bits (0 a 255), ele ajusta a intensidade do LED de flash traseiro com precisão milimétrica via web, sem bloquear a CPU através da função atualizada para a API v3.x:

ledcAttach(LED_GPIO_NUM, 5000, 8);

5. Guia de Implementação e Conectividade

Para replicar e implementar o módulo com base nesta arquitetura de software validada, segue o protocolo abaixo:

  1. Estado de Boot de Programação: Realiza um curto-circuito físico entre os pinos GPIO 0 e GND do módulo ESP32-CAM.
  2. Ligação TTL: Conecta um programador USB-Série externo alimentando os pinos 5V e GND, cruzando as linhas de dados (TX->U0R e RX->U0T).
  3. Compilação: No Arduino IDE, garante que a opção de suporte a PSRAM está ativada nas configurações da placa (conforme exigido pelo ficheiro de automação ci.yml). Clica em Upload.
  4. Ativação do Módulo: Remove a ponte física do GPIO 0 e prime o botão físico RST da placa. O módulo irá conectar-se à rede Wi-Fi e imprimirá o endereço IP no Monitor Série a 115200 baud.

Embutir o sinal diretamente na tua Página Web:

Graças ao fluxo estruturado no código em app_httpd.cpp, podes renderizar a câmara em tempo real no teu próprio site de alojamento público usando apenas a porta do stream redirecionada no teu router doméstico:

Para saberes o teu Ip público vai a https://meu-ip.pt/
<!-- Integração direta em HTML5 -->
<div class="video-container">
    <h3>Câmera OV2640 em Direto</h3>
    <img src="http://IP_PUBLICO_OU_DDNS:PORTA_ROUTER/stream" width="640" height="480" alt="Stream da câmera">
</div>

Câmera OV2640 em Direto

Stream da câmera