mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-03 17:59:27 +02:00
Add cellpower BMS support
This commit is contained in:
parent
123fecc22e
commit
79ee6c896a
7 changed files with 529 additions and 2 deletions
|
@ -11,6 +11,7 @@
|
|||
/* Select battery used */
|
||||
//#define BMW_I3_BATTERY
|
||||
//#define BYD_ATTO_3_BATTERY
|
||||
//#define CELLPOWER_BMS
|
||||
//#define CHADEMO_BATTERY //NOTE: inherently enables CONTACTOR_CONTROL below
|
||||
//#define IMIEV_CZERO_ION_BATTERY
|
||||
//#define JAGUAR_IPACE_BATTERY
|
||||
|
@ -45,7 +46,7 @@
|
|||
//#define SOLAX_CAN //Enable this line to emulate a "SolaX Triple Power LFP" over CAN bus
|
||||
|
||||
/* Select hardware used for Battery-Emulator */
|
||||
#define HW_LILYGO
|
||||
//#define HW_LILYGO
|
||||
//#define HW_STARK
|
||||
|
||||
/* Other options */
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
#include "BYD-ATTO-3-BATTERY.h"
|
||||
#endif
|
||||
|
||||
#ifdef CELLPOWER_BMS
|
||||
#include "CELLPOWER-BMS.h"
|
||||
#endif
|
||||
|
||||
#ifdef CHADEMO_BATTERY
|
||||
#include "CHADEMO-BATTERY.h"
|
||||
#endif
|
||||
|
|
298
Software/src/battery/CELLPOWER-BMS.cpp
Normal file
298
Software/src/battery/CELLPOWER-BMS.cpp
Normal file
|
@ -0,0 +1,298 @@
|
|||
#include "../include.h"
|
||||
#ifdef CELLPOWER_BMS
|
||||
#include "../datalayer/datalayer.h"
|
||||
#include "../datalayer/datalayer_extended.h" //For "More battery info" webpage
|
||||
#include "../devboard/utils/events.h"
|
||||
#include "CELLPOWER-BMS.h"
|
||||
|
||||
/* Do not change code below unless you are sure what you are doing */
|
||||
static unsigned long previousMillis1s = 0; // will store last time a 1s CAN Message was sent
|
||||
|
||||
//Actual content messages
|
||||
// Optional add-on charger module. Might not be needed to send these towards the BMS to keep it happy.
|
||||
CAN_frame CELLPOWER_18FF50E9 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 5,
|
||||
.ID = 0x18FF50E9,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
CAN_frame CELLPOWER_18FF50E8 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 5,
|
||||
.ID = 0x18FF50E8,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
CAN_frame CELLPOWER_18FF50E7 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 5,
|
||||
.ID = 0x18FF50E7,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
CAN_frame CELLPOWER_18FF50E5 = {.FD = false,
|
||||
.ext_ID = true,
|
||||
.DLC = 5,
|
||||
.ID = 0x18FF50E5,
|
||||
.data = {0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
|
||||
static bool system_state_discharge = false;
|
||||
static bool system_state_charge = false;
|
||||
static bool system_state_cellbalancing = false;
|
||||
static bool system_state_tricklecharge = false;
|
||||
static bool system_state_idle = false;
|
||||
static bool system_state_chargecompleted = false;
|
||||
static bool system_state_maintenancecharge = false;
|
||||
static bool IO_state_main_positive_relay = false;
|
||||
static bool IO_state_main_negative_relay = false;
|
||||
static bool IO_state_charge_enable = false;
|
||||
static bool IO_state_precharge_relay = false;
|
||||
static bool IO_state_discharge_enable = false;
|
||||
static bool IO_state_IO_6 = false;
|
||||
static bool IO_state_IO_7 = false;
|
||||
static bool IO_state_IO_8 = false;
|
||||
static bool error_Cell_overvoltage = false;
|
||||
static bool error_Cell_undervoltage = false;
|
||||
static bool error_Cell_end_of_life_voltage = false;
|
||||
static bool error_Cell_voltage_misread = false;
|
||||
static bool error_Cell_over_temperature = false;
|
||||
static bool error_Cell_under_temperature = false;
|
||||
static bool error_Cell_unmanaged = false;
|
||||
static bool error_LMU_over_temperature = false;
|
||||
static bool error_LMU_under_temperature = false;
|
||||
static bool error_Temp_sensor_open_circuit = false;
|
||||
static bool error_Temp_sensor_short_circuit = false;
|
||||
static bool error_SUB_communication = false;
|
||||
static bool error_LMU_communication = false;
|
||||
static bool error_Over_current_IN = false;
|
||||
static bool error_Over_current_OUT = false;
|
||||
static bool error_Short_circuit = false;
|
||||
static bool error_Leak_detected = false;
|
||||
static bool error_Leak_detection_failed = false;
|
||||
static bool error_Voltage_difference = false;
|
||||
static bool error_BMCU_supply_over_voltage = false;
|
||||
static bool error_BMCU_supply_under_voltage = false;
|
||||
static bool error_Main_positive_contactor = false;
|
||||
static bool error_Main_negative_contactor = false;
|
||||
static bool error_Precharge_contactor = false;
|
||||
static bool error_Midpack_contactor = false;
|
||||
static bool error_Precharge_timeout = false;
|
||||
static bool error_Emergency_connector_override = false;
|
||||
static bool warning_High_cell_voltage = false;
|
||||
static bool warning_Low_cell_voltage = false;
|
||||
static bool warning_High_cell_temperature = false;
|
||||
static bool warning_Low_cell_temperature = false;
|
||||
static bool warning_High_LMU_temperature = false;
|
||||
static bool warning_Low_LMU_temperature = false;
|
||||
static bool warning_SUB_communication_interfered = false;
|
||||
static bool warning_LMU_communication_interfered = false;
|
||||
static bool warning_High_current_IN = false;
|
||||
static bool warning_High_current_OUT = false;
|
||||
static bool warning_Pack_resistance_difference = false;
|
||||
static bool warning_High_pack_resistance = false;
|
||||
static bool warning_Cell_resistance_difference = false;
|
||||
static bool warning_High_cell_resistance = false;
|
||||
static bool warning_High_BMCU_supply_voltage = false;
|
||||
static bool warning_Low_BMCU_supply_voltage = false;
|
||||
static bool warning_Low_SOC = false;
|
||||
static bool warning_Balancing_required_OCV_model = false;
|
||||
static bool warning_Charger_not_responding = false;
|
||||
static uint16_t cell_voltage_max_mV = 3700;
|
||||
static uint16_t cell_voltage_min_mV = 3700;
|
||||
static int8_t pack_temperature_high_C = 0;
|
||||
static int8_t pack_temperature_low_C = 0;
|
||||
static uint16_t battery_pack_voltage_dV = 3700;
|
||||
static int16_t battery_pack_current_dA = 0;
|
||||
static uint8_t battery_SOH_percentage = 99;
|
||||
static uint8_t battery_SOC_percentage = 50;
|
||||
static uint16_t battery_remaining_dAh = 0;
|
||||
static uint8_t cell_with_highest_voltage = 0;
|
||||
static uint8_t cell_with_lowest_voltage = 0;
|
||||
static uint16_t requested_charge_current_dA = 0;
|
||||
static uint16_t average_charge_current_dA = 0;
|
||||
static uint16_t actual_charge_current_dA = 0;
|
||||
static bool requested_exceeding_average_current = 0;
|
||||
static bool error_state = false;
|
||||
|
||||
void update_values_battery() {
|
||||
|
||||
/* Update values from CAN */
|
||||
|
||||
datalayer.battery.status.real_soc = battery_SOC_percentage * 100;
|
||||
|
||||
datalayer.battery.status.remaining_capacity_Wh = static_cast<uint32_t>(
|
||||
(static_cast<double>(datalayer.battery.status.real_soc) / 10000) * datalayer.battery.info.total_capacity_Wh);
|
||||
|
||||
datalayer.battery.status.soh_pptt = battery_SOH_percentage * 100;
|
||||
|
||||
datalayer.battery.status.voltage_dV = battery_pack_voltage_dV;
|
||||
|
||||
datalayer.battery.status.current_dA = battery_pack_current_dA;
|
||||
|
||||
datalayer.battery.status.active_power_W = //Power in watts, Negative = charging batt
|
||||
((datalayer.battery.status.voltage_dV * datalayer.battery.status.current_dA) / 100);
|
||||
|
||||
datalayer.battery.status.max_charge_power_W = ((requested_charge_current_dA * battery_pack_voltage_dV) / 100);
|
||||
|
||||
datalayer.battery.status.max_discharge_power_W = 5000; //TODO, is this available via CAN?
|
||||
|
||||
datalayer.battery.status.temperature_min_dC = (int16_t)(pack_temperature_low_C * 10);
|
||||
|
||||
datalayer.battery.status.temperature_max_dC = (int16_t)(pack_temperature_high_C * 10);
|
||||
|
||||
datalayer.battery.status.cell_max_voltage_mV = cell_voltage_max_mV;
|
||||
|
||||
datalayer.battery.status.cell_min_voltage_mV = cell_voltage_min_mV;
|
||||
|
||||
/* Peform safety checks */
|
||||
if (system_state_chargecompleted) {
|
||||
//TODO, shall we set max_charge_power_W to 0 incase this is true?
|
||||
}
|
||||
if (IO_state_charge_enable) {
|
||||
//TODO, shall we react on this?
|
||||
}
|
||||
if (IO_state_discharge_enable) {
|
||||
//TODO, shall we react on this?
|
||||
}
|
||||
}
|
||||
|
||||
void receive_can_battery(CAN_frame rx_frame) {
|
||||
|
||||
/*
|
||||
// All CAN messages recieved will be logged via serial
|
||||
Serial.print(millis()); // Example printout, time, ID, length, data: 7553 1DB 8 FF C0 B9 EA 0 0 2 5D
|
||||
Serial.print(" ");
|
||||
Serial.print(rx_frame.ID, HEX);
|
||||
Serial.print(" ");
|
||||
Serial.print(rx_frame.DLC);
|
||||
Serial.print(" ");
|
||||
for (int i = 0; i < rx_frame.DLC; ++i) {
|
||||
Serial.print(rx_frame.data.u8[i], HEX);
|
||||
Serial.print(" ");
|
||||
}
|
||||
Serial.println("");
|
||||
*/
|
||||
switch (rx_frame.ID) {
|
||||
case 0x1A4: //PDO1_TX - 200ms
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
cell_voltage_max_mV = (uint16_t)((rx_frame.data.u8[1] << 8) | rx_frame.data.u8[0]);
|
||||
cell_voltage_min_mV = (uint16_t)((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[2]);
|
||||
pack_temperature_high_C = (int8_t)rx_frame.data.u8[4];
|
||||
pack_temperature_low_C = (int8_t)rx_frame.data.u8[5];
|
||||
system_state_discharge = (rx_frame.data.u8[6] & 0x01);
|
||||
system_state_charge = ((rx_frame.data.u8[6] & 0x02) >> 1);
|
||||
system_state_cellbalancing = ((rx_frame.data.u8[6] & 0x04) >> 2);
|
||||
system_state_tricklecharge = ((rx_frame.data.u8[6] & 0x08) >> 3);
|
||||
system_state_idle = ((rx_frame.data.u8[6] & 0x10) >> 4);
|
||||
system_state_chargecompleted = ((rx_frame.data.u8[6] & 0x20) >> 5);
|
||||
system_state_maintenancecharge = ((rx_frame.data.u8[6] & 0x40) >> 6);
|
||||
IO_state_main_positive_relay = (rx_frame.data.u8[7] & 0x01);
|
||||
IO_state_main_negative_relay = ((rx_frame.data.u8[7] & 0x02) >> 1);
|
||||
IO_state_charge_enable = ((rx_frame.data.u8[7] & 0x04) >> 2);
|
||||
IO_state_precharge_relay = ((rx_frame.data.u8[7] & 0x08) >> 3);
|
||||
IO_state_discharge_enable = ((rx_frame.data.u8[7] & 0x10) >> 4);
|
||||
IO_state_IO_6 = ((rx_frame.data.u8[7] & 0x20) >> 5);
|
||||
IO_state_IO_7 = ((rx_frame.data.u8[7] & 0x40) >> 6);
|
||||
IO_state_IO_8 = ((rx_frame.data.u8[7] & 0x80) >> 7);
|
||||
break;
|
||||
case 0x2A4: //PDO2_TX - 200ms
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
battery_pack_voltage_dV = (uint16_t)((rx_frame.data.u8[1] << 8) | rx_frame.data.u8[0]);
|
||||
battery_pack_current_dA = (int16_t)((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[2]);
|
||||
battery_SOH_percentage = (uint8_t)rx_frame.data.u8[4];
|
||||
battery_SOC_percentage = (uint8_t)rx_frame.data.u8[5];
|
||||
battery_remaining_dAh = (uint16_t)((rx_frame.data.u8[7] << 8) | rx_frame.data.u8[6]);
|
||||
break;
|
||||
case 0x3A4: //PDO3_TX - 200ms
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
cell_with_highest_voltage = (uint8_t)rx_frame.data.u8[0];
|
||||
cell_with_lowest_voltage = (uint8_t)rx_frame.data.u8[1];
|
||||
break;
|
||||
case 0x4A4: //PDO4_TX - 200ms
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
error_Cell_overvoltage = (rx_frame.data.u8[0] & 0x01);
|
||||
error_Cell_undervoltage = ((rx_frame.data.u8[0] & 0x02) >> 1);
|
||||
error_Cell_end_of_life_voltage = ((rx_frame.data.u8[0] & 0x04) >> 2);
|
||||
error_Cell_voltage_misread = ((rx_frame.data.u8[0] & 0x08) >> 3);
|
||||
error_Cell_over_temperature = ((rx_frame.data.u8[0] & 0x10) >> 4);
|
||||
error_Cell_under_temperature = ((rx_frame.data.u8[0] & 0x20) >> 5);
|
||||
error_Cell_unmanaged = ((rx_frame.data.u8[0] & 0x40) >> 6);
|
||||
error_LMU_over_temperature = ((rx_frame.data.u8[0] & 0x80) >> 7);
|
||||
error_LMU_under_temperature = (rx_frame.data.u8[1] & 0x01);
|
||||
error_Temp_sensor_open_circuit = ((rx_frame.data.u8[1] & 0x02) >> 1);
|
||||
error_Temp_sensor_short_circuit = ((rx_frame.data.u8[1] & 0x04) >> 2);
|
||||
error_SUB_communication = ((rx_frame.data.u8[1] & 0x08) >> 3);
|
||||
error_LMU_communication = ((rx_frame.data.u8[1] & 0x10) >> 4);
|
||||
error_Over_current_IN = ((rx_frame.data.u8[1] & 0x20) >> 5);
|
||||
error_Over_current_OUT = ((rx_frame.data.u8[1] & 0x40) >> 6);
|
||||
error_Short_circuit = ((rx_frame.data.u8[1] & 0x80) >> 7);
|
||||
error_Leak_detected = (rx_frame.data.u8[2] & 0x01);
|
||||
error_Leak_detection_failed = ((rx_frame.data.u8[2] & 0x02) >> 1);
|
||||
error_Voltage_difference = ((rx_frame.data.u8[2] & 0x04) >> 2);
|
||||
error_BMCU_supply_over_voltage = ((rx_frame.data.u8[2] & 0x08) >> 3);
|
||||
error_BMCU_supply_under_voltage = ((rx_frame.data.u8[2] & 0x10) >> 4);
|
||||
error_Main_positive_contactor = ((rx_frame.data.u8[2] & 0x20) >> 5);
|
||||
error_Main_negative_contactor = ((rx_frame.data.u8[2] & 0x40) >> 6);
|
||||
error_Precharge_contactor = ((rx_frame.data.u8[2] & 0x80) >> 7);
|
||||
error_Midpack_contactor = (rx_frame.data.u8[3] & 0x01);
|
||||
error_Precharge_timeout = ((rx_frame.data.u8[3] & 0x02) >> 1);
|
||||
error_Emergency_connector_override = ((rx_frame.data.u8[3] & 0x04) >> 2);
|
||||
warning_High_cell_voltage = (rx_frame.data.u8[4] & 0x01);
|
||||
warning_Low_cell_voltage = ((rx_frame.data.u8[4] & 0x02) >> 1);
|
||||
warning_High_cell_temperature = ((rx_frame.data.u8[4] & 0x04) >> 2);
|
||||
warning_Low_cell_temperature = ((rx_frame.data.u8[4] & 0x08) >> 3);
|
||||
warning_High_LMU_temperature = ((rx_frame.data.u8[4] & 0x10) >> 4);
|
||||
warning_Low_LMU_temperature = ((rx_frame.data.u8[4] & 0x20) >> 5);
|
||||
warning_SUB_communication_interfered = ((rx_frame.data.u8[4] & 0x40) >> 6);
|
||||
warning_LMU_communication_interfered = ((rx_frame.data.u8[4] & 0x80) >> 7);
|
||||
warning_High_current_IN = (rx_frame.data.u8[5] & 0x01);
|
||||
warning_High_current_OUT = ((rx_frame.data.u8[5] & 0x02) >> 1);
|
||||
warning_Pack_resistance_difference = ((rx_frame.data.u8[5] & 0x04) >> 2);
|
||||
warning_High_pack_resistance = ((rx_frame.data.u8[5] & 0x08) >> 3);
|
||||
warning_Cell_resistance_difference = ((rx_frame.data.u8[5] & 0x10) >> 4);
|
||||
warning_High_cell_resistance = ((rx_frame.data.u8[5] & 0x20) >> 5);
|
||||
warning_High_BMCU_supply_voltage = ((rx_frame.data.u8[5] & 0x40) >> 6);
|
||||
warning_Low_BMCU_supply_voltage = ((rx_frame.data.u8[5] & 0x80) >> 7);
|
||||
warning_Low_SOC = (rx_frame.data.u8[6] & 0x01);
|
||||
warning_Balancing_required_OCV_model = ((rx_frame.data.u8[6] & 0x02) >> 1);
|
||||
warning_Charger_not_responding = ((rx_frame.data.u8[6] & 0x04) >> 2);
|
||||
break;
|
||||
case 0x7A4: //PDO7_TX - 200ms
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
requested_charge_current_dA = (uint16_t)((rx_frame.data.u8[1] << 8) | rx_frame.data.u8[0]);
|
||||
average_charge_current_dA = (uint16_t)((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[2]);
|
||||
actual_charge_current_dA = (uint16_t)((rx_frame.data.u8[5] << 8) | rx_frame.data.u8[4]);
|
||||
requested_exceeding_average_current = (rx_frame.data.u8[6] & 0x01);
|
||||
break;
|
||||
case 0x7A5: //PDO7.1_TX - 200ms
|
||||
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||
error_state = (rx_frame.data.u8[0] & 0x01);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void send_can_battery() {
|
||||
unsigned long currentMillis = millis();
|
||||
// Send 1s CAN Message
|
||||
if (currentMillis - previousMillis1s >= INTERVAL_1_S) {
|
||||
|
||||
previousMillis1s = currentMillis;
|
||||
|
||||
/*
|
||||
transmit_can(&CELLPOWER_18FF50E9, can_config.battery);
|
||||
transmit_can(&CELLPOWER_18FF50E8, can_config.battery);
|
||||
transmit_can(&CELLPOWER_18FF50E7, can_config.battery);
|
||||
transmit_can(&CELLPOWER_18FF50E5, can_config.battery);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
void setup_battery(void) { // Performs one time setup at startup
|
||||
#ifdef DEBUG_VIA_USB
|
||||
Serial.println("Cellpower BMS selected");
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#endif // CELLPOWER_BMS
|
19
Software/src/battery/CELLPOWER-BMS.h
Normal file
19
Software/src/battery/CELLPOWER-BMS.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#ifndef CELLPOWER_BMS_H
|
||||
#define CELLPOWER_BMS_H
|
||||
#include <Arduino.h>
|
||||
#include "../include.h"
|
||||
|
||||
/* Tweak these according to your battery build */
|
||||
#define MAX_PACK_VOLTAGE_DV 5000 //5000 = 500.0V
|
||||
#define MIN_PACK_VOLTAGE_DV 1500
|
||||
#define MAX_CELL_VOLTAGE_MV 4250 //Battery is put into emergency stop if one cell goes over this value
|
||||
#define MIN_CELL_VOLTAGE_MV 2700 //Battery is put into emergency stop if one cell goes below this value
|
||||
|
||||
/* Do not modify any rows below*/
|
||||
#define BATTERY_SELECTED
|
||||
#define NATIVECAN_250KBPS
|
||||
|
||||
void setup_battery(void);
|
||||
void transmit_can(CAN_frame* tx_frame, int interface);
|
||||
|
||||
#endif
|
|
@ -64,6 +64,72 @@ typedef struct {
|
|||
|
||||
} DATALAYER_INFO_BYDATTO3;
|
||||
|
||||
typedef struct {
|
||||
/** bool */
|
||||
/** All values either True or false */
|
||||
bool system_state_discharge = false;
|
||||
bool system_state_charge = false;
|
||||
bool system_state_cellbalancing = false;
|
||||
bool system_state_tricklecharge = false;
|
||||
bool system_state_idle = false;
|
||||
bool system_state_chargecompleted = false;
|
||||
bool system_state_maintenancecharge = false;
|
||||
bool IO_state_main_positive_relay = false;
|
||||
bool IO_state_main_negative_relay = false;
|
||||
bool IO_state_charge_enable = false;
|
||||
bool IO_state_precharge_relay = false;
|
||||
bool IO_state_discharge_enable = false;
|
||||
bool IO_state_IO_6 = false;
|
||||
bool IO_state_IO_7 = false;
|
||||
bool IO_state_IO_8 = false;
|
||||
bool error_Cell_overvoltage = false;
|
||||
bool error_Cell_undervoltage = false;
|
||||
bool error_Cell_end_of_life_voltage = false;
|
||||
bool error_Cell_voltage_misread = false;
|
||||
bool error_Cell_over_temperature = false;
|
||||
bool error_Cell_under_temperature = false;
|
||||
bool error_Cell_unmanaged = false;
|
||||
bool error_LMU_over_temperature = false;
|
||||
bool error_LMU_under_temperature = false;
|
||||
bool error_Temp_sensor_open_circuit = false;
|
||||
bool error_Temp_sensor_short_circuit = false;
|
||||
bool error_SUB_communication = false;
|
||||
bool error_LMU_communication = false;
|
||||
bool error_Over_current_IN = false;
|
||||
bool error_Over_current_OUT = false;
|
||||
bool error_Short_circuit = false;
|
||||
bool error_Leak_detected = false;
|
||||
bool error_Leak_detection_failed = false;
|
||||
bool error_Voltage_difference = false;
|
||||
bool error_BMCU_supply_over_voltage = false;
|
||||
bool error_BMCU_supply_under_voltage = false;
|
||||
bool error_Main_positive_contactor = false;
|
||||
bool error_Main_negative_contactor = false;
|
||||
bool error_Precharge_contactor = false;
|
||||
bool error_Midpack_contactor = false;
|
||||
bool error_Precharge_timeout = false;
|
||||
bool error_Emergency_connector_override = false;
|
||||
bool warning_High_cell_voltage = false;
|
||||
bool warning_Low_cell_voltage = false;
|
||||
bool warning_High_cell_temperature = false;
|
||||
bool warning_Low_cell_temperature = false;
|
||||
bool warning_High_LMU_temperature = false;
|
||||
bool warning_Low_LMU_temperature = false;
|
||||
bool warning_SUB_communication_interfered = false;
|
||||
bool warning_LMU_communication_interfered = false;
|
||||
bool warning_High_current_IN = false;
|
||||
bool warning_High_current_OUT = false;
|
||||
bool warning_Pack_resistance_difference = false;
|
||||
bool warning_High_pack_resistance = false;
|
||||
bool warning_Cell_resistance_difference = false;
|
||||
bool warning_High_cell_resistance = false;
|
||||
bool warning_High_BMCU_supply_voltage = false;
|
||||
bool warning_Low_BMCU_supply_voltage = false;
|
||||
bool warning_Low_SOC = false;
|
||||
bool warning_Balancing_required_OCV_model = false;
|
||||
bool warning_Charger_not_responding = false;
|
||||
} DATALAYER_INFO_CELLPOWER;
|
||||
|
||||
typedef struct {
|
||||
/** uint8_t */
|
||||
/** Contactor status */
|
||||
|
@ -139,6 +205,7 @@ class DataLayerExtended {
|
|||
public:
|
||||
DATALAYER_INFO_BMWI3 bmwi3;
|
||||
DATALAYER_INFO_BYDATTO3 bydAtto3;
|
||||
DATALAYER_INFO_CELLPOWER cellpower;
|
||||
DATALAYER_INFO_TESLA tesla;
|
||||
DATALAYER_INFO_NISSAN_LEAF nissanleaf;
|
||||
};
|
||||
|
|
|
@ -100,6 +100,141 @@ String advanced_battery_processor(const String& var) {
|
|||
|
||||
#endif //BMW_I3_BATTERY
|
||||
|
||||
#ifdef CELLPOWER_BMS
|
||||
static const char* falseTrue[2] = {"False", "True"};
|
||||
content += "<h3>States:</h3>";
|
||||
content += "<h4>Discharge: " + String(falseTrue[datalayer_extended.cellpower.system_state_discharge]) + "</h4>";
|
||||
content += "<h4>Charge: " + String(falseTrue[datalayer_extended.cellpower.system_state_charge]) + "</h4>";
|
||||
content +=
|
||||
"<h4>Cellbalancing: " + String(falseTrue[datalayer_extended.cellpower.system_state_cellbalancing]) + "</h4>";
|
||||
content +=
|
||||
"<h4>Tricklecharging: " + String(falseTrue[datalayer_extended.cellpower.system_state_tricklecharge]) + "</h4>";
|
||||
content += "<h4>Idle: " + String(falseTrue[datalayer_extended.cellpower.system_state_idle]) + "</h4>";
|
||||
content += "<h4>Charge completed: " + String(falseTrue[datalayer_extended.cellpower.system_state_chargecompleted]) +
|
||||
"</h4>";
|
||||
content +=
|
||||
"<h4>Maintenance charge: " + String(falseTrue[datalayer_extended.cellpower.system_state_maintenancecharge]) +
|
||||
"</h4>";
|
||||
content += "<h3>IO:</h3>";
|
||||
content +=
|
||||
"<h4>Main positive relay: " + String(falseTrue[datalayer_extended.cellpower.IO_state_main_positive_relay]) +
|
||||
"</h4>";
|
||||
content +=
|
||||
"<h4>Main negative relay: " + String(falseTrue[datalayer_extended.cellpower.IO_state_main_negative_relay]) +
|
||||
"</h4>";
|
||||
content +=
|
||||
"<h4>Charge enabled: " + String(falseTrue[datalayer_extended.cellpower.IO_state_charge_enable]) + "</h4>";
|
||||
content +=
|
||||
"<h4>Precharge relay: " + String(falseTrue[datalayer_extended.cellpower.IO_state_precharge_relay]) + "</h4>";
|
||||
content +=
|
||||
"<h4>Discharge enable: " + String(falseTrue[datalayer_extended.cellpower.IO_state_discharge_enable]) + "</h4>";
|
||||
content += "<h4>IO 6: " + String(falseTrue[datalayer_extended.cellpower.IO_state_IO_6]) + "</h4>";
|
||||
content += "<h4>IO 7: " + String(falseTrue[datalayer_extended.cellpower.IO_state_IO_7]) + "</h4>";
|
||||
content += "<h4>IO 8: " + String(falseTrue[datalayer_extended.cellpower.IO_state_IO_8]) + "</h4>";
|
||||
content += "<h3>Errors:</h3>";
|
||||
content +=
|
||||
"<h4>Cell overvoltage: " + String(falseTrue[datalayer_extended.cellpower.error_Cell_overvoltage]) + "</h4>";
|
||||
content +=
|
||||
"<h4>Cell undervoltage: " + String(falseTrue[datalayer_extended.cellpower.error_Cell_undervoltage]) + "</h4>";
|
||||
content += "<h4>Cell end of life voltage: " +
|
||||
String(falseTrue[datalayer_extended.cellpower.error_Cell_end_of_life_voltage]) + "</h4>";
|
||||
content +=
|
||||
"<h4>Cell voltage misread: " + String(falseTrue[datalayer_extended.cellpower.error_Cell_voltage_misread]) +
|
||||
"</h4>";
|
||||
content +=
|
||||
"<h4>Cell over temperature: " + String(falseTrue[datalayer_extended.cellpower.error_Cell_over_temperature]) +
|
||||
"</h4>";
|
||||
content +=
|
||||
"<h4>Cell under temperature: " + String(falseTrue[datalayer_extended.cellpower.error_Cell_under_temperature]) +
|
||||
"</h4>";
|
||||
content += "<h4>Cell unmanaged: " + String(falseTrue[datalayer_extended.cellpower.error_Cell_unmanaged]) + "</h4>";
|
||||
content +=
|
||||
"<h4>LMU over temperature: " + String(falseTrue[datalayer_extended.cellpower.error_LMU_over_temperature]) +
|
||||
"</h4>";
|
||||
content +=
|
||||
"<h4>LMU under temperature: " + String(falseTrue[datalayer_extended.cellpower.error_LMU_under_temperature]) +
|
||||
"</h4>";
|
||||
content += "<h4>Temp sensor open circuit: " +
|
||||
String(falseTrue[datalayer_extended.cellpower.error_Temp_sensor_open_circuit]) + "</h4>";
|
||||
content += "<h4>Temp sensor short circuit: " +
|
||||
String(falseTrue[datalayer_extended.cellpower.error_Temp_sensor_short_circuit]) + "</h4>";
|
||||
content += "<h4>SUB comm: " + String(falseTrue[datalayer_extended.cellpower.error_SUB_communication]) + "</h4>";
|
||||
content += "<h4>LMU comm: " + String(falseTrue[datalayer_extended.cellpower.error_LMU_communication]) + "</h4>";
|
||||
content +=
|
||||
"<h4>Over current In: " + String(falseTrue[datalayer_extended.cellpower.error_Over_current_IN]) + "</h4>";
|
||||
content +=
|
||||
"<h4>Over current Out: " + String(falseTrue[datalayer_extended.cellpower.error_Over_current_OUT]) + "</h4>";
|
||||
content += "<h4>Short circuit: " + String(falseTrue[datalayer_extended.cellpower.error_Short_circuit]) + "</h4>";
|
||||
content += "<h4>Leak detected: " + String(falseTrue[datalayer_extended.cellpower.error_Leak_detected]) + "</h4>";
|
||||
content +=
|
||||
"<h4>Leak detection failed: " + String(falseTrue[datalayer_extended.cellpower.error_Leak_detection_failed]) +
|
||||
"</h4>";
|
||||
content +=
|
||||
"<h4>Voltage diff: " + String(falseTrue[datalayer_extended.cellpower.error_Voltage_difference]) + "</h4>";
|
||||
content += "<h4>BMCU supply overvoltage: " +
|
||||
String(falseTrue[datalayer_extended.cellpower.error_BMCU_supply_over_voltage]) + "</h4>";
|
||||
content += "<h4>BMCU supply undervoltage: " +
|
||||
String(falseTrue[datalayer_extended.cellpower.error_BMCU_supply_under_voltage]) + "</h4>";
|
||||
content += "<h4>Main positive contactor: " +
|
||||
String(falseTrue[datalayer_extended.cellpower.error_Main_positive_contactor]) + "</h4>";
|
||||
content += "<h4>Main negative contactor: " +
|
||||
String(falseTrue[datalayer_extended.cellpower.error_Main_negative_contactor]) + "</h4>";
|
||||
content += "<h4>Precharge contactor: " + String(falseTrue[datalayer_extended.cellpower.error_Precharge_contactor]) +
|
||||
"</h4>";
|
||||
content +=
|
||||
"<h4>Midpack contactor: " + String(falseTrue[datalayer_extended.cellpower.error_Midpack_contactor]) + "</h4>";
|
||||
content +=
|
||||
"<h4>Precharge timeout: " + String(falseTrue[datalayer_extended.cellpower.error_Precharge_timeout]) + "</h4>";
|
||||
content += "<h4>EMG connector override: " +
|
||||
String(falseTrue[datalayer_extended.cellpower.error_Emergency_connector_override]) + "</h4>";
|
||||
content += "<h3>Warnings:</h3>";
|
||||
content +=
|
||||
"<h4>High cell voltage: " + String(falseTrue[datalayer_extended.cellpower.warning_High_cell_voltage]) + "</h4>";
|
||||
content +=
|
||||
"<h4>Low cell voltage: " + String(falseTrue[datalayer_extended.cellpower.warning_Low_cell_voltage]) + "</h4>";
|
||||
content +=
|
||||
"<h4>High cell temperature: " + String(falseTrue[datalayer_extended.cellpower.warning_High_cell_temperature]) +
|
||||
"</h4>";
|
||||
content +=
|
||||
"<h4>Low cell temperature: " + String(falseTrue[datalayer_extended.cellpower.warning_Low_cell_temperature]) +
|
||||
"</h4>";
|
||||
content +=
|
||||
"<h4>High LMU temperature: " + String(falseTrue[datalayer_extended.cellpower.warning_High_LMU_temperature]) +
|
||||
"</h4>";
|
||||
content +=
|
||||
"<h4>Low LMU temperature: " + String(falseTrue[datalayer_extended.cellpower.warning_Low_LMU_temperature]) +
|
||||
"</h4>";
|
||||
content +=
|
||||
"<h4>SUB comm interf: " + String(falseTrue[datalayer_extended.cellpower.warning_SUB_communication_interfered]) +
|
||||
"</h4>";
|
||||
content +=
|
||||
"<h4>LMU comm interf: " + String(falseTrue[datalayer_extended.cellpower.warning_LMU_communication_interfered]) +
|
||||
"</h4>";
|
||||
content +=
|
||||
"<h4>High current In: " + String(falseTrue[datalayer_extended.cellpower.warning_High_current_IN]) + "</h4>";
|
||||
content +=
|
||||
"<h4>High current Out: " + String(falseTrue[datalayer_extended.cellpower.warning_High_current_OUT]) + "</h4>";
|
||||
content += "<h4>Pack resistance diff: " +
|
||||
String(falseTrue[datalayer_extended.cellpower.warning_Pack_resistance_difference]) + "</h4>";
|
||||
content +=
|
||||
"<h4>High pack resistance: " + String(falseTrue[datalayer_extended.cellpower.warning_High_pack_resistance]) +
|
||||
"</h4>";
|
||||
content += "<h4>Cell resistance diff: " +
|
||||
String(falseTrue[datalayer_extended.cellpower.warning_Cell_resistance_difference]) + "</h4>";
|
||||
content +=
|
||||
"<h4>High cell resistance: " + String(falseTrue[datalayer_extended.cellpower.warning_High_cell_resistance]) +
|
||||
"</h4>";
|
||||
content += "<h4>High BMCU supply voltage: " +
|
||||
String(falseTrue[datalayer_extended.cellpower.warning_High_BMCU_supply_voltage]) + "</h4>";
|
||||
content += "<h4>Low BMCU supply voltage: " +
|
||||
String(falseTrue[datalayer_extended.cellpower.warning_Low_BMCU_supply_voltage]) + "</h4>";
|
||||
content += "<h4>Low SOC: " + String(falseTrue[datalayer_extended.cellpower.warning_Low_SOC]) + "</h4>";
|
||||
content += "<h4>Balancing required: " +
|
||||
String(falseTrue[datalayer_extended.cellpower.warning_Balancing_required_OCV_model]) + "</h4>";
|
||||
content += "<h4>Charger not responding: " +
|
||||
String(falseTrue[datalayer_extended.cellpower.warning_Charger_not_responding]) + "</h4>";
|
||||
#endif //CELLPOWER_BMS
|
||||
|
||||
#ifdef BYD_ATTO_3_BATTERY
|
||||
content += "<h4>SOC estimated: " + String(datalayer_extended.bydAtto3.SOC_estimated) + "</h4>";
|
||||
content += "<h4>SOC highprec: " + String(datalayer_extended.bydAtto3.SOC_highprec) + "</h4>";
|
||||
|
@ -160,7 +295,7 @@ String advanced_battery_processor(const String& var) {
|
|||
#endif
|
||||
|
||||
#if !defined(TESLA_BATTERY) && !defined(NISSAN_LEAF_BATTERY) && !defined(BMW_I3_BATTERY) && \
|
||||
!defined(BYD_ATTO_3_BATTERY) //Only the listed types have extra info
|
||||
!defined(BYD_ATTO_3_BATTERY) && !defined(CELLPOWER_BMS) //Only the listed types have extra info
|
||||
content += "No extra information available for this battery type";
|
||||
#endif
|
||||
|
||||
|
|
|
@ -516,6 +516,9 @@ String processor(const String& var) {
|
|||
#ifdef BYD_ATTO_3_BATTERY
|
||||
content += "BYD Atto 3";
|
||||
#endif // BYD_ATTO_3_BATTERY
|
||||
#ifdef CELLPOWER_BMS
|
||||
content += "Cellpower BMS";
|
||||
#endif // CELLPOWER_BMS
|
||||
#ifdef CHADEMO_BATTERY
|
||||
content += "Chademo V2X mode";
|
||||
#endif // CHADEMO_BATTERY
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue