Skip to content

Commit d8028d5

Browse files
committed
Power management: fix UI, fix deep sleep, allow disabling deep sleep
1 parent 53fbe90 commit d8028d5

File tree

10 files changed

+124
-69
lines changed

10 files changed

+124
-69
lines changed

vehicle/OVMS.V3/components/ovms_script/src/ovms_script.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2002,15 +2002,15 @@ void DuktapeVFSSave::SaveTask(void *param)
20022002
MyEvents.RegisterEvent(tag, "system.shuttingdown",
20032003
[&](std::string event, void* data)
20042004
{
2005-
MyBoot.RestartPending(tag.c_str());
2005+
MyBoot.ShutdownPending(tag.c_str());
20062006
shuttingdown = true;
20072007
});
20082008

20092009
me->Save();
20102010
me->Unref();
20112011

20122012
MyEvents.DeregisterEvent(tag);
2013-
if (shuttingdown) MyBoot.RestartReady(tag.c_str());
2013+
if (shuttingdown) MyBoot.ShutdownReady(tag.c_str());
20142014
}
20152015

20162016
vTaskDelete(NULL);

vehicle/OVMS.V3/components/ovms_webserver/src/ovms_webserver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ OvmsWebServer::OvmsWebServer()
5555

5656
m_running = false;
5757
m_configured = false;
58-
m_restart_countdown = 0;
58+
m_shutdown_countdown = 0;
5959
memset(m_sessions, 0, sizeof(m_sessions));
6060

6161
#if MG_ENABLE_FILESYSTEM

vehicle/OVMS.V3/components/ovms_webserver/src/ovms_webserver.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ class OvmsWebServer : public ExternalRamAllocated
596596
TimerHandle_t m_update_ticker;
597597

598598
int m_init_timeout;
599-
int m_restart_countdown;
599+
int m_shutdown_countdown;
600600
};
601601

602602
extern OvmsWebServer MyWebServer;

vehicle/OVMS.V3/components/ovms_webserver/src/ovms_websockethandler.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -523,15 +523,15 @@ void OvmsWebServer::EventListener(std::string event, void* data)
523523
{
524524
// shutdown delay to finish command output transmissions:
525525
if (event == "system.shuttingdown") {
526-
MyBoot.RestartPending("webserver");
527-
m_restart_countdown = 3;
526+
MyBoot.ShutdownPending("webserver");
527+
m_shutdown_countdown = 3;
528528
}
529529

530530
// ticker:
531531
else if (event == "ticker.1") {
532532
CfgInitTicker();
533-
if (m_restart_countdown > 0 && --m_restart_countdown == 0)
534-
MyBoot.RestartReady("webserver");
533+
if (m_shutdown_countdown > 0 && --m_shutdown_countdown == 0)
534+
MyBoot.ShutdownReady("webserver");
535535
}
536536

537537
// reload plugins on changes:

vehicle/OVMS.V3/components/powermgmt/powermgmt.cpp

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ static const char *TAG = "powermgmt";
3333
#include "ovms_config.h"
3434
#include "powermgmt.h"
3535
#include "ovms_peripherals.h"
36+
#include "ovms_boot.h"
3637
#include "metrics_standard.h"
3738

3839
powermgmt MyPowerMgmt __attribute__ ((init_priority (8500)));
@@ -155,31 +156,24 @@ void powermgmt::Ticker1(std::string event, void* data)
155156
if (StandardMetrics.ms_v_bat_12v_voltage_alert->AsBool())
156157
{
157158
m_12v_alert_timer++;
158-
if (m_12v_alert_timer > m_12v_shutdown_delay*60) // minutes to seconds
159+
if (m_12v_shutdown_delay && m_12v_alert_timer == 1)
160+
{
161+
ESP_LOGW(TAG, "12V battery alert detected, will shutdown in %d minutes", m_12v_shutdown_delay);
162+
}
163+
if (m_12v_shutdown_delay && m_12v_alert_timer > m_12v_shutdown_delay*60) // minutes to seconds
159164
{
160165
ESP_LOGE(TAG,"Ongoing 12V battery alert time limit exceeded! Shutting down OVMS..");
161166
MyEvents.SignalEvent("powermgmt.ovms.shutdown",NULL);
162-
vTaskDelay(500 / portTICK_PERIOD_MS); // make sure all notifications all transmitted before powerring down OVMS
163-
#ifdef CONFIG_OVMS_COMP_WIFI
164-
MyPeripherals->m_esp32wifi->SetPowerMode(Off);
165-
#endif
166-
#ifdef CONFIG_OVMS_COMP_MODEM_SIMCOM
167-
MyPeripherals->m_simcom->SetPowerMode(Off);
168-
#endif
169-
#ifdef CONFIG_OVMS_COMP_EXTERNAL_SWCAN
170-
MyPeripherals->m_mcp2515_swcan->SetPowerMode(Off);
171-
#endif
172-
#ifdef CONFIG_OVMS_COMP_ESP32CAN
173-
MyPeripherals->m_esp32can->SetPowerMode(Off);
174-
#endif
175-
#ifdef CONFIG_OVMS_COMP_EXT12V
176-
MyPeripherals->m_ext12v->SetPowerMode(Off);
177-
#endif
178-
MyPeripherals->m_esp32->SetPowerMode(DeepSleep);
167+
MyBoot.DeepSleep();
168+
m_12v_shutdown_delay = 0;
179169
}
180170
}
181171
else
182172
{
173+
if (m_12v_shutdown_delay && m_12v_alert_timer)
174+
{
175+
ESP_LOGI(TAG, "12V battery alert resolved, shutdown cancelled");
176+
}
183177
m_12v_alert_timer = 0;
184178
}
185179
}

