
ブラウンアウトリセットが何回か連続したら、WiFi接続をあきらめて、しばらくDeepsleepで寝るというプログラムを書いてみました。バッテリ動作時のテストに使えます。
ブラウンアウトリセット
「電池2,3本で動作するESP32-C3ボード」は電源電圧が低下した状態でWiFi接続すると、ESP32が大電流を消費し、低電圧状態になりリセットしてしまいます。これをブラウンアウトリセットと言います。
このため起動時のリセット要因として、ブラウンアウトリセットを検出したら、WiFiの接続をあきらめるか、長時間待ってバッテリー回復を待つかする必要があります。
そこで、起動時にリセット要因をチェックして、10回連続でブラウンアウトリセットを検出したら、1時間DeepSleepする。そうでなければ、WiFiに接続し、接続できたら5秒間Deepsleepする。という動作テスト用のプログラムを書いてみました。
テストプログラム
#include <WiFi.h>
#define WIFI_BEGIN_TIMEOUT 10 //[s]
#define SLEEP_TIME 5*1000*1000 //[us] 5sec
#define SSID "SSID"
#define PASSWORD "PASSWORD"
#define WIFI_LED_PIN 7 //Tring connect WiFi
#define BOR_LED_PIN 10 //Brounot reset counter overflow
#include <Preferences.h>
Preferences prefs;
#define BROWNOUT_RST_MAX 10
#define BROWNOUT_SLEEP_TIME 60*60*1000*1000 //[us] 1hour
RTC_DATA_ATTR bool brownoutResetFlag = false;
#define BROWNOUTDETECT_SLEEP_TIME 1*1000*1000 //[us] 1sec
void setup() {
WiFi.disconnect(true); //WiFi OFF
pinMode(WIFI_LED_PIN, OUTPUT);
digitalWrite(WIFI_LED_PIN, LOW); //OFF
pinMode(BOR_LED_PIN, OUTPUT);
digitalWrite(BOR_LED_PIN, LOW); //OFF
Serial.begin(115200);
Serial.println("");
Serial.println("start");
resetReason(); //Show RESET reason
//Brownout detection
prefs.begin("brownout", false);
uint8_t count = prefs.getUChar("count", 0); // Read 1Byte(default:0)
Serial.printf("ReadValue: %u\n", count);
esp_reset_reason_t reason = esp_reset_reason();
if( ESP_RST_BROWNOUT == reason )
{
//Brownout reset is detected
brownoutResetFlag = true;
prefs.end();
esp_deep_sleep(BROWNOUTDETECT_SLEEP_TIME); //All peripherals are disabled
}
if( ESP_RST_DEEPSLEEP == reason && brownoutResetFlag == true )
{
brownoutResetFlag = false;
count++;
if( BROWNOUT_RST_MAX < count )
{
prefs.end();
//Brownout count is overflow
for( int i=0 ; i<20 ; i++){
digitalWrite(BOR_LED_PIN, HIGH);
delay(250);
digitalWrite(BOR_LED_PIN, LOW);
delay(250);
}
//Long deepsleep
esp_deep_sleep(BROWNOUT_SLEEP_TIME);
}else{
prefs.putUChar("count", count);
Serial.printf("WriteValue: %u\n", count);
}
}else{
if( 0 != count )
{
//Clear the counter
count = 0;
prefs.putUChar("count", count);
Serial.printf("WriteValue: %u\n", count);
}
}
prefs.end();
//WiFi connect
digitalWrite(WIFI_LED_PIN, HIGH); //ON
WiFi.mode(WIFI_MODE_STA);
Serial.println("tring Wifi connect");
WiFi.begin(SSID,PASSWORD);
for (int i = 0; i < WIFI_BEGIN_TIMEOUT; i++) {
if (WiFi.status() == WL_CONNECTED) {
Serial.println(" connected");
break;
}
Serial.print("o");
delay(1000);
}
if (WiFi.status() != WL_CONNECTED) {
ESP.restart();
}
for(int i=0 ; i<3 ; i++){
digitalWrite(WIFI_LED_PIN, LOW); //OFF
delay(100);
digitalWrite(WIFI_LED_PIN, HIGH); //ON
delay(100);
}
//DeepSleep
digitalWrite(WIFI_LED_PIN, LOW); //OFF
Serial.print("DeepSleep\n");
esp_deep_sleep(SLEEP_TIME);
}
void loop() {
}
//Show RESET reason
void resetReason() {
esp_reset_reason_t reason = esp_reset_reason();
switch (reason) {
case ESP_RST_UNKNOWN: Serial.println("ESP_RST_UNKNOWN : Reset reason can not be determined"); break;
case ESP_RST_POWERON: Serial.println("ESP_RST_POWERON : Reset due to power-on event"); break;
case ESP_RST_EXT: Serial.println("ESP_RST_EXT : Reset by external pin (not applicable for ESP32)"); break;
case ESP_RST_SW: Serial.println("ESP_RST_SW : Software reset via esp_restart"); break;
case ESP_RST_PANIC: Serial.println("ESP_RST_PANIC : Software reset due to exception/panic"); break;
case ESP_RST_INT_WDT: Serial.println("ESP_RST_INT_WDT : Reset (software or hardware) due to interrupt watchdog"); break;
case ESP_RST_TASK_WDT: Serial.println("ESP_RST_TASK_WDT : Reset due to task watchdog"); break;
case ESP_RST_WDT: Serial.println("ESP_RST_WDT : Reset due to other watchdogs"); break;
case ESP_RST_DEEPSLEEP: Serial.println("ESP_RST_DEEPSLEEP : Reset after exiting deep sleep mode"); break;
case ESP_RST_BROWNOUT: Serial.println("ESP_RST_BROWNOUT : Brownout reset (software or hardware)"); break;
case ESP_RST_SDIO: Serial.println("ESP_RST_SDIO : Reset over SDIO"); break;
default: break;
}
}
4行目 #define SSID にご自身のアクセスポイントのSSIDを設定し、5行目 #define PASSWORD にパスワードを設定してください。
WiFi.begin()でBrownoutResetが発生した場合、リセットはしてもWiFiの回路が暴走したままなので、一旦DeepSleepさせてWiFiの回路を停止させます(40行目)。RTCメモリのbrownoutResetFlag をtrueにしておきます。
DeepSleepから復帰してbrownoutResetFlagがtrueだったら(43行目)、FlashメモリにBrownoutResetの回数を設定します。この回数がBROWNOUT_RST_MAXの回数に達したら、WiFiの起動を諦めてDeepSleepに入ります。
その他の復帰条件だった場合、FlashメモリにBrownoutResetの回数を0に設定します(71行目)。
動作回路

GPIOの7ピンに1kΩ程度(470Ωから4.7kΩくらい)の抵抗と赤色のLEDを接続します。10ピンにも同様に1kΩ程度(100Ωから2.2kΩくらい)の抵抗と青色のLEDを接続します。
VINとGNDに電源や電池などを接続します。電源の配線は太いものを使ってください。
USBを接続するとUSBから電源が供給されてしまうので、テストすることができません。プログラムを書き込んで動作チェックがお済みになったら、USBは外してください。
動作

電源を入れます。青いLEDが点灯している間は、WiFiへの接続を試行している状態です。数秒間点灯しWiFiに接続できたら消灯します。その後5秒間Deepsleepします。
このため正常に動作していれば、数秒間青色LEDが点灯し、5秒間消灯するという動作を繰り返します。
しかし電源電圧が低いとWiFi接続の試行時にブラウンアウトリセットしてしまい、青色LEDがすぐに消灯します。このため、青色LEDが点滅しているように見えます。
10回連続してブラウンアウトリセットが起こるとWiFi接続の試行をあきらめ、赤いLEDが10秒間点灯します。10秒後は1時間のDeepsleepに入ります。
ご自身の環境で上記のプログラムを実行し、赤色LEDが点灯してしまうのであれば電圧不足か、配線の太さが細すぎると判断できます。
テストプログラムを使うことで、ご自身の環境において、どの電圧までWiFiが試行できるか、またどの電圧まで動作を継続することができるかテストすることができます。
「電池2,3本で動作するESP32-C3ボード」をお使いになる際のテストにご利用ください。
この記事で利用している「電池2,3本で動作するESP32-C3ボード」はkohacraftのshopで販売しています。



コメント