Componentes · 15 min de lectura

ESP32-CAM: tutorial para programarla, ver vídeo y guardar fotos

Cómo programar la ESP32-CAM: pines AI-Thinker, carga con ESP32-CAM-MB o USB-TTL, CameraWebServer, PSRAM, errores 0x105 y brownout, flash y fotos en la SD.

La ESP32-CAM es una placa de cámara Wi-Fi económica que, pese a medir solo 27 × 40 mm, incluye un procesador ESP32, una cámara OV2640 de 2 megapíxeles, una ranura para tarjeta microSD y un LED de flash blanco. Por sí sola se conecta a la red de casa, transmite vídeo en directo al navegador, hace fotos y las guarda en la tarjeta SD o las envía por internet. Es la placa más popular para cámaras de vigilancia, cámaras de timbre, time-lapses del crecimiento de una planta y coches robot con vídeo, pero como no tiene conector USB, la puesta en marcha es algo distinta a la de las placas ESP32 a las que quizá estés acostumbrado.

En esta guía conocerás los pines de la ESP32-CAM de AI-Thinker, cómo programarla con el adaptador ESP32-CAM-MB o con un convertidor USB-TTL (incluida la conexión IO0-GND), cómo ver la imagen en directo en el navegador con el ejemplo CameraWebServer y qué ajustes de PSRAM y de particiones debes usar. Después verás las causas de los errores más habituales, Camera init failed with error 0x105 y brownout, controlarás el LED de flash y crearás un sketch que guarda una foto en la microSD al pulsar un botón.

Módulo de cámara ESP32-CAM de AI-Thinker
ESP32-CAM: módulo ESP32-S, cámara OV2640, ranura microSD y LED de flash en una sola placa. No tiene conector USB, así que necesitas un adaptador para programarla.

¿Qué es la ESP32-CAM y cómo funciona?

El corazón de la placa es el módulo ESP32-S, que lleva el chip ESP32 de doble núcleo con Wi-Fi y Bluetooth. La cámara se conecta a un conector de 24 pines de la placa mediante un cable plano fino (FPC). El ESP32 envía a la cámara una señal de reloj de 20 MHz (XCLK) por el GPIO 0 y la configura a través del bus SCCB, parecido al I2C, en los GPIO 26 y 27. Como el sensor OV2640 puede comprimir la imagen en JPEG por sí mismo, al ESP32 le llegan pequeñas imágenes JPEG en lugar de píxeles en bruto. Estas imágenes pasan por un bus de datos paralelo de 8 bits a los 4 MB de PSRAM de la placa, y el Wi-Fi las lleva al navegador o a un servidor.

CaracterísticaValor
ProcesadorESP32 (módulo ESP32-S), doble núcleo, hasta 240 MHz
InalámbricoWi-Fi 802.11 b/g/n (solo 2,4 GHz), Bluetooth 4.2 y BLE
Memoria520 KB de SRAM interna + 4 MB de PSRAM, 4 MB de flash
CámaraOV2640, 2 MP, hasta 1600×1200 (UXGA), salida JPEG
AlmacenamientoRanura microSD (hasta 4 GB según la documentación oficial)
LuzLED de flash blanco (GPIO 4), LED rojo de estado en la parte trasera (GPIO 33)
Alimentación5 V en el pin 5V (recomendado) o 3,3 V en el pin 3V3
Consumo (a 5 V)Unos 180 mA con el flash apagado y unos 310 mA con el flash al máximo; los picos de Wi-Fi son mayores
Tamaño27 × 40,5 × 4,5 mm

Pines de la ESP32-CAM de AI-Thinker: ¿cuáles están libres?

En los dos bordes de la placa hay 16 pines, pero solo unos pocos están realmente libres: la cámara usa por sí sola 15 GPIO y la ranura microSD comparte otros seis. La tabla resume los pines del borde y cuándo puedes usarlos. También puedes consultar las características generales de los pines del ESP32 en la herramienta Pinout.

PinFunción¿Uso libre?
5VEntrada de alimentación (recomendada)-
3V3Entrada de alimentación de 3,3 V-
GND (3 pines)Tierra-
VCCSalida de alimentación (3,3 V por defecto)No la uses para alimentar la placa
U0R (GPIO 3)RX serie: programación y Monitor SerieSolo si no necesitas el puerto serie
U0T (GPIO 1)TX serie: programación y Monitor SerieSolo si no necesitas el puerto serie
GPIO 0Reloj de la cámara (XCLK) y modo de arranqueNo; solo se conecta a GND al subir el código
GPIO 16Conectado a la PSRAM en muchas placasNo
GPIO 2SD DATA0Si no usas la SD; pin de arranque (strapping)
GPIO 4SD DATA1 y LED de flashCon la SD en modo de 1 bit o sin SD
GPIO 12SD DATA2Con la SD en modo de 1 bit o sin SD; debe estar en LOW al arrancar
GPIO 13SD DATA3Con la SD en modo de 1 bit o sin SD; el pin libre más seguro
GPIO 14SD CLKSi no usas la SD
GPIO 15SD CMDSi no usas la SD; pin de arranque (strapping)
GPIO 33LED rojo (no está en el borde)Solo el LED; se enciende con LOW
El pin VCC no es una entrada, sino la salida del regulador de la placa, y por defecto da 3,3 V. Si conectas aquí 5 V, llevas la línea de 3,3 V directamente a 5 V y puedes quemar el ESP32; alimenta siempre la placa por el pin 5V. Además, si el GPIO 12 está en HIGH al arrancar, el ESP32 intenta hacer funcionar la flash a 1,8 V y la placa no arranca, así que no conectes a este pin una resistencia pull-up ni un módulo que lo lleve a HIGH.

¿Cómo se programa la ESP32-CAM? Dos opciones

El chip USB-serie que permite a las placas ESP32 normales hablar con el ordenador no está en la ESP32-CAM. Para subir el código tienes dos opciones: el adaptador ESP32-CAM-MB, que se coloca debajo de la placa (una pequeña placa base con chip CH340 y conector micro USB), o un convertidor USB-TTL que ya tengas (FTDI, CH340, CP2102). Elijas el que elijas, la lógica es la misma: si el GPIO 0 está en LOW al arrancar, el ESP32 entra en modo de descarga (download mode) y espera el código; si está en HIGH, ejecuta el programa de la flash. El botón IO0 del adaptador MB y el cable IO0-GND que pones con el USB-TTL hacen exactamente eso.

Convertidor USB-TTL CP2102
Convertidor USB-TTL CP2102: para programar la ESP32-CAM bastan los pines GND, 5V, TX y RX.
Convertidor USB-TTLESP32-CAMNota
GNDGNDTierra común
5V5VAlimenta la placa; la salida de 3,3 V del convertidor no es suficiente
TXU0R (GPIO 3)Cruzado: transmisor a receptor
RXU0T (GPIO 1)Cruzado: receptor a transmisor
-Entre IO0 y GNDSolo al subir el código; un cable corto entre los dos pines contiguos

Si tu convertidor tiene un jumper para elegir entre 3,3 V y 5 V, ponlo en 3,3 V para que la línea TX tenga un nivel adecuado para los pines del ESP32. Eso sí, alimenta la placa desde el pin 5V del convertidor. La salida de 3,3 V de la mayoría de los convertidores solo da unos 50–100 mA; en cuanto la ESP32-CAM activa el Wi-Fi, esa alimentación cae y la placa se reinicia.

Ajustes del Arduino IDE: placa, esquema de particiones y PSRAM

  1. Abre el Gestor de placas del Arduino IDE e instala el paquete esp32 by Espressif Systems; lo explicamos en detalle en instalar el Arduino IDE.
  2. Elige la placa AI Thinker ESP32-CAM en Herramientas > Placa > esp32.
  3. Comprueba que Partition Scheme esté en Huge APP (3MB No OTA/1MB SPIFFS); el ejemplo de la cámara necesita al menos 3 MB para la aplicación.
  4. Conecta la placa al adaptador o al convertidor y elige el puerto nuevo en Herramientas > Puerto (COMx en Windows, /dev/cu.usbserial... o /dev/cu.wchusbserial... en macOS).
  5. Si no aparece ningún puerto, instala el driver del CH340 o del CP2102 y usa un cable USB que transmita datos.
AjusteValor recomendado¿Por qué?
PlacaAI Thinker ESP32-CAMTrae ya configurados la PSRAM, los 4 MB de flash y el esquema de particiones
Partition SchemeHuge APP (3MB No OTA/1MB SPIFFS)Los 3 MB de aplicación que necesita CameraWebServer
PSRAMSiempre activa en esta placaCon ESP32 Dev Module elige PSRAM: Enabled; en ESP32 Wrover Module ya está activa
CPU Frequency240MHz (WiFi/BT)Máxima velocidad para la imagen y el Wi-Fi
Flash Mode / Flash FrequencyQIO / 80MHzSi falla la carga o el arranque, prueba DIO / 40MHz
Core Debug LevelNone (Info para buscar fallos)En Info, el Monitor Serie muestra datos de la cámara y los FPS
Upload Speed460800 (fija en esta placa)Si la carga se corta a menudo, elige ESP32 Wrover Module y prueba 115200
Abre siempre el Monitor Serie a 115200 baudios. Los mensajes de arranque solo aparecen en el momento del reinicio, así que si la pantalla está vacía, pulsa el botón RST de la placa. Si ves waiting for download, el IO0 sigue conectado a GND; quita el cable, pulsa RST de nuevo y tu programa empezará a funcionar.

La primera carga, paso a paso

  1. Haz el cableado: coloca la placa sobre el adaptador MB con los pines alineados o conecta el convertidor USB-TTL según la tabla anterior. Si usas el USB-TTL, pon también el cable corto entre IO0 y GND.
  2. Pon la placa en modo de descarga: en el adaptador MB, mantén pulsado el botón IO0, pulsa y suelta RST y luego suelta IO0. Con el USB-TTL basta con pulsar RST mientras el cable IO0-GND está puesto. Algunos adaptadores MB con circuito de reinicio automático suben el código sin pulsar nada.
  3. Haz clic en Subir en el Arduino IDE. En la salida aparece primero Connecting... y luego el progreso de escritura en porcentaje.
  4. Cuando aparezca la línea Hard resetting via RTS pin..., la carga habrá terminado. Si usas el USB-TTL, quita ahora el cable IO0-GND.
  5. Abre el Monitor Serie a 115200 baudios y pulsa RST; el nuevo programa empieza a funcionar.