vehicle/OVMS.V3/components/powermgmt/powermgmt_web.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,19 +134,23 @@ void powermgmt::WebCleanup()
134134
c.input("number", "Delay before SIMCOM modem is turned off", "modemoff_delay", modemoff_delay.c_str(),
135135
"Default: " STR(POWERMGMT_MODEMOFF_DELAY) " hours",
136136
"<p>0 = disabled</p>",
137-
"min=\"1\" step=\"1\"", "hours");
137+
"min=\"0\" step=\"1\"", "hours");
138138
#endif
139139

140140
c.input("number", "Delay before WiFi is turned off", "wifioff_delay", wifioff_delay.c_str(),
141141
"Default: " STR(POWERMGMT_WIFIOFF_DELAY) " hours",
142142
"<p>0 = disabled</p>",
143-
"min=\"1\" step=\"1\"", "hours");
143+
"min=\"0\" step=\"1\"", "hours");
144144

145145
c.input("number", "Delay before OVMS is shut down (after initial 12V battery level alert)", "12v_shutdown_delay", b12v_shutdown_delay.c_str(),
146146
"Default: " STR(POWERMGMT_12V_SHUTDOWN_DELAY) " minutes",
147+
"<p>0 = disabled</p>"
148+
"<p><b class=\"text-danger\">⚠</b> This depends on a proper 12V calibration "
149+
"(see <a href=\"/cfg/vehicle\" target=\"#main\">vehicle configuration</a>).</p>"
147150
"<p>If 12V battery is depleted under certain threshold, an alarm is set. OVMS waits this time period during which user can begin charging the batteries. "
148-
"If this period is exceeded without canceled alarm, OVMS will be shut down to prevent further battery depletion.</p>",
149-
"min=\"1\" step=\"1\"", "minutes");
151+
"If this period is exceeded without canceled alarm, OVMS will be shut down (sleep) to prevent further battery depletion.</p>"
152+
"<p>The module will then check the 12V level once per minute, and automatically reboot when the voltage has ben restored.</p>",
153+
"min=\"0\" step=\"1\"", "minutes");
150154

151155
c.print("<hr>");
152156
c.input_button("default", "Save");

vehicle/OVMS.V3/components/sdcard/src/sdcard.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ void sdcard::Ticker1(std::string event, void* data)
6868
{
6969
MyEvents.SignalEvent("sd.unmounted", NULL);
7070
if (MyBoot.IsShuttingDown())
71-
MyBoot.RestartReady(TAG);
71+
MyBoot.ShutdownReady(TAG);
7272
}
7373
}
7474
}
@@ -78,7 +78,7 @@ void sdcard::EventSystemShutDown(std::string event, void* data)
7878
{
7979
if (m_mounted && event == "system.shuttingdown")
8080
{
81-
MyBoot.RestartPending(TAG);
81+
MyBoot.ShutdownPending(TAG);
8282
ESP_LOGI(TAG,"Unmounting SDCARD for reset");
8383
unmount();
8484
}

vehicle/OVMS.V3/components/simcom/src/simcom.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ void simcom::EventListener(std::string event, void* data)
398398
{
399399
if (m_state1 != PoweredOff)
400400
{
401-
MyBoot.RestartPending(TAG);
401+
MyBoot.ShutdownPending(TAG);
402402
SetState1(PoweringOff);
403403
}
404404
}
@@ -578,7 +578,7 @@ void simcom::State1Enter(SimcomState1 newstate)
578578
case PoweredOff:
579579
ESP_LOGI(TAG,"State: Enter PoweredOff state");
580580
MyEvents.SignalEvent("system.modem.poweredoff", NULL);
581-
if (MyBoot.IsShuttingDown()) MyBoot.RestartReady(TAG);
581+
if (MyBoot.IsShuttingDown()) MyBoot.ShutdownReady(TAG);
582582
m_mux.Stop();
583583
break;
584584
case PowerOffOn:

vehicle/OVMS.V3/main/ovms_boot.cpp

Lines changed: 84 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ static const char *TAG = "boot";
3838
#include "esp_system.h"
3939
#include "esp_panic.h"
4040
#include "esp_task_wdt.h"
41+
#include <driver/adc.h>
4142

4243
#include "ovms.h"
4344
#include "ovms_boot.h"
@@ -80,6 +81,7 @@ static const char *sdesc[] = {
8081
// Boot reasons [bootreason_t]
8182
static const char* const bootreason_name[] = {
8283
"PowerOn",
84+
"Wakeup",
8385
"SoftReset",
8486
"FirmwareUpdate",
8587
"EarlyCrash",
@@ -150,10 +152,11 @@ void boot_status(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc,
150152
writer->printf(" Reset reason: %s (%d)\n",MyBoot.GetResetReasonName(),MyBoot.GetResetReason());
151153
writer->printf(" Crash counters: %d total, %d early\n",MyBoot.GetCrashCount(),MyBoot.GetEarlyCrashCount());
152154

153-
if (MyBoot.m_restart_timer>0)
155+
if (MyBoot.m_shutdown_timer>0)
154156
{
155-
writer->printf("\nRestart in progress (%d secs, waiting for %d tasks)\n",
156-
MyBoot.m_restart_timer, MyBoot.m_restart_pending);
157+
writer->printf("\nShutdown for %s in progress (%d secs, waiting for %d tasks)\n",
158+
MyBoot.m_shutdown_deepsleep ? "DeepSleep" : "Restart",
159+
MyBoot.m_shutdown_timer, MyBoot.m_shutdown_pending);
157160
}
158161

159162
if (MyBoot.GetCrashCount() > 0)
@@ -203,8 +206,9 @@ Boot::Boot()
203206
RESET_REASON cpu0 = rtc_get_reset_reason(0);
204207
RESET_REASON cpu1 = rtc_get_reset_reason(1);
205208

206-
m_restart_timer = 0;
207-
m_restart_pending = 0;
209+
m_shutdown_timer = 0;
210+
m_shutdown_pending = 0;
211+
m_shutdown_deepsleep = false;
208212
m_shutting_down = false;
209213

210214
m_resetreason = esp_reset_reason(); // Note: necessary to link reset_reason module
@@ -215,6 +219,40 @@ Boot::Boot()
215219
m_bootreason = BR_PowerOn;
216220
ESP_LOGI(TAG, "Power cycle reset detected");
217221
}
222+
else if (cpu0 == DEEPSLEEP_RESET)
223+
{
224+
memset(&boot_data,0,sizeof(boot_data_t));
225+
m_bootreason = BR_Wakeup;
226+
esp_sleep_wakeup_cause_t wakeup_cause = esp_sleep_get_wakeup_cause();
227+
ESP_LOGI(TAG, "Wakeup from deep sleep detected, wakeup cause %d", wakeup_cause);
228+
229+
// There is currently only one deep sleep application: saving the 12V battery
230+
// from depletion. So we need to check if the voltage level is sufficient for
231+
// normal operation now. MyPeripherals has not been initialized yet, so we need
232+
// to read the ADC manually here.
233+
#ifdef CONFIG_OVMS_COMP_ADC
234+
// Note: RTC_MODULE nags about a lock release before aquire, this can be ignored
235+
// (reason: RTC_MODULE needs FreeRTOS for locking, which hasn't been started yet)
236+
adc1_config_width(ADC_WIDTH_12Bit);
237+
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_11db);
238+
uint32_t adc_level = 0;
239+
for (int i = 0; i < 5; i++)
240+
adc_level += adc1_get_raw(ADC1_CHANNEL_0);
241+
float level_12v = adc_level / 5 / 195.7;
242+
ESP_LOGI(TAG, "12V level: ~%.1fV", level_12v);
243+
if (level_12v > 11.0)
244+
ESP_LOGI(TAG, "12V level sufficient, proceeding with boot");
245+
else if (level_12v < 1.0)
246+
ESP_LOGI(TAG, "Assuming USB powered, proceeding with boot");
247+
else
248+
{
249+
ESP_LOGE(TAG, "12V level insufficient, re-entering deep sleep");
250+
esp_deep_sleep(1000000LL * 60);
251+
}
252+
#else
253+
ESP_LOGW(TAG, "ADC not available, cannot check 12V level");
254+
#endif // CONFIG_OVMS_COMP_ADC
255+
}
218256
else if (boot_data.crc != boot_data.calc_crc())
219257
{
220258
memset(&boot_data,0,sizeof(boot_data_t));
@@ -320,13 +358,22 @@ const char* Boot::GetResetReasonName()
320358
static void boot_shutdown_done(const char* event, void* data)
321359
{
322360
MyConfig.unmount();
323-
esp_restart();
361+
362+
if (MyBoot.m_shutdown_deepsleep)
363+
{
364+
// For consistency with init, instead of calling MyPeripherals->m_esp32->SetPowerMode(DeepSleep):
365+
esp_deep_sleep(1000000LL * 60);
366+
}
367+
else
368+
{
369+
esp_restart();
370+
}
324371
}
325372

326373
static void boot_shuttingdown_done(const char* event, void* data)
327374
{
328-
if (MyBoot.m_restart_pending == 0)
329-
MyBoot.m_restart_timer = 2;
375+
if (MyBoot.m_shutdown_pending == 0)
376+
MyBoot.m_shutdown_timer = 2;
330377
}
331378

332379
void Boot::Restart(bool hard)
@@ -339,11 +386,11 @@ void Boot::Restart(bool hard)
339386
return;
340387
}
341388

342-
ESP_LOGI(TAG,"Shutting down for restart...");
343-
OvmsMutexLock lock(&m_restart_mutex);
389+
ESP_LOGI(TAG,"Shutting down for %s...", m_shutdown_deepsleep ? "DeepSleep" : "Restart");
390+
OvmsMutexLock lock(&m_shutdown_mutex);
344391
m_shutting_down = true;
345-
m_restart_pending = 0;
346-
m_restart_timer = 60; // Give them 60 seconds to shutdown
392+
m_shutdown_pending = 0;
393+
m_shutdown_timer = 60; // Give them 60 seconds to shutdown
347394
MyEvents.SignalEvent("system.shuttingdown", NULL, boot_shuttingdown_done);
348395

349396
#undef bind // Kludgy, but works
@@ -352,39 +399,46 @@ void Boot::Restart(bool hard)
352399
MyEvents.RegisterEvent(TAG,"ticker.1", std::bind(&Boot::Ticker1, this, _1, _2));
353400
}
354401

355-
void Boot::RestartPending(const char* tag)
402+
void Boot::DeepSleep()
403+
{
404+
m_shutdown_deepsleep = true;
405+
Restart(false);
406+
}
407+
408+
void Boot::ShutdownPending(const char* tag)
356409
{
357-
OvmsMutexLock lock(&m_restart_mutex);
358-
m_restart_pending++;
359-
ESP_LOGW(TAG, "Restart: %s pending, %d total", tag, m_restart_pending);
410+
OvmsMutexLock lock(&m_shutdown_mutex);
411+
m_shutdown_pending++;
412+
ESP_LOGW(TAG, "Shutdown: %s pending, %d total", tag, m_shutdown_pending);
360413
}
361414

362-
void Boot::RestartReady(const char* tag)
415+
void Boot::ShutdownReady(const char* tag)
363416
{
364-
OvmsMutexLock lock(&m_restart_mutex);
365-
m_restart_pending--;
366-
ESP_LOGI(TAG, "Restart: %s ready, %d pending", tag, m_restart_pending);
367-
if (m_restart_pending == 0)
368-
m_restart_timer = 2;
417+
OvmsMutexLock lock(&m_shutdown_mutex);
418+
m_shutdown_pending--;
419+
ESP_LOGI(TAG, "Shutdown: %s ready, %d pending", tag, m_shutdown_pending);
420+
if (m_shutdown_pending == 0)
421+
m_shutdown_timer = 2;
369422
}
370423

371424
void Boot::Ticker1(std::string event, void* data)
372425
{
373-
if (m_restart_timer > 0)
426+
if (m_shutdown_timer > 0)
374427
{
375-
OvmsMutexLock lock(&m_restart_mutex);
376-
m_restart_timer--;
377-
if (m_restart_timer == 1)
428+
OvmsMutexLock lock(&m_shutdown_mutex);
429+
m_shutdown_timer--;
430+
if (m_shutdown_timer == 1)
378431
{
379-
ESP_LOGI(TAG,"Restart now");
432+
ESP_LOGI(TAG, "%s now", m_shutdown_deepsleep ? "DeepSleep" : "Restart");
380433
}
381-
else if (m_restart_timer == 0)
434+
else if (m_shutdown_timer == 0)
382435
{
383436
MyEvents.SignalEvent("system.shutdown", NULL, boot_shutdown_done);
384437
return;
385438
}
386-
else if ((m_restart_timer % 5)==0)
387-
ESP_LOGI(TAG,"Restart in %d seconds (%d pending)...",m_restart_timer,m_restart_pending);
439+
else if ((m_shutdown_timer % 5)==0)
440+
ESP_LOGI(TAG, "%s in %d seconds (%d pending)...",
441+
m_shutdown_deepsleep ? "DeepSleep" : "Restart", m_shutdown_timer, m_shutdown_pending);
388442
}
389443
}
390444

vehicle/OVMS.V3/main/ovms_boot.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
typedef enum
4343
{
4444
BR_PowerOn = 0, // standard power on / hard reset
45+
BR_Wakeup, // reboot from deep sleep
4546
BR_SoftReset, // user requested reset ("module reset")
4647
BR_FirmwareUpdate, // Firmware update reset
4748
BR_EarlyCrash, // crash during boot/init phase
@@ -106,15 +107,17 @@ class Boot
106107
void SetSoftReset();
107108
void SetFirmwareUpdate();
108109
void Restart(bool hard=false);
109-
void RestartPending(const char* tag);
110-
void RestartReady(const char* tag);
110+
void DeepSleep();
111+
void ShutdownPending(const char* tag);
112+
void ShutdownReady(const char* tag);
111113
bool IsShuttingDown();
112114
void Ticker1(std::string event, void* data);
113115

114116
public:
115-
OvmsMutex m_restart_mutex;
116-
unsigned int m_restart_timer;
117-
unsigned int m_restart_pending;
117+
OvmsMutex m_shutdown_mutex;
118+
unsigned int m_shutdown_timer;
119+
unsigned int m_shutdown_pending;
120+
bool m_shutdown_deepsleep;
118121
bool m_shutting_down;
119122

120123
public:

0 commit comments

Comments
 (0)