タイムラプスやるなら外で(ESP32_Dev_CAM その1)

前回、”ESP32CAMと技適対応(その2)”で技適対応しました。今後はこの技適対応カメラを、”EPS32CAM”ならず、”ESP32_Dev_CAM”と呼ぶことにします。先ずは、”EPS32CAM”で使用していたスッケチを使えるレベルまでハードを改善して行きます。

現時点で、”EPS32CAM”に有って”ESP32_Dev_CAM”に無いハードは、

  • MicroSD
  • 乾電池および電圧変換回路
  • 乾電池電圧測定回路

です。これらを追加すると全体の回路はこうなります。左側が追加回路です。

左上が乾電池および電圧変換回路と電圧測定回路ですが、これは”EPS32CAM”の時と同じ回路です。

左下がMicroSD回路です。Banggoodで、”これ”を使っています。ただこの商品、届いてから分かったのですがヘッダーピンVDD(電源)が5Vでした。最終的には3.3Vで駆動させたいのでMicroSD基板に乗っているレギュレータに細工しています。

上手く写真が取れず、上手くモザイクが掛かってしまいましたが、

  • レギュレータのコネクター側2本のピンを基板のパッドから浮かす。またはレギュレータを基板から外す。
  • ピンを浮かしたパッド同士をショートする。

でヘッダーピンのVDD端子に3.3V入力でOKになります。

MISO端子ですが、”EPS32CAM”ではGPIO2が使用されていました。”ESP32_Dev_CAM”ではGPIO2は基板に実装されているLEDに繋がっています。MicroSDをアクセスする度にLEDが光るのを避ける為、GPIO32に変更しています。

何でGPIO4をPWDN端子に繋いだか

OV2640のPWDN端子をHIGHにするとパワーセーブに入ります。よって、

  • DeepSleepの間はHIGH
    • ESP32はDeepSleep時は各端子はハイインピーダンスになるのでPullUpすれば、HIGHにキープ出来る。
  • 動作時はLOW
    • Setupでカメラを初期化する前に端子をLowにすればOK

この時点で空いているGPIOピンは

  • GPIO1,3 : これらはパソコンと通信に使っている。
  • GPIO2  : 既にLEDに使用されている。
  • GPIO12  : ESP本体で使用している模様。

を外すと、GPIO4,6,11となります。そこでGPIO11を使って配線したのですが、電源投入後に下記のエラーが出て動きませんでした。

[E][camera.c:1049] camera_probe(): Detected camera not supported.

カメラが認識されないというエラー(対応2で出た奴)がです。

この回路ではGPIO11をPullUpしているので電源投入直後の状態は、”HIGH”になる思います。OV2640のデータシートを見るとPWDNピンをHIGHにすると機能が停止すると有ります。とすると、電源投入直後GPIO11の出力が、”HIGH”になりOV2640のリセット信号が無視されリセットされないのが原因では無いかと推測しました。

そこでGPIO11の電源投入直後(リセット後)の状態を調べてみました。ここー>ESP32 Datasheetに載っていました。リンク先、Appendix AIO_MUXに GPIO11の状態は oe=0, ie=1, wpu と有ります。これは、

  • oe=0: Outputモードは無効
  • ie=1: Inputモードは有効
  • wpu: PullUpされている。

予想通り電源投入後は、”HIGH”でした。残りのGPIO4,6を見ると。GPIO6は11と同じ。GPIO4は oe=0, ie=1, wpd と有ります。GPIO4は電源投入後、入力モードで状態は、”LOW”になる事が分かりました。よってGPIO4を1kΩでPullUpしPWDN信号として使用しています。

これで起動時のエラーが出なくなりました。このままでは、GPIO4は入力モードなので、スケッチの一番最初で出力モードにし、”LOW”に設定しています。

ちょっと疑問

回路は動いているので良いのですが、

  • DeepSleepモード時は全てのGPIOはハイインピーダンスになるので、Ov2640のPWDNピンを、”HIGH”にしたいならPullUpは必要。
  • GPIO4はリセット後、oe=0, ie=1, wpd。PullDownされているなら多分抵抗はメガΩ単位。

