Skip to content

Commit

Permalink
Vehicle: add 12V shutdown delay & notification
Browse files Browse the repository at this point in the history
New configs:
  [vehicle] 12v.shutdown_delay      -- Shutdown delay in minutes (default: 2)

New events:
  vehicle.alert.12v.low             -- 12V shutdown voltage level detected
  vehicle.alert.12v.operational     -- 12V recovered above shutdown level

New notifications:
  [alert] batt.12v.shutdown         -- Alert about imminent 12V shutdown
  • Loading branch information
dexterbg committed Sep 21, 2023
1 parent ceceac6 commit 1437482
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 6 deletions.
2 changes: 2 additions & 0 deletions docs/source/userguide/events.rst
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ vehicle.alarm.off Vehicle alarm has been disarmed
vehicle.alarm.on Vehicle alarm has been armed
vehicle.alert.12v.off 12V system voltage has recovered
vehicle.alert.12v.on 12V system voltage is below alert threshold
vehicle.alert.12v.low 12V shutdown voltage level detected
vehicle.alert.12v.operational 12V recovered above shutdown level
vehicle.alert.12v.shutdown 12V shutdown threshold reached, entering deep sleep
vehicle.alert.bms BMS cell/pack volts/temps exceeded thresholds
vehicle.asleep Vehicle systems are asleep
Expand Down
48 changes: 48 additions & 0 deletions docs/source/userguide/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,35 @@ triggered if the voltage drops below 11.0V. This is suitable for standard lead-a
If you've got another chemistry, change the values accordingly.


^^^^^^^^^^^^^^^^^
Shutdown / Reboot
^^^^^^^^^^^^^^^^^

You can set a voltage level to trigger a system shutdown. The module will close all connections,
shutdown all components and enter deep sleep mode to achieve minimal power consumption. It will
then wait for the voltage level to recover above the configured minimum wakeup voltage before
doing a reboot.

On most vehicles, this can also be used to automatically shutdown the module when the vehicle
isn't operated (driven or charged), as the 12V level normally is above 13V when the vehicle is
in an operational state, and drops to below 13V when the vehicle is switched off.

The shutdown condition is checked once per minute. You can configure a minimum delay for the actual
shutdown to be done, default is 2 minutes (= 3 consecutive tests = 2-3 minutes).

To test for a recovered 12V level, the module needs to do short wakeups of ~3 seconds (only CPU,
no components). This is by default done every 60 seconds. If you use the auto shutdown to follow
the vehicle operational state, consider lowering this to e.g. 15 seconds to get a quick detection
of the vehicle being switched on.

Configuration can be done via the web UI or by these config variables::

config set vehicle 12v.shutdown <voltage>
config set vehicle 12v.shutdown_delay <minutes>
config set vehicle 12v.wakeup <voltage>
config set vehicle 12v.wakeup_interval <seconds>


^^^^^^^^^^^^^^^
Related Metrics
^^^^^^^^^^^^^^^
Expand All @@ -291,6 +320,25 @@ Event Data Purpose
=================================== ========= =======
vehicle.alert.12v.on 12V system voltage is below alert threshold
vehicle.alert.12v.off 12V system voltage has recovered
vehicle.alert.12v.low 12V shutdown voltage level detected
vehicle.alert.12v.operational 12V recovered above shutdown level
vehicle.alert.12v.shutdown 12V shutdown threshold reached, entering deep sleep
vehicle.charge.12v.start Vehicle 12V battery is charging
vehicle.charge.12v.stop Vehicle 12V battery has stopped charging
=================================== ========= =======

See :doc:`scripting` on how to attach custom scripts to events.

^^^^^^^^^^^^^^^^^^^^^
Related Notifications
^^^^^^^^^^^^^^^^^^^^^

======= =========================== ================================================================
Type Subtype Purpose / Content
======= =========================== ================================================================
alert batt.12v.alert 12V Battery critical
alert batt.12v.recovered 12V Battery restored
alert batt.12v.shutdown System shutdown (deep sleep) due to low 12V battery level
======= =========================== ================================================================

