ESP32など

電子工作してます

Timer Camera X/F単体で写真を撮影&Webサーバー化してブラウザで表示する

ESP32-CAM / Timer Camera X/F / Unit Cam(M5Stack)などででウェブサーバーを立てて、外部のPCなどのブラウザでアクセスすると、写真が撮影されて表示されるようにするコード。

最小限。

コード

#include <WiFi.h>
#include <esp_http_server.h>
#include <esp_camera.h>
#include "camera_pins.h"

const char *ssid     = "*****";
const char *password = "*****";

void setup() {
  Serial.begin(115200);

  // カメラ用パラメータ
  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_XGA; // 1024x768
  config.jpeg_quality = 10;
  config.fb_count     = 2; // CAMERA_GRAB_LATEST設定時は2以上必要
  config.grab_mode    = CAMERA_GRAB_LATEST; // 最後のフレームバッファだけを取得

  // カメラ開始
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
      Serial.printf("Camera init failed with error 0x%x", err);
      return;
  }

  // 画像反転
  sensor_t *s = esp_camera_sensor_get();
  s->set_vflip(s, 1);
  
  // WiFi開始
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
  }
  Serial.println(WiFi.localIP());

  // Webサーバー開始
  startServer();
}

void loop() {}

void startServer(){
  httpd_handle_t camera_httpd = NULL;
  httpd_config_t config = HTTPD_DEFAULT_CONFIG();
  httpd_uri_t capture_uri = {
    .uri       = "/",
    .method    = HTTP_GET,
    .handler   = capture_handler,
    .user_ctx  = NULL
  };
  if (httpd_start(&camera_httpd, &config) == ESP_OK) {
    httpd_register_uri_handler(camera_httpd, &capture_uri);
  }
}

static esp_err_t capture_handler(httpd_req_t *req){
   camera_fb_t *fb = esp_camera_fb_get();
   if (!fb) {
       Serial.println("Camera capture failed");
       httpd_resp_send_500(req);
       return ESP_FAIL;
   }
   httpd_resp_set_type(req, "image/jpeg");
   httpd_resp_send(req, (const char *)fb->buf, fb->len);
   esp_camera_fb_return(fb);
   return ESP_OK;
}