In questo tutorial imparerai come scattare foto con un ESP32-CAM premendo un pulsante e salvarle sulla scheda SD. In pratica stiamo costruendo una semplice fotocamera digitale.
Componenti necessari
Ti servirà un ESP32-CAM per provare gli esempi di codice. Puoi procurarti un ESP32-CAM con uno Shield USB-TTL per la programmazione o un adattatore FTDI USB-TTL. L’adattatore FTDI USB-TTL è un po’ più scomodo da usare ma lascia i pin GPIO facilmente accessibili. Lo Shield USB-TTL è più semplice da usare ma è più difficile collegarsi ai pin GPIO.
Se vuoi usare il PC per vedere le foto scattate dall’ESP32-CAM e salvate sulla scheda SD, potresti anche aver bisogno di un lettore di schede SD.

ESP32-CAM con Shield USB-TTL

Adattatore FTDI USB-TTL

Set di cavi Dupont

Breadboard

Lettore di schede SD
Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.
Schema di collegamento
Vogliamo scattare una foto con l’ESP32-CAM ogni volta che si preme un pulsante. Nel seguente schema di collegamento colleghiamo quindi un pulsante tra il pin GND e il pin GPIO13:

Ogni volta che il pulsante è premuto (chiuso), GPIO13 viene portato a massa. Questo funziona perché GPIO13 (e altri pin GPIO) ha un pull-up interno che mantiene GPIO13 alto quando non è collegato nulla. Ciò significa che la funzione del pulsante è invertita (quando chiuso GPIO13 == LOW) e lo vedrai nella sezione del codice.
La seguente immagine mostra come puoi costruire questo circuito con una breadboard e l’ESP32-CAM:

Come puoi vedere, ho usato lo Shield USB-TTL e sono riuscito a creare un piccolo spazio tra l’ESP32-CAM e lo shield per collegare i fili del pulsante a GND e GPIO13:

In alternativa, potresti usare l’adattatore FTDI USB-TTL o collegare l’ESP32-CAM allo Shield USB-TTL tramite un set di cavi Dupont.
Codice per scattare e salvare foto
Lo sketch Arduino seguente scatta una foto con la fotocamera ESP32-CAM e la salva sulla scheda SD quando il pulsante collegato a GPIO13 viene premuto (chiuso).
Per questo codice ti servirà la esp32cam libreria. Puoi installarla tramite il LIBRARY MANAGER nell’IDE Arduino. Basta cercare “esp32cam” e premere INSTALLA. L’immagine sotto mostra l’installazione completata:

Qui sotto trovi il codice completo per la nostra piccola applicazione di scatto. Dagli un’occhiata prima, poi ne discuteremo i dettagli:
#include "FS.h"
#include "SD_MMC.h"
#include "esp32cam.h"
const byte btnPin = GPIO_NUM_13;
const auto RES = esp32cam::Resolution::find(1600, 1200);
void takePicAndSave() {
static int cnt = 0;
auto frame = esp32cam::capture();
if (frame == nullptr) {
Serial.println("Capture failed!");
return;
}
String path = "/img" + String(cnt++) + ".jpg";
File file = SD_MMC.open(path.c_str(), FILE_WRITE);
if (!file) {
Serial.println("Failed to open file!");
}
frame->writeTo(file);
Serial.printf("Wrote: %s\n", path.c_str());
file.close();
}
void enableFlash(bool enable) {
digitalWrite(GPIO_NUM_4, enable ? HIGH : LOW);
}
void initCamera() {
using namespace esp32cam;
Config cfg;
cfg.setPins(pins::AiThinker);
cfg.setResolution(RES);
cfg.setJpeg(80);
bool ok = Camera.begin(cfg);
Serial.println(ok ? "CAMERA OK" : "CAMERA FAIL");
}
void initSDCard() {
if (!SD_MMC.begin("/sdcard", true)) {
Serial.println("SD Card Mount Failed!");
} else if (SD_MMC.cardType() == CARD_NONE) {
Serial.println("No SD card inserted!");
}
Serial.println("SD card ready.");
}
void setup() {
Serial.begin(115200);
initCamera();
initSDCard();
pinMode(btnPin, INPUT);
pinMode(GPIO_NUM_4, OUTPUT);
enableFlash(false);
delay(1000);
}
void loop() {
if (!digitalRead(btnPin)) {
enableFlash(true);
takePicAndSave();
enableFlash(false);
delay(500);
}
}
Librerie
All’inizio del codice sono incluse tre librerie:
#include "FS.h" #include "SD_MMC.h" #include "esp32cam.h"
Queste librerie sono essenziali per il progetto ESP32-CAM. La FS.h libreria fornisce operazioni sul file system, SD_MMC.h permette all’ESP32 di interfacciarsi con le schede SD tramite il bus MMC (MultiMediaCard), e esp32cam.h è una libreria di livello superiore che semplifica la configurazione della fotocamera e la cattura delle immagini sul modulo ESP32-CAM.
Costanti
Poi, viene definita una costante per il pin del pulsante e un’impostazione della risoluzione della fotocamera:
const byte btnPin = GPIO_NUM_13; const auto RES = esp32cam::Resolution::find(1600, 1200);
Qui, btnPin è assegnato al GPIO 13, dove è collegato il pulsante. Potresti anche usare GPIO 12 ma in entrambi i casi devi far funzionare l’interfaccia della scheda SD in modalità 1-bit! Per maggiori dettagli vedi il More GPIO pins for ESP32-CAM tutorial.
L’oggetto RES definisce la risoluzione dell’immagine, in questo caso 1600×1200 pixel (UXGA), che sarà usata più avanti per configurare la fotocamera. Ecco una lista dei valori possibili per la risoluzione della fotocamera, anche se a seconda della fotocamera non tutte potrebbero funzionare:
- 96×96
- 160×120
- 128×128
- 176×144
- 240×176
- 240×240
- 320×240
- 320×320
- 400×296
- 480×320
- 640×480
- 800×600
- 1024×768
- 1280×720
- 1280×1024
- 1600×1200
takePicAndSave
La funzione takePicAndSave() è la funzione principale che cattura un’immagine e la scrive sulla scheda SD:
void takePicAndSave() {
static int cnt = 0;
La variabile cnt è dichiarata static, il che significa che mantiene il suo valore tra le chiamate della funzione. La usiamo per generare nomi di file unici per ogni foto.
auto frame = esp32cam::capture();
if (frame == nullptr) {
Serial.println("Capture failed!");
return;
}
La funzione chiama esp32cam::capture() per catturare un frame dalla fotocamera. Se la cattura fallisce (cioè frame è nullptr), viene stampato un messaggio di errore e la funzione termina anticipatamente.
String path = "/img" + String(cnt++) + ".jpg"; File file = SD_MMC.open(path.c_str(), FILE_WRITE);
Il codice costruisce un nome file concatenando “img” con il valore incrementale di cnt e aggiungendo “.jpg”. Il file viene quindi aperto sulla scheda SD per la scrittura.
if (!file) {
Serial.println("Failed to open file!");
}
Se il file non può essere aperto per qualche motivo (es. scheda SD assente, errore del file system), viene stampato un messaggio di errore.
frame->writeTo(file);
Serial.printf("Wrote: %s\n", path.c_str());
file.close();
}
Se il file si apre correttamente, il frame catturato viene scritto nel file, viene stampato un messaggio di conferma sul monitor seriale con il nome del file salvato, e infine il file viene chiuso per garantire l’integrità dei dati.
enableFlash
La funzione enableFlash(bool enable) controlla il flash LED integrato nell’ESP32-CAM:
void enableFlash(bool enable) {
digitalWrite(GPIO_NUM_4, enable ? HIGH : LOW);
}
Questa funzione imposta il livello di tensione su GPIO 4. Quando enable è true, imposta GPIO 4 a HIGH, accendendo il LED del flash; altrimenti lo imposta a LOW, spegnendo il flash.
Per maggiori informazioni su come controllare il LED del flash, vedi il Control ESP32-CAM Flash LED tutorial.
initCamera
La funzione initCamera() inizializza il modulo fotocamera:
void initCamera() {
using namespace esp32cam;
Config cfg;
cfg.setPins(pins::AiThinker);
cfg.setResolution(RES);
cfg.setJpeg(80);
All’interno di initCamera(), prima porta lo spazio dei nomi esp32cam in ambito locale. Poi crea un oggetto Config, cfg, e lo configura per usare i pin predefiniti per il layout della scheda Ai-Thinker, che è il tipo tipico per i moduli ESP32-CAM. Imposta la risoluzione della fotocamera a RES (1600×1200) e la qualità di compressione JPEG a 80 (dove 100 è la migliore qualità, valori più bassi significano più compressione e qualità peggiore).
bool ok = Camera.begin(cfg);
Serial.println(ok ? "CAMERA OK" : "CAMERA FAIL");
}
La funzione Camera.begin(cfg) prova ad avviare la fotocamera con le impostazioni specificate. Stampa “CAMERA OK” se ha successo, o “CAMERA FAIL” se fallisce.
initSDCard
La funzione initSDCard() monta la scheda SD:
void initSDCard() {
if (!SD_MMC.begin("/sdcard", true)) {
Serial.println("SD Card Mount Failed!");
} else if (SD_MMC.cardType() == CARD_NONE) {
Serial.println("No SD card inserted!");
}
Serial.println("SD card ready.");
}
Qui, SD_MMC.begin() inizializza il bus SD_MMC e prova a montare il file system sotto il percorso /sdcard. Il secondo argomento true abilita la modalità a 1 linea, che semplifica il cablaggio a scapito di una velocità inferiore. Se il montaggio fallisce, stampa “SD Card Mount Failed!”. Se la scheda è montata ma non è inserita fisicamente, stampa “No SD card inserted!”. Altrimenti assume che tutto sia a posto e stampa “SD card ready.”
setup
La funzione setup() prepara tutto all’avvio:
void setup() {
Serial.begin(115200);
initCamera();
initSDCard();
pinMode(btnPin, INPUT);
pinMode(GPIO_NUM_4, OUTPUT);
enableFlash(false);
delay(1000);
}
In setup(), la porta seriale viene avviata a 115200 baud per il debug. La fotocamera e la scheda SD vengono inizializzate chiamando le funzioni initCamera() e initSDCard(). Poi, il pin del pulsante (btnPin) viene impostato come input, e il pin di controllo del flash (GPIO 4) come output. enableFlash(false) assicura che il LED del flash sia spento all’inizio. Alla fine viene aggiunto un ritardo di 1 secondo (1000 millisecondi) per far stabilizzare il sistema prima di iniziare il loop principale.
loop
Infine, la funzione loop() controlla costantemente se il pulsante è premuto:
void loop() {
if (!digitalRead(btnPin)) {
enableFlash(true);
takePicAndSave();
enableFlash(false);
delay(500);
}
}
In loop(), legge lo stato di btnPin. Se il pulsante è premuto, digitalRead(btnPin) restituisce LOW perché il pin viene portato a massa quando premuto. Quando il pulsante è rilevato come premuto, il flash viene acceso chiamando enableFlash(true), poi viene scattata e salvata una foto chiamando takePicAndSave(), e infine il flash viene spento di nuovo con enableFlash(false). Segue un ritardo di 500 millisecondi per evitare di scattare più foto da una singola pressione.
Conclusioni
In questo tutorial hai imparato come costruire una piccola fotocamera digitale usando l’ESP32-CAM. L’esempio di codice configura un ESP32-CAM per monitorare un pulsante. Quando il pulsante viene premuto, accende il flash, scatta una foto a risoluzione 1600×1200, la salva sulla scheda SD con un nome file sequenziale come /img0.jpg, /img1.jpg, ecc., spegne il flash e aspetta brevemente prima di ascoltare di nuovo.
Se vuoi mettere l’ESP32 in deep-sleep tra uno scatto e l’altro dai un’occhiata al Motion Activated ESP32-CAM tutorial e per lo streaming video vedi l’articolo Stream Video with ESP32-CAM.
Inoltre, se vuoi ricevere notifiche quando viene rilevato un movimento, dai un’occhiata al nostro tutorial ESP32 send Telegram Message, che ti insegna come inviare messaggi all’app Telegram sul tuo telefono.
E se hai domande, sentiti libero di lasciarle nella sezione commenti.
Buon divertimento con il fai-da-te 😉

