Tweak logic for contactor closing

This commit is contained in:
Daniel 2024-04-20 21:45:41 +03:00
parent f83bbc35eb
commit 997866ef8c
5 changed files with 55 additions and 25 deletions

View file

@ -619,9 +619,19 @@ void send_can2() {
#ifdef DOUBLE_BATTERY
void handle_CAN_contactors() {
if (abs(datalayer.battery.status.voltage_dV - datalayer.battery2.status.voltage_dV) < 50) {
if (datalayer.battery.status.voltage_dV == 0 || datalayer.battery2.status.voltage_dV == 0) {
return; // Both voltage values need to be available to start check
}
if (abs(datalayer.battery.status.voltage_dV - datalayer.battery2.status.voltage_dV) < 30) { // If we are within 3.0V
clear_event(EVENT_VOLTAGE_DIFFERENCE);
if (datalayer.battery2.status.bms_status != FAULT) { // Only proceed if BMS on battery2 is not faulted
datalayer.system.status.battery2_allows_contactor_closing = true;
} //TODO: Shall we handle opening incase of fault here?
}
} else { //We are over 3.0V diff
set_event(EVENT_VOLTAGE_DIFFERENCE,
(uint8_t)(abs(datalayer.battery.status.voltage_dV - datalayer.battery2.status.voltage_dV) / 10));
}
}
#endif
@ -744,7 +754,29 @@ void update_SOC() {
datalayer.battery.status.reported_soc = calc_soc;
} else { // No SOC window wanted. Set scaled to same as real.
datalayer.battery.status.reported_soc = datalayer.battery.status.real_soc;
#ifdef DOUBLE_BATTERY
datalayer.battery.status.reported_soc =
(datalayer.battery.status.real_soc + datalayer.battery2.status.real_soc) / 2;
#endif
}
#ifdef DOUBLE_BATTERY
datalayer.battery.status.reported_soc = (datalayer.battery.status.real_soc + datalayer.battery2.status.real_soc) / 2;
if (datalayer.battery.status.real_soc < 100) { //If this battery is under 1.00%, use this as SOC instead of average
datalayer.battery.status.reported_soc = datalayer.battery.status.real_soc;
}
if (datalayer.battery2.status.real_soc < 100) { //If this battery is under 1.00%, use this as SOC instead of average
datalayer.battery.status.reported_soc = datalayer.battery2.status.real_soc;
}
if (datalayer.battery.status.real_soc > 9900) { //If this battery is over 99.00%, use this as SOC instead of average
datalayer.battery.status.reported_soc = datalayer.battery.status.real_soc;
}
if (datalayer.battery2.status.real_soc > 9900) { //If this battery is over 99.00%, use this as SOC instead of average
datalayer.battery.status.reported_soc = datalayer.battery2.status.real_soc;
}
#endif //TODO: Constrain according to the user settings. Help wanted on algoritm to use.
}
void summarize_battery_values() {

View file

@ -16,14 +16,6 @@ static unsigned long previousMillis1000 = 0; // will store last time a 1000m
static unsigned long previousMillis5000 = 0; // will store last time a 5000ms CAN Message was send
static unsigned long previousMillis10000 = 0; // will store last time a 10000ms CAN Message was send
static uint8_t CANstillAlive = 12; // counter for checking if CAN is still alive
static unsigned long previousMillis20_2 = 0; // will store last time a 20ms CAN Message was send
static unsigned long previousMillis100_2 = 0; // will store last time a 100ms CAN Message was send
static unsigned long previousMillis200_2 = 0; // will store last time a 200ms CAN Message was send
static unsigned long previousMillis500_2 = 0; // will store last time a 500ms CAN Message was send
static unsigned long previousMillis640_2 = 0; // will store last time a 600ms CAN Message was send
static unsigned long previousMillis1000_2 = 0; // will store last time a 1000ms CAN Message was send
static unsigned long previousMillis5000_2 = 0; // will store last time a 5000ms CAN Message was send
static unsigned long previousMillis10000_2 = 0; // will store last time a 10000ms CAN Message was send
static uint8_t CAN2stillAlive = 12; // counter for checking if CAN2 is still alive
static uint16_t CANerror = 0; // counter on how many CAN errors encountered
#define ALIVE_MAX_VALUE 14 // BMW CAN messages contain alive counter, goes from 0...14
@ -533,6 +525,7 @@ void update_values_battery2() { //This function maps all the values fetched via
if (!CAN2stillAlive) {
set_event(EVENT_CAN2_RX_FAILURE, 2);
datalayer.battery2.status.bms_status = FAULT; //TODO: Refactor handling of event for battery2
datalayer.system.status.battery2_allows_contactor_closing = false;
} else {
CAN2stillAlive--;
clear_event(EVENT_CAN2_RX_FAILURE);
@ -788,7 +781,8 @@ void receive_can_battery2(CAN_frame_t rx_frame) {
CAN2stillAlive = 12; //This message is only sent if 30C (Wakeup pin on battery) is energized with 12V
battery2_current = (rx_frame.data.u8[1] << 8 | rx_frame.data.u8[0]) - 8192; //deciAmps (-819.2 to 819.0A)
battery2_volts = (rx_frame.data.u8[3] << 8 | rx_frame.data.u8[2]); //500.0 V
datalayer.battery2.status.voltage_dV = battery2_volts; // Update the datalayer as soon as possible with this info
datalayer.battery2.status.voltage_dV =
battery2_volts; // Update the datalayer as soon as possible with this info, needed for contactor control
battery2_HVBatt_SOC = ((rx_frame.data.u8[5] & 0x0F) << 8 | rx_frame.data.u8[4]);
battery2_request_open_contactors = (rx_frame.data.u8[5] & 0xC0) >> 6;
battery2_request_open_contactors_instantly = (rx_frame.data.u8[6] & 0x03);

View file

@ -143,6 +143,7 @@ void init_events(void) {
events.entries[EVENT_BATTERY_CHG_STOP_REQ].level = EVENT_LEVEL_ERROR;
events.entries[EVENT_BATTERY_DISCHG_STOP_REQ].level = EVENT_LEVEL_ERROR;
events.entries[EVENT_BATTERY_CHG_DISCHG_STOP_REQ].level = EVENT_LEVEL_ERROR;
events.entries[EVENT_VOLTAGE_DIFFERENCE].level = EVENT_LEVEL_INFO;
events.entries[EVENT_LOW_SOH].level = EVENT_LEVEL_ERROR;
events.entries[EVENT_HVIL_FAILURE].level = EVENT_LEVEL_ERROR;
events.entries[EVENT_INTERNAL_OPEN_FAULT].level = EVENT_LEVEL_ERROR;
@ -227,6 +228,8 @@ const char* get_event_message_string(EVENTS_ENUM_TYPE event) {
return "Info: COLD BATTERY! Battery requesting heating pads to activate!";
case EVENT_BATTERY_WARMED_UP:
return "Info: Battery requesting heating pads to stop. The battery is now warm enough.";
case EVENT_VOLTAGE_DIFFERENCE:
return "Info: Too large voltage diff between the batteries. Second battery cannot join the DC-link";
case EVENT_LOW_SOH:
return "ERROR: State of health critically low. Battery internal resistance too high to continue. Recycle "
"battery.";

View file

@ -45,6 +45,7 @@
XX(EVENT_BATTERY_CHG_DISCHG_STOP_REQ) \
XX(EVENT_BATTERY_REQUESTS_HEAT) \
XX(EVENT_BATTERY_WARMED_UP) \
XX(EVENT_VOLTAGE_DIFFERENCE) \
XX(EVENT_LOW_SOH) \
XX(EVENT_HVIL_FAILURE) \
XX(EVENT_INTERNAL_OPEN_FAULT) \

View file

@ -599,7 +599,7 @@ String processor(const String& var) {
socRealFloat =
static_cast<float>(datalayer.battery2.status.real_soc) / 100.0; // Convert to float and divide by 100
socScaledFloat =
static_cast<float>(datalayer.battery2.status.reported_soc) / 100.0; // Convert to float and divide by 100
static_cast<float>(datalayer.battery.status.reported_soc) / 100.0; // Convert to float and divide by 100
sohFloat = static_cast<float>(datalayer.battery2.status.soh_pptt) / 100.0; // Convert to float and divide by 100
voltageFloat =
static_cast<float>(datalayer.battery2.status.voltage_dV) / 10.0; // Convert to float and divide by 10