エントリー

【自作タイムラプス】ESP32-CAMをDeepSleepモードで省電力化してみた【Time Lapse】

自作のタイムラプスカメラの稼働時間延長にトライしてみた。
arduinoにはDeepSleepモードがあって、待機電力をかなり減らせるみたい。

20210227110453.jpg

普通だと平均80mAほど消費しているようですが、DeepSleepを使うと10~150μA程度に消費電力を抑えることができるそうです。
10マイクロから150マクロなんてほとんど流れてない状態みたいですね。

20210301121545.png

現在使用中のコードはこちら

【ESP32-CAM】タイムラプス用のカメラを自作してみた。【DIY】

コードの考察

DeepSleepのコードについては、ArduinoIDEにスケッチのサンプルがある。

ファイル → スケッチ例 → ESP32 → Deepsleep 

いくつかサンプルがあるが、ここではTimerWakeupを選択する。

62行目

esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

TIME_TO_SLEEP * uS_TO_S_FACTOR がスリープ時間になっている。
1000000Usが1秒なので、180*1000000として3分となる。

esp_deep_sleep_start();

88行目でDeepSleepがスタートする。

DeepSleepで変数が消える

 DeepSleepは半分リセットみたいなものなので、Void Loop() を使わずにSetup()で起動する。

 ここで困るのが、変数が消えてしまうこと。変数が消えてしまうと画像のファイル名もリセットされてしまい起動するたびにファイルが上書きされてしまう。
適当にテキストファイルを作ってファイル番号をRead、Writeさせる方法も考えたが、少し複雑になるのとSDの消費電力を考慮して見送った。

RTC_DATA_ATTR を使ってみる

RTC_DATA_ATTR を使うことで、ESP32のメモリーに変数を書き込むことができるようになるので、電源が落ちない限り保持することが可能になるみたい。

 これにより、電源を切っても保持されるEEPROMで親番のファイル名を保持し、子番はRTC_DATA_ATTRで電源が切れるまで保持することにした。

 こうすることでファイルが上書きされることを防ぐ。ただし、この方法だと256×999枚を超えるとP001_001.jpgから上書きされる。

できあがったタイムラプスのコード

#include "esp_camera.h"
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include "SD.h"

//SD Card Pins
#define sd_sck 14
#define sd_mosi 15
#define sd_ss 13
#define sd_miso 2

// read and write from flash memory
#include <EEPROM.h>

// define the number of bytes you want to access
#define EEPROM_SIZE 1
#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

RTC_DATA_ATTR int myF_No = 0;
RTC_DATA_ATTR int myS_No = 0;

char myFileName_str1[4];
char myFileName_str2[4];

void setup()
{
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);

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

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_VGA; //UXGA|SXGA|XGA|SVGA|VGA|CIF|QVGA|HQVGA|QQVGA
config.jpeg_quality = 10;
config.fb_count = 1;

esp_err_t err = esp_camera_init(&config);

if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
delay(1000);
ESP.restart();
}

// LED Pin Mode
pinMode(33, OUTPUT);
digitalWrite(33,LOW);
  delay (500);

camera_fb_t * fb = NULL;

// Take Picture with Camera

Serial.println(" ");
  Serial.println("Take Picture ");

fb = esp_camera_fb_get();

// Path where new picture will be saved in SD Card
Serial.println("Save SD Card");

// Get File Name
if (myS_No == 0 || myS_No == 999){

// initialize EEPROM with predefined size

EEPROM.begin(EEPROM_SIZE);
myF_No = EEPROM.read(0) + 1;
EEPROM.write(0, myF_No);
EEPROM.commit();

myS_No = 1;

}else{

myS_No = myS_No + 1;

}

sprintf(myFileName_str1, "%03d",myF_No);
sprintf(myFileName_str2, "%03d",myS_No);

String path = "/p" + String(myFileName_str1)+"_"+
String(myFileName_str2) +".jpg";

Serial.printf("Picture file name: %s\n", path.c_str());
SPI.begin(sd_sck, sd_miso, sd_mosi, sd_ss);
SD.begin(sd_ss);

File file = SD.open(path.c_str(), FILE_WRITE);
file.write(fb->buf, fb->len);

file.close();

esp_camera_fb_return(fb);
Serial.println("complete");

digitalWrite(33,HIGH);

// 1000000u秒 →1秒
esp_sleep_enable_timer_wakeup(180*1000000);
Serial.println("Deep Sleep Start.");
Serial.println(" ");

esp_deep_sleep_start();

}

void loop() {

}

従来のタイムラプスと比較してみた

 微量の電流を計る機材がないため、USBテスターで調べてみた。
従来のプログラムだと待機時に0.02Aを示していた。

20210227114649.jpg

今回のプログラムだと0.00Aと表示された。数値的にはどの程度の電流が流れているかは分からないが、明らかに消費電力が抑えれていることが分かる。

20210227114648.jpg

今後、稼働時間を測定してみたい。

参考サイト

ページ移動

ユーティリティ

サイト内検索

twitter

ありがとうございます

過去ログ