1kΩのPullUp抵抗とメガΩ単位のPullDown抵抗がGPIO4に掛かっているなら、電源投入時は、”HIGH”になる様な気がすんだけど

実機の写真

前回で載せた実機の写真にはこの辺の回路が既に配線されていました。よって今回は最終型のみ載せます。

前回のスケッチを実行

前回のスケッチから

#include "esp_camera.h"
#include "Arduino.h"
#include "SD.h"                          
#include <WiFi.h>
#include <WebServer.h>
#include "esp_deep_sleep.h"

// Pin definition for CAMERA_MODEL_AI_THINKER
#define PWDN                              4
#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

#define sd_sck  14
#define sd_mosi 15
#define sd_ss   13
#define sd_miso 32

WebServer server(80);
const char ssid[] = "ESP32DevCAM";  // SSID
const char pass[] = "12345678";   // password

// Take Picture with Camera
//camera_fb_t * fb = NULL;

RTC_DATA_ATTR int t_time[12]={0};
#define lap_h       0
#define lap_m       1
#define total_h     2
#define total_m     3
#define now_h       4
#define now_m       5
#define start_h     6
#define start_m     7
#define stop_h      8
#define stop_m      9
#define elapse_h    10
#define elapse_m    11

RTC_DATA_ATTR int bootCount = 0;
RTC_DATA_ATTR int skip_flg = 0;
uint64_t lap_Time = 0;

String index_Dt =
                  "<!DOCTYPE html>\n<html>\n<head>\n"
                  "<title>ESP32 Timelapse</title>\n"
                  "<style type='text/css'>\n"
                  "button.bt1 {background:#90ee90;font-size:50px;padding:10px;margin:20px;border-radius:30px;box-shadow:4px 4px #555;}\n"
                  "input.ip1 {font-size:40px;width:100px;}\n"
                  "input.ip2 {font-size:40px;width:70px;}\n"
                  "</style>\n</head>\n"
                  "<body>\n<center>\n"
                  "<div style='width:700px; background-color:#d8a373; border-style:solid; border-radius:30px; border-color:#6b3f31'>\n"
                  "<br><span style='font-size:70px'><b><i><u>Timelapse</u></i></b></span><br>\n"
                  "<span style='font-size:40px' id='p_vol'>50</span><span style='font-size:40px' id='p_no'> Done: xxx</span><br>\n"
                  "<img src='/data.jpg'>\n"
                  "<form method='get' style='font-size:40px'>\n"
                  "<button type='submit' name='1' class='bt1'>Take</button><br></form>\n"
                  "<form method='get' style='font-size:40px'>\n"
                  "<span>Lap : <input type='number' max='100' min='0' name='20' class='ip1'/>h\n"
                  "<input type='number' max='59' min='0' name='21' class='ip2'/>m<br>\n"
                  "Total:<input type='number' max='10000' min='0' name='22' class='ip1'/>h\n"
                  "<input type='number' max='59' min='0' name='23' class='ip2'/>m<br><br>\n"
                  "<input type='checkbox' style='scale:2.5;vertical-align:middle;' onclick='onBtnSkip()' name='30' />  Skip Time<br>\n"
                  "Now : <input type='number' max='100' min='0' name='24' class='ip1'/>h\n"
                  "<input type='number' max='59' min='0' name='25' class='ip2'/>m<br>"
                  "Start : <input type='number' max='100' min='0' name='26' class='ip1'/>h\n"
                  "<input type='number' max='59' min='0' name='27' class='ip2'/>m<br>\n"
                  "Stop : <input type='number' max='100' min='0' name='28' class='ip1'/>h\n"
                  "<input type='number' max='59' min='0' name='29' class='ip2'/>m</span><br>\n"
                  "<input type='checkbox' style='scale:2.5;vertical-align:middle;' onclick='onBtnStart()' name='31' />\n"
                  "<button type='submit' class='bt1' id='b_st'>Start</button>\n"
                  "</form>\n</div>\n</center>\n"
                  "<script>\n"
                  "function onBtnStart() {\n"
                  "if(document.getElementsByName('31')[0].checked)\n document.getElementById('b_st').disabled = '';\n"
                  "else document.getElementById('b_st').disabled = 'disabled';\n}\n\n"
                  "function onBtnSkip() {\n"
                  "if(!document.getElementsByName('30')[0].checked){\n";
                  
                  