See :doc:`notifications` on how to filter/suppress notifications.
1 change: 1 addition & 0 deletions docs/source/userguide/notifications.rst
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ alert alarm.sounding Vehicle alarm is sounding
alert alarm.stopped Vehicle alarm has stopped
alert batt.12v.alert 12V Battery critical
alert batt.12v.recovered 12V Battery restored
alert batt.12v.shutdown System shutdown (deep sleep) due to low 12V battery level
alert batt.bms.alert Battery pack/cell alert (critical voltage/temperature deviation)
alert batt.soc.alert Battery SOC critical
info charge.done ``stat`` on charge finished
Expand Down
8 changes: 8 additions & 0 deletions vehicle/OVMS.V3/changes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@ Open Vehicle Monitor System v3 - Change log
New events:
vehicle.alert.12v.shutdown -- 12V shutdown threshold reached, entering deep sleep
- BYD Atto 3 initial support
- Vehicle: add 12V shutdown delay & notification
New configs:
[vehicle] 12v.shutdown_delay -- Shutdown delay in minutes (default: 2)
New events:
vehicle.alert.12v.low -- 12V shutdown voltage level detected
vehicle.alert.12v.operational -- 12V recovered above shutdown level
New notifications:
[alert] batt.12v.shutdown -- Alert about imminent 12V shutdown


2022-09-01 MWJ 3.3.003 OTA release
Expand Down
9 changes: 8 additions & 1 deletion vehicle/OVMS.V3/components/ovms_webserver/src/web_cfg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ void OvmsWebServer::HandleCfgVehicle(PageEntry_t& p, PageContext_t& c)
{
std::string error, info;
std::string vehicleid, vehicletype, vehiclename, timezone, timezone_region, pin;
std::string bat12v_factor, bat12v_ref, bat12v_alert, bat12v_shutdown, bat12v_wakeup, bat12v_wakeup_interval;
std::string bat12v_factor, bat12v_ref, bat12v_alert, bat12v_shutdown, bat12v_shutdown_delay, bat12v_wakeup, bat12v_wakeup_interval;

std::map<metric_group_t,std::string> units_values;
metric_group_list_t unit_groups;
Expand All @@ -630,6 +630,7 @@ void OvmsWebServer::HandleCfgVehicle(PageEntry_t& p, PageContext_t& c)
bat12v_ref = c.getvar("bat12v_ref");
bat12v_alert = c.getvar("bat12v_alert");
bat12v_shutdown = c.getvar("bat12v_shutdown");
bat12v_shutdown_delay = c.getvar("bat12v_shutdown_delay");
bat12v_wakeup = c.getvar("bat12v_wakeup");
bat12v_wakeup_interval = c.getvar("bat12v_wakeup_interval");
pin = c.getvar("pin");
Expand Down Expand Up @@ -664,6 +665,7 @@ void OvmsWebServer::HandleCfgVehicle(PageEntry_t& p, PageContext_t& c)
MyConfig.SetParamValue("vehicle", "12v.ref", bat12v_ref);
MyConfig.SetParamValue("vehicle", "12v.alert", bat12v_alert);
MyConfig.SetParamValue("vehicle", "12v.shutdown", bat12v_shutdown);
MyConfig.SetParamValue("vehicle", "12v.shutdown_delay", bat12v_shutdown_delay);
MyConfig.SetParamValue("vehicle", "12v.wakeup", bat12v_wakeup);
MyConfig.SetParamValue("vehicle", "12v.wakeup_interval", bat12v_wakeup_interval);
if (!pin.empty())
Expand Down Expand Up @@ -697,6 +699,7 @@ void OvmsWebServer::HandleCfgVehicle(PageEntry_t& p, PageContext_t& c)
bat12v_ref = MyConfig.GetParamValue("vehicle", "12v.ref");
bat12v_alert = MyConfig.GetParamValue("vehicle", "12v.alert");
bat12v_shutdown = MyConfig.GetParamValue("vehicle", "12v.shutdown");
bat12v_shutdown_delay = MyConfig.GetParamValue("vehicle", "12v.shutdown_delay");
bat12v_wakeup = MyConfig.GetParamValue("vehicle", "12v.wakeup");
bat12v_wakeup_interval = MyConfig.GetParamValue("vehicle", "12v.wakeup_interval");
c.head(200);
Expand Down Expand Up @@ -809,6 +812,10 @@ void OvmsWebServer::HandleCfgVehicle(PageEntry_t& p, PageContext_t& c)
"<p>If the voltage drops to/below this level, the module will enter deep sleep and wait for the voltage to recover to the wakeup level.</p>"
"<p>Recommended shutdown level for standard lead acid batteries: not less than 10.5 V</p>",
"min=\"10\" max=\"15\" step=\"0.1\"", "V");
c.input("number", "Shutdown delay", "bat12v_shutdown_delay", bat12v_shutdown_delay.c_str(), "Default: 2",
"<p>The 12V shutdown condition needs to be present for at least this long to actually cause a shutdown "
"(0 = shutdown on first detection, check is done once per minute).</p>",
"min=\"0\" max=\"60\" step=\"1\"", "Minutes");
c.input("number", "12V wakeup", "bat12v_wakeup", bat12v_wakeup.c_str(), "Default: any",
"<p>The minimum voltage level to allow restarting the module after a 12V shutdown.</p>"
"<p>Recommended minimum level for standard lead acid batteries: not less than 11.0 V",
Expand Down
47 changes: 42 additions & 5 deletions vehicle/OVMS.V3/components/vehicle/vehicle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ OvmsVehicle::OvmsVehicle()

m_ticker = 0;
m_12v_ticker = 0;
m_12v_low_ticker = 0;
m_12v_shutdown_ticker = 0;
m_chargestate_ticker = 0;
m_vehicleon_ticker = 0;
m_vehicleoff_ticker = 0;
Expand Down Expand Up @@ -662,15 +664,42 @@ void OvmsVehicle::VehicleTicker1(std::string event, void* data)
}

