Clarify contactor control variables and usage

This commit is contained in:
Jaakko Haakana 2025-05-17 08:53:58 +03:00
parent 4cf08894f7
commit 2c2f05f186
11 changed files with 46 additions and 30 deletions

View file

@ -334,9 +334,9 @@ void check_interconnect_available() {
clear_event(EVENT_VOLTAGE_DIFFERENCE);
if (datalayer.battery.status.bms_status == FAULT) {
// If main battery is in fault state, disengage the second battery
datalayer.system.status.battery2_allows_contactor_closing = false;
datalayer.system.status.battery2_allowed_contactor_closing = false;
} else { // If main battery is OK, allow second battery to join
datalayer.system.status.battery2_allows_contactor_closing = true;
datalayer.system.status.battery2_allowed_contactor_closing = true;
}
} else { //Voltage between the two packs is too large
set_event(EVENT_VOLTAGE_DIFFERENCE, (uint8_t)(voltage_diff / 10));

View file

@ -30,9 +30,7 @@ void setup_battery() {
new SELECTED_BATTERY_CLASS(&datalayer.battery2, &datalayer.system.status.battery2_allows_contactor_closing,
can_config.battery_double, WUP_PIN2);
#else
battery2 =
new SELECTED_BATTERY_CLASS(&datalayer.battery2, &datalayer.system.status.battery2_allows_contactor_closing,
nullptr, can_config.battery_double);
battery2 = new SELECTED_BATTERY_CLASS(&datalayer.battery2, nullptr, can_config.battery_double);
#endif
}
battery2->setup();

View file

@ -1,10 +1,10 @@
#include "../include.h"
#ifdef BMW_I3_BATTERY
#include "BMW-I3-BATTERY.h"
#include "../communication/can/comm_can.h"
#include "../datalayer/datalayer.h"
#include "../datalayer/datalayer_extended.h"
#include "../devboard/utils/events.h"
#include "BMW-I3-BATTERY.h"
#include "../include.h"
/* Do not change code below unless you are sure what you are doing */
@ -329,11 +329,15 @@ void BmwI3Battery::transmit_can(unsigned long currentMillis) {
BMW_13E.data.u8[4] = BMW_13E_counter;
if (datalayer_battery->status.bms_status == FAULT) {
} //If battery is not in Fault mode, allow contactor to close by sending 10B
else if (*allows_contactor_closing == true) {
} else if (allows_contactor_closing) {
//If battery is not in Fault mode, and we are allowed to control contactors, we allow contactor to close by sending 10B
*allows_contactor_closing = true;
transmit_can_frame(&BMW_10B, can_interface);
} else if (contactor_closing_allowed && *contactor_closing_allowed) {
transmit_can_frame(&BMW_10B, can_interface);
}
}
// Send 100ms CAN Message
if (currentMillis - previousMillis100 >= INTERVAL_100_MS) {
previousMillis100 = currentMillis;
@ -512,7 +516,10 @@ void BmwI3Battery::setup(void) { // Performs one time setup at startup
datalayer_battery->info.max_design_voltage_dV = MAX_PACK_VOLTAGE_60AH;
datalayer_battery->info.min_design_voltage_dV = MIN_PACK_VOLTAGE_60AH;
datalayer_battery->info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
datalayer.system.status.battery_allows_contactor_closing = true;
if (allows_contactor_closing) {
*allows_contactor_closing = true;
}
datalayer_battery->info.number_of_cells = NUMBER_OF_CELLS;
pinMode(wakeup_pin, OUTPUT);

View file

@ -12,9 +12,10 @@
class BmwI3Battery : public CanBattery {
public:
// Use this constructor for the second battery.
BmwI3Battery(DATALAYER_BATTERY_TYPE* datalayer_ptr, bool* allows_contactor_closing_ptr, int targetCan, int wakeup) {
BmwI3Battery(DATALAYER_BATTERY_TYPE* datalayer_ptr, bool* contactor_closing_allowed_ptr, int targetCan, int wakeup) {
datalayer_battery = datalayer_ptr;
allows_contactor_closing = allows_contactor_closing_ptr;
contactor_closing_allowed = contactor_closing_allowed_ptr;
allows_contactor_closing = nullptr;
can_interface = targetCan;
wakeup_pin = wakeup;
*allows_contactor_closing = true;
@ -27,6 +28,7 @@ class BmwI3Battery : public CanBattery {
BmwI3Battery() {
datalayer_battery = &datalayer.battery;
allows_contactor_closing = &datalayer.system.status.battery_allows_contactor_closing;
contactor_closing_allowed = nullptr;
can_interface = can_config.battery;
wakeup_pin = WUP_PIN1;
}
@ -53,9 +55,14 @@ class BmwI3Battery : public CanBattery {
const int NUMBER_OF_CELLS = 96;
DATALAYER_BATTERY_TYPE* datalayer_battery;
bool* allows_contactor_closing;
int wakeup_pin;
// If not null, this battery decides when the contactor can be closed and writes the value here.
bool* allows_contactor_closing;
// If not null, this battery listens to this boolean to determine whether contactor closing is allowed
bool* contactor_closing_allowed;
int wakeup_pin;
int can_interface;
unsigned long previousMillis20 = 0; // will store last time a 20ms CAN Message was send

View file

@ -485,10 +485,12 @@ void BydAttoBattery::transmit_can(unsigned long currentMillis) {
previousMillis50 = currentMillis;
// Set close contactors to allowed (Useful for crashed packs, started via contactor control thru GPIO)
if (datalayer_battery->status.bms_status == ACTIVE) {
datalayer.system.status.battery_allows_contactor_closing = true;
} else { // Fault state, open contactors!
datalayer.system.status.battery_allows_contactor_closing = false;
if (allows_contactor_closing) {
if (datalayer_battery->status.bms_status == ACTIVE) {
*allows_contactor_closing = true;
} else { // Fault state, open contactors!
*allows_contactor_closing = false;
}
}
counter_50ms++;

View file

@ -33,11 +33,10 @@
class BydAttoBattery : public CanBattery {
public:
// Use this constructor for the second battery.
BydAttoBattery(DATALAYER_BATTERY_TYPE* datalayer_ptr, bool* allows_contactor_closing_ptr,
DATALAYER_INFO_BYDATTO3* extended, int targetCan) {
BydAttoBattery(DATALAYER_BATTERY_TYPE* datalayer_ptr, DATALAYER_INFO_BYDATTO3* extended, int targetCan) {
datalayer_battery = datalayer_ptr;
datalayer_bydatto = extended;
allows_contactor_closing = allows_contactor_closing_ptr;
allows_contactor_closing = nullptr;
can_interface = targetCan;
}

View file

@ -74,7 +74,7 @@ void NissanLeafBattery::
datalayer_battery->status.max_charge_power_W = (battery_Charge_Power_Limit * 1000); //kW to W
//Allow contactors to close
if (battery_can_alive) {
if (battery_can_alive && allows_contactor_closing) {
*allows_contactor_closing = true;
}

View file

@ -19,10 +19,9 @@
class NissanLeafBattery : public CanBattery {
public:
// Use this constructor for the second battery.
NissanLeafBattery(DATALAYER_BATTERY_TYPE* datalayer_ptr, bool* allows_contactor_closing_ptr,
DATALAYER_INFO_NISSAN_LEAF* extended, int targetCan) {
NissanLeafBattery(DATALAYER_BATTERY_TYPE* datalayer_ptr, DATALAYER_INFO_NISSAN_LEAF* extended, int targetCan) {
datalayer_battery = datalayer_ptr;
allows_contactor_closing = allows_contactor_closing_ptr;
allows_contactor_closing = nullptr;
datalayer_nissan = extended;
can_interface = targetCan;
@ -48,6 +47,8 @@ class NissanLeafBattery : public CanBattery {
DATALAYER_BATTERY_TYPE* datalayer_battery;
DATALAYER_INFO_NISSAN_LEAF* datalayer_nissan;
// If not null, this battery decides when the contactor can be closed and writes the value here.
bool* allows_contactor_closing;
int can_interface;

View file

@ -225,7 +225,7 @@ void handle_contactors() {
#ifdef CONTACTOR_CONTROL_DOUBLE_BATTERY
void handle_contactors_battery2() {
if ((contactorStatus == COMPLETED) && datalayer.system.status.battery2_allows_contactor_closing) {
if ((contactorStatus == COMPLETED) && datalayer.system.status.battery2_allowed_contactor_closing) {
set(SECOND_NEGATIVE_CONTACTOR_PIN, ON);
set(SECOND_POSITIVE_CONTACTOR_PIN, ON);
datalayer.system.status.contactors_battery2_engaged = true;

View file

@ -297,10 +297,12 @@ typedef struct {
* we report the inverter as missing entirely on the CAN bus.
*/
uint8_t CAN_inverter_still_alive = CAN_STILL_ALIVE;
/** True if the battery allows for the contactors to close */
/** True if the primary battery allows for the contactors to close */
bool battery_allows_contactor_closing = false;
/** True if the second battery allows for the contactors to close */
bool battery2_allows_contactor_closing = false;
/** True if the second battery is allowed to close the contactors */
bool battery2_allowed_contactor_closing = false;
/** True if the inverter allows for the contactors to close */
bool inverter_allows_contactor_closing = true;
#ifdef CONTACTOR_CONTROL

View file

@ -1379,7 +1379,7 @@ String processor(const String& var) {
content += "<h4>Automatic contactor closing allowed:</h4>";
content += "<h4>Battery: ";
if (datalayer.system.status.battery2_allows_contactor_closing == true) {
if (datalayer.system.status.battery2_allowed_contactor_closing == true) {
content += "<span>&#10003;</span>";
} else {
content += "<span style='color: red;'>&#10005;</span>";