В этой статье речь пойдет об интересной плате на базе микроконтроллера ESP32. Плата называется ESP32-cam, она необычна тем, что на борту нее есть 2х мегапиксельная камера OV2640. Данную плату можно купить тут: http://ali.pub/3f04uj
Также понадобится usb/ttl преобразователь: http://ali.pub/3f156r
Ну и муляж камеры: http://ali.pub/3f1631
Прежде чем приступить к материалу, я Вас попрошу, если нравится то, что я делаю и хотите следить за моей деятельностью, то рекомендую подписаться на мой телеграмм канал: https://t.me/ypavla
Там я публикую новости о вышедших видео, статьях и разные устройства для умного дома и не только показываю.
Спасибо за внимание, теперь продолжим.
Обычно мощностей микроконтроллера не хватает для того чтоб обрабатывать видео поток. Но данная плата настолько мощная, что вполне себе тянет потоковое видео. Вот краткая табличка сравнения контроллеров ESP32 и ESP8266:
Как видно из таблички ESP32 на голову выше своего младшего брата ESP8266.
Чтож давайте посмотрим теперь, что же можно сделать с камерой. Если вы установили плату ESP32 в программе arduino ide допустим по моей инструкции, То в стандартных примерах Файл -> примеры -> ESP32 -> camera -> CameraWebServer
В данном примере нам нужно сделать три правки, чтоб камера начала показывать.
Во первых нужно закоментировать одну камеру и раскоментировать другую:
// Select camera model //#define CAMERA_MODEL_WROVER_KIT //#define CAMERA_MODEL_ESP_EYE //#define CAMERA_MODEL_M5STACK_PSRAM //#define CAMERA_MODEL_M5STACK_WIDE #define CAMERA_MODEL_AI_THINKER
Далее нам нужно ввести SSID нашей wi-fi сети и пароль от нее:
const char* ssid = "*********"; const char* password = "*********";
Так как в модуле ESP32-cam нет гнезда под usb кабель, прошивать ее будем через usb/ttl адаптер. Вот схема подключения:
Обратите внимание, что для прошивки обязательно нужно замкнуть контакт IO0 и GND. Это обязательно иначе не зальется прошивка в ESP32. Также для заливки нужно выбрать плату “ESP32 Wrover Module” и Partition Scheme: ” Huge App (3MB no OTA)” . После того как вы все сделали так как я описал, скетч должен залиться без ошибок.
После заливки скетча нужно обязательно убрать перемычку IO0 и GND иначе ESP32 не загрузится в нормальном режиме. Итак включает плату и открываем монитор порта в программе Arduino ide. В мониторе порта должен показаться ip адрес устройства если ESP32 подключилась к wi-fi сети. Выглядит это так:
После этого вводим в браузер данный ip адрес и видим непосредственно настройки камеры и изображение с нее
Здесь много всяких настроек нет смысла их описывать. Даже есть распознавание лица, но только почему-то у меня оно не заработало. Если вы думаете, что разрешение камеры слишком маленькое, то его можно увеличить и например сделать оранжевым:
Давайте теперь уберем все лишнее, оставим только воспроизведение видео с камеры, сделаем для нее корпус. И получим самодельную камеру для видеонаблюдения.
Сначала отредактируем скетч, я это конечно же уже сделал, теперь он выглядит так:
/********* - Выбираем плату "ESP32 Wrover Module" - Выбираем в Partion Scheme "Huge APP (3MB No OTA) - GPIO 0 и GND замыкаем перемычкой для заливки скетча - Плсде заливки скетча, нужно отключить контроллер и разомкнуть перемычку, для того чтоб ESP32 загрузилась в стадартном режиме и заработала наша программ *********/ #include "esp_camera.h" #include <WiFi.h> #include "esp_timer.h" #include "img_converters.h" #include "Arduino.h" #include "fb_gfx.h" #include "soc/soc.h" #include "soc/rtc_cntl_reg.h" #include "dl_lib.h" #include "esp_http_server.h" //Настройки wi-fi const char* ssid = "******"; const char* password = "*******"; #define PART_BOUNDARY "123456789000000000000987654321" // Модуль камеры #define CAMERA_MODEL_AI_THINKER #if defined(CAMERA_MODEL_AI_THINKER) #define PWDN_GPIO_NUM 32 #define RESET_GPIO_NUM -1 #define XCLK_GPIO_NUM 0 #define SIOD_GPIO_NUM 26 #define SIOC_GPIO_NUM 27 #define Y9_GPIO_NUM 35 #define Y8_GPIO_NUM 34 #define Y7_GPIO_NUM 39 #define Y6_GPIO_NUM 36 #define Y5_GPIO_NUM 21 #define Y4_GPIO_NUM 19 #define Y3_GPIO_NUM 18 #define Y2_GPIO_NUM 5 #define VSYNC_GPIO_NUM 25 #define HREF_GPIO_NUM 23 #define PCLK_GPIO_NUM 22 #else #error "Модель камеры не выбрана" #endif static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY; static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n"; static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n"; httpd_handle_t stream_httpd = NULL; static esp_err_t stream_handler(httpd_req_t *req){ camera_fb_t * fb = NULL; esp_err_t res = ESP_OK; size_t _jpg_buf_len = 0; uint8_t * _jpg_buf = NULL; char * part_buf[64]; res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE); if(res != ESP_OK){ return res; } while(true){ fb = esp_camera_fb_get(); if (!fb) { Serial.println("Camera capture failed"); res = ESP_FAIL; } else { if(fb->width > 400){ if(fb->format != PIXFORMAT_JPEG){ bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len); esp_camera_fb_return(fb); fb = NULL; if(!jpeg_converted){ Serial.println("JPEG compression failed"); res = ESP_FAIL; } } else { _jpg_buf_len = fb->len; _jpg_buf = fb->buf; } } } if(res == ESP_OK){ size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len); res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen); } if(res == ESP_OK){ res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len); } if(res == ESP_OK){ res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY)); } if(fb){ esp_camera_fb_return(fb); fb = NULL; _jpg_buf = NULL; } else if(_jpg_buf){ free(_jpg_buf); _jpg_buf = NULL; } if(res != ESP_OK){ break; } } return res; } void startCameraServer(){ httpd_config_t config = HTTPD_DEFAULT_CONFIG(); config.server_port = 80; httpd_uri_t index_uri = { .uri = "/", .method = HTTP_GET, .handler = stream_handler, .user_ctx = NULL }; //Serial.printf("Starting web server on port: '%d'\n", config.server_port); if (httpd_start(&stream_httpd, &config) == ESP_OK) { httpd_register_uri_handler(stream_httpd, &index_uri); } } void setup() { WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector Serial.begin(115200); Serial.setDebugOutput(false); camera_config_t config; config.ledc_channel = LEDC_CHANNEL_0; config.ledc_timer = LEDC_TIMER_0; config.pin_d0 = Y2_GPIO_NUM; config.pin_d1 = Y3_GPIO_NUM; config.pin_d2 = Y4_GPIO_NUM; config.pin_d3 = Y5_GPIO_NUM; config.pin_d4 = Y6_GPIO_NUM; config.pin_d5 = Y7_GPIO_NUM; config.pin_d6 = Y8_GPIO_NUM; config.pin_d7 = Y9_GPIO_NUM; config.pin_xclk = XCLK_GPIO_NUM; config.pin_pclk = PCLK_GPIO_NUM; config.pin_vsync = VSYNC_GPIO_NUM; config.pin_href = HREF_GPIO_NUM; config.pin_sscb_sda = SIOD_GPIO_NUM; config.pin_sscb_scl = SIOC_GPIO_NUM; config.pin_pwdn = PWDN_GPIO_NUM; config.pin_reset = RESET_GPIO_NUM; config.xclk_freq_hz = 20000000; config.pixel_format = PIXFORMAT_JPEG; config.frame_size = FRAMESIZE_UXGA; config.jpeg_quality = 10; config.fb_count = 2; // Camera init esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { Serial.printf("Camera init failed with error 0x%x", err); return; } // Wi-Fi connection WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); // Start streaming web server startCameraServer(); Serial.print("Camera Stream Ready! Go to: http://"); Serial.print(WiFi.localIP()); } void loop() { delay(1); }
Готовый скетч можно скачать тут: https://yadi.sk/d/i70M_y-DmaGdVA
В данном скетче нужно указать только SSID wi-fi сети и пароль, остальное уже настроено под данный модуль. Выглядит изображение с него вот так:
Как видим нет ничего лишнего просто изображение с довольно хорошим разрешением.
Чтож с выводом изображения разобрались, теперь нужно что-то придумать с корпусом. На ум пришла идея купить с Aliexpress муляж камеры и вмонтировать ее туда. Сама камера выглядит вот таким образом, от оригинала не отличить, только внутри пусто:
Разбирается камера без усилий, нужно открутить только 3 самореза. Так выглядит разобранный корпус:
Та часть которая находится в левой руке, к ней и будем крепить нашу камеру, для этого рассверлим отверстие сквозное и приклеим камеру на термоклей.
Я нашел блок питания 5В поэтому никаких dc-dc преобразователей ненужно. Так выглядит камера в сборе:
Ну и вот изображение с камеры уже из корпуса :
На этом собственно и все, как по мне так получилось довольно не плохо. Сделали из муляжа настоящую камеру, с которой при желании можно видеть изображение с любой точки планеты. Из минусов только то, что я пока не смог записывать с нее видео. Live стрим есть, а вот просмотреть запись пока нельзя.
Также я все это дело снял на видео и рассказал в нем.