Arduino (C++)
1// ESP32-CAM ilk yükleme testi / ESP32-CAM first upload test
2const int KIRMIZI_LED = 33;   // arkadaki kırmızı LED, ters mantık / red LED on the back, inverted logic
3
4void setup() {
5  Serial.begin(115200);
6  pinMode(KIRMIZI_LED, OUTPUT);
7  delay(500);
8
9  // PSRAM kontrolü / PSRAM check
10  if (psramFound()) {
11    Serial.print("PSRAM bulundu / PSRAM found: ");
12    Serial.print(ESP.getPsramSize());
13    Serial.println(" bayt / bytes");
14  } else {
15    Serial.println("PSRAM yok / No PSRAM");
16  }
17}
18
19void loop() {
20  digitalWrite(KIRMIZI_LED, LOW);    // LOW = yanar / LOW = on
21  delay(500);
22  digitalWrite(KIRMIZI_LED, HIGH);   // HIGH = söner / HIGH = off
23  delay(500);
24}

Si la carga ha funcionado, el pequeño LED rojo de la parte trasera parpadea cada medio segundo. Este LED funciona con lógica invertida: se enciende con LOW y se apaga con HIGH. En el Monitor Serie deberías ver unos 4 millones de bytes de PSRAM; si pone No PSRAM, revisa la placa elegida y, si no se arregla, puede que tu placa no tenga chip de PSRAM. Hacer esta prueba corta antes del ejemplo de la cámara te dice enseguida si el problema está en la carga o en la cámara.

El ejemplo CameraWebServer: imagen en directo en el navegador

  1. Abre Archivo > Ejemplos > ESP32 > Camera > CameraWebServer.
  2. Elige el modelo de cámara: en la lista de la pestaña board_config.h (versiones nuevas) o al principio del archivo principal (versiones antiguas), añade // delante de la línea CAMERA_MODEL_ESP_EYE y quita las // de delante de CAMERA_MODEL_AI_THINKER.
  3. Escribe en las líneas ssid y password el nombre y la contraseña de tu red Wi-Fi de 2,4 GHz.
  4. Pon la placa en modo de descarga y sube el código; después quita la conexión de IO0 y pulsa RST.
  5. En el Monitor Serie verás una línea como Camera Ready! Use 'http://192.168.1.45' to connect; abre esa dirección en el navegador de un móvil o un ordenador conectado a la misma red.
  6. Inicia la imagen en directo con el botón Start Stream o haz una sola foto con Get Still.
Arduino (C++)
1// board_config.h (eski sürümlerde CameraWebServer.ino) / (CameraWebServer.ino in older versions)
2//#define CAMERA_MODEL_ESP_EYE      // Has PSRAM  <- kapat / comment out
3#define CAMERA_MODEL_AI_THINKER     // Has PSRAM  <- aç / enable
4
5// CameraWebServer.ino
6const char *ssid = "AgAdi";          // Wi-Fi adı / Wi-Fi name
7const char *password = "Sifre123";   // Wi-Fi şifresi / Wi-Fi password

La interfaz funciona con dos servidores distintos: la página de ajustes y la dirección /capture, que devuelve una sola foto, están en el puerto 80, mientras que el vídeo en directo está en /stream en el puerto 81 (p. ej. http://192.168.1.45:81/stream). Puedes añadir esta dirección del stream a tu propia página web o a un programa de domótica. En el menú de la izquierda cambias la resolución, la calidad JPEG, el brillo, el contraste y el balance de blancos, y si la imagen sale al revés, usa los interruptores V-Flip y H-Mirror; las versiones nuevas tienen además un control deslizante LED Intensity para el flash. La placa suele atender a un solo espectador del vídeo a la vez, y un stream abierto en una segunda pestaña puede congelarse. Si la página no abre, comprueba que el móvil y la placa estén en la misma red; para problemas de conexión, mira el ESP32 no se conecta al Wi-Fi.

Tabla de resolución y FPS de la ESP32-CAM

Sobre el papel, el sensor OV2640 da 15 fotogramas por segundo a 1600×1200, 30 a 800×600 y 60 en tamaño CIF. En la práctica, la velocidad la marcan sobre todo la conexión Wi-Fi y el tamaño de cada imagen JPEG: al subir la resolución y la calidad, cada fotograma pesa más y tarda más en cruzar la red. Los valores de abajo son rangos aproximados con CameraWebServer, buena señal Wi-Fi y calidad JPEG de 10–12. Para medir tu propia placa, pon Core Debug Level en Info; durante el stream, el Monitor Serie escribe para cada fotograma una línea como MJPG: ... (x fps).

ResoluciónPíxelesFPS aprox. (stream Wi-Fi)Ideal para
QQVGA160×12025–30Detección de movimiento, redes muy débiles
QVGA320×24020–30Coche robot, vídeo en directo fluido
CIF400×29615–25Vista fluida en pantallas pequeñas
VGA640×48010–20Vídeo en directo de uso general
SVGA800×6008–15Imagen más nítida; el tamaño máximo sin PSRAM
XGA1024×7685–10Imágenes con más detalle
HD1280×7204–8Encuadre panorámico (16:9)
SXGA1280×10243–6Fotos
UXGA1600×12002–5Fotos a la máxima resolución

En tu propio código puedes cambiar la resolución, la calidad y la orientación de la imagen a través del objeto del sensor, una vez que la cámara se ha iniciado correctamente. La calidad JPEG es un número de 0 a 63, y un número más bajo significa más calidad; bajar de 10 hace que los fotogramas pesen más y puede dar imágenes a medias.

Arduino (C++)
1// esp_camera_init() başarılı olduktan sonra / after esp_camera_init() succeeds
2sensor_t *s = esp_camera_sensor_get();
3s->set_framesize(s, FRAMESIZE_VGA);   // 640x480 çözünürlük / resolution
4s->set_quality(s, 12);                // 0-63: küçük = daha kaliteli, 10 altı önerilmez / lower = better, below 10 not advised
5s->set_vflip(s, 1);                   // görüntüyü dikey çevir / flip vertically
6s->set_hmirror(s, 1);                 // yatay ayna / mirror horizontally
7s->set_brightness(s, 1);              // parlaklık -2..2 / brightness -2..2

¿Por qué es tan importante la PSRAM en la ESP32-CAM?

La memoria interna del ESP32 es de 520 KB, y buena parte la usa la pila Wi-Fi. En cambio, una sola imagen JPEG de 1600×1200 puede ocupar entre 100 y 250 KB según la escena y la calidad. Por eso el driver de la cámara coloca sus búferes de imagen (frame buffer) en la PSRAM. CameraWebServer comprueba con la función psramFound() si hay PSRAM: si la hay, empieza con la resolución máxima y dos búferes; si no, limita la resolución a SVGA (800×600) y deja un único búfer en la memoria interna.

Si pides una resolución alta sin la PSRAM activada, el Monitor Serie muestra frame buffer malloc failed y luego Camera init failed with error 0xffffffff. La solución es elegir AI Thinker ESP32-CAM como placa (con ESP32 Dev Module, pon Herramientas > PSRAM: Enabled) o bajar la resolución y dejar un solo búfer. Algunos clones baratos pueden no llevar chip de PSRAM; la línea de PSRAM del primer sketch de prueba lo revela al instante.

Camera init failed with error 0x105 y otros errores de la cámara

La mayoría de los errores de la cámara tienen una de tres causas: un modelo de cámara equivocado en el código, un cable plano mal encajado en el conector o una alimentación insuficiente. Leer el código de error del Monitor Serie acota la causa rápidamente:

Mensaje del Monitor SerieSignificadoSolución
Camera probe failed with error 0x105(ESP_ERR_NOT_FOUND)El ESP32 no encontró ninguna cámara en el bus SCCBComprueba que esté elegido CAMERA_MODEL_AI_THINKER, vuelve a encajar el cable plano, alimenta con 5 V / 2 A
Detected camera not supported y 0x106La misma situación en versiones nuevas del driver: cámara no encontrada o no reconocidaLos mismos pasos que con 0x105; si sigue, cambia el módulo de cámara
frame buffer malloc failed y 0xffffffffNo se pudo reservar memoria para el búfer de imagenActiva la PSRAM, baja la resolución, pon fb_count a 1
cam_hal: EV-VSYNC-OVF o FB-OVFLlegó un fotograma nuevo antes de procesar el anterior y se descartó unoInofensivo si aparece de vez en cuando; si es frecuente, baja la resolución y mejora la señal Wi-Fi
NO-SOI (JPEG start marker missing)Fotograma JPEG dañado o incompletoRevisa la alimentación y el cable plano, pon xclk_freq_hz a 10000000
Imagen a medias, verde o con rayasEl fotograma no cupo en el búfer o la alimentación tiene ruidoSube el valor de calidad JPEG a 12 o más, mejora la alimentación
Al conectar el cable plano, levanta la pestaña negra de bloqueo del conector, empuja el cable recto hasta el fondo y cierra la pestaña. Nunca conectes ni desconectes la cámara con la placa alimentada: pueden dañarse tanto la cámara como el ESP32. Y no olvides quitar el plástico protector de la lente de un módulo de cámara nuevo, o la imagen se verá borrosa.

Error de brownout y la alimentación correcta (5 V / 2 A)

Si el Monitor Serie muestra Brownout detector was triggered y la placa se reinicia sin parar, la tensión de alimentación del ESP32 ha caído por un instante por debajo de un nivel seguro. La ESP32-CAM consume picos de corriente breves pero altos en cuanto activa el transmisor Wi-Fi y la cámara empieza a capturar. Un puerto USB débil, cables jumper finos y largos o la salida de 3,3 V del convertidor no pueden con esos picos. Estas son las soluciones definitivas:

  • Usa una fuente de alimentación de 5 V y al menos 2 A y conéctala al pin 5V de la placa; el regulador de la placa la baja a 3,3 V.
  • Usa cables de alimentación cortos y gruesos; la protoboard y los jumpers largos aumentan la caída de tensión.
  • Añade un condensador electrolítico de 470–1000 µF entre los pines 5V y GND, lo más cerca posible de la placa (patilla positiva a 5V).
  • Si la alimentas desde el ordenador, conéctala directamente a un puerto trasero en lugar de a un hub USB.
  • Para funcionar con batería, usa una celda 18650 con un módulo elevador (boost) de 5 V; es mucho más estable que varias pilas AA en serie.
Batería de iones de litio 18650
Batería 18650 de iones de litio: junto con un elevador de 5 V da una alimentación estable a los proyectos de ESP32-CAM con batería.

En internet verás a menudo la línea WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0), que desactiva el detector de brownout por código. Detiene los reinicios, pero no resuelve el problema: la tensión sigue cayendo y ahora la placa puede bloquearse, generar imágenes dañadas o perder datos al escribir en la flash. Úsala solo para una prueba temporal; todos los mensajes de reinicio están explicados en ESP32 brownout y Guru Meditation. Para calcular la autonomía, cuenta con que la placa consume de media 180 mA transmitiendo sin parar: una 18650 de 2600 mAh con un elevador del 85 % de rendimiento da unos 1600 mAh en el lado de 5 V, es decir, unas 9 horas de vídeo. Calcula tus propios valores con la calculadora de duración de batería, y recuerda que incluso en deep sleep la placa consume unos 6 mA por el regulador y la PSRAM.

Controlar el LED de flash (GPIO 4)

El LED blanco y brillante de la parte delantera se controla mediante un transistor conectado al GPIO 4: el pin solo conmuta el transistor y la corriente alta del LED sale de la alimentación. Con digitalWrite(4, HIGH) se enciende y con LOW se apaga. El LED es muy potente y, si se queda encendido mucho tiempo, se calientan tanto él como la placa; lo mejor es encender el flash solo unos cientos de milisegundos al hacer la foto. El GPIO 4 es además la línea DATA1 de la microSD, así que con la tarjeta en modo de 4 bits el flash parpadea solo en cada lectura y escritura. Para evitarlo, inicia la SD en modo de 1 bit (SD_MMC.begin("/sdcard", true)); en algunas placas el LED puede seguir brillando muy levemente.

Guardar fotos en la microSD con la ESP32-CAM

El siguiente sketch enciende el flash, hace una foto a 1600×1200 y la guarda en la microSD como foto1.jpg, foto2.jpg... cada vez que pulsas un botón conectado al GPIO 13. Formatea la tarjeta en el ordenador como FAT32; aunque la documentación oficial habla de tarjetas de hasta 4 GB, en la práctica las de 16–32 GB en FAT32 suelen funcionar sin problemas. Conecta una patilla del pulsador al GPIO 13 y la otra a GND; el sketch activa la resistencia pull-up interna, así que no hace falta ninguna resistencia extra. Para entender cómo se conecta un pulsador, mira cómo conectar un botón a Arduino.

Arduino (C++)
1#include "esp_camera.h"
2#include "FS.h"
3#include "SD_MMC.h"
4
5// AI-Thinker ESP32-CAM kamera pinleri / AI-Thinker ESP32-CAM camera pins
6#define PWDN_GPIO_NUM     32
7#define RESET_GPIO_NUM    -1
8#define XCLK_GPIO_NUM      0
9#define SIOD_GPIO_NUM     26
10#define SIOC_GPIO_NUM     27
11#define Y9_GPIO_NUM       35
12#define Y8_GPIO_NUM       34
13#define Y7_GPIO_NUM       39
14#define Y6_GPIO_NUM       36
15#define Y5_GPIO_NUM       21
16#define Y4_GPIO_NUM       19
17#define Y3_GPIO_NUM       18
18#define Y2_GPIO_NUM        5
19#define VSYNC_GPIO_NUM    25
20#define HREF_GPIO_NUM     23
21#define PCLK_GPIO_NUM     22
22
23#define FLAS_LED  4    // beyaz flaş LED'i / white flash LED
24#define BUTON    13    // butonun diğer ucu GND'de / other button leg to GND
25
26int fotoNo = 1;        // sıradaki dosya numarası / next file number
27bool hazir = false;    // kamera ve SD hazır mı? / are camera and SD ready?
28
29bool kameraBaslat() {
30  camera_config_t config = {};
31  config.ledc_channel = LEDC_CHANNEL_0;
32  config.ledc_timer   = LEDC_TIMER_0;
33  config.pin_d0 = Y2_GPIO_NUM;
34  config.pin_d1 = Y3_GPIO_NUM;
35  config.pin_d2 = Y4_GPIO_NUM;
36  config.pin_d3 = Y5_GPIO_NUM;
37  config.pin_d4 = Y6_GPIO_NUM;
38  config.pin_d5 = Y7_GPIO_NUM;
39  config.pin_d6 = Y8_GPIO_NUM;
40  config.pin_d7 = Y9_GPIO_NUM;
41  config.pin_xclk     = XCLK_GPIO_NUM;
42  config.pin_pclk     = PCLK_GPIO_NUM;
43  config.pin_vsync    = VSYNC_GPIO_NUM;
44  config.pin_href     = HREF_GPIO_NUM;
45  config.pin_sccb_sda = SIOD_GPIO_NUM;
46  config.pin_sccb_scl = SIOC_GPIO_NUM;
47  config.pin_pwdn     = PWDN_GPIO_NUM;
48  config.pin_reset    = RESET_GPIO_NUM;
49  config.xclk_freq_hz = 20000000;           // 20 MHz kamera saati / 20 MHz camera clock
50  config.pixel_format = PIXFORMAT_JPEG;
51
52  if (psramFound()) {
53    config.frame_size   = FRAMESIZE_UXGA;   // 1600x1200
54    config.jpeg_quality = 10;               // küçük = daha kaliteli / lower = better quality
55    config.fb_count     = 2;
56    config.fb_location  = CAMERA_FB_IN_PSRAM;
57    config.grab_mode    = CAMERA_GRAB_LATEST;
58  } else {
59    config.frame_size   = FRAMESIZE_SVGA;   // PSRAM yoksa 800x600 / 800x600 without PSRAM
60    config.jpeg_quality = 12;
61    config.fb_count     = 1;
62    config.fb_location  = CAMERA_FB_IN_DRAM;
63    config.grab_mode    = CAMERA_GRAB_WHEN_EMPTY;
64  }
65
66  esp_err_t err = esp_camera_init(&config);
67  if (err != ESP_OK) {
68    Serial.printf("Camera init failed 0x%x (%s)\n", err, esp_err_to_name(err));
69    return false;
70  }
71  return true;
72}
73
74void fotoCek() {
75  digitalWrite(FLAS_LED, HIGH);              // flaşı yak / flash on
76  delay(150);                                // pozlama otursun / let exposure settle
77
78  camera_fb_t *fb = esp_camera_fb_get();     // eski kareyi at / discard the stale frame
79  if (fb) esp_camera_fb_return(fb);
80  fb = esp_camera_fb_get();                  // asıl fotoğraf / the real photo
81  digitalWrite(FLAS_LED, LOW);               // flaşı söndür / flash off
82
83  if (!fb) {
84    Serial.println("Kare alinamadi / Capture failed");
85    return;
86  }
87
88  String yol = "/foto" + String(fotoNo) + ".jpg";
89  File dosya = SD_MMC.open(yol, FILE_WRITE);
90  if (dosya) {
91    dosya.write(fb->buf, fb->len);           // JPEG verisini yaz / write the JPEG data
92    dosya.close();
93    Serial.printf("Kaydedildi / Saved: %s (%u bayt / bytes)\n", yol.c_str(), (unsigned)fb->len);
94    fotoNo++;
95  } else {
96    Serial.println("Dosya acilamadi / Could not open file");
97  }
98  esp_camera_fb_return(fb);                  // tamponu geri ver / return the buffer
99}
100
101void setup() {
102  Serial.begin(115200);
103  pinMode(BUTON, INPUT_PULLUP);
104
105  if (!kameraBaslat()) return;               // kamera yoksa dur / stop without a camera
106
107  // 1-bit mod: GPIO 4, 12 ve 13 boşta kalır / 1-bit mode keeps GPIO 4, 12 and 13 free
108  if (!SD_MMC.begin("/sdcard", true)) {
109    Serial.println("SD kart takilamadi / SD card mount failed");
110    return;
111  }
112  if (SD_MMC.cardType() == CARD_NONE) {
113    Serial.println("SD kart yok / No SD card");
114    return;
115  }
116
117  pinMode(FLAS_LED, OUTPUT);
118  digitalWrite(FLAS_LED, LOW);
119
120  // Var olan fotoğrafların üzerine yazma / don't overwrite existing photos
121  while (SD_MMC.exists("/foto" + String(fotoNo) + ".jpg")) fotoNo++;
122
123  hazir = true;
124  Serial.println("Hazir, butona bas / Ready, press the button");
125}
126
127void loop() {
128  if (!hazir) {                              // hata varsa bekle / wait if setup failed
129    delay(1000);
130    return;
131  }
132  if (digitalRead(BUTON) == LOW) {
133    delay(30);                               // buton sıçramasını (bounce) önle / debounce
134    if (digitalRead(BUTON) == LOW) {
135      fotoCek();
136      while (digitalRead(BUTON) == LOW) delay(10);   // bırakılmasını bekle / wait for release
137    }
138  }
139}

Como el sketch inicia la SD en modo de 1 bit, solo usa los GPIO 2, 14 y 15, y quedan libres el GPIO 4 para el flash y el GPIO 13 para el botón. Antes de la foto se toma un fotograma y se devuelve enseguida: la cámara genera imágenes sin parar, así que el primer fotograma del búfer puede ser de antes de encender el flash, y la exposición automática necesita una breve pausa para adaptarse a la nueva luz. El número de archivo se calcula mirando los archivos que ya hay en la tarjeta, así que las fotos antiguas no se sobrescriben aunque la placa se reinicie. Para las reglas generales de registro de datos en SD, echa un vistazo a el módulo de tarjeta SD.

MicroPython y placas de cámara más nuevas

También puedes programar la ESP32-CAM con MicroPython, pero la versión oficial de MicroPython no incluye driver de cámara; tienes que cargar un firmware de la comunidad que añada esa función. Por eso, para empezar, el camino del Arduino IDE es mucho más sencillo. Si prefieres no pelearte con una placa sin USB, mira también las placas de cámara basadas en el ESP32-S3, con USB y más memoria (p. ej. Seeed XIAO ESP32S3 Sense o ESP32-S3-EYE); también aparecen en la lista de modelos de CameraWebServer.

Ideas de proyectos con la ESP32-CAM

  • Foto al detectar movimiento: haz una foto cuando un sensor PIR detecte a alguien y envíala al móvil; la guía paso a paso está en fotos de la ESP32-CAM a Telegram.
  • Time-lapse: que la placa se despierte cada 10 minutos, haga una foto, la guarde en la SD y vuelva al deep sleep; observa cómo crece una planta o cómo cambia el tiempo.
  • Cámara para el timbre: fotografía la puerta cuando alguien llame y envía un aviso con un bot de Telegram.
  • Coche robot con vídeo: conduce el coche mientras ves en el móvil un vídeo fluido en QVGA.
  • Cámara para mascotas: mira el vídeo en directo en la red de casa y enciende el flash desde la página web cuando haga falta.
  • Tu propio panel de control: inserta el vídeo en tu propia página web y añade junto a él interruptores de relé y lecturas de sensores; la guía ESP32 WebSocket te enseña cómo.

Errores frecuentes y cómo solucionarlos

SíntomaCausa probableSolución
Failed to connect to ESP32: No serial data received (Timed out waiting for packet header en versiones antiguas)La placa no está en modo de descarga, o TX y RX están malConecta IO0 a GND o usa el botón IO0 y pulsa RST; comprueba que TX vaya a U0R y RX a U0T
Wrong boot mode detected (0x13)El GPIO 0 no estaba en LOW al arrancarPulsa siempre RST después de hacer la conexión IO0-GND
waiting for download en el Monitor SerieEl IO0 sigue conectado a GNDQuita el cable de IO0 y pulsa RST
Caracteres extraños en el Monitor SerieVelocidad en baudios incorrectaPon el Monitor Serie a 115200 baudios
La placa no aparece en la lista de puertosFalta el driver o el cable solo sirve para cargarInstala el driver del CH340 o del CP2102 y usa un cable de datos
La carga falla con la tarjeta SD puestaEl GPIO 2 es a la vez línea de la SD y pin de arranqueQuita la microSD mientras subes el código
Imagen muy lenta o que se congela a menudoSeñal Wi-Fi débil o resolución altaBaja a VGA o QVGA, acerca la placa al router y usa una antena externa si hace falta
El flash brilla débilmente todo el tiempoSD en modo de 4 bits o GPIO 4 al aireInicia la SD en modo de 1 bit y pon el GPIO 4 como OUTPUT en LOW
Si quieres conectar una antena externa (IPEX), la posición de una diminuta resistencia de 0 Ω junto a la antena decide cuál usa la placa; no basta con enchufar la antena, también tienes que mover la resistencia. Si la placa no arranca o la SD no se inicia, desconecta los módulos de los GPIO 2, 12 y 13 y vuelve a probar: el 2 y el 12 son pines de arranque, y el 13 es la línea DATA3 de la SD, que no debe estar en LOW mientras se inicializa la tarjeta.

La ESP32-CAM es la forma más fácil de montar una cámara Wi-Fi con una placa económica, y casi todas las dificultades vienen de la conexión de programación o de la alimentación. Cuando resuelves esos dos puntos, la placa emite vídeo en directo desde su propio servidor web, hace fotos y las guarda en la SD. En la app BlueGrays encontrarás proyectos con ESP32 como la conexión Wi-Fi, un servidor web, mDNS, registro de datos en microSD y una alarma de movimiento con avisos por Telegram, cada uno con su esquema de circuito paso a paso y su código listo para usar.

Preguntas frecuentes

¿Cómo se programa la ESP32-CAM?

Como la ESP32-CAM no tiene conector USB, necesitas un adaptador ESP32-CAM-MB o un convertidor USB-TTL. En el Arduino IDE eliges la placa AI Thinker ESP32-CAM y pones la placa en modo de descarga pulsando RST mientras el GPIO 0 está conectado a GND (o mientras mantienes pulsado el botón IO0 del MB). Al terminar la carga, quitas la conexión de IO0 y vuelves a pulsar RST.

¿Se puede programar la ESP32-CAM con un Arduino Uno?

Sí; si conectas el pin RESET del Uno a GND, su chip USB funciona como un puente USB-serie. En ese caso la conexión es directa, no cruzada: el D0 (RX) del Uno va a U0R, el D1 (TX) va a U0T y el IO0 sigue conectado a GND. Como las señales del Uno son de 5 V, esto lleva al ESP32 al límite; para un uso continuado es más seguro un adaptador MB o un convertidor USB-TTL de 3,3 V.

¿Con cuántos voltios funciona la ESP32-CAM?

Lo recomendable es alimentarla con 5 V por el pin 5V; el regulador de la placa los baja a 3,3 V. También puedes darle 3,3 V por el pin 3V3, pero si la fuente no aguanta los picos de corriente del Wi-Fi, la placa se reiniciará una y otra vez. Una fuente que dé al menos 2 A evita la mayoría de los errores de brownout.

¿Cómo se soluciona el error Camera init failed de la ESP32-CAM?

Los códigos 0x105 o 0x106 indican que no se encontró ninguna cámara: primero comprueba que en el código esté elegido CAMERA_MODEL_AI_THINKER, luego que el cable plano esté bien encajado, y alimenta la placa con 5 V / 2 A. Si el problema sigue, el módulo de cámara puede estar averiado. Si ves 0xffffffff junto con frame buffer malloc failed, activa la PSRAM o baja la resolución.

¿Funciona la ESP32-CAM sin internet?

Sí. Para ver la imagen solo necesitas una red local, no internet; la ESP32-CAM también puede crear su propia red Wi-Fi con WiFi.softAP() y entonces se abre en el navegador en la dirección 192.168.4.1. Incluso puedes usarla sin ninguna red, como una cámara que solo guarda fotos en la microSD.

¿La ESP32-CAM puede grabar vídeo?

Los ejemplos incluidos transmiten la imagen en directo como MJPEG y hacen fotos sueltas; no graban un archivo de vídeo directamente. Hay proyectos de la comunidad que escriben fotogramas JPEG consecutivos en la microSD para formar un archivo AVI, pero la velocidad es limitada incluso a baja resolución. La placa no tiene micrófono, así que tampoco graba sonido.

Ver todos los proyectos
LED Parpadeante con ESP32
#103Principiante

LED Parpadeante con ESP32

Enseña el uso básico de la salida GPIO con ESP32. Conseguimos un efecto de parpadeo encendiendo y apagando un LED desde el pin digital. Versión para ESP32 del clásico proyecto blink en Arduino UNO; los comandos básicos de blink en el entorno Arduino son los mismos, pero la distribución de pines y los niveles GPIO de 3,3 V del ESP32 difieren de los del Arduino UNO.

4.7(36)
96
Parpadeo del LED interno del ESP32
#106Principiante

Parpadeo del LED interno del ESP32

Parpadeo del LED azul incorporado en el ESP32 DevKit V1. ¡No se necesitan componentes externos! El primer proyecto que debe probar cuando compra un ESP32. GPIO 2 está conectado al LED interno.

4.8(29)
53
Conexión Wi-Fi STA con ESP32 (con pantalla LCD)
#127Avanzado
Premium

Conexión Wi-Fi STA con ESP32 (con pantalla LCD)

En este proyecto, conectamos el ESP32 a la red Wi-Fi doméstica en modo Station (STA) de forma segura y tolerante a fallos. Separamos el SSID y la contraseña en el archivo `secrets.h` para evitar que se filtren a Git, configuramos un mecanismo de reconexión automática y mostramos el nivel de señal RSSI y la dirección IP en una pantalla LCD I2C. El LED interno actúa como indicador de estado.

4.4(21)
33
Servidor web asíncrono ESP32 (con indicación de IP en la pantalla LCD)
#129Avanzado
Premium

Servidor web asíncrono ESP32 (con indicación de IP en la pantalla LCD)

En este proyecto, convertimos el ESP32 en un **servidor web asíncrono** que puedes controlar desde tu teléfono o tu ordenador, siempre que estén conectados a la misma red Wi-Fi. Gracias a la biblioteca ESPAsyncWebServer, el servidor puede procesar varias solicitudes al mismo tiempo (a diferencia del clásico `WebServer.h`, que se bloquea con una sola solicitud).

4.8(16)
26
ESP32 mDNS: Acceso al dispositivo mediante bluegrays-esp.local (con pantalla LCD)
#131Avanzado
Premium

ESP32 mDNS: Acceso al dispositivo mediante bluegrays-esp.local (con pantalla LCD)

En este proyecto, al añadir el servicio mDNS (Multicast DNS) al ESP32, permitimos el acceso mediante un nombre de host legible, como `bluegrays-esp.local`, en lugar de una dirección IP. Aunque la IP asignada por el DHCP cambie, siempre podrás acceder al dispositivo con el mismo nombre. Además, al ejecutar un pequeño servidor web en él, enviamos comandos de control de los LED desde el navegador mediante la dirección `http://bluegrays-esp.local/`. En la pantalla LCD I2C se muestran el nombre de ho

4.8(14)
23
Registrador de Temperatura ESP32 (DHT22 + DS1307 RTC + microSD + OLED)
#144Avanzado
Premium

Registrador de Temperatura ESP32 (DHT22 + DS1307 RTC + microSD + OLED)

¡Construye un registrador de temperatura con marca de tiempo con ESP32! Lee temperatura/humedad del DHT22 cada minuto, obtén la hora real del DS1307 RTC y registra en tarjeta microSD como CSV. El OLED muestra en vivo la temperatura (fuente grande), porcentaje de humedad, marca de tiempo y contador de registros. El archivo `/temp_log.csv` en la tarjeta SD se abre en Excel, Google Sheets o Python pandas para análisis — perfecto para monitoreo de invernadero, seguimiento de temperatura del hog

4.7(7)
12
Sistema de Alarma de Movimiento ESP32 (PIR + Buzzer + LED + Telegram)
#145Avanzado
Premium

Sistema de Alarma de Movimiento ESP32 (PIR + Buzzer + LED + Telegram)

Un sistema inteligente de alarma de seguridad que activa el buzzer y el LED cuando el sensor PIR detecta movimiento, y envía simultáneamente una notificación instantánea al propietario vía Telegram. Cuenta con un tiempo de espera de 30 segundos para limitar la frecuencia de las alarmas repetidas; este mecanismo no comprueba la validez de las detecciones del sensor PIR ni elimina las falsas detecciones. Ideal para seguridad del hogar, vigilancia de garajes, almacenes o salas de trabajo. Con ESP32

0.0(0)
8
Alarma con sensor de movimiento ESP32
#140Intermedio
Premium

Alarma con sensor de movimiento ESP32

En este proyecto, elaborado con un ESP32 y un sensor PIR, cuando se detecta movimiento, el zumbador se activa y emite una alarma sonora. Se trata de una aplicación sencilla y económica para un sistema de seguridad. (Las imágenes son ilustrativas; por favor, conéctelas según las instrucciones)

4.4(10)
15