Add more battery info page for Chademo

This commit is contained in:
Daniel Öster 2025-06-26 22:20:32 +03:00
parent 92daa175d3
commit 6936681366
6 changed files with 144 additions and 38 deletions

View file

@ -32,6 +32,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() {}
@ -46,6 +48,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() { return static_cast<float>(datalayer.battery.status.voltage_dV) / 10.0; }

View file

@ -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 += "<h4>Chademo state: ";
switch (datalayer_extended.chademo.CHADEMO_Status) {
case 0:
content += String("FAULT</h4>");
break;
case 1:
content += String("STOP</h4>");
break;
case 2:
content += String("IDLE</h4>");
break;
case 3:
content += String("CONNECTED</h4>");
break;
case 4:
content += String("INIT</h4>");
break;
case 5:
content += String("NEGOTIATE</h4>");
break;
case 6:
content += String("EV ALLOWED</h4>");
break;
case 7:
content += String("EVSE PREPARE</h4>");
break;
case 8:
content += String("EVSE START</h4>");
break;
case 9:
content += String("EVSE CONTACTORS ENABLED</h4>");
break;
case 10:
content += String("POWERFLOW</h4>");
break;
default:
content += String("Unknown</h4>");
break;
}
if (datalayer_extended.chademo.FaultBatteryCurrentDeviation) {
content += "<h4>FAULT: Battery Current Deviation</h4>";
}
if (datalayer_extended.chademo.FaultBatteryOverVoltage) {
content += "<h4>FAULT: Battery Overvoltage</h4>";
}
if (datalayer_extended.chademo.FaultBatteryUnderVoltage) {
content += "<h4>FAULT: Battery Undervoltage</h4>";
}
if (datalayer_extended.chademo.FaultBatteryVoltageDeviation) {
content += "<h4>FAULT: Battery Voltage Deviation</h4>";
}
if (datalayer_extended.chademo.FaultHighBatteryTemperature) {
content += "<h4>FAULT: Battery Temperature</h4>";
}
content += "<h4>Protocol: " + String(datalayer_extended.chademo.ControlProtocolNumberEV) + "</h4>";
return content;
}
};
#endif

View file

@ -5,17 +5,24 @@
#include "CHADEMO-BATTERY.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 =
@ -48,6 +55,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
@ -277,19 +293,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
@ -303,9 +306,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);

View file

@ -1,7 +1,10 @@
#ifndef CHADEMO_BATTERY_H
#define CHADEMO_BATTERY_H
#include <Arduino.h>
#include "../datalayer/datalayer.h"
#include "../datalayer/datalayer_extended.h"
#include "../include.h"
#include "CHADEMO-BATTERY-HTML.h"
#include "CanBattery.h"
//Contactor control is required for CHADEMO support
@ -21,6 +24,12 @@ 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; }
private:
void process_vehicle_charging_minimums(CAN_frame rx_frame);
void process_vehicle_charging_maximums(CAN_frame rx_frame);
@ -40,19 +49,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 };
@ -291,7 +298,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,

View file

@ -274,6 +274,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;
@ -885,6 +898,7 @@ class DataLayerExtended {
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;

View file

@ -12,6 +12,15 @@ std::vector<BatteryCommand> 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();