ESP32-CAM: симулятор скетчей в браузере — что проверять без камеры
ESP32-CAM — плата-головастик: на одном чипе ESP32, OV2640-камера и слот microSD. Дешевая (700-1000 руб.) и капризная: программатор через UART-USB без пина 5V, нет USB-разъёма на самой плате, GPIO0 нужно замыкать на землю при прошивке. Скетч из интернета даёт поток в браузере, но на полпути валится с ошибкой памяти — heap фрагментируется. В браузере поток вы не проверите, но WiFi-подключение, HTTP-сервер и MQTT-телеметрию — да.
Встроенной камеры в симуляторе нет, но движок поддерживает WiFi.begin, WiFiClient, WiFiServer, HTTPClient и PubSubClient — то есть скетч под ESP32-CAM с HTTP-сервером или MQTT-телеметрией компилируется и исполняется в основном симуляторе. Ниже — проба HTTP-сервера, разбор границ и грабли самой платы.
Что у ESP32-CAM внутри
ESP32-D0WDQ6 — двухъядерный Xtensa LX6 на 240 МГц, 520 КБ SRAM, 4 МБ флеша в PSRAM-расширении на AI-Thinker-плате. Камера OV2640 — 2 Мп, JPEG-сжатие в чипе, до UXGA (1600x1200) при 15 fps. Слот microSD — SPI-режим, 1-битная шина. Пины GPIO выведены на гребёнку: 4, 5, 12-16, 17-19 свободны, GPIO0 — кнопка загрузчика, GPIO33 — пин PSRAM. Из 38 пинов половина занята камерой и SD.
- ESP32-D0WDQ6: 2 ядра × 240 МГц, 520 КБ SRAM, WiFi + Bluetooth в одном чипе.
- OV2640: 2 Мп JPEG-камера, до UXGA при 15 fps, через 16-пинный шлейф к плате.
- PSRAM 4 МБ: внешняя SRAM для кадров — без неё UXGA не вытянуть.
- microSD по SPI: 1-битный режим, до 4 ГБ на карте FAT32.
- UART-USB через внешний программатор: на самой плате нет USB-разъёма, нужен FTDI/CH340 на 3V3.
Скетч-проба: HTTP-сервер на порту 80
#include <WiFi.h>#include <WiFiServer.h> const char* SSID = "MyWiFi";const char* PASS = "12345678"; WiFiServer server(80); void setup() { Serial.begin(115200); WiFi.begin(SSID, PASS); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(); Serial.print("IP: "); Serial.println(WiFi.localIP()); server.begin();} void loop() { WiFiClient client = server.available(); if (!client) return; client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/plain"); client.println(); client.println("Hello from ESP32-CAM"); delay(1); client.stop();}Скетч вставьте в основной симулятор: WiFi.begin подключится к фейковому «MyWiFi», server.available() примет «клиента», и в монитор уйдёт «IP: 192.168.1.100». Сам HTTP-сервер на плате отвечает на запросы браузера, а в симуляторе — только скомпилированная логика без реальной сети. Подробно HTTP-сервер на ESP32 разобран в уроке про веб-сервер.
Поток JPEG с камеры — только на живой плате
#include "esp_camera.h"#include <WiFi.h>#include <WiFiClient.h> // пины камеры для AI-Thinker ESP32-CAMcamera_config_t config;config.ledc_channel = LEDC_CHANNEL_0;config.ledc_timer = LEDC_TIMER_0;config.pin_d0 = 5;config.pin_d1 = 18;// ... остальные 14 пинов камерыconfig.xclk_freq_hz = 20000000;config.frame_size = FRAMESIZE_UXGA;config.jpeg_quality = 10; void setup() { Serial.begin(115200); WiFi.begin("MyWiFi", "12345678"); esp_camera_init(&config);} void loop() { camera_fb_t *fb = esp_camera_fb_get(); if (fb) { // отправка кадра по WiFi esp_camera_fb_return(fb); } delay(100);}Скетч под esp_camera.h компилируется только в Arduino IDE с установленным пакетом ESP32 — библиотека нестандартная, и в браузере её нет. Этот код — иллюстрация: что проверять в симуляторе (WiFi, HTTP), а что только на плате (захват кадра, отправка JPEG). Полный разбор потока JPEG с разбором кадров в браузере — в уроке про SSE-поток в браузер.
Честная граница: что в браузере, что только на плате
| Проверка | Симулятор | Только железо |
|---|---|---|
| WiFi.begin и localIP | да: фейковое подключение | то же, плюс реальные сети и IP |
| HTTP-сервер: server.available | компилируется, без реального клиента | да — отвечает браузеру |
| HTTPClient GET/POST | да: фейковые ответы | да — реальные запросы |
| Захват кадра с OV2640 | нет: нет камеры в каталоге | да — JPEG через 16 пинов |
| PSRAM и фрагментация heap | нет: модель без физики памяти | да — UXGA валится без PSRAM |
| microSD-запись через SPI | нет: нет SD в каталоге | да — FAT32, ограничение 4 ГБ |
Браузер исполняет логику WiFi и HTTP — половина рабочего скетча под ESP32-CAM. Камера, PSRAM и SD-карта в симуляторе не поддержаны: esp_camera_init() не выполнится, и захват кадра остаётся на живой плате. Так что стратегия проверки: HTTP-сервер, WiFi-роутинг, MQTT-телеметрия — в основном симуляторе; захват JPEG, поток, SD-запись — на живой ESP32-CAM с программатором FTDI.
Грабли ESP32-CAM
- GPIO0 на землю при прошивке: без перемычки плата не входит в режим загрузчика, и IDE пишет «Failed to connect». Перемычку снимают после прошивки.
- Питание 5V, не 3V3: камера при UXGA берёт 300-400 мА, на 3V3-пине программатора просадка, и плата уходит в brownout. Питайте от отдельного 5V-блока.
- PSRAM не включён в Tools: без PSRAM UXGA не работает — включите «PSRAM: Enabled» в меню Tools, иначе кадры по 200 КБ не помещаются в 520 КБ SRAM.
- Светодиод на GPIO4: на AI-Thinker-плате GPIO4 — это и flash-память, и пин LED. Используйте GPIO33 для своей индикации, GPIO4 оставьте флеш-памяти.
- Зависание с «Brownout detector was triggered»: просадка питания. Лечится ёмким конденсатором 470 мкФ по 5V или внешним блоком питания.