mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-05 02:39:57 +02:00
Clarify contactor control variables and usage
This commit is contained in:
parent
4cf08894f7
commit
2c2f05f186
11 changed files with 46 additions and 30 deletions
|
@ -334,9 +334,9 @@ void check_interconnect_available() {
|
||||||
clear_event(EVENT_VOLTAGE_DIFFERENCE);
|
clear_event(EVENT_VOLTAGE_DIFFERENCE);
|
||||||
if (datalayer.battery.status.bms_status == FAULT) {
|
if (datalayer.battery.status.bms_status == FAULT) {
|
||||||
// If main battery is in fault state, disengage the second battery
|
// 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
|
} 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
|
} else { //Voltage between the two packs is too large
|
||||||
set_event(EVENT_VOLTAGE_DIFFERENCE, (uint8_t)(voltage_diff / 10));
|
set_event(EVENT_VOLTAGE_DIFFERENCE, (uint8_t)(voltage_diff / 10));
|
||||||
|
|
|
@ -30,9 +30,7 @@ void setup_battery() {
|
||||||
new SELECTED_BATTERY_CLASS(&datalayer.battery2, &datalayer.system.status.battery2_allows_contactor_closing,
|
new SELECTED_BATTERY_CLASS(&datalayer.battery2, &datalayer.system.status.battery2_allows_contactor_closing,
|
||||||
can_config.battery_double, WUP_PIN2);
|
can_config.battery_double, WUP_PIN2);
|
||||||
#else
|
#else
|
||||||
battery2 =
|
battery2 = new SELECTED_BATTERY_CLASS(&datalayer.battery2, nullptr, can_config.battery_double);
|
||||||
new SELECTED_BATTERY_CLASS(&datalayer.battery2, &datalayer.system.status.battery2_allows_contactor_closing,
|
|
||||||
nullptr, can_config.battery_double);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
battery2->setup();
|
battery2->setup();
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include "../include.h"
|
|
||||||
#ifdef BMW_I3_BATTERY
|
#ifdef BMW_I3_BATTERY
|
||||||
|
#include "BMW-I3-BATTERY.h"
|
||||||
#include "../communication/can/comm_can.h"
|
#include "../communication/can/comm_can.h"
|
||||||
#include "../datalayer/datalayer.h"
|
#include "../datalayer/datalayer.h"
|
||||||
#include "../datalayer/datalayer_extended.h"
|
#include "../datalayer/datalayer_extended.h"
|
||||||
#include "../devboard/utils/events.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 */
|
/* 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;
|
BMW_13E.data.u8[4] = BMW_13E_counter;
|
||||||
|
|
||||||
if (datalayer_battery->status.bms_status == FAULT) {
|
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) {
|
||||||
else if (*allows_contactor_closing == true) {
|
//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);
|
transmit_can_frame(&BMW_10B, can_interface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send 100ms CAN Message
|
// Send 100ms CAN Message
|
||||||
if (currentMillis - previousMillis100 >= INTERVAL_100_MS) {
|
if (currentMillis - previousMillis100 >= INTERVAL_100_MS) {
|
||||||
previousMillis100 = currentMillis;
|
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.max_design_voltage_dV = MAX_PACK_VOLTAGE_60AH;
|
||||||
datalayer_battery->info.min_design_voltage_dV = MIN_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_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;
|
datalayer_battery->info.number_of_cells = NUMBER_OF_CELLS;
|
||||||
|
|
||||||
pinMode(wakeup_pin, OUTPUT);
|
pinMode(wakeup_pin, OUTPUT);
|
||||||
|
|
|
@ -12,9 +12,10 @@
|
||||||
class BmwI3Battery : public CanBattery {
|
class BmwI3Battery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
// Use this constructor for the second battery.
|
// 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;
|
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;
|
can_interface = targetCan;
|
||||||
wakeup_pin = wakeup;
|
wakeup_pin = wakeup;
|
||||||
*allows_contactor_closing = true;
|
*allows_contactor_closing = true;
|
||||||
|
@ -27,6 +28,7 @@ class BmwI3Battery : public CanBattery {
|
||||||
BmwI3Battery() {
|
BmwI3Battery() {
|
||||||
datalayer_battery = &datalayer.battery;
|
datalayer_battery = &datalayer.battery;
|
||||||
allows_contactor_closing = &datalayer.system.status.battery_allows_contactor_closing;
|
allows_contactor_closing = &datalayer.system.status.battery_allows_contactor_closing;
|
||||||
|
contactor_closing_allowed = nullptr;
|
||||||
can_interface = can_config.battery;
|
can_interface = can_config.battery;
|
||||||
wakeup_pin = WUP_PIN1;
|
wakeup_pin = WUP_PIN1;
|
||||||
}
|
}
|
||||||
|
@ -53,9 +55,14 @@ class BmwI3Battery : public CanBattery {
|
||||||
const int NUMBER_OF_CELLS = 96;
|
const int NUMBER_OF_CELLS = 96;
|
||||||
|
|
||||||
DATALAYER_BATTERY_TYPE* datalayer_battery;
|
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;
|
int can_interface;
|
||||||
|
|
||||||
unsigned long previousMillis20 = 0; // will store last time a 20ms CAN Message was send
|
unsigned long previousMillis20 = 0; // will store last time a 20ms CAN Message was send
|
||||||
|
|
|
@ -485,10 +485,12 @@ void BydAttoBattery::transmit_can(unsigned long currentMillis) {
|
||||||
previousMillis50 = currentMillis;
|
previousMillis50 = currentMillis;
|
||||||
|
|
||||||
// Set close contactors to allowed (Useful for crashed packs, started via contactor control thru GPIO)
|
// Set close contactors to allowed (Useful for crashed packs, started via contactor control thru GPIO)
|
||||||
if (datalayer_battery->status.bms_status == ACTIVE) {
|
if (allows_contactor_closing) {
|
||||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
if (datalayer_battery->status.bms_status == ACTIVE) {
|
||||||
} else { // Fault state, open contactors!
|
*allows_contactor_closing = true;
|
||||||
datalayer.system.status.battery_allows_contactor_closing = false;
|
} else { // Fault state, open contactors!
|
||||||
|
*allows_contactor_closing = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
counter_50ms++;
|
counter_50ms++;
|
||||||
|
|
|
@ -33,11 +33,10 @@
|
||||||
class BydAttoBattery : public CanBattery {
|
class BydAttoBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
// Use this constructor for the second battery.
|
// Use this constructor for the second battery.
|
||||||
BydAttoBattery(DATALAYER_BATTERY_TYPE* datalayer_ptr, bool* allows_contactor_closing_ptr,
|
BydAttoBattery(DATALAYER_BATTERY_TYPE* datalayer_ptr, DATALAYER_INFO_BYDATTO3* extended, int targetCan) {
|
||||||
DATALAYER_INFO_BYDATTO3* extended, int targetCan) {
|
|
||||||
datalayer_battery = datalayer_ptr;
|
datalayer_battery = datalayer_ptr;
|
||||||
datalayer_bydatto = extended;
|
datalayer_bydatto = extended;
|
||||||
allows_contactor_closing = allows_contactor_closing_ptr;
|
allows_contactor_closing = nullptr;
|
||||||
can_interface = targetCan;
|
can_interface = targetCan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ void NissanLeafBattery::
|
||||||
datalayer_battery->status.max_charge_power_W = (battery_Charge_Power_Limit * 1000); //kW to W
|
datalayer_battery->status.max_charge_power_W = (battery_Charge_Power_Limit * 1000); //kW to W
|
||||||
|
|
||||||
//Allow contactors to close
|
//Allow contactors to close
|
||||||
if (battery_can_alive) {
|
if (battery_can_alive && allows_contactor_closing) {
|
||||||
*allows_contactor_closing = true;
|
*allows_contactor_closing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,9 @@
|
||||||
class NissanLeafBattery : public CanBattery {
|
class NissanLeafBattery : public CanBattery {
|
||||||
public:
|
public:
|
||||||
// Use this constructor for the second battery.
|
// Use this constructor for the second battery.
|
||||||
NissanLeafBattery(DATALAYER_BATTERY_TYPE* datalayer_ptr, bool* allows_contactor_closing_ptr,
|
NissanLeafBattery(DATALAYER_BATTERY_TYPE* datalayer_ptr, DATALAYER_INFO_NISSAN_LEAF* extended, int targetCan) {
|
||||||
DATALAYER_INFO_NISSAN_LEAF* extended, int targetCan) {
|
|
||||||
datalayer_battery = datalayer_ptr;
|
datalayer_battery = datalayer_ptr;
|
||||||
allows_contactor_closing = allows_contactor_closing_ptr;
|
allows_contactor_closing = nullptr;
|
||||||
datalayer_nissan = extended;
|
datalayer_nissan = extended;
|
||||||
can_interface = targetCan;
|
can_interface = targetCan;
|
||||||
|
|
||||||
|
@ -48,6 +47,8 @@ class NissanLeafBattery : public CanBattery {
|
||||||
|
|
||||||
DATALAYER_BATTERY_TYPE* datalayer_battery;
|
DATALAYER_BATTERY_TYPE* datalayer_battery;
|
||||||
DATALAYER_INFO_NISSAN_LEAF* datalayer_nissan;
|
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;
|
bool* allows_contactor_closing;
|
||||||
|
|
||||||
int can_interface;
|
int can_interface;
|
||||||
|
|
|
@ -225,7 +225,7 @@ void handle_contactors() {
|
||||||
|
|
||||||
#ifdef CONTACTOR_CONTROL_DOUBLE_BATTERY
|
#ifdef CONTACTOR_CONTROL_DOUBLE_BATTERY
|
||||||
void handle_contactors_battery2() {
|
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_NEGATIVE_CONTACTOR_PIN, ON);
|
||||||
set(SECOND_POSITIVE_CONTACTOR_PIN, ON);
|
set(SECOND_POSITIVE_CONTACTOR_PIN, ON);
|
||||||
datalayer.system.status.contactors_battery2_engaged = true;
|
datalayer.system.status.contactors_battery2_engaged = true;
|
||||||
|
|
|
@ -297,10 +297,12 @@ typedef struct {
|
||||||
* we report the inverter as missing entirely on the CAN bus.
|
* we report the inverter as missing entirely on the CAN bus.
|
||||||
*/
|
*/
|
||||||
uint8_t CAN_inverter_still_alive = CAN_STILL_ALIVE;
|
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;
|
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 */
|
/** True if the inverter allows for the contactors to close */
|
||||||
bool inverter_allows_contactor_closing = true;
|
bool inverter_allows_contactor_closing = true;
|
||||||
#ifdef CONTACTOR_CONTROL
|
#ifdef CONTACTOR_CONTROL
|
||||||
|
|
|
@ -1379,7 +1379,7 @@ String processor(const String& var) {
|
||||||
|
|
||||||
content += "<h4>Automatic contactor closing allowed:</h4>";
|
content += "<h4>Automatic contactor closing allowed:</h4>";
|
||||||
content += "<h4>Battery: ";
|
content += "<h4>Battery: ";
|
||||||
if (datalayer.system.status.battery2_allows_contactor_closing == true) {
|
if (datalayer.system.status.battery2_allowed_contactor_closing == true) {
|
||||||
content += "<span>✓</span>";
|
content += "<span>✓</span>";
|
||||||
} else {
|
} else {
|
||||||
content += "<span style='color: red;'>✕</span>";
|
content += "<span style='color: red;'>✕</span>";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue