ESP32-CAM: guida per programmarla, streaming video e foto su SD
Come programmare l'ESP32-CAM: pinout AI-Thinker, caricamento con ESP32-CAM-MB o USB-TTL, CameraWebServer, PSRAM, errori 0x105 e brownout, flash e foto su SD.
L'ESP32-CAM è una scheda telecamera Wi-Fi economica che, pur misurando solo 27 × 40 mm, integra un processore ESP32, una fotocamera OV2640 da 2 megapixel, uno slot per scheda microSD e un LED flash bianco. Da sola si collega alla rete di casa, trasmette il video in diretta al browser, scatta foto e le salva sulla scheda SD o le invia su internet. È la scheda più usata per telecamere di sorveglianza, videocitofoni, time-lapse della crescita delle piante e robot car con telecamera, ma poiché non ha una presa USB, la messa in funzione è un po' diversa da quella delle schede ESP32 a cui forse sei abituato.
In questa guida scoprirai il pinout dell'ESP32-CAM di AI-Thinker, come programmarla con l'adattatore ESP32-CAM-MB o con un convertitore USB-TTL (compreso il collegamento IO0-GND), come vedere l'immagine in diretta nel browser con l'esempio CameraWebServer e quali impostazioni di PSRAM e di partizione usare. Poi vedrai le cause degli errori più comuni, Camera init failed with error 0x105 e brownout, controllerai il LED flash e scriverai uno sketch che salva una foto sulla microSD quando premi un pulsante.

Cos'è l'ESP32-CAM e come funziona?
Il cuore della scheda è il modulo ESP32-S, che contiene il chip ESP32 dual core con Wi-Fi e Bluetooth. La fotocamera si inserisce in un connettore a 24 pin della scheda tramite un sottile cavo flat (FPC). L'ESP32 invia alla fotocamera un segnale di clock a 20 MHz (XCLK) sul GPIO 0 e la configura attraverso il bus SCCB, simile all'I2C, sui GPIO 26 e 27. Poiché il sensore OV2640 sa comprimere da solo l'immagine in JPEG, all'ESP32 arrivano piccoli fotogrammi JPEG invece di pixel grezzi. Questi fotogrammi passano su un bus dati parallelo a 8 bit fino ai 4 MB di PSRAM della scheda, e il Wi-Fi li porta al browser o a un server.
| Caratteristica | Valore |
|---|---|
| Processore | ESP32 (modulo ESP32-S), dual core, fino a 240 MHz |
| Wireless | Wi-Fi 802.11 b/g/n (solo 2,4 GHz), Bluetooth 4.2 e BLE |
| Memoria | 520 KB di SRAM interna + 4 MB di PSRAM, 4 MB di flash |
| Fotocamera | OV2640, 2 MP, fino a 1600×1200 (UXGA), uscita JPEG |
| Archiviazione | Slot microSD (fino a 4 GB secondo la documentazione ufficiale) |
| Luce | LED flash bianco (GPIO 4), LED di stato rosso sul retro (GPIO 33) |
| Alimentazione | 5 V sul pin 5V (consigliato) oppure 3,3 V sul pin 3V3 |
| Corrente (a 5 V) | Circa 180 mA con flash spento, circa 310 mA con flash alla massima luminosità; i picchi del Wi-Fi sono più alti |
| Dimensioni | 27 × 40,5 × 4,5 mm |
Pinout dell'ESP32-CAM AI-Thinker: quali pin sono liberi?
Sui due lati della scheda ci sono 16 pin, ma solo pochi sono davvero liberi: la fotocamera da sola usa 15 GPIO e lo slot microSD ne condivide altri sei. La tabella riassume i pin sui lati e quando puoi usarli. Puoi consultare anche le caratteristiche generali dei pin dell'ESP32 nello strumento Pinout.
| Pin | Funzione | Uso libero? |
|---|---|---|
| 5V | Ingresso di alimentazione (consigliato) | - |
| 3V3 | Ingresso di alimentazione a 3,3 V | - |
| GND (3 pin) | Massa | - |
| VCC | Uscita di alimentazione (3,3 V di default) | Non usarlo per alimentare la scheda |
| U0R (GPIO 3) | RX seriale: programmazione e Monitor seriale | Solo se non serve la porta seriale |
| U0T (GPIO 1) | TX seriale: programmazione e Monitor seriale | Solo se non serve la porta seriale |
| GPIO 0 | Clock della fotocamera (XCLK) e modalità di avvio | No; va a GND solo durante il caricamento |
| GPIO 16 | Collegato alla PSRAM su molte schede | No |
| GPIO 2 | SD DATA0 | Se la SD non è usata; pin di strapping |
| GPIO 4 | SD DATA1 e LED flash | Con la SD in modalità 1 bit o senza SD |
| GPIO 12 | SD DATA2 | Con la SD in modalità 1 bit o senza SD; deve essere LOW all'avvio |
| GPIO 13 | SD DATA3 | Con la SD in modalità 1 bit o senza SD; il pin libero più sicuro |
| GPIO 14 | SD CLK | Se la SD non è usata |
| GPIO 15 | SD CMD | Se la SD non è usata; pin di strapping |
| GPIO 33 | LED rosso (non sui lati) | Solo LED; si accende con LOW |
Come si programma l'ESP32-CAM? Due modi
Il chip USB-seriale che permette alle normali schede ESP32 di comunicare con il computer sull'ESP32-CAM non c'è. Per caricare il codice hai due possibilità: l'adattatore ESP32-CAM-MB, che si innesta sotto la scheda (una piccola base con chip CH340 e presa micro USB), oppure un convertitore USB-TTL che hai già (FTDI, CH340, CP2102). Qualunque strada tu scelga, il principio è lo stesso: se all'avvio il GPIO 0 è LOW, l'ESP32 entra in modalità download e aspetta il codice; se è HIGH, esegue il programma nella flash. Il pulsante IO0 dell'adattatore MB e il filo IO0-GND aggiunto con il convertitore USB-TTL fanno esattamente questo.

| Convertitore USB-TTL | ESP32-CAM | Nota |
|---|---|---|
| GND | GND | Massa comune |
| 5V | 5V | Alimenta la scheda; l'uscita a 3,3 V del convertitore non basta |
| TX | U0R (GPIO 3) | Incrociato: trasmettitore verso ricevitore |
| RX | U0T (GPIO 1) | Incrociato: ricevitore verso trasmettitore |
| - | Tra IO0 e GND | Solo durante il caricamento; un filo corto tra i due pin vicini |
Se il convertitore ha un jumper per scegliere tra 3,3 V e 5 V, mettilo su 3,3 V, così la linea TX resta a un livello adatto ai pin dell'ESP32. Alimenta però la scheda dal pin 5V del convertitore. L'uscita a 3,3 V della maggior parte dei convertitori fornisce solo circa 50–100 mA; appena l'ESP32-CAM accende il Wi-Fi, questa alimentazione crolla e la scheda si riavvia.
Impostazioni dell'Arduino IDE: scheda, schema di partizione e PSRAM
- Apri il Gestore schede dell'Arduino IDE e installa il pacchetto esp32 by Espressif Systems; i dettagli sono nella guida installare l'Arduino IDE.
- Scegli la scheda AI Thinker ESP32-CAM da Strumenti > Scheda > esp32.
- Verifica che Partition Scheme sia impostato su Huge APP (3MB No OTA/1MB SPIFFS); l'esempio della fotocamera richiede almeno 3 MB per l'applicazione.
- Collega la scheda all'adattatore o al convertitore e scegli la nuova porta da Strumenti > Porta (COMx su Windows, /dev/cu.usbserial... o /dev/cu.wchusbserial... su macOS).
- Se non compare nessuna porta, installa il driver CH340 o CP2102 e usa un cavo USB che trasmetta dati.
| Impostazione | Valore consigliato | Perché? |
|---|---|---|
| Scheda | AI Thinker ESP32-CAM | PSRAM, 4 MB di flash e schema di partizione corretto già impostati |
| Partition Scheme | Huge APP (3MB No OTA/1MB SPIFFS) | I 3 MB di applicazione richiesti da CameraWebServer |
| PSRAM | Sempre attiva su questa scheda | Con ESP32 Dev Module scegli PSRAM: Enabled; con ESP32 Wrover Module è già attiva |
| CPU Frequency | 240MHz (WiFi/BT) | Massima velocità per immagini e Wi-Fi |
| Flash Mode / Flash Frequency | QIO / 80MHz | Se il caricamento o l'avvio falliscono, prova DIO / 40MHz |
| Core Debug Level | None (Info per la diagnosi) | Con Info il Monitor seriale mostra i dati della fotocamera e gli FPS |
| Upload Speed | 460800 (fissa su questa scheda) | Se il caricamento si interrompe spesso, scegli ESP32 Wrover Module e prova 115200 |
Il primo caricamento passo dopo passo
- Fai i collegamenti: inserisci la scheda sull'adattatore MB con i pin allineati oppure collega il convertitore USB-TTL come nella tabella sopra. Se usi il convertitore USB-TTL, aggiungi anche il filo corto tra IO0 e GND.
- Metti la scheda in modalità download: sull'adattatore MB tieni premuto il pulsante IO0, premi e rilascia RST, poi rilascia IO0. Con il convertitore USB-TTL basta premere RST mentre il filo IO0-GND è inserito. Alcuni adattatori MB con circuito di reset automatico caricano anche senza premere nulla.
- Clicca su Carica nell'Arduino IDE. Nell'output compare prima Connecting... e poi l'avanzamento della scrittura in percentuale.
- Quando appare la riga Hard resetting via RTS pin..., il caricamento è finito. Se usi il convertitore USB-TTL, togli adesso il filo IO0-GND.
- Apri il Monitor seriale a 115200 baud e premi RST: il nuovo programma parte.
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}Se il caricamento è andato a buon fine, il piccolo LED rosso sul retro lampeggia ogni mezzo secondo. Questo LED funziona a logica invertita: si accende con LOW e si spegne con HIGH. Nel Monitor seriale dovresti vedere circa 4 milioni di byte di PSRAM; se compare No PSRAM, controlla la scheda selezionata e, se non cambia nulla, la tua scheda potrebbe non avere il chip PSRAM. Fare questo breve test prima dell'esempio della fotocamera ti dice subito se il problema è nel caricamento o nella fotocamera.
L'esempio CameraWebServer: immagine in diretta nel browser
- Apri File > Esempi > ESP32 > Camera > CameraWebServer.
- Scegli il modello di fotocamera: nell'elenco della scheda board_config.h (versioni recenti) o all'inizio del file principale (versioni vecchie), aggiungi // davanti alla riga CAMERA_MODEL_ESP_EYE e togli le // davanti a CAMERA_MODEL_AI_THINKER.
- Scrivi nelle righe ssid e password il nome e la password della tua rete Wi-Fi a 2,4 GHz.
- Metti la scheda in modalità download e carica lo sketch; poi togli il collegamento IO0 e premi RST.
- Nel Monitor seriale vedrai una riga come Camera Ready! Use 'http://192.168.1.45' to connect; apri questo indirizzo nel browser di uno smartphone o di un computer collegato alla stessa rete.
- Avvia l'immagine in diretta con il pulsante Start Stream oppure scatta una singola foto con Get Still.
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 passwordL'interfaccia usa due server separati: la pagina delle impostazioni e l'indirizzo /capture, che restituisce una singola foto, sono sulla porta 80, mentre lo streaming è su /stream alla porta 81 (es. http://192.168.1.45:81/stream). Puoi inserire questo indirizzo nella tua pagina web o in un software di domotica. Nel menu a sinistra puoi cambiare risoluzione, qualità JPEG, luminosità, contrasto e bilanciamento del bianco; se l'immagine è capovolta, usa gli interruttori V-Flip e H-Mirror, e le versioni recenti hanno anche un cursore LED Intensity per il flash. Di solito la scheda serve un solo spettatore dello streaming alla volta, e uno streaming aperto in una seconda scheda del browser può bloccarsi. Se la pagina non si apre, verifica che smartphone e scheda siano sulla stessa rete; per i problemi di connessione leggi l'ESP32 non si connette al Wi-Fi.
Tabella di risoluzione e FPS dell'ESP32-CAM
Sulla carta il sensore OV2640 produce 15 fotogrammi al secondo a 1600×1200, 30 a 800×600 e 60 in formato CIF. In pratica la frequenza dipende soprattutto dalla connessione Wi-Fi e dalle dimensioni dei fotogrammi JPEG: aumentando risoluzione e qualità, ogni fotogramma diventa più pesante e attraversa la rete più lentamente. I valori qui sotto sono intervalli indicativi ottenuti con CameraWebServer, un buon segnale Wi-Fi e qualità JPEG 10–12. Per misurare la tua scheda, imposta Core Debug Level su Info: durante lo streaming il Monitor seriale scrive per ogni fotogramma una riga come MJPG: ... (x fps).
| Risoluzione | Pixel | FPS indicativi (streaming Wi-Fi) | Ideale per |
|---|---|---|---|
| QQVGA | 160×120 | 25–30 | Rilevamento di movimento, reti molto deboli |
| QVGA | 320×240 | 20–30 | Robot car, video in diretta fluido |
| CIF | 400×296 | 15–25 | Visione fluida su schermi piccoli |
| VGA | 640×480 | 10–20 | Video in diretta per uso generale |
| SVGA | 800×600 | 8–15 | Immagine più nitida; dimensione massima senza PSRAM |
| XGA | 1024×768 | 5–10 | Immagini dettagliate |
| HD | 1280×720 | 4–8 | Inquadratura ampia (16:9) |
| SXGA | 1280×1024 | 3–6 | Foto |
| UXGA | 1600×1200 | 2–5 | Foto alla massima risoluzione |
Nel tuo codice puoi cambiare risoluzione, qualità e orientamento dell'immagine tramite l'oggetto sensore, dopo che la fotocamera è stata avviata correttamente. La qualità JPEG è un numero da 0 a 63 e un numero più basso significa qualità più alta; scendere sotto 10 rende i fotogrammi più pesanti e può produrre immagini a metà.
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..2Perché l'impostazione PSRAM dell'ESP32-CAM è così importante?
La memoria interna dell'ESP32 è di 520 KB e buona parte la usa lo stack Wi-Fi. Un singolo fotogramma JPEG a 1600×1200, invece, può occupare da 100 a 250 KB a seconda della scena e della qualità. Per questo il driver della fotocamera mette i buffer dei fotogrammi (frame buffer) nella PSRAM. CameraWebServer controlla con la funzione psramFound() se la PSRAM c'è: se c'è, parte alla risoluzione massima con due buffer; altrimenti limita la risoluzione a SVGA (800×600) e tiene un solo buffer nella memoria interna.
Se chiedi una risoluzione alta senza PSRAM attiva, il Monitor seriale mostra frame buffer malloc failed e poi Camera init failed with error 0xffffffff. La soluzione è scegliere AI Thinker ESP32-CAM come scheda (con ESP32 Dev Module imposta Strumenti > PSRAM: Enabled) oppure abbassare la risoluzione e ridurre i buffer a 1. Alcuni cloni economici potrebbero non avere affatto il chip PSRAM; la riga PSRAM del primo sketch di prova lo rivela subito.
Camera init failed with error 0x105 e gli altri errori della fotocamera
La maggior parte degli errori della fotocamera ha una di tre cause: modello di fotocamera sbagliato nel codice, cavo flat non ben inserito nel connettore o alimentazione insufficiente. Leggere il codice di errore nel Monitor seriale restringe subito il campo:
| Messaggio nel Monitor seriale | Significato | Soluzione |
|---|---|---|
| Camera probe failed with error 0x105(ESP_ERR_NOT_FOUND) | L'ESP32 non ha trovato nessuna fotocamera sul bus SCCB | Verifica che sia selezionato CAMERA_MODEL_AI_THINKER, reinserisci il cavo flat, alimenta con 5 V / 2 A |
| Detected camera not supported e 0x106 | La stessa situazione nelle versioni recenti del driver: fotocamera non trovata o non riconosciuta | Stessi passi di 0x105; se persiste, sostituisci il modulo fotocamera |
| frame buffer malloc failed e 0xffffffff | Impossibile allocare la memoria per il buffer del fotogramma | Attiva la PSRAM, abbassa la risoluzione, imposta fb_count a 1 |
| cam_hal: EV-VSYNC-OVF o FB-OVF | È arrivato un nuovo fotogramma prima che il precedente fosse elaborato, uno è stato saltato | Innocuo se capita ogni tanto; se è frequente, abbassa la risoluzione e migliora il segnale Wi-Fi |
| NO-SOI (JPEG start marker missing) | Fotogramma JPEG danneggiato o incompleto | Controlla alimentazione e cavo flat, imposta xclk_freq_hz a 10000000 |
| Immagine a metà, verde o a righe | Il fotogramma non è entrato nel buffer o l'alimentazione è disturbata | Porta il valore di qualità JPEG a 12 o più, migliora l'alimentazione |
Errore di brownout e alimentazione corretta (5 V / 2 A)
Se il Monitor seriale mostra Brownout detector was triggered e la scheda continua a riavviarsi, la tensione di alimentazione dell'ESP32 è scesa per un attimo sotto un livello sicuro. L'ESP32-CAM assorbe picchi di corrente brevi ma elevati appena accende il trasmettitore Wi-Fi e la fotocamera inizia a catturare. Una porta USB debole, cavetti jumper sottili e lunghi o l'uscita a 3,3 V del convertitore non reggono questi picchi. Ecco le soluzioni definitive:
- Usa un alimentatore da 5 V e almeno 2 A collegato al pin 5V della scheda; il regolatore integrato lo abbassa a 3,3 V.
- Tieni i cavi di alimentazione corti e spessi; breadboard e cavetti lunghi aumentano la caduta di tensione.
- Aggiungi un condensatore elettrolitico da 470–1000 µF tra i pin 5V e GND, il più vicino possibile alla scheda (terminale positivo su 5V).
- Se la alimenti dal computer, collegala direttamente a una porta sul retro invece che a un hub USB.
- Per il funzionamento a batteria usa una cella 18650 con un modulo step-up (boost) a 5 V; è molto più stabile di più pile AA in serie.

In rete troverai spesso la riga WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0), che disattiva da codice il rilevatore di brownout. Ferma i riavvii ma non risolve il problema: la tensione continua a calare e ora la scheda può bloccarsi, produrre fotogrammi danneggiati o perdere dati mentre scrive nella flash. Usala solo per una prova temporanea; tutti i messaggi di riavvio sono spiegati in ESP32 brownout e Guru Meditation. Per stimare l'autonomia considera che la scheda assorbe in media 180 mA in streaming continuo: una 18650 da 2600 mAh con uno step-up con rendimento dell'85 % dà circa 1600 mAh sul lato a 5 V, cioè circa 9 ore di streaming. Puoi calcolare i tuoi valori con il calcolatore di durata della batteria, ricordando che anche in deep sleep la scheda assorbe circa 6 mA a causa del regolatore e della PSRAM.
Controllare il LED flash (GPIO 4)
Il LED bianco molto luminoso sul davanti della scheda è pilotato da un transistor collegato al GPIO 4: il pin comanda solo il transistor e l'alta corrente del LED arriva dall'alimentazione. Si accende con digitalWrite(4, HIGH) e si spegne con LOW. Il LED è molto potente e, se resta acceso a lungo, si scaldano sia il LED sia la scheda; è meglio accendere il flash solo per qualche centinaio di millisecondi mentre scatti la foto. Il GPIO 4 è anche la linea DATA1 della microSD, quindi con la scheda in modalità 4 bit il flash lampeggia da solo a ogni lettura e scrittura. Per evitarlo, avvia la SD in modalità 1 bit (SD_MMC.begin("/sdcard", true)); su alcune schede il LED può comunque restare acceso molto debolmente.
Salvare foto sulla microSD con l'ESP32-CAM
Lo sketch seguente, ogni volta che premi un pulsante collegato al GPIO 13, accende il flash, scatta una foto a 1600×1200 e la salva sulla microSD con i nomi foto1.jpg, foto2.jpg.... Formatta la scheda sul computer in FAT32; anche se la documentazione ufficiale parla di schede fino a 4 GB, in pratica le schede FAT32 da 16–32 GB di solito funzionano senza problemi. Collega un terminale del pulsante al GPIO 13 e l'altro a GND; lo sketch attiva la resistenza di pull-up interna, quindi non serve una resistenza aggiuntiva. Per capire come si collega un pulsante, leggi come collegare un pulsante ad Arduino.
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}Poiché lo sketch avvia la SD in modalità 1 bit, usa solo i GPIO 2, 14 e 15, lasciando il GPIO 4 al flash e il GPIO 13 al pulsante. Prima dello scatto viene preso un fotogramma e restituito subito: la fotocamera produce fotogrammi di continuo, quindi il primo nel buffer potrebbe essere stato catturato prima dell'accensione del flash, e l'esposizione automatica ha bisogno di una breve pausa per adattarsi alla nuova luce. Il numero del file si ricava dai file già presenti sulla scheda, così le foto vecchie non vengono sovrascritte nemmeno dopo un riavvio. Per le regole generali sulla registrazione di dati su SD, dai un'occhiata alla guida modulo scheda SD.
MicroPython e schede fotocamera più recenti
Puoi programmare l'ESP32-CAM anche in MicroPython, ma la versione ufficiale di MicroPython non include il driver della fotocamera; devi installare un firmware della community che lo aggiunga. Per iniziare, quindi, la strada dell'Arduino IDE è molto più semplice. Se preferisci evitare una scheda senza presa USB, valuta anche le schede fotocamera basate su ESP32-S3, con USB e più memoria (ad es. Seeed XIAO ESP32S3 Sense o ESP32-S3-EYE); compaiono anche loro nell'elenco dei modelli di CameraWebServer.
Idee di progetti con l'ESP32-CAM
- Foto al rilevamento di movimento: scatta una foto quando un sensore PIR rileva qualcuno e inviala allo smartphone; la guida passo dopo passo è in foto dell'ESP32-CAM su Telegram.
- Time-lapse: fai svegliare la scheda ogni 10 minuti, scattare una foto, salvarla sulla SD e tornare in deep sleep; osserva la crescita di una pianta o il cambiare del tempo.
- Telecamera per il campanello: fotografa l'ingresso quando qualcuno suona e invia una notifica con un bot Telegram.
- Robot car con telecamera: guida l'auto guardando sullo smartphone uno streaming fluido in QVGA.
- Telecamera per animali: guarda lo streaming sulla rete di casa e accendi il flash dalla pagina web quando serve.
- Il tuo pannello di controllo: inserisci lo streaming nella tua pagina web e aggiungi accanto comandi per relè e letture dei sensori; la guida ESP32 WebSocket ti mostra come fare.
Errori comuni e soluzioni
| Sintomo | Causa probabile | Soluzione |
|---|---|---|
| Failed to connect to ESP32: No serial data received (nelle versioni vecchie Timed out waiting for packet header) | La scheda non è in modalità download, oppure TX e RX sono sbagliati | Collega IO0 a GND o usa il pulsante IO0, premi RST; verifica che TX vada a U0R e RX a U0T |
| Wrong boot mode detected (0x13) | All'avvio il GPIO 0 non era LOW | Dopo aver collegato IO0 a GND premi sempre RST |
| waiting for download nel Monitor seriale | IO0 è ancora collegato a GND | Togli il filo di IO0 e premi RST |
| Caratteri incomprensibili nel Monitor seriale | Velocità in baud sbagliata | Imposta il Monitor seriale a 115200 baud |
| La scheda non compare nell'elenco delle porte | Driver mancante o cavo di sola ricarica | Installa il driver CH340 o CP2102, usa un cavo dati |
| Il caricamento fallisce con la SD inserita | Il GPIO 2 è sia linea SD sia pin di strapping | Togli la microSD durante il caricamento |
| Immagine molto lenta o che si blocca spesso | Segnale Wi-Fi debole o risoluzione alta | Scendi a VGA o QVGA, avvicina la scheda al router, usa un'antenna esterna se serve |
| Il flash resta sempre leggermente acceso | SD in modalità 4 bit o GPIO 4 lasciato flottante | Avvia la SD in modalità 1 bit, imposta il GPIO 4 come OUTPUT a LOW |
L'ESP32-CAM è il modo più semplice per costruire una telecamera Wi-Fi con una scheda economica, e quasi tutte le difficoltà nascono dal collegamento di programmazione o dall'alimentazione. Una volta sistemati questi due punti, la scheda trasmette in diretta dal proprio web server, scatta foto e le salva sulla SD. Nell'app BlueGrays trovi progetti con ESP32 come la connessione Wi-Fi, un web server, mDNS, la registrazione di dati su microSD e un allarme di movimento con notifiche Telegram, ognuno con schema del circuito passo dopo passo e codice pronto all'uso.
Domande frequenti
Come si programma l'ESP32-CAM?
Poiché l'ESP32-CAM non ha una presa USB, serve un adattatore ESP32-CAM-MB o un convertitore USB-TTL. Nell'Arduino IDE scegli la scheda AI Thinker ESP32-CAM e metti la scheda in modalità download premendo RST mentre il GPIO 0 è collegato a GND (o mentre tieni premuto il pulsante IO0 dell'MB). Finito il caricamento, togli il collegamento IO0 e premi di nuovo RST.
Si può programmare l'ESP32-CAM con un Arduino Uno?
Sì; se colleghi il pin RESET dell'Uno a GND, il suo chip USB funziona come un ponte USB-seriale. In questo caso il collegamento è diretto e non incrociato: il D0 (RX) dell'Uno va a U0R, il D1 (TX) a U0T e IO0 resta collegato a GND. Poiché i segnali dell'Uno sono a 5 V, questo mette l'ESP32 al limite; per un uso continuativo è più sicuro un adattatore MB o un convertitore USB-TTL a 3,3 V.
Con quanti volt funziona l'ESP32-CAM?
Si consiglia di alimentare la scheda con 5 V sul pin 5V; il regolatore integrato li abbassa a 3,3 V. Puoi anche fornire 3,3 V sul pin 3V3, ma se la sorgente non regge i picchi di corrente del Wi-Fi, la scheda si riavvia di continuo. Un alimentatore da almeno 2 A evita la maggior parte degli errori di brownout.
Come si risolve l'errore Camera init failed dell'ESP32-CAM?
I codici 0x105 o 0x106 indicano che non è stata trovata nessuna fotocamera: controlla prima che nel codice sia selezionato CAMERA_MODEL_AI_THINKER, poi che il cavo flat sia inserito fino in fondo, e alimenta la scheda con 5 V / 2 A. Se il problema persiste, il modulo fotocamera potrebbe essere guasto. Se vedi 0xffffffff insieme a frame buffer malloc failed, attiva la PSRAM o abbassa la risoluzione.
L'ESP32-CAM funziona senza internet?
Sì. Per vedere l'immagine serve solo una rete locale, non internet; l'ESP32-CAM può anche creare una propria rete Wi-Fi con WiFi.softAP() e allora si apre nel browser all'indirizzo 192.168.4.1. Puoi persino usarla senza alcuna rete, come una fotocamera che salva le foto solo sulla microSD.
L'ESP32-CAM può registrare video?
Gli esempi forniti trasmettono l'immagine in diretta in MJPEG e scattano singole foto; non registrano direttamente un file video. Esistono progetti della community che scrivono fotogrammi JPEG consecutivi sulla microSD per creare un file AVI, ma la frequenza resta limitata anche a bassa risoluzione. La scheda non ha un microfono, quindi non registra nemmeno l'audio.
Progetti da realizzare dopo questo articolo
Vedi tutti i progetti
LED Lampeggiante con ESP32
Insegna l'uso di base delle uscite GPIO con l'ESP32. Otteniamo un effetto lampeggiante accendendo e spegnendo un LED dal pin digitale. Versione ESP32 del classico progetto blink su Arduino UNO; i comandi di base di blink nell'ambiente Arduino sono gli stessi, ma la disposizione dei pin e i livelli GPIO a 3,3 V dell'ESP32 sono diversi da quelli di Arduino UNO.

Lampeggio del LED interno dell'ESP32
Far lampeggiare il LED blu integrato nell'ESP32 DevKit V1. Non sono necessari componenti esterni! Il primo progetto da provare quando si acquista un ESP32. Il GPIO 2 è collegato al LED interno.

Connessione Wi-Fi STA con ESP32 (con display LCD)
In questo progetto colleghiamo l'ESP32 alla rete Wi-Fi domestica in modalità Station (STA) in modo sicuro e tollerante agli errori. Separiamo SSID e password in un file `secrets.h` per impedire fughe su Git, impostiamo un meccanismo di riconnessione automatica e visualizziamo il livello del segnale RSSI e l'indirizzo IP su un display LCD I2C. Il LED interno funge da indicatore di stato.

Server web asincrono ESP32 (con indicazione dell'IP sul display LCD)
In questo progetto trasformiamo l'ESP32 in un **server web asincrono** che potrete controllare dal vostro telefono o computer collegato alla stessa rete Wi-Fi. Grazie alla libreria ESPAsyncWebServer, il server è in grado di elaborare più richieste contemporaneamente (a differenza del classico `WebServer.h`, che si blocca su una singola richiesta).

ESP32 mDNS: accesso al dispositivo tramite bluegrays-esp.local (con schermo LCD)
In questo progetto, aggiungendo il servizio mDNS (Multicast DNS) all'ESP32, consentiamo l'accesso tramite un nome host leggibile, come `bluegrays-esp.local`, anziché tramite l'indirizzo IP. Anche se l'IP assegnato dal DHCP dovesse cambiare, potrete sempre raggiungere il dispositivo con lo stesso nome. Eseguendo anche un piccolo server web, inviamo comandi di controllo dei LED dal browser all’indirizzo `http://bluegrays-esp.local/`. Sul display LCD I2C vengono visualizzati il nome host, l’IP e lo

Data Logger di Temperatura ESP32 (DHT22 + DS1307 RTC + microSD + OLED)
Costruisci un data logger di temperatura con timestamp usando ESP32! Leggi temperatura/umidità dal DHT22 ogni minuto, ottieni l'ora reale dal DS1307 RTC e registra su scheda microSD in formato CSV. L'OLED mostra dal vivo temperatura (font grande), percentuale di umidità, timestamp e contatore di log. Il file `/temp_log.csv` sulla scheda SD si apre in Excel, Google Sheets o Python pandas per l'analisi — perfetto per il monitoraggio di serre, tracciamento della temperatura domestica, raccolta

Sistema di Allarme Movimento ESP32 (PIR + Buzzer + LED + Telegram)
Un sistema di allarme di sicurezza intelligente che attiva buzzer e LED quando il sensore PIR rileva movimento, inviando contemporaneamente una notifica istantanea al proprietario tramite Telegram. Dispone di un tempo di attesa di 30 secondi per limitare la frequenza degli allarmi ripetuti; questo meccanismo non verifica la validità dei rilevamenti del sensore PIR né elimina le false attivazioni. Adatto a sicurezza domestica, monitoraggio di garage, magazzini o studi. Con l'ESP32-CAM è possibile

Allarme con sensore di movimento ESP32
In questo progetto, realizzato utilizzando un ESP32 e un sensore PIR, quando viene rilevato un movimento, il cicalino si attiva emettendo un allarme acustico. Si tratta di un'applicazione semplice ed economica per un sistema di sicurezza. (Le immagini sono puramente illustrative; collegarle in base al testo)
Altri articoli
App BlueGrays
Costruisci questo circuito passo passo sul telefono
Schema, codice ed elenco componenti in un’unica schermata. Oltre 160 progetti Arduino, ESP32 e Pico da realizzare.
Inquadra con il telefono
Punta la fotocamera sul codice: si apre lo store del tuo telefono.
oppure apri lo store