void setup() {
    pinMode(PWDN, OUTPUT);
    digitalWrite(PWDN, LOW);

  camera_config_t config;
    // Init Camera
    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;
    config.pin_reset = RESET_GPIO_NUM;
    config.xclk_freq_hz = 20000000;
    config.pixel_format = PIXFORMAT_JPEG; 
    config.frame_size = FRAMESIZE_VGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
    config.jpeg_quality = 10;
    config.fb_count = 2;
  • 9行 PWDN宣言
    • define PWDN_GPIO_NUM 32 をdefine PWDN 4に変更
  • 30行 MISOの変更
    • define sd_miso 2 から define sd_miso 32 に変更
  • 33行 アクセスポイント名の変更
    • ESP32CAMからESP32DevCamに変更
  • 96,97行 PWDNピンの設定
    • ここでGPIO4を出力モードに設定。状態をLOWにしています。
  • 117行
    • コンフィグのPWDMピン変更

修正を終わったらコンパイル実行して下さい。ESP32_Dev_CAMでもちゃんと動きます。

スケッチにバグが

このスケッチ、ケースによって指定時間より速く終了してします事が起こる様です。原因を調べると、関数 int check_Tow(int *st, int *sp)に誤りが有ることが分かりました。

int check_Two(int *st, int *sp)
{
//  st - sp then, st > sp :0   st =< sp :1
  
  int a,b,c;
  
    a = st[0];
    b = st[1] - sp[1];
    if(b < 0) a --;
    a -= sp[0];

    c=0;
    if(a < 0) c=1;
    else 
      if(a == 0 && b < 1) c=1; 
    
    return (c); 
}

この関数は、2つの時間、stとspを比較して、st > spの時 0を st =< sp の時に1を返すものです。 15行が間違いでした。stの時間がst[0]に、分がst[1]に入っています。同様にspも時間がsp[0]に分がsp[1]に入っています。関数は st – sp を行っています。

  • 7行:stの時間を変数aに代入
  • 8行:st – sp の”分”の部分の計算
  • 9行:st の分がspの分より小さければ、stの時間の値から1を引く
  • 10行:時間の部分の計算
  • 13行:時間の部分で値がマイナスになれが、戻り値:1
  • 15行:時間の部分が0で、分の計算で1より小さければ 戻り値:1 
    • ここが間違いです。例えば、st:0時5分 sp:1時0分の様な場合、st < sp ですが戻り値が1にならない。
    • そこで、ここを if(! (a | b)) c=1; に修正しました。

修正したスケッチ(全体)を載せます。今回修正した箇所は246行です。

// Timelaps ESP32_Dev_CAM version 1
#include "esp_camera.h"
#include "Arduino.h"
#include "SD.h"                          
#include <WiFi.h>
#include <WebServer.h>
#include "esp_deep_sleep.h"

// Pin definition for CAMERA_MODEL_AI_THINKER
#define PWDN               4
#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

#define sd_sck  14
#define sd_mosi 15
#define sd_ss   13
#define sd_miso 32

WebServer server(80);
const char ssid[] = "ESP32CAM";  // SSID
const char pass[] = "12345678";   // password

// Take Picture with Camera
//camera_fb_t * fb = NULL;

RTC_DATA_ATTR int t_time[12]={0};
#define lap_h       0
#define lap_m       1
#define total_h     2
#define total_m     3
#define now_h       4
#define now_m       5
#define start_h     6
#define start_m     7
#define stop_h      8
#define stop_m      9
#define elapse_h    10
#define elapse_m    11

RTC_DATA_ATTR int bootCount = 0;
RTC_DATA_ATTR int skip_flg = 0;
uint64_t lap_Time = 0;

String index_Dt =
                  "<!DOCTYPE html>\n<html>\n<head>\n"
                  "<title>ESP32 Timelapse</title>\n"
                  "<style type='text/css'>\n"
                  "button.bt1 {background:#90ee90;font-size:50px;padding:10px;margin:20px;border-radius:30px;box-shadow:4px 4px #555;}\n"
                  "input.ip1 {font-size:40px;width:100px;}\n"
                  "input.ip2 {font-size:40px;width:70px;}\n"
                  "</style>\n</head>\n"
                  "<body>\n<center>\n"
                  "<div style='width:700px; background-color:#d8a373; border-style:solid; border-radius:30px; border-color:#6b3f31'>\n"
                  "<br><span style='font-size:70px'><b><i><u>Timelapse</u></i></b></span><br>\n"
                  "<span style='font-size:40px' id='p_vol'>50</span><span style='font-size:40px' id='p_no'> Done: xxx</span><br>\n"
                  "<img src='/data.jpg'>\n"
                  "<form method='get' style='font-size:40px'>\n"
                  "<button type='submit' name='1' class='bt1'>Take</button><br></form>\n"
                  "<form method='get' style='font-size:40px'>\n"
                  "<span>Lap : <input type='number' max='100' min='0' name='20' class='ip1'/>h\n"
                  "<input type='number' max='59' min='0' name='21' class='ip2'/>m<br>\n"
                  "Total:<input type='number' max='10000' min='0' name='22' class='ip1'/>h\n"
                  "<input type='number' max='59' min='0' name='23' class='ip2'/>m<br><br>\n"
                  "<input type='checkbox' style='scale:2.5;vertical-align:middle;' onclick='onBtnSkip()' name='30' />  Skip Time<br>\n"
                  "Now : <input type='number' max='100' min='0' name='24' class='ip1'/>h\n"
                  "<input type='number' max='59' min='0' name='25' class='ip2'/>m<br>"
                  "Start : <input type='number' max='100' min='0' name='26' class='ip1'/>h\n"
                  "<input type='number' max='59' min='0' name='27' class='ip2'/>m<br>\n"
                  "Stop : <input type='number' max='100' min='0' name='28' class='ip1'/>h\n"
                  "<input type='number' max='59' min='0' name='29' class='ip2'/>m</span><br>\n"
                  "<input type='checkbox' style='scale:2.5;vertical-align:middle;' onclick='onBtnStart()' name='31' />\n"
                  "<button type='submit' class='bt1' id='b_st'>Start</button>\n"
                  "</form>\n</div>\n</center>\n"
                  "<script>\n"
                  "function onBtnStart() {\n"
                  "if(document.getElementsByName('31')[0].checked)\n document.getElementById('b_st').disabled = '';\n"
                  "else document.getElementById('b_st').disabled = 'disabled';\n}\n\n"
                  "function onBtnSkip() {\n"
                  "if(!document.getElementsByName('30')[0].checked){\n";
                  
                  
void setup() {
  pinMode(PWDN, OUTPUT);
  digitalWrite(PWDN, LOW);

  camera_config_t config;
    // Init Camera
    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;
    config.pin_reset = RESET_GPIO_NUM;
    config.xclk_freq_hz = 20000000;
    config.pixel_format = PIXFORMAT_JPEG; 
    config.frame_size = FRAMESIZE_VGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
    config.jpeg_quality = 10;
    config.fb_count = 2;

  Serial.begin(115200);
  delay(1000);

  WiFi.disconnect(true);
  WiFi.softAPdisconnect(true);
  
  esp_camera_init(&config);

  SPI.begin(sd_sck, sd_miso, sd_mosi, sd_ss);
  SD.begin(sd_ss);

  if(esp_sleep_get_wakeup_cause() != 4)
  { 
    Serial.println("Connecting to WiFi");
    WiFi.disconnect(true);
    WiFi.softAPdisconnect(true);
    delay(500);
    
    WiFi.softAP(ssid, pass); 
    delay(1000);

    Serial.print("AP IP address: ");
    Serial.println(WiFi.softAPIP());

    server.on("/", handleRoot);
    server.onNotFound(handleWebRequests); 
    server.begin();
    Serial.println("HTTP server started");
  }
  else
  {
    take_Poto();
    switch(check_Next())
    {
      case 0: 
      case 1: esp_sleep_enable_timer_wakeup(lap_Time);
              break;
              
      case 2: esp_sleep_enable_ext0_wakeup(GPIO_NUM_0,0);
    }

    esp_deep_sleep_start(); 
    delay(500);
  }
}

int check_Next()
{
  int a,b,flg;
  int d_data[12];

    flg=0;
    for(a=0; a<12; a++) d_data[a] = t_time[a];
    
    if(check_Two(&d_data[total_h], &d_data[elapse_h])) flg=2;  
    //  esp_sleep_enable_ext0_wakeup(GPIO_NUM_16,0);
    else
    {
      if(skip_flg)                                            // Skip = On
      {
        if(check_Two(&d_data[start_h], &d_data[stop_h]))      // start < stop
        {
          if(check_Two(&d_data[stop_h], &d_data[now_h])) ;    // now >= stop 
          else                                                // now  < stop
          {
            if(check_Two(&d_data[start_h], &d_data[now_h]))   // start =< now 
            {
                calc_Wait(0); flg=1;          
            }
          }
        }
        else                                                  // start > stop
        {
          if(check_Two(&d_data[start_h], &d_data[now_h]))     // now > start     
          {
             calc_Wait(1); flg=1;          
          }
        }
      }
    }
    
    if(flg == 0)
    {
      lap_Time = t_time[lap_h] * 60 + t_time[lap_m];
      t_time[now_m] += t_time[lap_m]; 
      if(t_time[now_m] > 59) 
      {
        t_time[now_m] -= 60;
        t_time[now_h] ++;
      }
      t_time[now_h] += t_time[lap_h]; 
      if(t_time[now_h] > 23) t_time[now_h] -= 24;

      t_time[elapse_m] += t_time[lap_m]; 
      if(t_time[elapse_m] > 59) 
      {
        t_time[elapse_m] -= 60;
        t_time[elapse_h] ++;
      }
      t_time[elapse_h] += t_time[lap_h]; 
    }
    //Set timer 
    lap_Time *= 60000000;
     
    return(flg); 
}

int check_Two(int *st, int *sp)
{
//  st - sp then, st > sp :0   st =< sp :1
  
  int a,b,c;
  
    a = st[0];
    b = st[1] - sp[1];
    if(b < 0) a --;
    a -= sp[0];

    c=0;
    if(a < 0) c=1;
    else 
      if(!(a | b)) c=1; 
    
    return (c); 
}

void calc_Wait(int flg)
{
  int a,b;

    b = t_time[stop_h];
    if(flg) b += 24;

    a = t_time[stop_m] - t_time[now_m];
    if( a < 0)
    {
      a = t_time[stop_m] + 60 - t_time[now_m];
      b --;
    }
    
    b -= t_time[now_h];
    lap_Time = b * 60 + a;
    t_time[now_h] = t_time[stop_h];
    t_time[now_m] = t_time[stop_m];  
}

void loop() {
  
  server.handleClient();
}

void handleRoot() {
  String cmd,buf;
  int a,b,flg;
  File dataFile;
  camera_fb_t * fb = NULL;
  float d_vol;
  char temp[16];

    flg=0;
    cmd=server.argName(0);
    switch(cmd.toInt())
    {
      case 1:   // Start Log
                fb = esp_camera_fb_get();
                dataFile = SD.open("/data.jpg", FILE_WRITE);
                dataFile.write(fb->buf, fb->len); // payload (image), payload length
                dataFile.close();
                esp_camera_fb_return(fb); 
                Serial.printf("Take a photo.\n");
                break;
                
      case 20:   // Start Log
                skip_flg=1; b=30;
                if(server.arg("30") == "") { skip_flg=0; b=24; }

                for(a=20; a<b; a++)
                {
                  cmd=server.arg(String(a));
                  t_time[a-20]=cmd.toInt(); 
                }
                
                t_time[elapse_h] = t_time[elapse_m] = 0;
                bootCount = 0;
                switch(check_Next())
                {
                  case 0: take_Poto();
                  case 1: esp_sleep_enable_timer_wakeup(lap_Time);
                          break;
              
                  case 2: esp_sleep_enable_ext0_wakeup(GPIO_NUM_0,0);
                        break;
                }
                flg=1;

                break;
    }

    buf=index_Dt;
    for(a=24; a<29; a++)
      buf += ("document.getElementsByName('" + String(a) + "')[0].disabled =\n");
    buf += "document.getElementsByName('29')[0].disabled =true;}\nelse{\n";
    for(a=24; a<29; a++)
      buf += ("document.getElementsByName('" + String(a) + "')[0].disabled =\n");
    buf += "document.getElementsByName('29')[0].disabled =false;}}\n\n";
    
    d_vol = analogRead(33);
    d_vol *= 3.3; d_vol /= 2048;
    dtostrf(d_vol, 5, 2,temp);
    cmd=temp;
    buf += ("document.getElementById('p_vol').innerHTML=\"Battery: " + cmd +  " V \";\n");
    buf += ("document.getElementById('p_no').innerHTML=\"Elapsed: " + String(t_time[elapse_h]) + ":" + String(t_time[elapse_m]) + "\";\n\n");

    for(a=20; a<30; a++)
      buf += ("document.getElementsByName('" + String(a) + "')[0].value=" + String(t_time[a-20]) +";\n");
    
    if(skip_flg)
      buf += "document.getElementById('lap').checked=true;\n";
      
    buf += "onBtnStart();\nonBtnSkip();\nhistory.pushState(null,null,'/');\n</script>\n</body>\n</html>";

    server.send(200, "text/html", buf);

    if(flg)
    {
      esp_deep_sleep_start();
      delay(500);
    }
}

void handleWebRequests()
{
  String dataType = "text/plain";
  String path;
  File dataFile;
   
    path = server.uri();
    if(path.endsWith(".txt")) dataType = "text/plain";
    else if(path.endsWith(".css")) dataType = "text/css";
    else if(path.endsWith(".js")) dataType = "application/javascript";
    else if(path.endsWith(".png")) dataType = "image/png";
    else if(path.endsWith(".gif")) dataType = "image/gif";
    else if(path.endsWith(".jpg")) dataType = "image/jpeg";
    delay(5);
    
    dataFile = SD.open(path.c_str(), "r");
    server.streamFile(dataFile, dataType);
    dataFile.close();
    delay(5);
}

void take_Poto()
{
  File dataFile;
  camera_fb_t * fb = NULL;
  String f_name;
  char s_name[15];
  
    fb = esp_camera_fb_get();
    sprintf(s_name,"%08d",bootCount);
    f_name = s_name; 
    f_name = "/" + f_name + ".jpg" ;
    dataFile = SD.open(f_name, FILE_WRITE);
    dataFile.write(fb->buf, fb->len); // payload (image), payload length
    dataFile.close();
    esp_camera_fb_return(fb); 
    bootCount ++;
    Serial.println("No." + String(bootCount));
}

これで、”ESP32CAM”と同じレベル?

殆ど同じですが、全く同じでは有りません。”ESP32_Dev_CAM”が”ESP32CAM”より有利な点は、

  • 技適に対応(これが一番)
  • OV2640のPWDN制御が出来る。TimeLaps時のパワーセーブが出来る。
  • カメラと本体を切り離す事が可能。

不利な点は

  • 技適に不対応か?
  • カメラの焦点が自動では無く手動。
  • PC<ー>ESP32間のシリアル変換ICはTimeLaps時必要無いが、その電源を切れない。
  • FLASH(異常に明るいLED)が無い
  • カメラのパッケージがされていない。本体とカメラと2つパックする必要がある。

次はこれを元に改善して行きたいと思います。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする