diff --git a/README.md b/README.md
index 22c85ada..2184126e 100644
--- a/README.md
+++ b/README.md
@@ -109,8 +109,11 @@ It is also based on the information found in the following excellent repositorie
- Pylon hacking https://www.eevblog.com/forum/programming/pylontech-sc0500-protocol-hacking/
## Like this project? 💖
-Leave a ⭐ If you think this project is useful. Consider hopping onto my Patreon to encourage more open-source projects!
+Leave a ⭐ If you think this project is useful. Consider hopping onto my Patreon to encourage more open-source projects! As a bonus, you will get access to the Discord server, where we hangout, develop, support, share, discuss etc. all things related to DIY EV storage solutions. See you on the server? ;)
-
+ <------ Click here to learn more!
+
+
+
diff --git a/Software/src/battery/BMW-I3-BATTERY.cpp b/Software/src/battery/BMW-I3-BATTERY.cpp
index 788de470..10009a3f 100644
--- a/Software/src/battery/BMW-I3-BATTERY.cpp
+++ b/Software/src/battery/BMW-I3-BATTERY.cpp
@@ -103,21 +103,6 @@ void BmwI3Battery::update_values() { //This function maps all the values fetche
} else {
clear_event(EVENT_CONTACTOR_WELDED);
}
-
- // Update webserver datalayer
- datalayer_extended.bmwi3.SOC_raw = (battery_HVBatt_SOC * 10);
- datalayer_extended.bmwi3.SOC_dash = (battery_display_SOC * 50);
- datalayer_extended.bmwi3.SOC_OBD2 = battery_soc;
- datalayer_extended.bmwi3.ST_iso_ext = battery_status_error_isolation_external_Bordnetz;
- datalayer_extended.bmwi3.ST_iso_int = battery_status_error_isolation_internal_Bordnetz;
- datalayer_extended.bmwi3.ST_valve_cooling = battery_status_valve_cooling;
- datalayer_extended.bmwi3.ST_interlock = battery_status_error_locking;
- datalayer_extended.bmwi3.ST_precharge = battery_status_precharge_locked;
- datalayer_extended.bmwi3.ST_DCSW = battery_status_disconnecting_switch;
- datalayer_extended.bmwi3.ST_EMG = battery_status_emergency_mode;
- datalayer_extended.bmwi3.ST_WELD = battery_status_error_disconnecting_switch;
- datalayer_extended.bmwi3.ST_isolation = battery_status_warning_isolation;
- datalayer_extended.bmwi3.ST_cold_shutoff_valve = battery_status_cold_shutoff_valve;
}
void BmwI3Battery::handle_incoming_can_frame(CAN_frame rx_frame) {
diff --git a/Software/src/battery/BMW-I3-BATTERY.h b/Software/src/battery/BMW-I3-BATTERY.h
index 21b1bdc9..aaa0b94b 100644
--- a/Software/src/battery/BMW-I3-BATTERY.h
+++ b/Software/src/battery/BMW-I3-BATTERY.h
@@ -2,7 +2,6 @@
#define BMW_I3_BATTERY_H
#include "../datalayer/datalayer.h"
-#include "../datalayer/datalayer_extended.h"
#include "../include.h"
#include "BMW-I3-HTML.h"
#include "CanBattery.h"
@@ -16,7 +15,7 @@ class BmwI3Battery : public CanBattery {
// Use this constructor for the second battery.
BmwI3Battery(DATALAYER_BATTERY_TYPE* datalayer_ptr, bool* contactor_closing_allowed_ptr, CAN_Interface targetCan,
gpio_num_t wakeup)
- : CanBattery(targetCan) {
+ : CanBattery(targetCan), renderer(*this) {
datalayer_battery = datalayer_ptr;
contactor_closing_allowed = contactor_closing_allowed_ptr;
allows_contactor_closing = nullptr;
@@ -27,7 +26,7 @@ class BmwI3Battery : public CanBattery {
}
// Use the default constructor to create the first or single battery.
- BmwI3Battery() {
+ BmwI3Battery() : renderer(*this) {
datalayer_battery = &datalayer.battery;
allows_contactor_closing = &datalayer.system.status.battery_allows_contactor_closing;
contactor_closing_allowed = nullptr;
@@ -40,6 +39,33 @@ class BmwI3Battery : public CanBattery {
virtual void transmit_can(unsigned long currentMillis);
static constexpr const char* Name = "BMW i3";
+ // SOC% raw battery value. Might not always reach 100%
+ uint16_t SOC_raw() { return (battery_HVBatt_SOC * 10); }
+ // SOC% instrumentation cluster value. Will always reach 100%
+ uint16_t SOC_dash() { return (battery_display_SOC * 50); }
+ // SOC% OBD2 value, polled actively
+ uint16_t SOC_OBD2() { return battery_soc; }
+ // Status isolation external, 0 not evaluated, 1 OK, 2 error active, 3 Invalid signal
+ uint8_t ST_iso_ext() { return battery_status_error_isolation_external_Bordnetz; }
+ // Status isolation external, 0 not evaluated, 1 OK, 2 error active, 3 Invalid signal
+ uint8_t ST_iso_int() { return battery_status_error_isolation_internal_Bordnetz; }
+ // Status cooling valve error, 0 not evaluated, 1 OK valve closed, 2 error active valve open, 3 Invalid signal
+ uint8_t ST_valve_cooling() { return battery_status_valve_cooling; }
+ // Status interlock error, 0 not evaluated, 1 OK, 2 error active, 3 Invalid signal
+ uint8_t ST_interlock() { return battery_status_error_locking; }
+ // Status precharge, 0 no statement, 1 Not active closing not blocked, 2 error precharge blocked, 3 Invalid signal
+ uint8_t ST_precharge() { return battery_status_precharge_locked; }
+ // Status DC switch, 0 contactors open, 1 precharge ongoing, 2 contactors engaged, 3 Invalid signal
+ uint8_t ST_DCSW() { return battery_status_disconnecting_switch; }
+ // Status emergency, 0 not evaluated, 1 OK, 2 error active, 3 Invalid signal
+ uint8_t ST_EMG() { return battery_status_emergency_mode; }
+ // Status welding detection, 0 Contactors OK, 1 One contactor welded, 2 Two contactors welded, 3 Invalid signal
+ uint8_t ST_WELD() { return battery_status_error_disconnecting_switch; }
+ // Status isolation, 0 not evaluated, 1 OK, 2 error active, 3 Invalid signal
+ uint8_t ST_isolation() { return battery_status_warning_isolation; }
+ // Status cold shutoff valve, 0 OK, 1 Short circuit to GND, 2 Short circuit to 12V, 3 Line break, 6 Driver error, 12 Stuck, 13 Stuck, 15 Invalid Signal
+ uint8_t ST_cold_shutoff_valve() { return battery_status_cold_shutoff_valve; }
+
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
private:
diff --git a/Software/src/battery/BMW-I3-HTML.cpp b/Software/src/battery/BMW-I3-HTML.cpp
new file mode 100644
index 00000000..b982adf4
--- /dev/null
+++ b/Software/src/battery/BMW-I3-HTML.cpp
@@ -0,0 +1,99 @@
+#include "BMW-I3-HTML.h"
+#include "../include.h"
+#include "BMW-I3-BATTERY.h"
+
+// Helper function for safe array access
+static const char* safeArrayAccess(const char* const arr[], size_t arrSize, int idx) {
+ if (idx >= 0 && static_cast(idx) < arrSize) {
+ return arr[idx];
+ }
+ return "Unknown";
+}
+
+String BmwI3HtmlRenderer::get_status_html() {
+ String content;
+
+ content += "SOC raw: " + String(batt.SOC_raw()) + "
";
+ content += "SOC dash: " + String(batt.SOC_dash()) + "
";
+ content += "SOC OBD2: " + String(batt.SOC_OBD2()) + "
";
+ static const char* statusText[16] = {
+ "Not evaluated", "OK", "Error!", "Invalid signal", "", "", "", "", "", "", "", "", "", "", "", ""};
+ content += "Interlock: " + String(safeArrayAccess(statusText, 16, batt.ST_interlock())) + "
";
+ content += "Isolation external: " + String(safeArrayAccess(statusText, 16, batt.ST_iso_ext())) + "
";
+ content += "Isolation internal: " + String(safeArrayAccess(statusText, 16, batt.ST_iso_int())) + "
";
+ content += "Isolation: " + String(safeArrayAccess(statusText, 16, batt.ST_isolation())) + "
";
+ content += "Cooling valve: " + String(safeArrayAccess(statusText, 16, batt.ST_valve_cooling())) + "
";
+ content += "Emergency: " + String(safeArrayAccess(statusText, 16, batt.ST_EMG())) + "
";
+ static const char* prechargeText[16] = {"Not evaluated",
+ "Not active, closing not blocked",
+ "Error precharge blocked",
+ "Invalid signal",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""};
+ content += "Precharge: " + String(safeArrayAccess(prechargeText, 16, batt.ST_precharge())) +
+ "
"; //Still unclear of enum
+ static const char* DCSWText[16] = {"Contactors open",
+ "Precharge ongoing",
+ "Contactors engaged",
+ "Invalid signal",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""};
+ content += "Contactor status: " + String(safeArrayAccess(DCSWText, 16, batt.ST_DCSW())) + "
";
+ static const char* contText[16] = {"Contactors OK",
+ "One contactor welded!",
+ "Two contactors welded!",
+ "Invalid signal",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""};
+ content += "Contactor weld: " + String(safeArrayAccess(contText, 16, batt.ST_WELD())) + "
";
+ static const char* valveText[16] = {"OK",
+ "Short circuit to GND",
+ "Short circuit to 12V",
+ "Line break",
+ "",
+ "",
+ "Driver error",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "Stuck",
+ "Stuck",
+ "",
+ "Invalid Signal"};
+ content +=
+ "Cold shutoff valve: " + String(safeArrayAccess(valveText, 16, batt.ST_cold_shutoff_valve())) + "
";
+
+ return content;
+}
diff --git a/Software/src/battery/BMW-I3-HTML.h b/Software/src/battery/BMW-I3-HTML.h
index 88322a6d..a0ba265d 100644
--- a/Software/src/battery/BMW-I3-HTML.h
+++ b/Software/src/battery/BMW-I3-HTML.h
@@ -5,94 +5,16 @@
#include "../datalayer/datalayer_extended.h"
#include "src/devboard/webserver/BatteryHtmlRenderer.h"
+class BmwI3Battery;
+
class BmwI3HtmlRenderer : public BatteryHtmlRenderer {
+ private:
+ BmwI3Battery& batt;
+
public:
- String get_status_html() {
- String content;
+ BmwI3HtmlRenderer(BmwI3Battery& b) : batt(b) {}
- content += "SOC raw: " + String(datalayer_extended.bmwi3.SOC_raw) + "
";
- content += "SOC dash: " + String(datalayer_extended.bmwi3.SOC_dash) + "
";
- content += "SOC OBD2: " + String(datalayer_extended.bmwi3.SOC_OBD2) + "
";
- static const char* statusText[16] = {
- "Not evaluated", "OK", "Error!", "Invalid signal", "", "", "", "", "", "", "", "", "", "", "", ""};
- content += "Interlock: " + String(statusText[datalayer_extended.bmwi3.ST_interlock]) + "
";
- content += "Isolation external: " + String(statusText[datalayer_extended.bmwi3.ST_iso_ext]) + "
";
- content += "Isolation internal: " + String(statusText[datalayer_extended.bmwi3.ST_iso_int]) + "
";
- content += "Isolation: " + String(statusText[datalayer_extended.bmwi3.ST_isolation]) + "
";
- content += "Cooling valve: " + String(statusText[datalayer_extended.bmwi3.ST_valve_cooling]) + "
";
- content += "Emergency: " + String(statusText[datalayer_extended.bmwi3.ST_EMG]) + "
";
- static const char* prechargeText[16] = {"Not evaluated",
- "Not active, closing not blocked",
- "Error precharge blocked",
- "Invalid signal",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- ""};
- content += "Precharge: " + String(prechargeText[datalayer_extended.bmwi3.ST_precharge]) +
- "
"; //Still unclear of enum
- static const char* DCSWText[16] = {"Contactors open",
- "Precharge ongoing",
- "Contactors engaged",
- "Invalid signal",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- ""};
- content += "Contactor status: " + String(DCSWText[datalayer_extended.bmwi3.ST_DCSW]) + "
";
- static const char* contText[16] = {"Contactors OK",
- "One contactor welded!",
- "Two contactors welded!",
- "Invalid signal",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- ""};
- content += "Contactor weld: " + String(contText[datalayer_extended.bmwi3.ST_WELD]) + "
";
- static const char* valveText[16] = {"OK",
- "Short circuit to GND",
- "Short circuit to 12V",
- "Line break",
- "",
- "",
- "Driver error",
- "",
- "",
- "",
- "",
- "",
- "Stuck",
- "Stuck",
- "",
- "Invalid Signal"};
- content += "Cold shutoff valve: " + String(contText[datalayer_extended.bmwi3.ST_cold_shutoff_valve]) + "
";
-
- return content;
- }
+ String get_status_html();
};
#endif
diff --git a/Software/src/battery/BYD-ATTO-3-BATTERY.h b/Software/src/battery/BYD-ATTO-3-BATTERY.h
index ef4c6fac..3f80b8ae 100644
--- a/Software/src/battery/BYD-ATTO-3-BATTERY.h
+++ b/Software/src/battery/BYD-ATTO-3-BATTERY.h
@@ -61,6 +61,11 @@ class BydAttoBattery : public CanBattery {
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
private:
+ BydAtto3HtmlRenderer renderer;
+ DATALAYER_BATTERY_TYPE* datalayer_battery;
+ DATALAYER_INFO_BYDATTO3* datalayer_bydatto;
+ bool* allows_contactor_closing;
+
static const int CELLCOUNT_EXTENDED = 126;
static const int CELLCOUNT_STANDARD = 104;
static const int MAX_PACK_VOLTAGE_EXTENDED_DV = 4410; //Extended range
@@ -71,11 +76,6 @@ class BydAttoBattery : public CanBattery {
static const int MAX_CELL_VOLTAGE_MV = 3650; //Charging stops if one cell exceeds this value
static const int MIN_CELL_VOLTAGE_MV = 2800; //Discharging stops if one cell goes below this value
- BydAtto3HtmlRenderer renderer;
- DATALAYER_BATTERY_TYPE* datalayer_battery;
- DATALAYER_INFO_BYDATTO3* datalayer_bydatto;
- bool* allows_contactor_closing;
-
static const int POLL_FOR_BATTERY_SOC = 0x0005;
static const uint8_t NOT_DETERMINED_YET = 0;
static const uint8_t STANDARD_RANGE = 1;
diff --git a/Software/src/battery/Battery.h b/Software/src/battery/Battery.h
index a069991d..d41277f8 100644
--- a/Software/src/battery/Battery.h
+++ b/Software/src/battery/Battery.h
@@ -84,6 +84,8 @@ class Battery {
virtual bool supports_real_BMS_status() { return false; }
virtual bool supports_toggle_SOC_method() { return false; }
virtual bool supports_factory_mode_method() { return false; }
+ virtual bool supports_chademo_restart() { return false; }
+ virtual bool supports_chademo_stop() { return false; }
virtual void clear_isolation() {}
virtual void reset_BMS() {}
@@ -98,6 +100,8 @@ class Battery {
virtual void request_close_contactors() {}
virtual void toggle_SOC_method() {}
virtual void set_factory_mode() {}
+ virtual void chademo_restart() {}
+ virtual void chademo_stop() {}
virtual void set_fake_voltage(float v) {}
virtual float get_voltage();
diff --git a/Software/src/battery/CHADEMO-BATTERY-HTML.h b/Software/src/battery/CHADEMO-BATTERY-HTML.h
new file mode 100644
index 00000000..c9ed2277
--- /dev/null
+++ b/Software/src/battery/CHADEMO-BATTERY-HTML.h
@@ -0,0 +1,72 @@
+#ifndef _CHADEMO_BATTERY_HTML_H
+#define _CHADEMO_BATTERY_HTML_H
+
+#include "../datalayer/datalayer.h"
+#include "../datalayer/datalayer_extended.h"
+#include "src/devboard/webserver/BatteryHtmlRenderer.h"
+
+class ChademoBatteryHtmlRenderer : public BatteryHtmlRenderer {
+ public:
+ String get_status_html() {
+ String content;
+ content += "Chademo state: ";
+ switch (datalayer_extended.chademo.CHADEMO_Status) {
+ case 0:
+ content += String("FAULT
");
+ break;
+ case 1:
+ content += String("STOP");
+ break;
+ case 2:
+ content += String("IDLE");
+ break;
+ case 3:
+ content += String("CONNECTED");
+ break;
+ case 4:
+ content += String("INIT");
+ break;
+ case 5:
+ content += String("NEGOTIATE");
+ break;
+ case 6:
+ content += String("EV ALLOWED");
+ break;
+ case 7:
+ content += String("EVSE PREPARE");
+ break;
+ case 8:
+ content += String("EVSE START");
+ break;
+ case 9:
+ content += String("EVSE CONTACTORS ENABLED");
+ break;
+ case 10:
+ content += String("POWERFLOW");
+ break;
+ default:
+ content += String("Unknown");
+ break;
+ }
+ if (datalayer_extended.chademo.FaultBatteryCurrentDeviation) {
+ content += "FAULT: Battery Current Deviation
";
+ }
+ if (datalayer_extended.chademo.FaultBatteryOverVoltage) {
+ content += "FAULT: Battery Overvoltage
";
+ }
+ if (datalayer_extended.chademo.FaultBatteryUnderVoltage) {
+ content += "FAULT: Battery Undervoltage
";
+ }
+ if (datalayer_extended.chademo.FaultBatteryVoltageDeviation) {
+ content += "FAULT: Battery Voltage Deviation
";
+ }
+ if (datalayer_extended.chademo.FaultHighBatteryTemperature) {
+ content += "FAULT: Battery Temperature
";
+ }
+ content += "Protocol: " + String(datalayer_extended.chademo.ControlProtocolNumberEV) + "
";
+
+ return content;
+ }
+};
+
+#endif
diff --git a/Software/src/battery/CHADEMO-BATTERY.cpp b/Software/src/battery/CHADEMO-BATTERY.cpp
index 63f283b1..6791c452 100644
--- a/Software/src/battery/CHADEMO-BATTERY.cpp
+++ b/Software/src/battery/CHADEMO-BATTERY.cpp
@@ -4,17 +4,24 @@
#include "../include.h"
#include "CHADEMO-SHUNTS.h"
-/* CHADEMO handling runs at 6.25 times the rate of most other code, so, rather than the
- * default value of 12 (for 12 iterations of the 5s value update loop) * 5 for a 60s timeout,
- * instead use 75 for 75*0.8s = 60s
- */
-#undef CAN_STILL_ALIVE
-#define CAN_STILL_ALIVE 75
-//#define CH_CAN_DEBUG
-
//This function maps all the values fetched via CAN to the correct parameters used for the inverter
void ChademoBattery::update_values() {
+ datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
+ //On this integration, we don't care if no CAN messages flow (normal before user plugs in)
+ //Always write the CAN as alive!
+
+ //Check if user is requesting an action, if so, have statemachine jump there
+ if (datalayer_extended.chademo.UserRequestStop) {
+ CHADEMO_Status = CHADEMO_STOP;
+ datalayer_extended.chademo.UserRequestStop = false;
+ }
+
+ if (datalayer_extended.chademo.UserRequestRestart) {
+ CHADEMO_Status = CHADEMO_IDLE;
+ datalayer_extended.chademo.UserRequestRestart = false;
+ }
+
datalayer.battery.status.real_soc = x102_chg_session.StateOfCharge * 100; //Convert % to pptt
datalayer.battery.status.max_discharge_power_W =
@@ -47,6 +54,15 @@ void ChademoBattery::update_values() {
chargingrate = x102_chg_session.StateOfCharge / x100_chg_lim.ConstantOfChargingRateIndication * 100;
}
}
+
+ //Update extended datalayer for easier visualization of what's going on
+ datalayer_extended.chademo.CHADEMO_Status = CHADEMO_Status;
+ datalayer_extended.chademo.ControlProtocolNumberEV = x102_chg_session.ControlProtocolNumberEV;
+ datalayer_extended.chademo.FaultBatteryVoltageDeviation = x102_chg_session.f.fault.FaultBatteryVoltageDeviation;
+ datalayer_extended.chademo.FaultHighBatteryTemperature = x102_chg_session.f.fault.FaultHighBatteryTemperature;
+ datalayer_extended.chademo.FaultBatteryCurrentDeviation = x102_chg_session.f.fault.FaultBatteryCurrentDeviation;
+ datalayer_extended.chademo.FaultBatteryUnderVoltage = x102_chg_session.f.fault.FaultBatteryUnderVoltage;
+ datalayer_extended.chademo.FaultBatteryOverVoltage = x102_chg_session.f.fault.FaultBatteryOverVoltage;
}
//TODO simplified start/stop helper functions
@@ -276,19 +292,6 @@ void ChademoBattery::process_vehicle_vendor_ID(CAN_frame rx_frame) {
}
void ChademoBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
-#ifdef CH_CAN_DEBUG
- logging.print(millis()); // Example printout, time, ID, length, data: 7553 1DB 8 FF C0 B9 EA 0 0 2 5D
- logging.print(" ");
- logging.print(rx_frame.ID, HEX);
- logging.print(" ");
- logging.print(rx_frame.DLC);
- logging.print(" ");
- for (int i = 0; i < rx_frame.DLC; ++i) {
- logging.print(rx_frame.data.u8[i], HEX);
- logging.print(" ");
- }
- logging.println("");
-#endif
// CHADEMO coexists with a CAN-based shunt. Only process CHADEMO-specific IDs
// 202 is unknown
@@ -302,9 +305,6 @@ void ChademoBattery::handle_incoming_can_frame(CAN_frame rx_frame) {
* has not yet been receied from a vehicle
*/
- datalayer.battery.status.CAN_battery_still_alive =
- CAN_STILL_ALIVE; //We are getting CAN messages from the vehicle, inform the watchdog
-
switch (rx_frame.ID) {
case 0x100:
process_vehicle_charging_minimums(rx_frame);
diff --git a/Software/src/battery/CHADEMO-BATTERY.h b/Software/src/battery/CHADEMO-BATTERY.h
index 19f39566..23d56828 100644
--- a/Software/src/battery/CHADEMO-BATTERY.h
+++ b/Software/src/battery/CHADEMO-BATTERY.h
@@ -1,7 +1,10 @@
#ifndef CHADEMO_BATTERY_H
#define CHADEMO_BATTERY_H
#include
+#include "../datalayer/datalayer.h"
+#include "../datalayer/datalayer_extended.h"
#include "../include.h"
+#include "CHADEMO-BATTERY-HTML.h"
#include "CanBattery.h"
#ifdef CHADEMO_BATTERY
@@ -30,10 +33,18 @@ class ChademoBattery : public CanBattery {
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
+ bool supports_chademo_restart() { return true; }
+ bool supports_chademo_stop() { return true; }
+
+ void chademo_restart() { datalayer_extended.chademo.UserRequestRestart = true; }
+ void chademo_stop() { datalayer_extended.chademo.UserRequestStop = true; }
+
+ BatteryHtmlRenderer& get_status_renderer() { return renderer; }
static constexpr const char* Name = "Chademo V2X mode";
private:
gpio_num_t pin2, pin10, pin4, pin7, pin_lock, precharge, positive_contactor;
+ ChademoBatteryHtmlRenderer renderer;
void process_vehicle_charging_minimums(CAN_frame rx_frame);
void process_vehicle_charging_maximums(CAN_frame rx_frame);
@@ -53,19 +64,17 @@ class ChademoBattery : public CanBattery {
static const int MAX_EVSE_OUTPUT_VOLTAGE = 410;
static const int MAX_EVSE_OUTPUT_CURRENT = 11;
- enum CHADEMO_STATE {
- CHADEMO_FAULT,
- CHADEMO_STOP,
- CHADEMO_IDLE,
- CHADEMO_CONNECTED,
- CHADEMO_INIT, // intermediate state indicating CAN from Vehicle not yet received after connection
- CHADEMO_NEGOTIATE,
- CHADEMO_EV_ALLOWED,
- CHADEMO_EVSE_PREPARE,
- CHADEMO_EVSE_START,
- CHADEMO_EVSE_CONTACTORS_ENABLED,
- CHADEMO_POWERFLOW,
- };
+#define CHADEMO_FAULT 0
+#define CHADEMO_STOP 1
+#define CHADEMO_IDLE 2
+#define CHADEMO_CONNECTED 3
+#define CHADEMO_INIT 4 // intermediate state indicating CAN from Vehicle not yet received after connection
+#define CHADEMO_NEGOTIATE 5
+#define CHADEMO_EV_ALLOWED 6
+#define CHADEMO_EVSE_PREPARE 7
+#define CHADEMO_EVSE_START 8
+#define CHADEMO_EVSE_CONTACTORS_ENABLED 9
+#define CHADEMO_POWERFLOW 10
enum Mode { CHADEMO_CHARGE, CHADEMO_DISCHARGE, CHADEMO_BIDIRECTIONAL };
@@ -304,7 +313,7 @@ should determine that the other is the EVSE or the vehicle of the model before t
// permissible rate of change is -20A/s to 20A/s relative to 102.3
Mode EVSE_mode = CHADEMO_DISCHARGE;
- CHADEMO_STATE CHADEMO_Status = CHADEMO_IDLE;
+ uint8_t CHADEMO_Status = CHADEMO_IDLE;
/* Charge/discharge sequence, indicating applicable V2H guideline
* If sequence number is not agreed upon via H201/H209 between EVSE and Vehicle,
diff --git a/Software/src/battery/RENAULT-ZOE-GEN1-BATTERY.h b/Software/src/battery/RENAULT-ZOE-GEN1-BATTERY.h
index 2d78d6e2..d004f373 100644
--- a/Software/src/battery/RENAULT-ZOE-GEN1-BATTERY.h
+++ b/Software/src/battery/RENAULT-ZOE-GEN1-BATTERY.h
@@ -36,14 +36,14 @@ class RenaultZoeGen1Battery : public CanBattery {
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
private:
+ RenaultZoeGen1HtmlRenderer renderer;
+
static const int MAX_PACK_VOLTAGE_DV = 4200; //5000 = 500.0V
static const int MIN_PACK_VOLTAGE_DV = 3000;
static const int MAX_CELL_DEVIATION_MV = 150;
static const int MAX_CELL_VOLTAGE_MV = 4250; //Battery is put into emergency stop if one cell goes over this value
static const int MIN_CELL_VOLTAGE_MV = 2700; //Battery is put into emergency stop if one cell goes below this value
- RenaultZoeGen1HtmlRenderer renderer;
-
DATALAYER_BATTERY_TYPE* datalayer_battery;
DATALAYER_INFO_ZOE* datalayer_zoe;
diff --git a/Software/src/battery/RENAULT-ZOE-GEN2-BATTERY.cpp b/Software/src/battery/RENAULT-ZOE-GEN2-BATTERY.cpp
index 4970f7bd..4c2a44bc 100644
--- a/Software/src/battery/RENAULT-ZOE-GEN2-BATTERY.cpp
+++ b/Software/src/battery/RENAULT-ZOE-GEN2-BATTERY.cpp
@@ -24,35 +24,35 @@ https://github.com/fesch/CanZE/tree/master/app/src/main/assets/ZOE_Ph2
void RenaultZoeGen2Battery::update_values() {
- datalayer.battery.status.soh_pptt = battery_soh;
+ datalayer_battery->status.soh_pptt = battery_soh;
if (battery_soc >= 300) {
- datalayer.battery.status.real_soc = battery_soc - 300;
+ datalayer_battery->status.real_soc = battery_soc - 300;
} else {
- datalayer.battery.status.real_soc = 0;
+ datalayer_battery->status.real_soc = 0;
}
- datalayer.battery.status.voltage_dV = battery_pack_voltage;
+ datalayer_battery->status.voltage_dV = battery_pack_voltage;
- datalayer.battery.status.current_dA = ((battery_current - 32640) * 0.3125);
+ datalayer_battery->status.current_dA = ((battery_current - 32640) * 0.3125);
//Calculate the remaining Wh amount from SOC% and max Wh value.
- datalayer.battery.status.remaining_capacity_Wh = static_cast(
- (static_cast(datalayer.battery.status.real_soc) / 10000) * datalayer.battery.info.total_capacity_Wh);
+ datalayer_battery->status.remaining_capacity_Wh = static_cast(
+ (static_cast(datalayer_battery->status.real_soc) / 10000) * datalayer_battery->info.total_capacity_Wh);
- datalayer.battery.status.max_discharge_power_W = battery_max_available * 10;
+ datalayer_battery->status.max_discharge_power_W = battery_max_available * 10;
- datalayer.battery.status.max_charge_power_W = battery_max_generated * 10;
+ datalayer_battery->status.max_charge_power_W = battery_max_generated * 10;
//Temperatures and voltages update at slow rate. Only publish new values once both have been sampled to avoid events
if ((battery_min_temp != 920) && (battery_max_temp != 920)) {
- datalayer.battery.status.temperature_min_dC = ((battery_min_temp - 640) * 0.625);
- datalayer.battery.status.temperature_max_dC = ((battery_max_temp - 640) * 0.625);
+ datalayer_battery->status.temperature_min_dC = ((battery_min_temp - 640) * 0.625);
+ datalayer_battery->status.temperature_max_dC = ((battery_max_temp - 640) * 0.625);
}
if ((battery_min_cell_voltage != 3700) && (battery_max_cell_voltage != 3700)) {
- datalayer.battery.status.cell_min_voltage_mV = (battery_min_cell_voltage * 0.976563);
- datalayer.battery.status.cell_max_voltage_mV = (battery_max_cell_voltage * 0.976563);
+ datalayer_battery->status.cell_min_voltage_mV = (battery_min_cell_voltage * 0.976563);
+ datalayer_battery->status.cell_max_voltage_mV = (battery_max_cell_voltage * 0.976563);
}
if (battery_12v < 11000) { //11.000V
@@ -103,12 +103,12 @@ void RenaultZoeGen2Battery::update_values() {
}
void RenaultZoeGen2Battery::handle_incoming_can_frame(CAN_frame rx_frame) {
- datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
+ datalayer_battery->status.CAN_battery_still_alive = CAN_STILL_ALIVE;
switch (rx_frame.ID) {
case 0x18DAF1DB: // LBC Reply from active polling
if (rx_frame.data.u8[0] == 0x10) { //First frame of a group
- transmit_can_frame(&ZOE_POLL_FLOW_CONTROL, can_config.battery);
+ transmit_can_frame(&ZOE_POLL_FLOW_CONTROL, can_interface);
//frame 2 & 3 contains which PID is sent
reply_poll = (rx_frame.data.u8[3] << 8) | rx_frame.data.u8[4];
}
@@ -360,292 +360,292 @@ void RenaultZoeGen2Battery::handle_incoming_can_frame(CAN_frame rx_frame) {
battery_soc_max = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_0:
- datalayer.battery.status.cell_voltages_mV[0] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[0] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_1:
- datalayer.battery.status.cell_voltages_mV[1] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[1] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_2:
- datalayer.battery.status.cell_voltages_mV[2] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[2] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_3:
- datalayer.battery.status.cell_voltages_mV[3] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[3] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_4:
- datalayer.battery.status.cell_voltages_mV[4] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[4] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_5:
- datalayer.battery.status.cell_voltages_mV[5] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[5] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_6:
- datalayer.battery.status.cell_voltages_mV[6] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[6] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_7:
- datalayer.battery.status.cell_voltages_mV[7] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[7] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_8:
- datalayer.battery.status.cell_voltages_mV[8] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[8] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_9:
- datalayer.battery.status.cell_voltages_mV[9] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[9] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_10:
- datalayer.battery.status.cell_voltages_mV[10] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[10] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_11:
- datalayer.battery.status.cell_voltages_mV[11] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[11] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_12:
- datalayer.battery.status.cell_voltages_mV[12] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[12] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_13:
- datalayer.battery.status.cell_voltages_mV[13] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[13] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_14:
- datalayer.battery.status.cell_voltages_mV[14] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[14] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_15:
- datalayer.battery.status.cell_voltages_mV[15] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[15] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_16:
- datalayer.battery.status.cell_voltages_mV[16] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[16] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_17:
- datalayer.battery.status.cell_voltages_mV[17] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[17] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_18:
- datalayer.battery.status.cell_voltages_mV[18] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[18] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_19:
- datalayer.battery.status.cell_voltages_mV[19] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[19] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_20:
- datalayer.battery.status.cell_voltages_mV[20] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[20] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_21:
- datalayer.battery.status.cell_voltages_mV[21] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[21] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_22:
- datalayer.battery.status.cell_voltages_mV[22] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[22] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_23:
- datalayer.battery.status.cell_voltages_mV[23] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[23] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_24:
- datalayer.battery.status.cell_voltages_mV[24] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[24] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_25:
- datalayer.battery.status.cell_voltages_mV[25] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[25] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_26:
- datalayer.battery.status.cell_voltages_mV[26] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[26] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_27:
- datalayer.battery.status.cell_voltages_mV[27] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[27] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_28:
- datalayer.battery.status.cell_voltages_mV[28] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[28] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_29:
- datalayer.battery.status.cell_voltages_mV[29] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[29] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_30:
- datalayer.battery.status.cell_voltages_mV[30] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[30] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_31:
- datalayer.battery.status.cell_voltages_mV[31] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[31] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_32:
- datalayer.battery.status.cell_voltages_mV[32] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[32] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_33:
- datalayer.battery.status.cell_voltages_mV[33] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[33] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_34:
- datalayer.battery.status.cell_voltages_mV[34] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[34] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_35:
- datalayer.battery.status.cell_voltages_mV[35] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[35] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_36:
- datalayer.battery.status.cell_voltages_mV[36] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[36] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_37:
- datalayer.battery.status.cell_voltages_mV[37] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[37] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_38:
- datalayer.battery.status.cell_voltages_mV[38] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[38] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_39:
- datalayer.battery.status.cell_voltages_mV[39] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[39] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_40:
- datalayer.battery.status.cell_voltages_mV[40] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[40] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_41:
- datalayer.battery.status.cell_voltages_mV[41] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[41] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_42:
- datalayer.battery.status.cell_voltages_mV[42] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[42] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_43:
- datalayer.battery.status.cell_voltages_mV[43] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[43] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_44:
- datalayer.battery.status.cell_voltages_mV[44] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[44] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_45:
- datalayer.battery.status.cell_voltages_mV[45] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[45] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_46:
- datalayer.battery.status.cell_voltages_mV[46] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[46] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_47:
- datalayer.battery.status.cell_voltages_mV[47] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[47] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_48:
- datalayer.battery.status.cell_voltages_mV[48] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[48] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_49:
- datalayer.battery.status.cell_voltages_mV[49] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[49] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_50:
- datalayer.battery.status.cell_voltages_mV[50] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[50] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_51:
- datalayer.battery.status.cell_voltages_mV[51] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[51] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_52:
- datalayer.battery.status.cell_voltages_mV[52] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[52] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_53:
- datalayer.battery.status.cell_voltages_mV[53] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[53] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_54:
- datalayer.battery.status.cell_voltages_mV[54] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[54] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_55:
- datalayer.battery.status.cell_voltages_mV[55] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[55] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_56:
- datalayer.battery.status.cell_voltages_mV[56] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[56] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_57:
- datalayer.battery.status.cell_voltages_mV[57] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[57] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_58:
- datalayer.battery.status.cell_voltages_mV[58] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[58] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_59:
- datalayer.battery.status.cell_voltages_mV[59] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[59] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_60:
- datalayer.battery.status.cell_voltages_mV[60] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[60] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_61:
- datalayer.battery.status.cell_voltages_mV[61] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[61] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_62:
- datalayer.battery.status.cell_voltages_mV[62] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[62] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_63:
- datalayer.battery.status.cell_voltages_mV[63] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[63] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_64:
- datalayer.battery.status.cell_voltages_mV[64] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[64] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_65:
- datalayer.battery.status.cell_voltages_mV[65] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[65] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_66:
- datalayer.battery.status.cell_voltages_mV[66] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[66] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_67:
- datalayer.battery.status.cell_voltages_mV[67] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[67] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_68:
- datalayer.battery.status.cell_voltages_mV[68] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[68] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_69:
- datalayer.battery.status.cell_voltages_mV[69] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[69] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_70:
- datalayer.battery.status.cell_voltages_mV[70] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[70] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_71:
- datalayer.battery.status.cell_voltages_mV[71] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[71] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_72:
- datalayer.battery.status.cell_voltages_mV[72] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[72] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_73:
- datalayer.battery.status.cell_voltages_mV[73] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[73] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_74:
- datalayer.battery.status.cell_voltages_mV[74] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[74] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_75:
- datalayer.battery.status.cell_voltages_mV[75] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[75] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_76:
- datalayer.battery.status.cell_voltages_mV[76] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[76] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_77:
- datalayer.battery.status.cell_voltages_mV[77] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[77] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_78:
- datalayer.battery.status.cell_voltages_mV[78] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[78] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_79:
- datalayer.battery.status.cell_voltages_mV[79] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[79] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_80:
- datalayer.battery.status.cell_voltages_mV[80] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[80] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_81:
- datalayer.battery.status.cell_voltages_mV[81] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[81] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_82:
- datalayer.battery.status.cell_voltages_mV[82] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[82] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_83:
- datalayer.battery.status.cell_voltages_mV[83] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[83] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_84:
- datalayer.battery.status.cell_voltages_mV[84] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[84] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_85:
- datalayer.battery.status.cell_voltages_mV[85] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[85] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_86:
- datalayer.battery.status.cell_voltages_mV[86] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[86] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_87:
- datalayer.battery.status.cell_voltages_mV[87] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[87] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_88:
- datalayer.battery.status.cell_voltages_mV[88] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[88] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_89:
- datalayer.battery.status.cell_voltages_mV[89] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[89] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_90:
- datalayer.battery.status.cell_voltages_mV[90] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[90] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_91:
- datalayer.battery.status.cell_voltages_mV[91] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[91] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_92:
- datalayer.battery.status.cell_voltages_mV[92] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[92] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_93:
- datalayer.battery.status.cell_voltages_mV[93] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[93] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_94:
- datalayer.battery.status.cell_voltages_mV[94] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[94] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
case POLL_CELL_95:
- datalayer.battery.status.cell_voltages_mV[95] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
+ datalayer_battery->status.cell_voltages_mV[95] = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5];
break;
default: // Unknown reply
break;
@@ -676,7 +676,7 @@ void RenaultZoeGen2Battery::transmit_can(unsigned long currentMillis) {
counter_373 = (counter_373 + 1) % 10;
*/
- transmit_can_frame(&ZOE_373, can_config.battery);
+ transmit_can_frame(&ZOE_373, can_interface);
transmit_can_frame_376();
}
@@ -691,7 +691,7 @@ void RenaultZoeGen2Battery::transmit_can(unsigned long currentMillis) {
ZOE_POLL_18DADBF1.data.u8[2] = (uint8_t)((currentpoll & 0xFF00) >> 8);
ZOE_POLL_18DADBF1.data.u8[3] = (uint8_t)(currentpoll & 0x00FF);
- transmit_can_frame(&ZOE_POLL_18DADBF1, can_config.battery);
+ transmit_can_frame(&ZOE_POLL_18DADBF1, can_interface);
}
if (currentMillis - previousMillis1000 >= INTERVAL_1_S) {
@@ -707,12 +707,12 @@ void RenaultZoeGen2Battery::setup(void) { // Performs one time setup at startup
strncpy(datalayer.system.info.battery_protocol, Name, 63);
datalayer.system.info.battery_protocol[63] = '\0';
datalayer.system.status.battery_allows_contactor_closing = true;
- datalayer.battery.info.number_of_cells = 96;
- datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_DV;
- datalayer.battery.info.min_design_voltage_dV = MIN_PACK_VOLTAGE_DV;
- datalayer.battery.info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV;
- datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
- datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
+ datalayer_battery->info.number_of_cells = 96;
+ datalayer_battery->info.max_design_voltage_dV = MAX_PACK_VOLTAGE_DV;
+ datalayer_battery->info.min_design_voltage_dV = MIN_PACK_VOLTAGE_DV;
+ datalayer_battery->info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV;
+ datalayer_battery->info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
+ datalayer_battery->info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
}
void RenaultZoeGen2Battery::transmit_can_frame_376(void) {
@@ -733,7 +733,7 @@ void RenaultZoeGen2Battery::transmit_can_frame_376(void) {
ZOE_376.data.u8[4] = hourSeg;
ZOE_376.data.u8[5] = minuteSeg;
- transmit_can_frame(&ZOE_376, can_config.battery);
+ transmit_can_frame(&ZOE_376, can_interface);
}
void RenaultZoeGen2Battery::transmit_reset_nvrol_frames(void) {
@@ -742,14 +742,14 @@ void RenaultZoeGen2Battery::transmit_reset_nvrol_frames(void) {
startTimeNVROL = millis();
// NVROL reset, part 1: send 0x021003AAAAAAAAAA
ZOE_POLL_18DADBF1.data = {0x02, 0x10, 0x03, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
- transmit_can_frame(&ZOE_POLL_18DADBF1, can_config.battery);
+ transmit_can_frame(&ZOE_POLL_18DADBF1, can_interface);
NVROLstateMachine = 1;
break;
case 1: // wait 100 ms
if ((millis() - startTimeNVROL) > INTERVAL_100_MS) {
// NVROL reset, part 2: send 0x043101B00900AAAA
ZOE_POLL_18DADBF1.data = {0x04, 0x31, 0x01, 0xB0, 0x09, 0x00, 0xAA, 0xAA};
- transmit_can_frame(&ZOE_POLL_18DADBF1, can_config.battery);
+ transmit_can_frame(&ZOE_POLL_18DADBF1, can_interface);
startTimeNVROL = millis(); //Reset time start, so we can check time for next step
NVROLstateMachine = 2;
}
@@ -758,7 +758,7 @@ void RenaultZoeGen2Battery::transmit_reset_nvrol_frames(void) {
if ((millis() - startTimeNVROL) > INTERVAL_1_S) {
// Enable temporisation before sleep, part 1: send 0x021003AAAAAAAAAA
ZOE_POLL_18DADBF1.data = {0x02, 0x10, 0x03, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
- transmit_can_frame(&ZOE_POLL_18DADBF1, can_config.battery);
+ transmit_can_frame(&ZOE_POLL_18DADBF1, can_interface);
startTimeNVROL = millis(); //Reset time start, so we can check time for next step
NVROLstateMachine = 3;
}
@@ -767,7 +767,7 @@ void RenaultZoeGen2Battery::transmit_reset_nvrol_frames(void) {
if ((millis() - startTimeNVROL) > INTERVAL_100_MS) {
// Enable temporisation before sleep, part 2: send 0x042E928101AAAAAA
ZOE_POLL_18DADBF1.data = {0x04, 0x2E, 0x92, 0x81, 0x01, 0xAA, 0xAA, 0xAA};
- transmit_can_frame(&ZOE_POLL_18DADBF1, can_config.battery);
+ transmit_can_frame(&ZOE_POLL_18DADBF1, can_interface);
// Set data back to init values, we are done with the ZOE_POLL_18DADBF1 frame
ZOE_POLL_18DADBF1.data = {0x03, 0x22, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00};
poll_index = 0;
diff --git a/Software/src/battery/RENAULT-ZOE-GEN2-BATTERY.h b/Software/src/battery/RENAULT-ZOE-GEN2-BATTERY.h
index 2cdbc737..c375b996 100644
--- a/Software/src/battery/RENAULT-ZOE-GEN2-BATTERY.h
+++ b/Software/src/battery/RENAULT-ZOE-GEN2-BATTERY.h
@@ -11,6 +11,23 @@
class RenaultZoeGen2Battery : public CanBattery {
public:
+ // Use this constructor for the second battery.
+ RenaultZoeGen2Battery(DATALAYER_BATTERY_TYPE* datalayer_ptr, DATALAYER_INFO_ZOE_PH2* extended,
+ CAN_Interface targetCan)
+ : CanBattery(targetCan) {
+ datalayer_battery = datalayer_ptr;
+ allows_contactor_closing = nullptr;
+ datalayer_zoePH2 = extended;
+
+ battery_pack_voltage = 0;
+ }
+
+ // Use the default constructor to create the first or single battery.
+ RenaultZoeGen2Battery() {
+ datalayer_battery = &datalayer.battery;
+ allows_contactor_closing = &datalayer.system.status.battery_allows_contactor_closing;
+ datalayer_zoePH2 = &datalayer_extended.zoePH2;
+ }
virtual void setup(void);
virtual void handle_incoming_can_frame(CAN_frame rx_frame);
virtual void update_values();
@@ -25,6 +42,13 @@ class RenaultZoeGen2Battery : public CanBattery {
private:
RenaultZoeGen2HtmlRenderer renderer;
+
+ DATALAYER_BATTERY_TYPE* datalayer_battery;
+ DATALAYER_INFO_ZOE_PH2* datalayer_zoePH2;
+
+ // If not null, this battery decides when the contactor can be closed and writes the value here.
+ bool* allows_contactor_closing;
+
static const int MAX_PACK_VOLTAGE_DV = 4100; //5000 = 500.0V
static const int MIN_PACK_VOLTAGE_DV = 3000;
static const int MAX_CELL_DEVIATION_MV = 150;
@@ -174,7 +198,7 @@ class RenaultZoeGen2Battery : public CanBattery {
uint16_t battery_soc = 0;
uint16_t battery_usable_soc = 5000;
uint16_t battery_soh = 10000;
- uint16_t battery_pack_voltage = 370;
+ uint16_t battery_pack_voltage = 3700;
uint16_t battery_max_cell_voltage = 3700;
uint16_t battery_min_cell_voltage = 3700;
uint16_t battery_12v = 12000;
diff --git a/Software/src/datalayer/datalayer_extended.h b/Software/src/datalayer/datalayer_extended.h
index 9c10deab..a78911c0 100644
--- a/Software/src/datalayer/datalayer_extended.h
+++ b/Software/src/datalayer/datalayer_extended.h
@@ -124,48 +124,6 @@ typedef struct {
} DATALAYER_INFO_BMWPHEV;
-typedef struct {
- /** uint16_t */
- /** SOC% raw battery value. Might not always reach 100% */
- uint16_t SOC_raw = 0;
- /** uint16_t */
- /** SOC% instrumentation cluster value. Will always reach 100% */
- uint16_t SOC_dash = 0;
- /** uint16_t */
- /** SOC% OBD2 value, polled actively */
- uint16_t SOC_OBD2 = 0;
- /** uint8_t */
- /** Status isolation external, 0 not evaluated, 1 OK, 2 error active, 3 Invalid signal*/
- uint8_t ST_iso_ext = 0;
- /** uint8_t */
- /** Status isolation external, 0 not evaluated, 1 OK, 2 error active, 3 Invalid signal*/
- uint8_t ST_iso_int = 0;
- /** uint8_t */
- /** Status cooling valve error, 0 not evaluated, 1 OK valve closed, 2 error active valve open, 3 Invalid signal*/
- uint8_t ST_valve_cooling = 0;
- /** uint8_t */
- /** Status interlock error, 0 not evaluated, 1 OK, 2 error active, 3 Invalid signal*/
- uint8_t ST_interlock = 0;
- /** uint8_t */
- /** Status precharge, 0 no statement, 1 Not active closing not blocked, 2 error precharge blocked, 3 Invalid signal*/
- uint8_t ST_precharge = 0;
- /** uint8_t */
- /** Status DC switch, 0 contactors open, 1 precharge ongoing, 2 contactors engaged, 3 Invalid signal*/
- uint8_t ST_DCSW = 0;
- /** uint8_t */
- /** Status emergency, 0 not evaluated, 1 OK, 2 error active, 3 Invalid signal*/
- uint8_t ST_EMG = 0;
- /** uint8_t */
- /** Status welding detection, 0 Contactors OK, 1 One contactor welded, 2 Two contactors welded, 3 Invalid signal*/
- uint8_t ST_WELD = 0;
- /** uint8_t */
- /** Status isolation, 0 not evaluated, 1 OK, 2 error active, 3 Invalid signal*/
- uint8_t ST_isolation = 0;
- /** uint8_t */
- /** Status cold shutoff valve, 0 OK, 1 Short circuit to GND, 2 Short circuit to 12V, 3 Line break, 6 Driver error, 12 Stuck, 13 Stuck, 15 Invalid Signal*/
- uint8_t ST_cold_shutoff_valve = 0;
-} DATALAYER_INFO_BMWI3;
-
typedef struct {
/** bool */
/** User requesting crash reset via WebUI*/
@@ -274,6 +232,19 @@ typedef struct {
bool warning_Charger_not_responding = false;
} DATALAYER_INFO_CELLPOWER;
+typedef struct {
+ bool UserRequestRestart = false;
+ bool UserRequestStop = false;
+ bool FaultBatteryVoltageDeviation = false;
+ bool FaultHighBatteryTemperature = false;
+ bool FaultBatteryCurrentDeviation = false;
+ bool FaultBatteryUnderVoltage = false;
+ bool FaultBatteryOverVoltage = false;
+ uint8_t CHADEMO_Status = 0;
+ uint8_t ControlProtocolNumberEV = 0;
+
+} DATALAYER_INFO_CHADEMO;
+
typedef struct {
uint16_t soc_z = 0;
uint16_t soc_u = 0;
@@ -882,9 +853,9 @@ class DataLayerExtended {
DATALAYER_INFO_BOLTAMPERA boltampera;
DATALAYER_INFO_BMWIX bmwix;
DATALAYER_INFO_BMWPHEV bmwphev;
- DATALAYER_INFO_BMWI3 bmwi3;
DATALAYER_INFO_BYDATTO3 bydAtto3;
DATALAYER_INFO_CELLPOWER cellpower;
+ DATALAYER_INFO_CHADEMO chademo;
DATALAYER_INFO_CMFAEV CMFAEV;
DATALAYER_INFO_ECMP stellantisECMP;
DATALAYER_INFO_GEELY_GEOMETRY_C geometryC;
diff --git a/Software/src/devboard/webserver/advanced_battery_html.cpp b/Software/src/devboard/webserver/advanced_battery_html.cpp
index f1877137..911ea166 100644
--- a/Software/src/devboard/webserver/advanced_battery_html.cpp
+++ b/Software/src/devboard/webserver/advanced_battery_html.cpp
@@ -12,6 +12,15 @@ std::vector battery_commands = {
[](Battery* b) {
b->clear_isolation();
}},
+ {"chademoRestart", "Restart", "restart the V2X session?",
+ [](Battery* b) { return b && b->supports_chademo_restart(); },
+ [](Battery* b) {
+ b->chademo_restart();
+ }},
+ {"chademoStop", "Stop", "stop V2X?", [](Battery* b) { return b && b->supports_chademo_restart(); },
+ [](Battery* b) {
+ b->chademo_restart();
+ }},
{"resetBMS", "BMS reset", "reset the BMS?", [](Battery* b) { return b && b->supports_reset_BMS(); },
[](Battery* b) {
b->reset_BMS();