¿Quieres vigilar el patio, el taller o la pieza de la guagua sin pagar una suscripción mensual ni instalar la app de un fabricante? Este proyecto convierte una placa ESP32-S3 con cámara y un micrófono digital INMP441 en una cámara de seguridad que transmite imagen y sonido a cualquier navegador de tu red WiFi. La página web vive dentro del propio ESP32-S3, así que no hay nube, no hay cuenta y no hay servidor aparte.
Al terminar vas a saber cablear un micrófono I²S a un ESP32-S3, configurar la PSRAM y el esquema de particiones en Arduino IDE, y entender por qué la grabación de video con audio ocurre en el computador o el celular que mira, y no en una tarjeta microSD. También vas a ver cómo se arma la alimentación con batería, tanto en la PCB del diseño original como en una versión más simple en protoboard con módulos que se consiguen en Chile.
Qué hace la cámara
Antes de soldar nada conviene tener claro qué entrega el firmware y qué no:
- Video y sonido en la misma página: ves la cámara y escuchas lo que capta el INMP441.
- Visor 16:9: el modo Fill recorta arriba y abajo para llenar el cuadro; Fit frame muestra la imagen completa con barras laterales. Ninguno deforma la imagen.
- Grabación desde el navegador: grabas un clip con audio, lo revisas y lo descargas.
- Fecha y hora impresas en el video, con el desfase UTC, en la esquina inferior derecha.
- Foto instantánea en JPEG desde la vista en vivo.
- Temas claro, oscuro y automático.
- Dos modos de red: conectada a tu router de 2,4 GHz o como punto de acceso propio.
- Contraseña para entrar al visor y a los streams.
Lo que no hace: no graba de forma continua ni se dispara sola al detectar movimiento, no tiene audio de vuelta (no puedes hablar por un parlante) y está pensada para un solo espectador a la vez. Si buscas un sistema de vigilancia 24/7, esta es la base, no el producto terminado.
El hardware, por bloques
La placa: ESP32-S3 N16R8 con cámara
El diseño original usa la placa de cámara de Freenove con el módulo ESP32-S3-WROOM-1: procesador Xtensa LX7 de doble núcleo a 240 MHz, WiFi de 2,4 GHz y Bluetooth 5 LE. La sigla N16R8 indica 16 MB de flash y 8 MB de PSRAM. Esa PSRAM es la que hace posible el proyecto: cada cuadro JPEG de la cámara se guarda en un búfer, y la RAM interna del ESP32-S3 (unos 512 KB) no alcanza para varios cuadros en resolución VGA más el servidor web y el búfer de audio. Existe también la versión N8R8, con 8 MB de flash, que sirve igual.

