Skip to content

Commit d4d8b57

Browse files
authored
Merge pull request #1422 from zorgms/refactor-trickle-charge-and-pre-cond
smartEQ: Add CommandClimateControlEQ and 12V trickle support
2 parents f8c21eb + 8ef9198 commit d4d8b57

6 files changed

Lines changed: 84 additions & 104 deletions

File tree

vehicle/OVMS.V3/components/vehicle_smarteq/src/eq_cmds_override.cpp

Lines changed: 61 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,12 @@ static const char *TAG = "v-smarteq";
3434

3535
#include "vehicle_smarteq.h"
3636

37-
// can can1 tx st 634 40 01 72 00
37+
// can can1 tx st 634 40 01 00 00
3838
OvmsVehicle::vehicle_command_t OvmsVehicleSmartEQ::CommandClimateControl(bool enable) {
39+
return CommandClimateControlEQ(enable, false, 0, false);
40+
}
41+
42+
OvmsVehicle::vehicle_command_t OvmsVehicleSmartEQ::CommandClimateControlEQ(bool enable, bool restart, int minutes, bool trickle) {
3943

4044
if(!IsCANwrite())
4145
{
@@ -61,12 +65,11 @@ OvmsVehicle::vehicle_command_t OvmsVehicleSmartEQ::CommandClimateControl(bool en
6165
}
6266
}
6367

64-
if (StandardMetrics.ms_v_bat_soc->AsInt(0) < 31)
68+
if (StdMetrics.ms_v_bat_soc->AsInt(can_soc) < 31)
6569
{
6670
char msg[100];
67-
snprintf(msg, sizeof(msg), "Scheduled precondition skipped: Battery SOC too low (%d%%)",
68-
StandardMetrics.ms_v_bat_soc->AsInt(0));
69-
ESP_LOGW(TAG, "%s", msg);
71+
snprintf(msg, sizeof(msg), "Scheduled precondition skipped: HV SOC too low (%d%%)", StdMetrics.ms_v_bat_soc->AsInt(can_soc));
72+
ESP_LOGI(TAG, "%s", msg);
7073
MyNotify.NotifyString("alert", "climatecontrol.schedule", msg);
7174
m_climate_restart_ticker = 0;
7275
m_climate_restart = false;
@@ -80,111 +83,94 @@ OvmsVehicle::vehicle_command_t OvmsVehicleSmartEQ::CommandClimateControl(bool en
8083
return Success;
8184
}
8285

83-
OvmsVehicle::vehicle_command_t res = Fail;
84-
8586
if (enable && !IsOnHVACEQ())
8687
{
88+
CommandWakeup();
8789
uint8_t data[4] = {0x40, 0x01, 0x00, 0x00};
8890
canbus *obd;
8991
obd = m_can1;
90-
res = Fail;
9192
for (int i = 0; i < 15; i++)
9293
{
9394
if (IsOnHVACEQ())
9495
{
95-
ESP_LOGI(TAG, "Climate control started");
96-
res = Success;
96+
StdMetrics.ms_v_env_awake->SetValue(true);
97+
ESP_LOGD(TAG, "Climate control is now on");
9798
break;
9899
}
99100
obd->WriteStandard(0x634, 4, data);
100101
vTaskDelay(200 / portTICK_PERIOD_MS);
101102
}
103+
104+
if (IsOnHVACEQ())
105+
{
106+
// if true, climate will be restarted after 5 minutes by Ticker1, if false, climate will not be restarted after 5 minutes
107+
m_climate_restart = restart;
108+
m_climate_restart_ticker = minutes;
109+
if (trickle)
110+
{
111+
ESP_LOGI(TAG, "activated 12V trickle charging successfully");
112+
Notify12Vcharge();
113+
}
114+
else
115+
{
116+
// add 2 minutes to display time if restart is true, because climate will be restarted after 5/10 minutes
117+
int minutes_display = restart ? minutes + 2 : 5;
118+
char msg[100];
119+
snprintf(msg, sizeof(msg), "%d minutes precondition started, HV SOC is %d%%", minutes_display, StdMetrics.ms_v_bat_soc->AsInt(can_soc));
120+
ESP_LOGI(TAG, "%s", msg);
121+
MyNotify.NotifyString("info", "climatecontrol.schedule", msg);
122+
}
123+
return Success;
124+
}
125+
else
126+
{
127+
if (trickle)
128+
{
129+
ESP_LOGI(TAG, "Failed to activate 12V trickle charging");
130+
MyNotify.NotifyString("info", "12v.trickle.charge", "Failed to activate 12V trickle charging!");
131+
}
132+
else
133+
{
134+
ESP_LOGI(TAG, "Failed to activate precondition");
135+
MyNotify.NotifyString("info", "climatecontrol.schedule","Failed to activate precondition!");
136+
}
137+
return Fail;
138+
}
102139
}
103140
else
104141
{
105-
res = NotImplemented;
106-
}
107-
// fallback to default implementation?
108-
if (res == NotImplemented)
109-
{
110-
res = OvmsVehicle::CommandClimateControl(enable);
142+
// fallback to default implementation?
143+
return OvmsVehicle::CommandClimateControl(enable);
111144
}
112-
return res;
113145
}
114146

115147
OvmsVehicle::vehicle_command_t OvmsVehicleSmartEQ::CommandHomelink(int button, int durationms) {
116-
// This is needed to enable climate control via Homelink for the iOS app
148+
// This is needed to enable climate control via Homelink
117149
ESP_LOGI(TAG, "CommandHomelink button=%d durationms=%d", button, durationms);
118-
OvmsVehicle::vehicle_command_t res = NotImplemented;
119150

120151
switch (button)
121152
{
122153
case 0:
123154
{
124-
res = CommandClimateControl(true);
125-
126-
if (res == Success)
127-
{
128-
m_climate_restart = false;
129-
m_climate_restart_ticker = 0; // 5 minutes default runtime, no ticker required
130-
ESP_LOGI(TAG, "Precondition activated successfully");
131-
MyNotify.NotifyString("info", "climatecontrol.schedule",
132-
"5 minutes precondition started");
133-
}
134-
else
135-
{
136-
ESP_LOGE(TAG, "Failed to activate precondition (result=%d)", res);
137-
MyNotify.NotifyString("error", "climatecontrol.schedule",
138-
"precondition failed to start");
139-
}
140-
break;
155+
// 5 minutes default runtime, no ticker required
156+
CommandClimateControlEQ(true,false,0,false);
157+
return Success;
141158
}
142159
case 1:
143160
{
144-
res = CommandClimateControl(true);
145-
146-
if (res == Success)
147-
{
148-
m_climate_restart = true;
149-
m_climate_restart_ticker = 8; // 10 minutes
150-
ESP_LOGI(TAG, "Precondition activated successfully");
151-
MyNotify.NotifyString("info", "climatecontrol.schedule",
152-
"10 minutes precondition started");
153-
}
154-
else
155-
{
156-
ESP_LOGE(TAG, "Failed to activate precondition (result=%d)", res);
157-
MyNotify.NotifyString("error", "climatecontrol.schedule",
158-
"precondition failed to start");
159-
}
160-
break;
161+
// 10 minutes runtime, will be restarted after 5 minutes by Ticker60, so total runtime will be 10 minutes
162+
CommandClimateControlEQ(true,true,8,false);
163+
return Success;
161164
}
162165
case 2:
163166
{
164-
res = CommandClimateControl(true);
165-
166-
if (res == Success)
167-
{
168-
m_climate_restart = true;
169-
m_climate_restart_ticker = 12; // 15 minutes
170-
ESP_LOGI(TAG, "Precondition activated successfully");
171-
MyNotify.NotifyString("info", "climatecontrol.schedule",
172-
"15 minutes precondition started");
173-
}
174-
else
175-
{
176-
ESP_LOGE(TAG, "Failed to activate precondition (result=%d)", res);
177-
MyNotify.NotifyString("error", "climatecontrol.schedule",
178-
"precondition failed to start");
179-
}
180-
break;
167+
// 15 minutes runtime, will be restarted after 5 and 10 minutes by Ticker60, so total runtime will be 15 minutes
168+
CommandClimateControlEQ(true,true,13,false);
169+
return Success;
181170
}
182171
default:
183-
res = OvmsVehicle::CommandHomelink(button, durationms);
184-
break;
172+
return OvmsVehicle::CommandHomelink(button, durationms);
185173
}
186-
187-
return res;
188174
}
189175

190176
OvmsVehicle::vehicle_command_t OvmsVehicleSmartEQ::CommandWakeup() {
@@ -215,7 +201,7 @@ OvmsVehicle::vehicle_command_t OvmsVehicleSmartEQ::CommandWakeup() {
215201
vTaskDelay(200 / portTICK_PERIOD_MS);
216202
}
217203
res = Success;
218-
can_awake = true;
204+
StdMetrics.ms_v_env_awake->SetValue(true);
219205
ESP_LOGI(TAG, "Vehicle is now awake");
220206
}
221207
else

vehicle/OVMS.V3/components/vehicle_smarteq/src/eq_commands.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -390,9 +390,9 @@ void OvmsVehicleSmartEQ::xsq_calc_adc(int verbosity, OvmsWriter* writer, OvmsCom
390390
writer->puts("Error: invalid number");
391391
return;
392392
}
393-
if (val < 12.0 || val > 15.0)
393+
if (val < 11.0 || val > 16.0)
394394
{
395-
writer->puts("Error: voltage out of plausible range (12.0–15.0)");
395+
writer->puts("Error: voltage out of plausible range (11.0–16.0)");
396396
return;
397397
}
398398
writer->printf("Recalculating ADC factor using override voltage %.2fV\n", val);
@@ -401,7 +401,7 @@ void OvmsVehicleSmartEQ::xsq_calc_adc(int verbosity, OvmsWriter* writer, OvmsCom
401401
}
402402
else if (argc == 0)
403403
{
404-
if (!StdMetrics.ms_v_env_charging12v->AsBool(false))
404+
if (!smarteq->Is12VchargeEQ())
405405
{
406406
writer->puts("Error: vehicle 12V DC-DC converter not active");
407407
return;

vehicle/OVMS.V3/components/vehicle_smarteq/src/eq_features.cpp

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,6 @@ void OvmsVehicleSmartEQ::ResetTotalCounters() {
235235

236236
// check the 12V alert periodically and charge the 12V battery if needed
237237
void OvmsVehicleSmartEQ::Check12vState() {
238-
OvmsVehicle::vehicle_command_t res = NotImplemented;
239238
static const float MIN_VOLTAGE = 10.0f;
240239
static const int ALERT_THRESHOLD_TICKS = 10;
241240

@@ -261,19 +260,7 @@ void OvmsVehicleSmartEQ::Check12vState() {
261260
{
262261
m_12v_ticker = 0;
263262
ESP_LOGI(TAG, "Initiating climate control due to 12V alert");
264-
res = CommandClimateControl(true);
265-
266-
if (res == Success)
267-
{
268-
m_climate_restart = true;
269-
m_climate_restart_ticker = 12; // 15 minutes
270-
ESP_LOGI(TAG, "activated 12V charging successfully");
271-
Notify12Vcharge();
272-
}
273-
else
274-
{
275-
ESP_LOGE(TAG, "Failed to activate 12V charging");
276-
}
263+
CommandClimateControlEQ(true,true,8,true); // Start climate control with restart and 10 minutes duration
277264
}
278265
}
279266
else if (m_12v_ticker > 0)
@@ -285,7 +272,7 @@ void OvmsVehicleSmartEQ::Check12vState() {
285272

286273
void OvmsVehicleSmartEQ::ReCalcADCfactor(float can12V, OvmsWriter* writer) {
287274
#ifdef CONFIG_OVMS_COMP_ADC
288-
if (can12V < 12.0f || can12V > 15.0f)
275+
if (can12V < 11.0f || can12V > 16.0f)
289276
{
290277
ESP_LOGW(TAG, "Skip ADC factor recalculation (invalid 12V input %.2f)", can12V);
291278
if (writer) writer->printf("Skip ADC factor recalculation (invalid 12V input %.2f)\n", can12V);
@@ -300,7 +287,7 @@ void OvmsVehicleSmartEQ::ReCalcADCfactor(float can12V, OvmsWriter* writer) {
300287
// Collect samples
301288
for (int i = 0; i < m_adc_samples; i++)
302289
{
303-
vTaskDelay(2 / portTICK_PERIOD_MS);
290+
vTaskDelay(5 / portTICK_PERIOD_MS);
304291
samples_adc[i] = adc1_get_raw(ADC1_CHANNEL_0);
305292
}
306293

@@ -346,9 +333,9 @@ void OvmsVehicleSmartEQ::ReCalcADCfactor(float can12V, OvmsWriter* writer) {
346333
// Calculate average of USM voltage samples
347334
float V_batt = can12V;
348335

349-
float adc_factor_median = (V_batt > 12.0f) ? (median_raw / V_batt) : 0.0f;
350-
float adc_factor_avg = (V_batt > 12.0f) ? (avg_raw / V_batt) : 0.0f;
351-
float adc_factor_trimmed = (V_batt > 12.0f) ? (trimmed_avg / V_batt) : 0.0f;
336+
float adc_factor_median = (V_batt > 11.0f) ? (median_raw / V_batt) : 0.0f;
337+
float adc_factor_avg = (V_batt > 11.0f) ? (avg_raw / V_batt) : 0.0f;
338+
float adc_factor_trimmed = (V_batt > 11.0f) ? (trimmed_avg / V_batt) : 0.0f;
352339

353340
float adc_factor_new = adc_factor_median;
354341
float adc_factor_prev = MyConfig.GetParamValueFloat("system.adc", "factor12v", 195.7f);

vehicle/OVMS.V3/components/vehicle_smarteq/src/eq_notify.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ void OvmsVehicleSmartEQ::NotifySOClimit() {
165165
}
166166

167167
OvmsVehicle::vehicle_command_t OvmsVehicleSmartEQ::Command12Vcharge(int verbosity, OvmsWriter* writer) {
168-
writer->puts("12V charge on:");
168+
writer->puts("12V trickle charge on:");
169169
writer->printf(" 12V: %s\n", (char*) StdMetrics.ms_v_bat_12v_voltage->AsUnitString("-", Native, 1).c_str());
170170
writer->printf(" SOC: %s\n", (char*) StdMetrics.ms_v_bat_soc->AsUnitString("-", Native, 1).c_str());
171171
writer->printf(" CAP: %s\n", (char*) StdMetrics.ms_v_bat_capacity->AsUnitString("-", Native, 1).c_str());

vehicle/OVMS.V3/components/vehicle_smarteq/src/eq_ticker.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,11 @@ void OvmsVehicleSmartEQ::Ticker10(uint32_t ticker)
8383
OnlineState();
8484

8585
// check 12V charging state for powermgmt system
86-
bool charge_12v = StdMetrics.ms_v_bat_12v_voltage->AsFloat(0.0f) > 13.1f ? true : false;
87-
if (charge_12v != StdMetrics.ms_v_env_charging12v->AsBool(false))
86+
if (Is12VchargeEQ() != StdMetrics.ms_v_env_charging12v->AsBool(false))
8887
{
89-
StdMetrics.ms_v_env_charging12v->SetValue(charge_12v);
88+
StdMetrics.ms_v_env_charging12v->SetValue(Is12VchargeEQ());
9089
m_ADCfactor_recalc_timer = 2;
91-
m_ADCfactor_recalc = charge_12v;
90+
m_ADCfactor_recalc = Is12VchargeEQ();
9291
}
9392
// if HVAC is on, then modify polling to get the DCDC data (reboot prevention)
9493
if (IsOnHVACEQ() && IsAwakeEQ() && m_enable_write_caron && !m_can_active)
@@ -100,6 +99,11 @@ void OvmsVehicleSmartEQ::Ticker10(uint32_t ticker)
10099
{
101100
smartChargeStart();
102101
}
102+
if (IsAwakeEQ() != StdMetrics.ms_v_env_awake->AsBool(false))
103+
{
104+
// if car is not awake but metric is, then set metric to false to prevent desync
105+
StdMetrics.ms_v_env_awake->SetValue(IsAwakeEQ());
106+
}
103107
}
104108

105109
void OvmsVehicleSmartEQ::Ticker60(uint32_t ticker) {
@@ -185,7 +189,7 @@ void OvmsVehicleSmartEQ::PollerStateTicker(canbus *bus)
185189
m_candata_timer = SQ_CANDATA_TIMEOUT;
186190
}
187191

188-
if (m_candata_timer > 0 && --m_candata_timer == 0 && m_candata_poll)
192+
if ((!IsAwakeEQ()) || (m_candata_timer > 0 && --m_candata_timer == 0 && m_candata_poll))
189193
{
190194
// Car has gone to sleep
191195
ESP_LOGI(TAG,"Car has gone to sleep (CAN bus timeout)");

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ class OvmsVehicleSmartEQ : public OvmsVehicle
158158
void smartCAN2Metrics();
159159

160160
// --- Command overrides ---
161-
vehicle_command_t CommandClimateControl(bool enable) override;
161+
vehicle_command_t CommandClimateControl(bool enable) override; // Override to add support for preconditioning and 12V trickle charge -> CommandClimateControlEQ
162162
vehicle_command_t CommandHomelink(int button, int durationms=1000) override;
163163
vehicle_command_t CommandWakeup() override;
164164
vehicle_command_t CommandStat(int verbosity, OvmsWriter* writer) override;
@@ -170,6 +170,8 @@ class OvmsVehicleSmartEQ : public OvmsVehicle
170170
vehicle_command_t CommandStopCharge() override;
171171

172172
// --- Custom vehicle commands ---
173+
174+
vehicle_command_t CommandClimateControlEQ(bool enable, bool restart = false, int minutes = 0, bool trickle = false);
173175
vehicle_command_t CommandCanVector(uint32_t txid, uint32_t rxid, std::vector<std::string> hexbytes, bool reset=false, bool wakeup=false);
174176
vehicle_command_t ProcessMsgCommand(std::string &result, int command, const char* args);
175177
vehicle_command_t MsgCommandCA(std::string &result, int command, const char* args);
@@ -231,6 +233,7 @@ class OvmsVehicleSmartEQ : public OvmsVehicle
231233
bool IsChargingEQ() { return can_charge_inprogress; }
232234
bool IsOnHVACEQ() { return can_hvac; }
233235
bool IsCANwrite() { return m_enable_write || m_enable_write_caron; }
236+
bool Is12VchargeEQ() { return StdMetrics.ms_v_bat_12v_voltage->AsFloat(0.0f) > 13.1f || StdMetrics.ms_v_env_charging12v->AsBool(false); }
234237

235238
// =========================================================================
236239
// protected

0 commit comments

Comments
 (0)