// Check for shutdown level:
float shutdown_threshold = MyConfig.GetParamValueFloat("vehicle", "12v.shutdown", 0);
if (shutdown_threshold > 0 && volt > 0 && volt <= shutdown_threshold && !MyBoot.IsShuttingDown())
if (!MyBoot.IsShuttingDown())
{
MyEvents.SignalEvent("vehicle.alert.12v.shutdown", NULL);
unsigned int wakeup_interval = MyConfig.GetParamValueInt("vehicle", "12v.wakeup_interval", 60);
MyBoot.DeepSleep(wakeup_interval);
float shutdown_threshold = MyConfig.GetParamValueFloat("vehicle", "12v.shutdown", 0);
if (shutdown_threshold > 0 && volt > 0 && volt <= shutdown_threshold)
{
++m_12v_low_ticker;
if (m_12v_low_ticker == 1)
{
MyEvents.SignalEvent("vehicle.alert.12v.low", NULL);
}
int shutdown_delay = MyConfig.GetParamValueInt("vehicle", "12v.shutdown_delay", 2);
if (m_12v_low_ticker > shutdown_delay)
{
MyEvents.SignalEvent("vehicle.alert.12v.shutdown", NULL);
if (m_autonotifications) Notify12vShutdown();
// shutdown in 10 seconds to allow for scripts & notifications:
m_12v_shutdown_ticker = 10;
}
}
else
{
if (m_12v_low_ticker > 0)
{
m_12v_low_ticker = 0;
MyEvents.SignalEvent("vehicle.alert.12v.operational", NULL);
}
}
}
}

if (m_12v_shutdown_ticker > 0 && --m_12v_shutdown_ticker == 0)
{
unsigned int wakeup_interval = MyConfig.GetParamValueInt("vehicle", "12v.wakeup_interval", 60);
MyBoot.DeepSleep(wakeup_interval);
}

if ((m_ticker % 10)==0)
{
// Check MINSOC
Expand Down Expand Up @@ -843,6 +872,14 @@ void OvmsVehicle::Notify12vRecovered()
MyNotify.NotifyStringf("alert", "batt.12v.recovered", "12V Battery restored: %.1fV (ref=%.1fV)", volt, vref);
}

void OvmsVehicle::Notify12vShutdown()
{
float volt = StandardMetrics.ms_v_bat_12v_voltage->AsFloat();
float wakeup = MyBoot.GetMin12VLevel();

MyNotify.NotifyStringf("alert", "batt.12v.shutdown", "12V Battery shutdown: %.1fV (wakeup at/above %.1fV)", volt, wakeup);
}

void OvmsVehicle::NotifyMinSocCritical()
{
float soc = StandardMetrics.ms_v_bat_soc->AsFloat();
Expand Down
3 changes: 3 additions & 0 deletions vehicle/OVMS.V3/components/vehicle/vehicle.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,8 @@ class OvmsVehicle : public InternalRamAllocated
protected:
uint32_t m_ticker;
int m_12v_ticker;
int m_12v_low_ticker;
int m_12v_shutdown_ticker;
int m_chargestate_ticker;
int m_vehicleon_ticker;
int m_vehicleoff_ticker;
Expand All @@ -401,6 +403,7 @@ class OvmsVehicle : public InternalRamAllocated
virtual void NotifyAlarmStopped();
virtual void Notify12vCritical();
virtual void Notify12vRecovered();
virtual void Notify12vShutdown();
virtual void NotifyMinSocCritical();
virtual void NotifyVehicleIdling();
virtual void NotifyVehicleOn();
Expand Down
1 change: 1 addition & 0 deletions vehicle/OVMS.V3/main/ovms_boot.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ class Boot
void SetSoftReset();
void SetFirmwareUpdate();
void SetMin12VLevel(float min_12v_level);
float GetMin12VLevel() { return boot_data.min_12v_level; }
void Restart(bool hard=false);
void DeepSleep(unsigned int seconds = 60);
void DeepSleep(time_t waketime);
Expand Down

0 comments on commit 1437482

Please sign in to comment.