La cámara entra por un cable plano y sus señales ya están ruteadas en la placa. Con un sensor OV2640 llegas a 1600 × 1200 píxeles (2 megapíxeles), aunque para streaming conviene bajar la resolución. Ojo: el sensor que trae la caja puede variar entre lotes, así que revisa el modelo antes de elegir la configuración. Estos son los GPIO que usa el driver de la cámara en esta placa:
| Señal de la cámara | GPIO del ESP32-S3 | Función |
|---|---|---|
| D0, D3 | 11, 9, 8, 10 | Bits de datos 0 a 3 |
| D4, D7 | 12, 18, 17, 16 | Bits de datos 4 a 7 |
| XCLK | 15 | Reloj que el ESP32 entrega a la cámara |
| PCLK | 13 | Reloj de píxel que devuelve la cámara |
| VSYNC | 6 | Sincronización de cuadro |
| HREF | 7 | Temporización de cada línea |
| SIOD (SDA del bus SCCB) | 4 | Datos de configuración |
| SIOC (SCL del bus SCCB) | 5 | Reloj de configuración |
| PWDN / RESET | sin GPIO | Se configura como, 1 en el driver |
Un detalle que conviene entender: la cámara no entrega la imagen por I²C ni por SPI, sino por un bus paralelo de 8 bits sincronizado por PCLK. Por eso ocupa tantos pines. El bus SCCB (un primo del I²C) solo sirve para escribir los registros del sensor: exposición, balance de blancos, resolución. Si usas otra placa ESP32-S3 con cámara, el código funciona igual pero tienes que cambiar esta tabla por la de tu placa, o la cámara no inicia.
La placa trae además ranura microSD, botones BOOT y RESET, y dos USB: uno con conversor USB UART (el que usas para programar) y el USB nativo del ESP32-S3. Toda la lógica externa trabaja a 3,3 V.
El micrófono INMP441
El INMP441 es un micrófono MEMS que entrega el audio ya digitalizado por I²S, sin amplificador ni conversor analógico de por medio. Esa es la gracia frente a un micrófono electret con amplificador: el ruido de la fuente y de la WiFi no se mete en la señal, porque viaja como bits y no como voltaje. Se conecta así:
| Pin del INMP441 | Conexión |
|---|---|
| VDD | 3,3 V |
| GND | GND |
| SD (datos) | GPIO3 |
| SCK (reloj de bit) | GPIO19 |
| WS (selección de canal) | GPIO20 |
| L/R | GND (canal izquierdo, el que lee el firmware) |
En la PCB original hay un condensador de 100 nF entre VDD y GND, pegado al micrófono, y una resistencia de 100 kΩ que lleva la línea de datos a GND cuando nadie la maneja. En protoboard pon al menos el condensador: el INMP441 es sensible al ruido de la línea de 3,3 V y sin él vas a escuchar un zumbido cada vez que la radio WiFi transmite.
La alimentación
El esquema completo de la PCB del autor:

Se lee de izquierda a derecha, siguiendo la energía:
- Entrada USB-C: trae 5 V solo para cargar. Los pines CC1 y CC2 llevan cada uno una resistencia de 5,1 kΩ a tierra. Sin esas resistencias, un cargador USB-C moderno no reconoce que hay un dispositivo conectado y simplemente no entrega corriente; es el error típico de los diseños caseros con conector USB-C.

- Cargador MCP73831: carga una celda de litio de 3,7 V nominales (4,2 V a plena carga). La resistencia de 2 kΩ en el pin PROG fija la corriente en unos 500 mA, y el pin STAT enciende un LED indicador a través de una resistencia de 470 Ω. Como la cámara cuelga de la misma línea de batería, si la dejas funcionando mientras carga el chip no detecta bien el fin de carga: apágala con el interruptor mientras se carga.

Conector de batería y protección: un MOSFET canal P AO3401A protege contra polaridad invertida y un diodo TVS SMBJ5.0CA recorta los transitorios. Esto no reemplaza la protección de la celda: la batería tiene que traer su propio circuito contra sobrecarga, descarga profunda y sobrecorriente. Y revisa la polaridad real del conector antes de enchufar; que el conector calce no garantiza que el rojo vaya al positivo.
Elevador TPS61023: sube los 3,0 a 4,2 V de la batería a 5 V para la placa de la cámara. Las resistencias de realimentación de 732 kΩ y 100 kΩ fijan la salida, y una bobina de 1 µH hace la conmutación. El dato de 3,7 A de la hoja de datos es el límite de corriente interno de conmutación, no lo que entrega a 5 V: con la batería baja, la corriente útil a la salida cae bastante.

