Pendahuluan — Dari Sensor ke Gambar
Seri 2 sudah mengajarkan telemetry: DHT22 (#5), MQTT (#7), bahkan LoRa jarak jauh (#26). Tapi kadang kamu butuh visual — cek kondisi kebun, pantau gerbang, atau dokumentasi lapangan.
ESP32-CAM menggabungkan ESP32 + kamera OV2640 dalam satu modul murah. Artikel Jalur D ini fokus pada streaming MJPEG ke browser dan capture foto JPEG via WiFi — pola mirip web server ESP32 (#6), tapi payload-nya frame gambar, bukan angka sensor.
Prasyarat: Sudah paham WiFi ESP32 (#4) dan idealnya pernah buat WebServer (#6). Video streaming bukan pengganti MQTT — lihat REST vs MQTT (#20).
Apa Itu ESP32-CAM?
ESP32-CAM adalah modul AI-Thinker (dan clone) berisi:
- Chip ESP32 (WiFi + dual-core)
- Kamera OV2640 (2 MP, JPEG built-in)
- Slot microSD (opsional, untuk simpan foto)
- LED flash putih + LED indikator merah
Modul ini hemat biaya (~Rp 40–60rb) tapi punya keterbatasan: butuh 5V stabil, panas saat stream lama, dan bandwidth WiFi tinggi dibanding sensor telemetry.
ESP32-CAM vs DevKit vs LoRa/ESP-NOW
| Modul | Cocok untuk | Data | Catatan |
|---|---|---|---|
| ESP32 DevKit + DHT22 | Telemetry angka | Suhu, RH, MQTT | Hemat bandwidth (#5, #7) |
| ESP-NOW (#25) | Node dekat, tanpa router | Paket kecil | Bukan video |
| LoRa (#26) | Sensor sangat jauh | Bytes jarang | Tidak untuk video |
| ESP32-CAM (artikel ini) | Visual monitoring | MJPEG / JPEG | Butuh WiFi stabil |
Yang Kamu Butuhkan
- 1× ESP32-CAM (AI-Thinker atau clone kompatibel)
- USB-to-TTL adapter (FTDI/CP2102) untuk flash — jangan colok USB langsung ke modul tanpa regulator
- Kabel jumper · breadboard (opsional)
- Router WiFi 2.4 GHz
- Library esp32-camera (biasanya sudah di board package)
Estimasi biaya: modul ESP32-CAM ~Rp 50rb + USB-TTL ~Rp 25rb → lab ~Rp 75–100rb.
Arsitektur Streaming MJPEG
| Komponen | Peran |
|---|---|
| OV2640 | Capture frame → kompres JPEG di chip kamera |
| ESP32 | WiFi + WebServer serve stream HTTP |
| Browser / HP | Buka http://IP_ESP32/stream atau /capture |
[ OV2640 ] --> JPEG frame --> [ ESP32 WebServer :80 ]
|
| WiFi LAN
v
[ Browser / HP di jaringan sama ]
Untuk telemetry paralel (suhu + gambar), kamu bisa gabungkan dengan MQTT (#7) di board terpisah — jangan paksa video lewat broker MQTT.
Power & Flashing — Penting!
ESP32-CAM tidak punya USB onboard. Wiring umum ke USB-TTL:
| ESP32-CAM | USB-TTL |
|---|---|
| 5V | 5V (supply stabil ≥500 mA) |
| GND | GND |
| U0R (GPIO 3) | TX |
| U0T (GPIO 1) | RX |
| GPIO 0 | GND saat flash (boot mode) |
Pro tip: Lepas jumper GPIO 0 → GND setelah upload. Tekan tombol RESET sebelum buka stream. Undervoltage = gambar corrupt atau reboot loop.
Instalasi Board & Library
- Arduino IDE → Board Manager → esp32 by Espressif
- Pilih board: AI Thinker ESP32-CAM
- Partition Scheme: Huge APP (3MB No OTA) — streaming butuh flash besar
- Library
esp_cameraikut board package (tidak perlu install terpisah)
Sketch — Inisialisasi Kamera
#include "esp_camera.h"
#include <WiFi.h>
#include <WebServer.h>
#define CAMERA_MODEL_AI_THINKER
const char* ssid = "GANTI_NAMA_WIFI";
const char* password = "GANTI_PASSWORD_WIFI";
WebServer server(80);
void setup() {
Serial.begin(115200);
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = 5;
config.pin_d1 = 18;
config.pin_d2 = 19;
config.pin_d3 = 21;
config.pin_d4 = 36;
config.pin_d5 = 39;
config.pin_d6 = 34;
config.pin_d7 = 35;
config.pin_xclk = 0;
config.pin_pclk = 22;
config.pin_vsync = 25;
config.pin_href = 23;
config.pin_sccb_sda = 26;
config.pin_sccb_scl = 27;
config.pin_pwdn = 32;
config.pin_reset = -1;
config.xclk_freq_hz = 20000000;
config.frame_size = FRAMESIZE_VGA;
config.pixel_format = PIXFORMAT_JPEG;
config.grab_mode = CAMERA_GRAB_LATEST;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.jpeg_quality = 12;
config.fb_count = 2;
if (esp_camera_init(&config) != ESP_OK) {
Serial.println("Camera init gagal");
return;
}
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println(WiFi.localIP());
}
Endpoint MJPEG Stream
Pola standar: boundary multipart HTTP. Browser menampilkan sebagai video live di jaringan lokal.
void handleStream() {
WiFiClient client = server.client();
String response = "HTTP/1.1 200 OK\r\n";
response += "Content-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n";
server.sendContent(response);
while (client.connected()) {
camera_fb_t* fb = esp_camera_fb_get();
if (!fb) continue;
client.printf("--frame\r\nContent-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n", fb->len);
client.write(fb->buf, fb->len);
client.print("\r\n");
esp_camera_fb_return(fb);
delay(30);
}
}
Endpoint Capture Foto
void handleCapture() {
camera_fb_t* fb = esp_camera_fb_get();
if (!fb) {
server.send(500, "text/plain", "Capture gagal");
return;
}
server.sendHeader("Content-Disposition", "inline; filename=capture.jpg");
server.send_P(200, "image/jpeg", (const char*)fb->buf, fb->len);
esp_camera_fb_return(fb);
}
void setupRoutes() {
server.on("/stream", HTTP_GET, handleStream);
server.on("/capture", HTTP_GET, handleCapture);
server.on("/", HTTP_GET, []() {
server.send(200, "text/html",
"<h1>ESP32-CAM</h1><p><a href='/stream'>Live stream</a> · "
"<a href='/capture'>Capture foto</a></p>");
});
server.begin();
}
void loop() {
server.handleClient();
}
Resolusi & Kualitas JPEG
FRAMESIZE_QVGA(320×240) — paling ringan, cocok WiFi lemahFRAMESIZE_VGA(640×480) — sweet spot labFRAMESIZE_SVGA/UXGA— lebih tajam, lag lebih besarjpeg_quality10–15 — angka lebih rendah = kualitas lebih baik (counter-intuitive di esp_camera)
Contoh metadata log (konsisten timestamp Seri 2 untuk proyek hybrid):
{"event":"capture","unix":1782977400,"iso":"2026-07-02T14:30:00","framesize":"VGA"}
Bandwidth & Latency
MJPEG di VGA bisa menghabiskan 1–3 Mbps — jauh di atas paket MQTT sensor. Pastikan:
- Klien dan ESP32-CAM di WiFi yang sama (2.4 GHz)
- Jangan stream 24/7 tanpa heatsink — modul panas
- Untuk monitoring jarang, pakai
/captureperiodik, bukan stream terus
MicroSD (Opsional) — Simpan Foto di Lapangan
Banyak modul ESP32-CAM punya slot microSD. Kamu bisa simpan hasil /capture ke kartu untuk audit lapangan tanpa koneksi terus-menerus — pola mirip logging offline SD Card (#37).
- Format kartu FAT32 · kapasitas ≤32 GB untuk kompatibilitas terbaik
- Gunakan library
SD_MMCatauFSdari board package - Nama file contoh:
/sdcard/cap_1782977400.jpg— selaraskan dengan timestamp NTP (#34) - Jangan stream MJPEG dan write SD bersamaan di sketch pertama — debug satu fitur dulu
Integrasi dengan Stack MQTT (Hybrid)
Polanya: ESP32-CAM untuk visual lokal, ESP32 DevKit terpisah untuk telemetry MQTT ke kodingindonesia/esp32/dht22/data via broker 192.168.1.50. Jangan kirim frame video lewat MQTT — bandwidth broker tidak dirancang untuk itu.
Event ringan yang masuk MQTT: {"event":"motion","unix":1782977400} atau trigger capture saat PIR (#23) terdeteksi — metadata saja, bukan binary JPEG.
WiFiManager untuk Deploy Lapangan
Ganti hardcode SSID dengan NVS + WiFiManager (#12) — portal konfigurasi saat pertama nyala, sama seperti node sensor produksi.
LED Flash & Kondisi Cahaya
ESP32-CAM punya LED flash putih di GPIO 4 (umum di AI-Thinker). Untuk foto malam di kebun:
- Aktifkan LED sebelum
esp_camera_fb_get()— matikan setelah capture untuk hemat arus - Exposure otomatis OV2640 butuh ~100–300 ms setelah LED nyala
- Stream siang hari tanpa LED — hindari backlight langsung ke lensa
- Gabungkan dengan sensor cahaya LDR (#35) untuk auto-flash
Untuk proyek greenhouse capstone (#39), kamera + suhu MQTT + pompa relay adalah tiga jalur terpisah yang saling melengkapi — visual tidak menggantikan angka sensor.
Checklist: Kapan Pakai ESP32-CAM?
- Butuh lihat kondisi visual real-time di LAN? → ESP32-CAM stream
- Butuh foto sesekali (audit kebun, bukti lapangan)? → /capture
- Butuh angka sensor ke dashboard MQTT? → DHT22/BME280 + MQTT (#7)
- Butuh jarak kilometer tanpa WiFi? → LoRa (#26), bukan kamera
- Butuh akses dari internet publik? → VPN / reverse proxy — jangan port-forward mentah
Uji Coba (Lab)
# Setelah flash & Serial menampilkan IP (mis. 192.168.1.88):
# Browser: http://192.168.1.88/
# Live: http://192.168.1.88/stream
# Foto: http://192.168.1.88/capture
# Cek MQTT sensor paralel (board terpisah) — topic Seri 2:
mosquitto_sub -h 192.168.1.50 -u kindo_esp32 -P GANTI_PASSWORD_MQTT \
-t kodingindonesia/esp32/dht22/data -v
- Flash sketch, buka Serial Monitor 115200 — catat IP
- Buka
/streamdi browser HP/laptop jaringan sama - Klik
/capture— harus muncul JPEG - Ubah
FRAMESIZE_QVGAjika lag — bandingkan smoothness - Matikan stream 5 menit — cek suhu modul tidak overheat
FAQ Singkat
- Bisa streaming ke Grafana?
- Grafana untuk time-series angka (#19). Video butuh stack lain (RTSP/WebRTC) — di luar scope tutorial ini.
- Bisa kirim frame lewat MQTT?
- Secara teknis bisa base64, tapi tidak efisien. MQTT untuk metadata/event; gambar simpan SD atau HTTP.
- ESP32-CAM vs CCTV IP camera?
- CCTV lebih matang untuk 24/7. ESP32-CAM cocok prototipe & belajar embedded vision murah.
Tips & Troubleshooting
- Camera init gagal: Cek model board AI-Thinker, partition Huge APP, power 5V cukup
- Gambar hijau/pink: Kabel kamera longgar atau PSRAM tidak aktif
- Stream putus-putus: Turunkan resolusi atau dekatkan ke router
- Tidak bisa flash: GPIO 0 harus ke GND saat boot flash
- IP tidak muncul: SSID/password salah — uji dengan #4 dulu
Keamanan & Produksi
- Jangan expose port 80 ESP32-CAM langsung ke internet — risiko bot scan kamera
- Ganti
GANTI_NAMA_WIFI/GANTI_PASSWORD_WIFI— jangan commit ke GitHub - Pertimbangkan MQTT TLS (#17) untuk channel kontrol terpisah
- Label modul & lokasi fisik — kamera di area privat perlu consent
Langkah Selanjutnya (Jalur D)
- Gateway LoRa → MQTT (#28): gabungkan sensor jauh + visual lokal
- Grafana (#19) — dashboard angka sensor (bukan video)
- OTA (#15) — update firmware kamera tanpa USB-TTL
- Home Assistant (#21) — integrasi stream kamera (addon terpisah)
- Capstone greenhouse (#39) — kamera + sensor MQTT + pompa
ESP32-CAM menambah dimensi visual ke toolkit IoT kamu — tetap di LAN untuk lab, dan pisahkan dari pipeline telemetry MQTT. Lanjutkan Seri 2 di halaman artikel Koding Indonesia.