¿Por qué elevar a 5 V para que después el regulador de la placa lo baje a 3,3 V? Porque la placa Freenove espera 5 V en su pin de alimentación, y una celda de litio pasa la mayor parte de su descarga entre 3,6 y 3,8 V: alimentar el regulador de 3,3 V directo desde la batería deja muy poco margen, y en los picos de la radio WiFi (más de 300 mA durante algunos microsegundos) el voltaje cae y el ESP32-S3 se reinicia con el famoso brownout detector was triggered.
Lo que trae la PCB y este firmware no usa
La placa del autor incluye conector para una pantalla TFT ILI9488, un amplificador I²S MAX98357A para parlante y un expansor de GPIO MCP23017 por I²C (dirección 0x20, SDA en GPIO47 y SCL en GPIO42). Ninguno de los tres participa en la cámara de seguridad: están pensados para proyectos futuros. Para este tutorial puedes ignorarlos sin problema.
La PCB del autor y la versión en protoboard
El autor diseñó la PCB en EasyEDA con casi todos los componentes de montaje superficial en la cara frontal, y la placa de la cámara va por detrás, enchufada en headers hembra para poder sacarla.


En la página del tutorial original están el esquemático en PDF, los Gerber, la lista de materiales y el archivo de posiciones para mandarla a fabricar y ensamblar.
Si no quieres mandar a hacer una PCB, el mismo circuito se arma en protoboard con módulos:
- Carga y elevación en un solo módulo: un controlador TP4056 con salida step up hace lo mismo que el MCP73831 más el TPS61023. Lo cargas por USB-C y entrega 5 V hacia la placa.
- Batería: una celda 18650 en su portapila, en vez de la LiPo plana. Dura bastante más con la cámara transmitiendo.
- Interruptor: un mini switch deslizante entre la salida de 5 V y la placa, para apagarla mientras carga.
- Micrófono: el módulo INMP441 se conecta con cuatro o cinco cables hembra hembra directo a los pines de la placa.
La conexión queda: batería → entrada BAT del módulo cargador; salida 5 V del módulo → interruptor → pin 5V de la placa; GND común a todo. El micrófono va a 3,3 V de la placa, nunca a 5 V.
El firmware
El sketch tiene tres archivos que van juntos en una carpeta llamada ESP32S3_Home_Camera:
| Archivo | Qué contiene |
|---|---|
ESP32S3_Home_Camera.ino |
Cámara, WiFi, captura del micrófono, autenticación y servidores de streaming |
audio_processing.h |
Procesamiento de las muestras del micrófono |
viewer.h |
La página web embebida: reproducción, temas, grabación y la marca de fecha y hora |
El código se descarga desde la página del tutorial original. Abre ESP32S3_Home_Camera.ino en Arduino IDE y, al principio del sketch, completa los datos de tu red de 2,4 GHz:
const char *WIFI_SSID = "YOUR_2_4_GHZ_WIFI_NAME";
const char *WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";
const char *CAMERA_PASSWORD = "";
Si dejas CAMERA_PASSWORD vacío, el firmware genera una contraseña única en el primer arranque, la guarda en la flash y la muestra en el monitor serial. Si prefieres poner la tuya, tiene que tener entre 12 y 63 caracteres ASCII imprimibles. Esa misma contraseña protege el punto de acceso propio de la cámara.
Para usar la cámara sin router, deja WIFI_SSID vacío y la placa levanta su propia red. El modo directo también arranca solo si la conexión al router falla después de unos 20 segundos, lo que es útil si te cambias de casa o se corta la WiFi.
Más abajo están los ajustes de video y audio:
constexpr float MIC_GAIN = 4.0f;
constexpr uint32_t VIDEO_FPS_LIMIT = 12;
constexpr bool USE_720P = false;
Déjalos así para la primera prueba. Si la voz se escucha saturada, baja MIC_GAIN a 2.0; si se oye muy despacio, súbelo a 8.0. El control de volumen del navegador solo cambia lo que escuchas, no la ganancia del micrófono. Con USE_720P en true la cámara captura a 1280 × 720 nativo: necesita PSRAM y un sensor compatible, usa más ancho de banda y probablemente baje los cuadros por segundo. Primero deja estable el video y el audio en la resolución por defecto.
Configuración de Arduino IDE
Elige ESP32S3 Dev Module en la lista de placas y ajusta:
| Opción | Valor para la placa N16R8 |
|---|---|
| Flash Size | 16MB (128Mb) |
| PSRAM | OPI PSRAM |
| Partition Scheme | Huge APP (3MB No OTA/1MB SPIFFS), o cualquiera con al menos 3 MB para la aplicación |
| USB CDC On Boot | Disabled |
| Port | el puerto serie del USB UART de la placa |
| Velocidad del monitor serial | 115200 baudios |
El ajuste que más se olvida es PSRAM en OPI. Los módulos R8 usan PSRAM octal; si la dejas en QSPI o desactivada, el firmware no la detecta y cae a cuadros de 320 × 240. Si con una placa N8R8 ves que la imagen sale chica, revisa eso antes que cualquier otra cosa. El esquema Huge APP hace falta porque la página web embebida en viewer.h infla el binario más allá de la partición por defecto de 1,2 MB.
Conecta el cable al USB UART, sube el sketch y abre el monitor serial a 115200 baudios. Si no ves nada, aprieta RESET: aparecen los mensajes de arranque, la dirección IP de la cámara y la contraseña.
Pruebas: ver, escuchar y grabar
Abrir la página
En modo router, conecta tu computador o celular a la misma red y abre la dirección HTTP que mostró el monitor serial. En modo directo, únete a la red HomeCam-xxxx con la contraseña impresa, acepta el aviso de "sin internet" del teléfono y abre http://192.168.4.1/. Escribe la contraseña de la cámara y espera el video. Para escuchar, toca el botón Sound off: los navegadores exigen un clic antes de reproducir audio. Si tu celular está cerca de la cámara, usa audífonos o vas a armar un acople.
Cómo viajan los streams
El ESP32-S3 sirve la página en el puerto 80, el video MJPEG en el 81 y el audio del micrófono en el 82. Son dos streams independientes, y eso explica algo que vas a notar: a veces el sonido va un poco adelantado o atrasado respecto a la imagen. No es un error de tu montaje, es la consecuencia de mandar dos flujos separados por una red que no garantiza tiempos.
MJPEG, además, es simplemente una seguidilla de fotos JPEG completas. Ocupa más ancho de banda que H.264, pero el ESP32-S3 no tiene codificador de video por hardware y sí puede pedirle a la cámara que entregue cada cuadro ya comprimido en JPEG. Por eso es la opción estándar en este tipo de cámaras. El límite de 12 cuadros por segundo de VIDEO_FPS_LIMIT evita saturar la WiFi y deja tiempo de CPU para el audio.
Un punto de seguridad importante: la página usa HTTP local sin cifrar. La contraseña controla quién entra, pero no protege lo que viaja por la red. Úsala en una red de confianza y no abras esos puertos hacia internet en tu router.
Grabar clips
La grabación ocurre en el dispositivo que mira. El JavaScript de la página dibuja cada cuadro en un canvas, junta esa pista de video con el audio del micrófono que llega por el puerto 82 y se lo pasa a la API MediaRecorder del navegador, que arma el archivo. Por eso no hace falta tarjeta microSD: el ESP32-S3 solo transmite.
- Espera a que la imagen en vivo se esté actualizando.
- Elige Fill o Fit frame antes de empezar.
- Toca Record. La página prepara el audio y parte el contador.
- Mantén la página visible y la pantalla encendida mientras grabas.
- Toca Stop, revisa el clip en la sección de grabaciones y descárgalo.
Silenciar el navegador no saca el audio de la grabación, así que puedes grabar en silencio. El formato depende del navegador: algunos entregan MP4 y otros WebM. Con la fuente VGA por defecto, el canvas de grabación es de 640 × 360.
Cada cuadro grabado lleva en la esquina inferior derecha la fecha, la hora y el desfase horario, quemados en los píxeles del video:
2026-10-25
14:32:08 UTC+05:30
Esa hora viene del reloj del dispositivo que graba, no de la cámara. Si tu celular tiene la hora mal, el video también. En Chile continental vas a ver UTC-03:00 en horario de verano y UTC-04:00 en invierno.
Los límites: un clip se corta a los 10 minutos o a los 64 MiB, lo que llegue primero, y la galería guarda hasta ocho clips con un total de 128 MiB en la memoria de la pestaña. No es almacenamiento permanente: si recargas, cierras la pestaña o cambias a otra, puedes perder lo que no descargaste.
Si algo falla
- El ESP32-S3 se reinicia al abrir el stream: casi siempre es alimentación. Mide los 5 V con la cámara transmitiendo; si caen bajo 4,7 V, la batería está baja o el elevador no da la corriente.
- La imagen sale en 320 × 240: la PSRAM no se detectó. Revisa que esté en OPI PSRAM.
- "Camera init failed" en el monitor serial: el cable plano está suelto o al revés, o tu placa usa otros GPIO para la cámara.
- Hay video pero no sonido: revisa que tocaste Sound off, que L/R va a GND y que SD está en GPIO3.
Variantes y mejoras
- Grabación por movimiento sin tocar el firmware de la cámara: como el video es MJPEG por HTTP, un computador o una Raspberry Pi de la casa puede leer el stream del puerto 81 con OpenCV, comparar cuadros consecutivos y guardar solo cuando cambia la imagen. La cámara sigue simple y la inteligencia queda en un equipo con disco.
- Sensor PIR para despertar la cámara: un sensor PIR HC SR501 en un GPIO libre puede sacar al ESP32-S3 de deep sleep solo cuando hay alguien. Así la batería dura días en vez de horas, a cambio de unos segundos de arranque antes de ver imagen.
- Audio de vuelta con el MAX98357A: la PCB ya trae el amplificador conectado a GPIO14, 19 y 20. Agregando un parlante de 3 W y un tercer stream de audio desde el navegador al ESP32-S3 tendrías un intercomunicador. Es la mejora natural, pero exige escribir firmware nuevo.
Personalización para Chile
En Chile consigues casi todo lo necesario en MechatronicStore:
- Módulo Micrófono I2S INMP441 (SKU GL3-12): el micrófono digital que capta el audio de la cámara.
- Controlador de Carga Baterías de Litio 18650 elevador voltaje Step up TP4056 USB C (SKU B-204V2): reemplaza en la versión de protoboard al cargador MCP73831 y al elevador TPS61023 de la PCB original; carga por USB-C y entrega 5 V.
- Batería 18650 recargable 3.7V (SKU GT2-10): la celda que alimenta la cámara.
- Porta Batería 18650×1 (SKU L-325): para conectar la celda sin soldarle cables.
- Mini Switch Interruptor Proto 3 Pin 7.5x23.5mm (SKU GF1-15): el interruptor de encendido, para apagar la cámara mientras carga.
- Cables hembra hembra 40 piezas 10cm (SKU C-416): para unir el micrófono y la alimentación con los pines de la placa.
La placa Freenove ESP32-S3 N16R8 con cámara no está hoy en el catálogo. Cualquier placa ESP32-S3 con cámara OV2640 y PSRAM octal sirve, siempre que ajustes la tabla de GPIO de la cámara en el código. Una ESP32-CAM clásica (ESP32 sin S3) no es equivalente: tiene menos pines libres y la mayoría trae PSRAM de 4 MB, que se queda corta para la página y el audio.
Recursos
- Tutorial original (inglés): DIY ESP32-S3 CAM Security Camera with Video Audio Stream, de How2Electronics, donde están el código, el esquemático, los Gerber y la lista de materiales.
- Hoja de datos del cargador: MCP73831 (Microchip)
- Hoja de datos del elevador: TPS61023 (Texas Instruments)
Basado en el proyecto de How2Electronics. Versión chilena con componentes en stock local.










