mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-04 18:29:48 +02:00
Merge branch 'dalathegreat:main' into tesla-bugfixes
This commit is contained in:
commit
87ac87cbf0
18 changed files with 561 additions and 79 deletions
2
.github/workflows/compile-all-batteries.yml
vendored
2
.github/workflows/compile-all-batteries.yml
vendored
|
@ -112,4 +112,4 @@ jobs:
|
||||||
# in the build matrix, and using build flags to define the
|
# in the build matrix, and using build flags to define the
|
||||||
# battery and inverter set in the build matrix.
|
# battery and inverter set in the build matrix.
|
||||||
- name: Compile Sketch
|
- name: Compile Sketch
|
||||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -Wextra -Wpedantic -Werror -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||||
|
|
|
@ -118,4 +118,4 @@ jobs:
|
||||||
# in the build matrix, and using build flags to define the
|
# in the build matrix, and using build flags to define the
|
||||||
# battery and inverter set in the build matrix.
|
# battery and inverter set in the build matrix.
|
||||||
- name: Compile Sketch
|
- name: Compile Sketch
|
||||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -Wextra -Wpedantic -Werror -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||||
|
|
|
@ -118,4 +118,4 @@ jobs:
|
||||||
# in the build matrix, and using build flags to define the
|
# in the build matrix, and using build flags to define the
|
||||||
# battery and inverter set in the build matrix.
|
# battery and inverter set in the build matrix.
|
||||||
- name: Compile Sketch
|
- name: Compile Sketch
|
||||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -Wextra -Wpedantic -Werror -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||||
|
|
2
.github/workflows/compile-all-hardware.yml
vendored
2
.github/workflows/compile-all-hardware.yml
vendored
|
@ -90,4 +90,4 @@ jobs:
|
||||||
# in the build matrix, and using build flags to define the
|
# in the build matrix, and using build flags to define the
|
||||||
# battery and inverter set in the build matrix.
|
# battery and inverter set in the build matrix.
|
||||||
- name: Compile Sketch
|
- name: Compile Sketch
|
||||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -Wextra -Wpedantic -Werror -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||||
|
|
2
.github/workflows/compile-all-inverters.yml
vendored
2
.github/workflows/compile-all-inverters.yml
vendored
|
@ -105,4 +105,4 @@ jobs:
|
||||||
# in the build matrix, and using build flags to define the
|
# in the build matrix, and using build flags to define the
|
||||||
# battery and inverter set in the build matrix.
|
# battery and inverter set in the build matrix.
|
||||||
- name: Compile Sketch
|
- name: Compile Sketch
|
||||||
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
run: arduino-cli compile --fqbn ${{ matrix.fqbn }} --build-property "build.extra_flags=-Wall -Wextra -Wpedantic -Werror -DESP32 -D${{ matrix.battery}} -D${{ matrix.inverter}} -D${{ matrix.hardware}}" ./Software
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
#endif // WIFI
|
#endif // WIFI
|
||||||
|
|
||||||
// The current software version, shown on webserver
|
// The current software version, shown on webserver
|
||||||
const char* version_number = "8.3.dev";
|
const char* version_number = "8.3.0";
|
||||||
|
|
||||||
// Interval settings
|
// Interval settings
|
||||||
uint16_t intervalUpdateValues = INTERVAL_1_S; // Interval at which to update inverter values / Modbus registers
|
uint16_t intervalUpdateValues = INTERVAL_1_S; // Interval at which to update inverter values / Modbus registers
|
||||||
|
|
|
@ -39,6 +39,38 @@ static int8_t heatertemp = 0;
|
||||||
static int8_t powerRelayTemperature = 0;
|
static int8_t powerRelayTemperature = 0;
|
||||||
static bool startedUp = false;
|
static bool startedUp = false;
|
||||||
|
|
||||||
|
#ifdef DOUBLE_BATTERY
|
||||||
|
static uint16_t battery2_soc_calculated = 0;
|
||||||
|
static uint16_t battery2_SOC_BMS = 0;
|
||||||
|
static uint16_t battery2_SOC_Display = 0;
|
||||||
|
static uint16_t battery2_batterySOH = 1000;
|
||||||
|
static uint16_t battery2_CellVoltMax_mV = 3700;
|
||||||
|
static uint16_t battery2_CellVoltMin_mV = 3700;
|
||||||
|
static uint16_t battery2_allowedDischargePower = 0;
|
||||||
|
static uint16_t battery2_allowedChargePower = 0;
|
||||||
|
static uint16_t battery2_batteryVoltage = 0;
|
||||||
|
static uint16_t battery2_inverterVoltageFrameHigh = 0;
|
||||||
|
static uint16_t battery2_inverterVoltage = 0;
|
||||||
|
static uint16_t battery2_cellvoltages_mv[98];
|
||||||
|
static int16_t battery2_leadAcidBatteryVoltage = 120;
|
||||||
|
static int16_t battery2_batteryAmps = 0;
|
||||||
|
static int16_t battery2_temperatureMax = 0;
|
||||||
|
static int16_t battery2_temperatureMin = 0;
|
||||||
|
static int16_t battery2_poll_data_pid = 0;
|
||||||
|
static bool battery2_holdPidCounter = false;
|
||||||
|
static uint8_t battery2_CellVmaxNo = 0;
|
||||||
|
static uint8_t battery2_CellVminNo = 0;
|
||||||
|
static uint8_t battery2_batteryManagementMode = 0;
|
||||||
|
static uint8_t battery2_BMS_ign = 0;
|
||||||
|
static uint8_t battery2_batteryRelay = 0;
|
||||||
|
static uint8_t battery2_waterleakageSensor = 164;
|
||||||
|
static uint8_t battery2_counter_200 = 0;
|
||||||
|
static int8_t battery2_temperature_water_inlet = 0;
|
||||||
|
static int8_t battery2_heatertemp = 0;
|
||||||
|
static int8_t battery2_powerRelayTemperature = 0;
|
||||||
|
static bool battery2_startedUp = false;
|
||||||
|
#endif //DOUBLE_BATTERY
|
||||||
|
|
||||||
CAN_frame KIA_HYUNDAI_200 = {.FD = false,
|
CAN_frame KIA_HYUNDAI_200 = {.FD = false,
|
||||||
.ext_ID = false,
|
.ext_ID = false,
|
||||||
.DLC = 8,
|
.DLC = 8,
|
||||||
|
@ -495,6 +527,397 @@ void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DOUBLE_BATTERY
|
||||||
|
void update_values_battery2() { // Handle the values coming in from battery #2
|
||||||
|
/* Start with mapping all values */
|
||||||
|
datalayer.battery2.status.real_soc = (battery2_SOC_Display * 10); //increase SOC range from 0-100.0 -> 100.00
|
||||||
|
|
||||||
|
datalayer.battery2.status.soh_pptt = (battery2_batterySOH * 10); //Increase decimals from 100.0% -> 100.00%
|
||||||
|
|
||||||
|
datalayer.battery2.status.voltage_dV = battery2_batteryVoltage; //value is *10 (3700 = 370.0)
|
||||||
|
|
||||||
|
datalayer.battery2.status.current_dA = -battery2_batteryAmps; //value is *10 (150 = 15.0) , invert the sign
|
||||||
|
|
||||||
|
datalayer.battery2.status.remaining_capacity_Wh = static_cast<uint32_t>(
|
||||||
|
(static_cast<double>(datalayer.battery2.status.real_soc) / 10000) * datalayer.battery2.info.total_capacity_Wh);
|
||||||
|
|
||||||
|
datalayer.battery2.status.max_charge_power_W = battery2_allowedChargePower * 10;
|
||||||
|
|
||||||
|
datalayer.battery2.status.max_discharge_power_W = battery2_allowedDischargePower * 10;
|
||||||
|
|
||||||
|
datalayer.battery2.status.temperature_min_dC =
|
||||||
|
(int8_t)battery2_temperatureMin * 10; //Increase decimals, 17C -> 17.0C
|
||||||
|
|
||||||
|
datalayer.battery2.status.temperature_max_dC =
|
||||||
|
(int8_t)battery2_temperatureMax * 10; //Increase decimals, 18C -> 18.0C
|
||||||
|
|
||||||
|
datalayer.battery2.status.cell_max_voltage_mV = battery2_CellVoltMax_mV;
|
||||||
|
|
||||||
|
datalayer.battery2.status.cell_min_voltage_mV = battery2_CellVoltMin_mV;
|
||||||
|
|
||||||
|
if (battery2_waterleakageSensor == 0) {
|
||||||
|
set_event(EVENT_WATER_INGRESS, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (battery2_leadAcidBatteryVoltage < 110) {
|
||||||
|
set_event(EVENT_12V_LOW, leadAcidBatteryVoltage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update webserver datalayer
|
||||||
|
datalayer_extended.KiaHyundai64.battery2_total_cell_count = datalayer.battery2.info.number_of_cells;
|
||||||
|
datalayer_extended.KiaHyundai64.battery2_battery_12V = battery2_leadAcidBatteryVoltage;
|
||||||
|
datalayer_extended.KiaHyundai64.battery2_waterleakageSensor = battery2_waterleakageSensor;
|
||||||
|
datalayer_extended.KiaHyundai64.battery2_temperature_water_inlet = battery2_temperature_water_inlet;
|
||||||
|
datalayer_extended.KiaHyundai64.battery2_powerRelayTemperature = battery2_powerRelayTemperature * 2;
|
||||||
|
datalayer_extended.KiaHyundai64.battery2_batteryManagementMode = battery2_batteryManagementMode;
|
||||||
|
datalayer_extended.KiaHyundai64.battery2_BMS_ign = battery2_BMS_ign;
|
||||||
|
datalayer_extended.KiaHyundai64.battery2_batteryRelay = battery2_batteryRelay;
|
||||||
|
|
||||||
|
//Perform logging if configured to do so
|
||||||
|
#ifdef DEBUG_LOG
|
||||||
|
logging.println(); //sepatator
|
||||||
|
logging.println("Values from battery: ");
|
||||||
|
logging.print("SOC BMS: ");
|
||||||
|
logging.print((uint16_t)battery2_SOC_BMS / 10.0, 1);
|
||||||
|
logging.print("% | SOC Display: ");
|
||||||
|
logging.print((uint16_t)battery2_SOC_Display / 10.0, 1);
|
||||||
|
logging.print("% | SOH ");
|
||||||
|
logging.print((uint16_t)battery2_batterySOH / 10.0, 1);
|
||||||
|
logging.println("%");
|
||||||
|
logging.print((int16_t)battery2_batteryAmps / 10.0, 1);
|
||||||
|
logging.print(" Amps | ");
|
||||||
|
logging.print((uint16_t)battery2_batteryVoltage / 10.0, 1);
|
||||||
|
logging.print(" Volts | ");
|
||||||
|
logging.print((int16_t)datalayer.battery2.status.active_power_W);
|
||||||
|
logging.println(" Watts");
|
||||||
|
logging.print("Allowed Charge ");
|
||||||
|
logging.print((uint16_t)battery2_allowedChargePower * 10);
|
||||||
|
logging.print(" W | Allowed Discharge ");
|
||||||
|
logging.print((uint16_t)battery2_allowedDischargePower * 10);
|
||||||
|
logging.println(" W");
|
||||||
|
logging.print("MaxCellVolt ");
|
||||||
|
logging.print(battery2_CellVoltMax_mV);
|
||||||
|
logging.print(" mV No ");
|
||||||
|
logging.print(battery2_CellVmaxNo);
|
||||||
|
logging.print(" | MinCellVolt ");
|
||||||
|
logging.print(battery2_CellVoltMin_mV);
|
||||||
|
logging.print(" mV No ");
|
||||||
|
logging.println(battery2_CellVminNo);
|
||||||
|
logging.print("TempHi ");
|
||||||
|
logging.print((int16_t)battery2_temperatureMax);
|
||||||
|
logging.print("°C TempLo ");
|
||||||
|
logging.print((int16_t)battery2_temperatureMin);
|
||||||
|
logging.print("°C WaterInlet ");
|
||||||
|
logging.print((int8_t)battery2_temperature_water_inlet);
|
||||||
|
logging.print("°C PowerRelay ");
|
||||||
|
logging.print((int8_t)battery2_powerRelayTemperature * 2);
|
||||||
|
logging.println("°C");
|
||||||
|
logging.print("Aux12volt: ");
|
||||||
|
logging.print((int16_t)battery2_leadAcidBatteryVoltage / 10.0, 1);
|
||||||
|
logging.println("V | ");
|
||||||
|
logging.print("BmsManagementMode ");
|
||||||
|
logging.print((uint8_t)battery2_batteryManagementMode, BIN);
|
||||||
|
if (bitRead((uint8_t)battery2_BMS_ign, 2) == 1) {
|
||||||
|
logging.print(" | BmsIgnition ON");
|
||||||
|
} else {
|
||||||
|
logging.print(" | BmsIgnition OFF");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bitRead((uint8_t)battery2_batteryRelay, 0) == 1) {
|
||||||
|
logging.print(" | PowerRelay ON");
|
||||||
|
} else {
|
||||||
|
logging.print(" | PowerRelay OFF");
|
||||||
|
}
|
||||||
|
logging.print(" | Inverter ");
|
||||||
|
logging.print(battery2_inverterVoltage);
|
||||||
|
logging.println(" Volts");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_number_of_cells_battery2() {
|
||||||
|
//If we have cell values and number_of_cells not initialized yet
|
||||||
|
if (battery2_cellvoltages_mv[0] > 0 && datalayer.battery2.info.number_of_cells == 0) {
|
||||||
|
// Check if we have 98S or 90S battery
|
||||||
|
if (datalayer.battery2.status.cell_voltages_mV[97] > 0) {
|
||||||
|
datalayer.battery2.info.number_of_cells = 98;
|
||||||
|
datalayer.battery2.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_98S_DV;
|
||||||
|
datalayer.battery2.info.min_design_voltage_dV = MIN_PACK_VOLTAGE_98S_DV;
|
||||||
|
datalayer.battery2.info.total_capacity_Wh = 64000;
|
||||||
|
} else {
|
||||||
|
datalayer.battery2.info.number_of_cells = 90;
|
||||||
|
datalayer.battery2.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_90S_DV;
|
||||||
|
datalayer.battery2.info.min_design_voltage_dV = MIN_PACK_VOLTAGE_90S_DV;
|
||||||
|
datalayer.battery2.info.total_capacity_Wh = 40000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_incoming_can_frame_battery2(CAN_frame rx_frame) {
|
||||||
|
switch (rx_frame.ID) {
|
||||||
|
case 0x4DE:
|
||||||
|
battery2_startedUp = true;
|
||||||
|
break;
|
||||||
|
case 0x542: //BMS SOC
|
||||||
|
battery2_startedUp = true;
|
||||||
|
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
|
||||||
|
battery2_SOC_Display = rx_frame.data.u8[0] * 5; //100% = 200 ( 200 * 5 = 1000 )
|
||||||
|
break;
|
||||||
|
case 0x594:
|
||||||
|
battery2_startedUp = true;
|
||||||
|
battery2_allowedChargePower = ((rx_frame.data.u8[1] << 8) | rx_frame.data.u8[0]);
|
||||||
|
battery2_allowedDischargePower = ((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[2]);
|
||||||
|
battery2_SOC_BMS = rx_frame.data.u8[5] * 5; //100% = 200 ( 200 * 5 = 1000 )
|
||||||
|
break;
|
||||||
|
case 0x595:
|
||||||
|
battery2_startedUp = true;
|
||||||
|
battery2_batteryVoltage = (rx_frame.data.u8[7] << 8) + rx_frame.data.u8[6];
|
||||||
|
battery2_batteryAmps = (rx_frame.data.u8[5] << 8) + rx_frame.data.u8[4];
|
||||||
|
if (battery2_counter_200 > 3) {
|
||||||
|
//KIA_HYUNDAI_524.data.u8[0] = (uint8_t)(battery2_batteryVoltage / 10);
|
||||||
|
//KIA_HYUNDAI_524.data.u8[1] = (uint8_t)((battery2_batteryVoltage / 10) >> 8);
|
||||||
|
} //VCU measured voltage sent back to bms (Not required since battery1 writes this)
|
||||||
|
break;
|
||||||
|
case 0x596:
|
||||||
|
battery2_startedUp = true;
|
||||||
|
battery2_leadAcidBatteryVoltage = rx_frame.data.u8[1]; //12v Battery Volts
|
||||||
|
battery2_temperatureMin = rx_frame.data.u8[6]; //Lowest temp in battery
|
||||||
|
battery2_temperatureMax = rx_frame.data.u8[7]; //Highest temp in battery
|
||||||
|
break;
|
||||||
|
case 0x598:
|
||||||
|
battery2_startedUp = true;
|
||||||
|
break;
|
||||||
|
case 0x5D5:
|
||||||
|
battery2_startedUp = true;
|
||||||
|
battery2_waterleakageSensor =
|
||||||
|
rx_frame.data.u8[3]; //Water sensor inside pack, value 164 is no water --> 0 is short
|
||||||
|
battery2_powerRelayTemperature = rx_frame.data.u8[7];
|
||||||
|
break;
|
||||||
|
case 0x5D8:
|
||||||
|
battery2_startedUp = true;
|
||||||
|
|
||||||
|
//PID data is polled after last message sent from battery every other time:
|
||||||
|
if (battery2_holdPidCounter == true) {
|
||||||
|
battery2_holdPidCounter = false;
|
||||||
|
} else {
|
||||||
|
battery2_holdPidCounter = true;
|
||||||
|
if (battery2_poll_data_pid >= 6) { //polling one of six PIDs at 100ms*2, resolution = 1200ms
|
||||||
|
battery2_poll_data_pid = 0;
|
||||||
|
}
|
||||||
|
battery2_poll_data_pid++;
|
||||||
|
if (battery2_poll_data_pid == 1) {
|
||||||
|
transmit_can_frame(&KIA64_7E4_id1, can_config.battery_double);
|
||||||
|
} else if (battery2_poll_data_pid == 2) {
|
||||||
|
transmit_can_frame(&KIA64_7E4_id2, can_config.battery_double);
|
||||||
|
} else if (battery2_poll_data_pid == 3) {
|
||||||
|
transmit_can_frame(&KIA64_7E4_id3, can_config.battery_double);
|
||||||
|
} else if (battery2_poll_data_pid == 4) {
|
||||||
|
transmit_can_frame(&KIA64_7E4_id4, can_config.battery_double);
|
||||||
|
} else if (battery2_poll_data_pid == 5) {
|
||||||
|
transmit_can_frame(&KIA64_7E4_id5, can_config.battery_double);
|
||||||
|
} else if (battery2_poll_data_pid == 6) {
|
||||||
|
transmit_can_frame(&KIA64_7E4_id6, can_config.battery_double);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x7EC: //Data From polled PID group, BigEndian
|
||||||
|
switch (rx_frame.data.u8[0]) {
|
||||||
|
case 0x10: //"PID Header"
|
||||||
|
if (rx_frame.data.u8[4] == battery2_poll_data_pid) {
|
||||||
|
transmit_can_frame(&KIA64_7E4_ack,
|
||||||
|
can_config.battery); //Send ack to BMS if the same frame is sent as polled
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x21: //First frame in PID group
|
||||||
|
if (battery2_poll_data_pid == 1) {
|
||||||
|
battery2_batteryRelay = rx_frame.data.u8[7];
|
||||||
|
} else if (battery2_poll_data_pid == 2) {
|
||||||
|
battery2_cellvoltages_mv[0] = (rx_frame.data.u8[2] * 20);
|
||||||
|
battery2_cellvoltages_mv[1] = (rx_frame.data.u8[3] * 20);
|
||||||
|
battery2_cellvoltages_mv[2] = (rx_frame.data.u8[4] * 20);
|
||||||
|
battery2_cellvoltages_mv[3] = (rx_frame.data.u8[5] * 20);
|
||||||
|
battery2_cellvoltages_mv[4] = (rx_frame.data.u8[6] * 20);
|
||||||
|
battery2_cellvoltages_mv[5] = (rx_frame.data.u8[7] * 20);
|
||||||
|
} else if (battery2_poll_data_pid == 3) {
|
||||||
|
battery2_cellvoltages_mv[32] = (rx_frame.data.u8[2] * 20);
|
||||||
|
battery2_cellvoltages_mv[33] = (rx_frame.data.u8[3] * 20);
|
||||||
|
battery2_cellvoltages_mv[34] = (rx_frame.data.u8[4] * 20);
|
||||||
|
battery2_cellvoltages_mv[35] = (rx_frame.data.u8[5] * 20);
|
||||||
|
battery2_cellvoltages_mv[36] = (rx_frame.data.u8[6] * 20);
|
||||||
|
battery2_cellvoltages_mv[37] = (rx_frame.data.u8[7] * 20);
|
||||||
|
} else if (battery2_poll_data_pid == 4) {
|
||||||
|
battery2_cellvoltages_mv[64] = (rx_frame.data.u8[2] * 20);
|
||||||
|
battery2_cellvoltages_mv[65] = (rx_frame.data.u8[3] * 20);
|
||||||
|
battery2_cellvoltages_mv[66] = (rx_frame.data.u8[4] * 20);
|
||||||
|
battery2_cellvoltages_mv[67] = (rx_frame.data.u8[5] * 20);
|
||||||
|
battery2_cellvoltages_mv[68] = (rx_frame.data.u8[6] * 20);
|
||||||
|
battery2_cellvoltages_mv[69] = (rx_frame.data.u8[7] * 20);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x22: //Second datarow in PID group
|
||||||
|
if (battery2_poll_data_pid == 2) {
|
||||||
|
battery2_cellvoltages_mv[6] = (rx_frame.data.u8[1] * 20);
|
||||||
|
battery2_cellvoltages_mv[7] = (rx_frame.data.u8[2] * 20);
|
||||||
|
battery2_cellvoltages_mv[8] = (rx_frame.data.u8[3] * 20);
|
||||||
|
battery2_cellvoltages_mv[9] = (rx_frame.data.u8[4] * 20);
|
||||||
|
battery2_cellvoltages_mv[10] = (rx_frame.data.u8[5] * 20);
|
||||||
|
battery2_cellvoltages_mv[11] = (rx_frame.data.u8[6] * 20);
|
||||||
|
battery2_cellvoltages_mv[12] = (rx_frame.data.u8[7] * 20);
|
||||||
|
} else if (battery2_poll_data_pid == 3) {
|
||||||
|
battery2_cellvoltages_mv[38] = (rx_frame.data.u8[1] * 20);
|
||||||
|
battery2_cellvoltages_mv[39] = (rx_frame.data.u8[2] * 20);
|
||||||
|
battery2_cellvoltages_mv[40] = (rx_frame.data.u8[3] * 20);
|
||||||
|
battery2_cellvoltages_mv[41] = (rx_frame.data.u8[4] * 20);
|
||||||
|
battery2_cellvoltages_mv[42] = (rx_frame.data.u8[5] * 20);
|
||||||
|
battery2_cellvoltages_mv[43] = (rx_frame.data.u8[6] * 20);
|
||||||
|
battery2_cellvoltages_mv[44] = (rx_frame.data.u8[7] * 20);
|
||||||
|
} else if (battery2_poll_data_pid == 4) {
|
||||||
|
battery2_cellvoltages_mv[70] = (rx_frame.data.u8[1] * 20);
|
||||||
|
battery2_cellvoltages_mv[71] = (rx_frame.data.u8[2] * 20);
|
||||||
|
battery2_cellvoltages_mv[72] = (rx_frame.data.u8[3] * 20);
|
||||||
|
battery2_cellvoltages_mv[73] = (rx_frame.data.u8[4] * 20);
|
||||||
|
battery2_cellvoltages_mv[74] = (rx_frame.data.u8[5] * 20);
|
||||||
|
battery2_cellvoltages_mv[75] = (rx_frame.data.u8[6] * 20);
|
||||||
|
battery2_cellvoltages_mv[76] = (rx_frame.data.u8[7] * 20);
|
||||||
|
} else if (battery2_poll_data_pid == 6) {
|
||||||
|
battery2_batteryManagementMode = rx_frame.data.u8[5];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x23: //Third datarow in PID group
|
||||||
|
if (battery2_poll_data_pid == 1) {
|
||||||
|
battery2_temperature_water_inlet = rx_frame.data.u8[6];
|
||||||
|
battery2_CellVoltMax_mV = (rx_frame.data.u8[7] * 20); //(volts *50) *20 =mV
|
||||||
|
} else if (battery2_poll_data_pid == 2) {
|
||||||
|
battery2_cellvoltages_mv[13] = (rx_frame.data.u8[1] * 20);
|
||||||
|
battery2_cellvoltages_mv[14] = (rx_frame.data.u8[2] * 20);
|
||||||
|
battery2_cellvoltages_mv[15] = (rx_frame.data.u8[3] * 20);
|
||||||
|
battery2_cellvoltages_mv[16] = (rx_frame.data.u8[4] * 20);
|
||||||
|
battery2_cellvoltages_mv[17] = (rx_frame.data.u8[5] * 20);
|
||||||
|
battery2_cellvoltages_mv[18] = (rx_frame.data.u8[6] * 20);
|
||||||
|
battery2_cellvoltages_mv[19] = (rx_frame.data.u8[7] * 20);
|
||||||
|
} else if (battery2_poll_data_pid == 3) {
|
||||||
|
battery2_cellvoltages_mv[45] = (rx_frame.data.u8[1] * 20);
|
||||||
|
battery2_cellvoltages_mv[46] = (rx_frame.data.u8[2] * 20);
|
||||||
|
battery2_cellvoltages_mv[47] = (rx_frame.data.u8[3] * 20);
|
||||||
|
battery2_cellvoltages_mv[48] = (rx_frame.data.u8[4] * 20);
|
||||||
|
battery2_cellvoltages_mv[49] = (rx_frame.data.u8[5] * 20);
|
||||||
|
battery2_cellvoltages_mv[50] = (rx_frame.data.u8[6] * 20);
|
||||||
|
battery2_cellvoltages_mv[51] = (rx_frame.data.u8[7] * 20);
|
||||||
|
} else if (battery2_poll_data_pid == 4) {
|
||||||
|
battery2_cellvoltages_mv[77] = (rx_frame.data.u8[1] * 20);
|
||||||
|
battery2_cellvoltages_mv[78] = (rx_frame.data.u8[2] * 20);
|
||||||
|
battery2_cellvoltages_mv[79] = (rx_frame.data.u8[3] * 20);
|
||||||
|
battery2_cellvoltages_mv[80] = (rx_frame.data.u8[4] * 20);
|
||||||
|
battery2_cellvoltages_mv[81] = (rx_frame.data.u8[5] * 20);
|
||||||
|
battery2_cellvoltages_mv[82] = (rx_frame.data.u8[6] * 20);
|
||||||
|
battery2_cellvoltages_mv[83] = (rx_frame.data.u8[7] * 20);
|
||||||
|
} else if (battery2_poll_data_pid == 5) {
|
||||||
|
battery2_heatertemp = rx_frame.data.u8[7];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x24: //Fourth datarow in PID group
|
||||||
|
if (battery2_poll_data_pid == 1) {
|
||||||
|
battery2_CellVmaxNo = rx_frame.data.u8[1];
|
||||||
|
battery2_CellVminNo = rx_frame.data.u8[3];
|
||||||
|
battery2_CellVoltMin_mV = (rx_frame.data.u8[2] * 20); //(volts *50) *20 =mV
|
||||||
|
} else if (battery2_poll_data_pid == 2) {
|
||||||
|
battery2_cellvoltages_mv[20] = (rx_frame.data.u8[1] * 20);
|
||||||
|
battery2_cellvoltages_mv[21] = (rx_frame.data.u8[2] * 20);
|
||||||
|
battery2_cellvoltages_mv[22] = (rx_frame.data.u8[3] * 20);
|
||||||
|
battery2_cellvoltages_mv[23] = (rx_frame.data.u8[4] * 20);
|
||||||
|
battery2_cellvoltages_mv[24] = (rx_frame.data.u8[5] * 20);
|
||||||
|
battery2_cellvoltages_mv[25] = (rx_frame.data.u8[6] * 20);
|
||||||
|
battery2_cellvoltages_mv[26] = (rx_frame.data.u8[7] * 20);
|
||||||
|
} else if (battery2_poll_data_pid == 3) {
|
||||||
|
battery2_cellvoltages_mv[52] = (rx_frame.data.u8[1] * 20);
|
||||||
|
battery2_cellvoltages_mv[53] = (rx_frame.data.u8[2] * 20);
|
||||||
|
battery2_cellvoltages_mv[54] = (rx_frame.data.u8[3] * 20);
|
||||||
|
battery2_cellvoltages_mv[55] = (rx_frame.data.u8[4] * 20);
|
||||||
|
battery2_cellvoltages_mv[56] = (rx_frame.data.u8[5] * 20);
|
||||||
|
battery2_cellvoltages_mv[57] = (rx_frame.data.u8[6] * 20);
|
||||||
|
battery2_cellvoltages_mv[58] = (rx_frame.data.u8[7] * 20);
|
||||||
|
} else if (battery2_poll_data_pid == 4) {
|
||||||
|
battery2_cellvoltages_mv[84] = (rx_frame.data.u8[1] * 20);
|
||||||
|
battery2_cellvoltages_mv[85] = (rx_frame.data.u8[2] * 20);
|
||||||
|
battery2_cellvoltages_mv[86] = (rx_frame.data.u8[3] * 20);
|
||||||
|
battery2_cellvoltages_mv[87] = (rx_frame.data.u8[4] * 20);
|
||||||
|
battery2_cellvoltages_mv[88] = (rx_frame.data.u8[5] * 20);
|
||||||
|
battery2_cellvoltages_mv[89] = (rx_frame.data.u8[6] * 20);
|
||||||
|
if (rx_frame.data.u8[7] > 4) { // Data only valid on 98S
|
||||||
|
battery2_cellvoltages_mv[90] = (rx_frame.data.u8[7] * 20); // Perform extra checks
|
||||||
|
}
|
||||||
|
} else if (battery2_poll_data_pid == 5) {
|
||||||
|
battery2_batterySOH = ((rx_frame.data.u8[2] << 8) + rx_frame.data.u8[3]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x25: //Fifth datarow in PID group
|
||||||
|
if (battery2_poll_data_pid == 2) {
|
||||||
|
battery2_cellvoltages_mv[27] = (rx_frame.data.u8[1] * 20);
|
||||||
|
battery2_cellvoltages_mv[28] = (rx_frame.data.u8[2] * 20);
|
||||||
|
battery2_cellvoltages_mv[29] = (rx_frame.data.u8[3] * 20);
|
||||||
|
battery2_cellvoltages_mv[30] = (rx_frame.data.u8[4] * 20);
|
||||||
|
battery2_cellvoltages_mv[31] = (rx_frame.data.u8[5] * 20);
|
||||||
|
} else if (battery2_poll_data_pid == 3) {
|
||||||
|
battery2_cellvoltages_mv[59] = (rx_frame.data.u8[1] * 20);
|
||||||
|
battery2_cellvoltages_mv[60] = (rx_frame.data.u8[2] * 20);
|
||||||
|
battery2_cellvoltages_mv[61] = (rx_frame.data.u8[3] * 20);
|
||||||
|
battery2_cellvoltages_mv[62] = (rx_frame.data.u8[4] * 20);
|
||||||
|
battery2_cellvoltages_mv[63] = (rx_frame.data.u8[5] * 20);
|
||||||
|
} else if (battery2_poll_data_pid == 4) { // Data only valid on 98S
|
||||||
|
if (rx_frame.data.u8[1] > 4) { // Perform extra checks
|
||||||
|
battery2_cellvoltages_mv[91] = (rx_frame.data.u8[1] * 20);
|
||||||
|
}
|
||||||
|
if (rx_frame.data.u8[2] > 4) { // Perform extra checks
|
||||||
|
battery2_cellvoltages_mv[92] = (rx_frame.data.u8[2] * 20);
|
||||||
|
}
|
||||||
|
if (rx_frame.data.u8[3] > 4) { // Perform extra checks
|
||||||
|
battery2_cellvoltages_mv[93] = (rx_frame.data.u8[3] * 20);
|
||||||
|
}
|
||||||
|
if (rx_frame.data.u8[4] > 4) { // Perform extra checks
|
||||||
|
battery2_cellvoltages_mv[94] = (rx_frame.data.u8[4] * 20);
|
||||||
|
}
|
||||||
|
if (rx_frame.data.u8[5] > 4) { // Perform extra checks
|
||||||
|
battery2_cellvoltages_mv[95] = (rx_frame.data.u8[5] * 20);
|
||||||
|
}
|
||||||
|
} else if (battery2_poll_data_pid == 5) { // Data only valid on 98S
|
||||||
|
if (rx_frame.data.u8[4] > 4) { // Perform extra checks
|
||||||
|
battery2_cellvoltages_mv[96] = (rx_frame.data.u8[4] * 20);
|
||||||
|
}
|
||||||
|
if (rx_frame.data.u8[5] > 4) { // Perform extra checks
|
||||||
|
battery2_cellvoltages_mv[97] = (rx_frame.data.u8[5] * 20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x26: //Sixth datarow in PID group
|
||||||
|
//We have read all cells, check that content is valid:
|
||||||
|
for (uint8_t i = 85; i < 97; ++i) {
|
||||||
|
if (battery2_cellvoltages_mv[i] < 300) { // Zero the value if it's below 300
|
||||||
|
battery2_cellvoltages_mv[i] = 0; // Some packs incorrectly report the last unpopulated cells as 20-60mV
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Map all cell voltages to the global array
|
||||||
|
memcpy(datalayer.battery2.status.cell_voltages_mV, battery2_cellvoltages_mv, 98 * sizeof(uint16_t));
|
||||||
|
//Update number of cells
|
||||||
|
update_number_of_cells_battery2();
|
||||||
|
break;
|
||||||
|
case 0x27: //Seventh datarow in PID group
|
||||||
|
if (battery2_poll_data_pid == 1) {
|
||||||
|
battery2_BMS_ign = rx_frame.data.u8[6];
|
||||||
|
battery2_inverterVoltageFrameHigh = rx_frame.data.u8[7];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x28: //Eighth datarow in PID group
|
||||||
|
if (battery2_poll_data_pid == 1) {
|
||||||
|
battery2_inverterVoltage = (battery2_inverterVoltageFrameHigh << 8) + rx_frame.data.u8[1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif //DOUBLE_BATTERY
|
||||||
|
|
||||||
void transmit_can_battery() {
|
void transmit_can_battery() {
|
||||||
unsigned long currentMillis = millis();
|
unsigned long currentMillis = millis();
|
||||||
|
|
||||||
|
@ -509,6 +932,13 @@ void transmit_can_battery() {
|
||||||
transmit_can_frame(&KIA64_553, can_config.battery);
|
transmit_can_frame(&KIA64_553, can_config.battery);
|
||||||
transmit_can_frame(&KIA64_57F, can_config.battery);
|
transmit_can_frame(&KIA64_57F, can_config.battery);
|
||||||
transmit_can_frame(&KIA64_2A1, can_config.battery);
|
transmit_can_frame(&KIA64_2A1, can_config.battery);
|
||||||
|
#ifdef DOUBLE_BATTERY
|
||||||
|
if (battery2_startedUp && datalayer.system.status.battery2_allows_contactor_closing) {
|
||||||
|
transmit_can_frame(&KIA64_553, can_config.battery_double);
|
||||||
|
transmit_can_frame(&KIA64_57F, can_config.battery_double);
|
||||||
|
transmit_can_frame(&KIA64_2A1, can_config.battery_double);
|
||||||
|
}
|
||||||
|
#endif // DOUBLE_BATTERY
|
||||||
}
|
}
|
||||||
// Send 10ms CAN Message
|
// Send 10ms CAN Message
|
||||||
if (currentMillis - previousMillis10 >= INTERVAL_10_MS) {
|
if (currentMillis - previousMillis10 >= INTERVAL_10_MS) {
|
||||||
|
@ -565,6 +995,16 @@ void transmit_can_battery() {
|
||||||
transmit_can_frame(&KIA_HYUNDAI_523, can_config.battery);
|
transmit_can_frame(&KIA_HYUNDAI_523, can_config.battery);
|
||||||
|
|
||||||
transmit_can_frame(&KIA_HYUNDAI_524, can_config.battery);
|
transmit_can_frame(&KIA_HYUNDAI_524, can_config.battery);
|
||||||
|
|
||||||
|
#ifdef DOUBLE_BATTERY
|
||||||
|
if (battery2_startedUp && datalayer.system.status.battery2_allows_contactor_closing) {
|
||||||
|
transmit_can_frame(&KIA_HYUNDAI_200, can_config.battery_double);
|
||||||
|
|
||||||
|
transmit_can_frame(&KIA_HYUNDAI_523, can_config.battery_double);
|
||||||
|
|
||||||
|
transmit_can_frame(&KIA_HYUNDAI_524, can_config.battery_double);
|
||||||
|
}
|
||||||
|
#endif // DOUBLE_BATTERY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -575,6 +1015,15 @@ void setup_battery(void) { // Performs one time setup at startup
|
||||||
datalayer.battery.info.min_design_voltage_dV = MIN_PACK_VOLTAGE_90S_DV; //Start with 90S value. Precised later
|
datalayer.battery.info.min_design_voltage_dV = MIN_PACK_VOLTAGE_90S_DV; //Start with 90S value. Precised later
|
||||||
datalayer.battery.info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV;
|
datalayer.battery.info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV;
|
||||||
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV;
|
||||||
|
datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV;
|
||||||
|
|
||||||
|
#ifdef DOUBLE_BATTERY
|
||||||
|
datalayer.battery2.info.max_design_voltage_dV = datalayer.battery.info.max_design_voltage_dV;
|
||||||
|
datalayer.battery2.info.min_design_voltage_dV = datalayer.battery.info.min_design_voltage_dV;
|
||||||
|
datalayer.battery2.info.max_cell_voltage_mV = datalayer.battery.info.max_cell_voltage_mV;
|
||||||
|
datalayer.battery2.info.min_cell_voltage_mV = datalayer.battery.info.min_cell_voltage_mV;
|
||||||
|
datalayer.battery2.info.max_cell_voltage_deviation_mV = datalayer.battery.info.max_cell_voltage_deviation_mV;
|
||||||
|
#endif //DOUBLE_BATTERY
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -237,6 +237,11 @@ void update_values_battery() { /* This function maps all the values fetched via
|
||||||
|
|
||||||
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
|
||||||
|
if (battery_can_alive) {
|
||||||
|
datalayer.system.status.battery_allows_contactor_closing = true;
|
||||||
|
}
|
||||||
|
|
||||||
/*Extra safety functions below*/
|
/*Extra safety functions below*/
|
||||||
if (battery_GIDS < 10) //700Wh left in battery!
|
if (battery_GIDS < 10) //700Wh left in battery!
|
||||||
{ //Battery is running abnormally low, some discharge logic might have failed. Zero it all out.
|
{ //Battery is running abnormally low, some discharge logic might have failed. Zero it all out.
|
||||||
|
@ -766,11 +771,6 @@ void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||||
battery_Relay_Cut_Request = ((rx_frame.data.u8[1] & 0x18) >> 3);
|
battery_Relay_Cut_Request = ((rx_frame.data.u8[1] & 0x18) >> 3);
|
||||||
battery_Failsafe_Status = (rx_frame.data.u8[1] & 0x07);
|
battery_Failsafe_Status = (rx_frame.data.u8[1] & 0x07);
|
||||||
battery_MainRelayOn_flag = (bool)((rx_frame.data.u8[3] & 0x20) >> 5);
|
battery_MainRelayOn_flag = (bool)((rx_frame.data.u8[3] & 0x20) >> 5);
|
||||||
if (battery_MainRelayOn_flag) {
|
|
||||||
datalayer.system.status.battery_allows_contactor_closing = true;
|
|
||||||
} else {
|
|
||||||
datalayer.system.status.battery_allows_contactor_closing = false;
|
|
||||||
}
|
|
||||||
battery_Full_CHARGE_flag = (bool)((rx_frame.data.u8[3] & 0x10) >> 4);
|
battery_Full_CHARGE_flag = (bool)((rx_frame.data.u8[3] & 0x10) >> 4);
|
||||||
battery_Interlock = (bool)((rx_frame.data.u8[3] & 0x08) >> 3);
|
battery_Interlock = (bool)((rx_frame.data.u8[3] & 0x08) >> 3);
|
||||||
break;
|
break;
|
||||||
|
@ -1064,9 +1064,19 @@ void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void transmit_can_battery() {
|
void transmit_can_battery() {
|
||||||
if (battery_can_alive) {
|
|
||||||
|
|
||||||
unsigned long currentMillis = millis();
|
unsigned long currentMillis = millis();
|
||||||
|
|
||||||
|
if (datalayer.system.status.BMS_reset_in_progress) {
|
||||||
|
// Transmitting towards battery is halted while BMS is being reset
|
||||||
|
// Reset sending counters to avoid overrun messages when reset is over
|
||||||
|
previousMillis10 = currentMillis;
|
||||||
|
previousMillis100 = currentMillis;
|
||||||
|
previousMillis10s = currentMillis;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (battery_can_alive) {
|
||||||
|
|
||||||
//Send 10ms message
|
//Send 10ms message
|
||||||
if (currentMillis - previousMillis10 >= INTERVAL_10_MS) {
|
if (currentMillis - previousMillis10 >= INTERVAL_10_MS) {
|
||||||
|
@ -1499,7 +1509,6 @@ void decodeChallengeData(unsigned int incomingChallenge, unsigned char* solvedCh
|
||||||
void setup_battery(void) { // Performs one time setup at startup
|
void setup_battery(void) { // Performs one time setup at startup
|
||||||
strncpy(datalayer.system.info.battery_protocol, "Nissan LEAF battery", 63);
|
strncpy(datalayer.system.info.battery_protocol, "Nissan LEAF battery", 63);
|
||||||
datalayer.system.info.battery_protocol[63] = '\0';
|
datalayer.system.info.battery_protocol[63] = '\0';
|
||||||
|
|
||||||
datalayer.battery.info.number_of_cells = 96;
|
datalayer.battery.info.number_of_cells = 96;
|
||||||
datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_DV;
|
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.min_design_voltage_dV = MIN_PACK_VOLTAGE_DV;
|
||||||
|
|
|
@ -105,8 +105,9 @@ void init_CAN() {
|
||||||
// Transmit functions
|
// Transmit functions
|
||||||
void transmit_can() {
|
void transmit_can() {
|
||||||
if (!allowed_to_send_CAN) {
|
if (!allowed_to_send_CAN) {
|
||||||
return;
|
return; //Global block of CAN messages
|
||||||
}
|
}
|
||||||
|
|
||||||
transmit_can_battery();
|
transmit_can_battery();
|
||||||
|
|
||||||
#ifdef CAN_INVERTER_SELECTED
|
#ifdef CAN_INVERTER_SELECTED
|
||||||
|
|
|
@ -43,7 +43,6 @@ unsigned long currentTime = 0;
|
||||||
unsigned long lastPowerRemovalTime = 0;
|
unsigned long lastPowerRemovalTime = 0;
|
||||||
const unsigned long powerRemovalInterval = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
|
const unsigned long powerRemovalInterval = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
|
||||||
const unsigned long powerRemovalDuration = 30000; // 30 seconds in milliseconds
|
const unsigned long powerRemovalDuration = 30000; // 30 seconds in milliseconds
|
||||||
bool isBMSResetActive = false;
|
|
||||||
|
|
||||||
void set(uint8_t pin, bool direction, uint32_t pwm_freq = 0xFFFF) {
|
void set(uint8_t pin, bool direction, uint32_t pwm_freq = 0xFFFF) {
|
||||||
#ifdef PWM_CONTACTOR_CONTROL
|
#ifdef PWM_CONTACTOR_CONTROL
|
||||||
|
@ -256,48 +255,38 @@ void handle_BMSpower() {
|
||||||
#endif //PERIODIC_BMS_RESET
|
#endif //PERIODIC_BMS_RESET
|
||||||
|
|
||||||
// If power has been removed for 30 seconds, restore the power and resume the emulator
|
// If power has been removed for 30 seconds, restore the power and resume the emulator
|
||||||
if (isBMSResetActive && currentTime - lastPowerRemovalTime >= powerRemovalDuration) {
|
if (datalayer.system.status.BMS_reset_in_progress && currentTime - lastPowerRemovalTime >= powerRemovalDuration) {
|
||||||
// Reapply power to the BMS
|
|
||||||
digitalWrite(BMS_POWER, HIGH);
|
|
||||||
|
|
||||||
//Resume the battery pause and CAN communication
|
|
||||||
setBatteryPause(false, false, false, false);
|
|
||||||
|
|
||||||
isBMSResetActive = false; // Reset the power removal flag
|
|
||||||
}
|
|
||||||
#endif //defined(PERIODIC_BMS_RESET) || defined(REMOTE_BMS_RESET)
|
|
||||||
}
|
|
||||||
|
|
||||||
void start_bms_reset() {
|
|
||||||
#if defined(PERIODIC_BMS_RESET) || defined(REMOTE_BMS_RESET)
|
|
||||||
if (!isBMSResetActive) {
|
|
||||||
lastPowerRemovalTime = currentTime; // Record the time when BMS reset was started
|
|
||||||
|
|
||||||
// Set emulator state to paused (Max Charge/Discharge = 0 & CAN = stop)
|
|
||||||
// TODO: We try to keep contactors engaged during this pause, and just ramp power down to 0.
|
|
||||||
// If this turns out to not work properly, set also the third option to true to open contactors
|
|
||||||
setBatteryPause(true, true, false, false);
|
|
||||||
|
|
||||||
digitalWrite(BMS_POWER, LOW); // Remove power by setting the BMS power pin to LOW
|
|
||||||
#ifdef BMS_2_POWER
|
|
||||||
digitalWrite(BMS_2_POWER, LOW); // Same for battery 2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
isBMSResetActive = true; // Set a flag to indicate power removal is active
|
|
||||||
}
|
|
||||||
|
|
||||||
// If power has been removed for 30 seconds, restore the power and resume the emulator
|
|
||||||
if (isBMSResetActive && currentTime - lastPowerRemovalTime >= powerRemovalDuration) {
|
|
||||||
// Reapply power to the BMS
|
// Reapply power to the BMS
|
||||||
digitalWrite(BMS_POWER, HIGH);
|
digitalWrite(BMS_POWER, HIGH);
|
||||||
#ifdef BMS_2_POWER
|
#ifdef BMS_2_POWER
|
||||||
digitalWrite(BMS_2_POWER, HIGH); // Same for battery 2
|
digitalWrite(BMS_2_POWER, HIGH); // Same for battery 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//Resume the battery pause and CAN communication
|
//Resume from the power pause
|
||||||
setBatteryPause(false, false, false, false);
|
setBatteryPause(false, false, false, false);
|
||||||
|
|
||||||
isBMSResetActive = false; // Reset the power removal flag
|
datalayer.system.status.BMS_reset_in_progress = false; // Reset the power removal flag
|
||||||
}
|
}
|
||||||
#endif //PERIODIC_BMS_RESET
|
#endif //defined(PERIODIC_BMS_RESET) || defined(REMOTE_BMS_RESET)
|
||||||
|
}
|
||||||
|
|
||||||
|
void start_bms_reset() {
|
||||||
|
#if defined(PERIODIC_BMS_RESET) || defined(REMOTE_BMS_RESET)
|
||||||
|
if (!datalayer.system.status.BMS_reset_in_progress) {
|
||||||
|
lastPowerRemovalTime = currentTime; // Record the time when BMS reset was started
|
||||||
|
|
||||||
|
// Set a flag to let the rest of the system know we are cutting power to the BMS.
|
||||||
|
// The battery CAN sending routine will then know not to try to send anything towards battery while active
|
||||||
|
datalayer.system.status.BMS_reset_in_progress = true;
|
||||||
|
|
||||||
|
// Set emulator state to paused (Max Charge/Discharge = 0 & CAN = stop)
|
||||||
|
// We try to keep contactors engaged during this pause, and just ramp power down to 0.
|
||||||
|
setBatteryPause(true, false, false, false);
|
||||||
|
|
||||||
|
digitalWrite(BMS_POWER, LOW); // Remove power by setting the BMS power pin to LOW
|
||||||
|
#ifdef BMS_2_POWER
|
||||||
|
digitalWrite(BMS_2_POWER, LOW); // Same for battery 2
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif //defined(PERIODIC_BMS_RESET) || defined(REMOTE_BMS_RESET)
|
||||||
}
|
}
|
||||||
|
|
|
@ -272,6 +272,8 @@ typedef struct {
|
||||||
/** True if the contactor controlled by battery-emulator is closed. Determined by check_interconnect_available(); if voltage is OK */
|
/** True if the contactor controlled by battery-emulator is closed. Determined by check_interconnect_available(); if voltage is OK */
|
||||||
bool contactors_battery2_engaged = false;
|
bool contactors_battery2_engaged = false;
|
||||||
#endif
|
#endif
|
||||||
|
/** True if the BMS is being reset, by cutting power towards it */
|
||||||
|
bool BMS_reset_in_progress = false;
|
||||||
} DATALAYER_SYSTEM_STATUS_TYPE;
|
} DATALAYER_SYSTEM_STATUS_TYPE;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -259,6 +259,16 @@ typedef struct {
|
||||||
uint8_t batteryManagementMode = 0;
|
uint8_t batteryManagementMode = 0;
|
||||||
uint8_t BMS_ign = 0;
|
uint8_t BMS_ign = 0;
|
||||||
uint8_t batteryRelay = 0;
|
uint8_t batteryRelay = 0;
|
||||||
|
#ifdef DOUBLE_BATTERY
|
||||||
|
uint8_t battery2_total_cell_count = 0;
|
||||||
|
int16_t battery2_battery_12V = 0;
|
||||||
|
uint8_t battery2_waterleakageSensor = 0;
|
||||||
|
int8_t battery2_temperature_water_inlet = 0;
|
||||||
|
int8_t battery2_powerRelayTemperature = 0;
|
||||||
|
uint8_t battery2_batteryManagementMode = 0;
|
||||||
|
uint8_t battery2_BMS_ign = 0;
|
||||||
|
uint8_t battery2_batteryRelay = 0;
|
||||||
|
#endif //DOUBLE BATTERY
|
||||||
} DATALAYER_INFO_KIAHYUNDAI64;
|
} DATALAYER_INFO_KIAHYUNDAI64;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -237,7 +237,7 @@ void update_machineryprotection() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (soh_diff_pptt > MAX_SOH_DEVIATION_PPTT) {
|
if (soh_diff_pptt > MAX_SOH_DEVIATION_PPTT) {
|
||||||
set_event(EVENT_SOH_DIFFERENCE, MAX_SOH_DEVIATION_PPTT);
|
set_event(EVENT_SOH_DIFFERENCE, (uint8_t)(MAX_SOH_DEVIATION_PPTT / 100));
|
||||||
} else {
|
} else {
|
||||||
clear_event(EVENT_SOH_DIFFERENCE);
|
clear_event(EVENT_SOH_DIFFERENCE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -443,6 +443,22 @@ String advanced_battery_processor(const String& var) {
|
||||||
content += "<h4>Batterymanagement mode: " + String(datalayer_extended.KiaHyundai64.batteryManagementMode) + "</h4>";
|
content += "<h4>Batterymanagement mode: " + String(datalayer_extended.KiaHyundai64.batteryManagementMode) + "</h4>";
|
||||||
content += "<h4>BMS ignition: " + String(datalayer_extended.KiaHyundai64.BMS_ign) + "</h4>";
|
content += "<h4>BMS ignition: " + String(datalayer_extended.KiaHyundai64.BMS_ign) + "</h4>";
|
||||||
content += "<h4>Battery relay: " + String(datalayer_extended.KiaHyundai64.batteryRelay) + "</h4>";
|
content += "<h4>Battery relay: " + String(datalayer_extended.KiaHyundai64.batteryRelay) + "</h4>";
|
||||||
|
#ifdef DOUBLE_BATTERY
|
||||||
|
content += "<h4>Values from battery 2</h4>";
|
||||||
|
content += "<h4>Cells: " + String(datalayer_extended.KiaHyundai64.battery2_total_cell_count) + "S</h4>";
|
||||||
|
content += "<h4>12V voltage: " + String(datalayer_extended.KiaHyundai64.battery2_battery_12V / 10.0, 1) + "</h4>";
|
||||||
|
content += "<h4>Waterleakage: " + String(datalayer_extended.KiaHyundai64.battery2_waterleakageSensor) + "</h4>";
|
||||||
|
content +=
|
||||||
|
"<h4>Temperature, water inlet: " + String(datalayer_extended.KiaHyundai64.battery2_temperature_water_inlet) +
|
||||||
|
"</h4>";
|
||||||
|
content +=
|
||||||
|
"<h4>Temperature, power relay: " + String(datalayer_extended.KiaHyundai64.battery2_powerRelayTemperature) +
|
||||||
|
"</h4>";
|
||||||
|
content += "<h4>Batterymanagement mode: " + String(datalayer_extended.KiaHyundai64.battery2_batteryManagementMode) +
|
||||||
|
"</h4>";
|
||||||
|
content += "<h4>BMS ignition: " + String(datalayer_extended.KiaHyundai64.battery2_BMS_ign) + "</h4>";
|
||||||
|
content += "<h4>Battery relay: " + String(datalayer_extended.KiaHyundai64.battery2_batteryRelay) + "</h4>";
|
||||||
|
#endif //DOUBLE_BATTERY
|
||||||
#endif //KIA_HYUNDAI_64_BATTERY
|
#endif //KIA_HYUNDAI_64_BATTERY
|
||||||
|
|
||||||
#ifdef BYD_ATTO_3_BATTERY
|
#ifdef BYD_ATTO_3_BATTERY
|
||||||
|
|
|
@ -37,26 +37,26 @@ void init_webserver() {
|
||||||
server.on("/GetFirmwareInfo", HTTP_GET, [](AsyncWebServerRequest* request) {
|
server.on("/GetFirmwareInfo", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
||||||
return request->requestAuthentication();
|
return request->requestAuthentication();
|
||||||
request->send_P(200, "application/json", get_firmware_info_html, get_firmware_info_processor);
|
request->send(200, "application/json", get_firmware_info_html, get_firmware_info_processor);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for root / web page
|
// Route for root / web page
|
||||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) {
|
server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
||||||
return request->requestAuthentication();
|
return request->requestAuthentication();
|
||||||
request->send_P(200, "text/html", index_html, processor);
|
request->send(200, "text/html", index_html, processor);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for going to settings web page
|
// Route for going to settings web page
|
||||||
server.on("/settings", HTTP_GET, [](AsyncWebServerRequest* request) {
|
server.on("/settings", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
||||||
return request->requestAuthentication();
|
return request->requestAuthentication();
|
||||||
request->send_P(200, "text/html", index_html, settings_processor);
|
request->send(200, "text/html", index_html, settings_processor);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for going to advanced battery info web page
|
// Route for going to advanced battery info web page
|
||||||
server.on("/advanced", HTTP_GET, [](AsyncWebServerRequest* request) {
|
server.on("/advanced", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
request->send_P(200, "text/html", index_html, advanced_battery_processor);
|
request->send(200, "text/html", index_html, advanced_battery_processor);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for going to CAN logging web page
|
// Route for going to CAN logging web page
|
||||||
|
@ -76,7 +76,7 @@ void init_webserver() {
|
||||||
// Define the handler to stop can logging
|
// Define the handler to stop can logging
|
||||||
server.on("/stop_can_logging", HTTP_GET, [](AsyncWebServerRequest* request) {
|
server.on("/stop_can_logging", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
datalayer.system.info.can_logging_active = false;
|
datalayer.system.info.can_logging_active = false;
|
||||||
request->send_P(200, "text/plain", "Logging stopped");
|
request->send(200, "text/plain", "Logging stopped");
|
||||||
});
|
});
|
||||||
|
|
||||||
#ifndef LOG_CAN_TO_SD
|
#ifndef LOG_CAN_TO_SD
|
||||||
|
@ -119,7 +119,7 @@ void init_webserver() {
|
||||||
// Define the handler to delete can log
|
// Define the handler to delete can log
|
||||||
server.on("/delete_can_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
server.on("/delete_can_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
delete_can_log();
|
delete_can_log();
|
||||||
request->send_P(200, "text/plain", "Log file deleted");
|
request->send(200, "text/plain", "Log file deleted");
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ void init_webserver() {
|
||||||
// Define the handler to delete log file
|
// Define the handler to delete log file
|
||||||
server.on("/delete_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
server.on("/delete_log", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
delete_log();
|
delete_log();
|
||||||
request->send_P(200, "text/plain", "Log file deleted");
|
request->send(200, "text/plain", "Log file deleted");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Define the handler to export debug log
|
// Define the handler to export debug log
|
||||||
|
@ -171,14 +171,14 @@ void init_webserver() {
|
||||||
server.on("/cellmonitor", HTTP_GET, [](AsyncWebServerRequest* request) {
|
server.on("/cellmonitor", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
||||||
return request->requestAuthentication();
|
return request->requestAuthentication();
|
||||||
request->send_P(200, "text/html", index_html, cellmonitor_processor);
|
request->send(200, "text/html", index_html, cellmonitor_processor);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for going to event log web page
|
// Route for going to event log web page
|
||||||
server.on("/events", HTTP_GET, [](AsyncWebServerRequest* request) {
|
server.on("/events", HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
||||||
return request->requestAuthentication();
|
return request->requestAuthentication();
|
||||||
request->send_P(200, "text/html", index_html, events_processor);
|
request->send(200, "text/html", index_html, events_processor);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for clearing all events
|
// Route for clearing all events
|
||||||
|
|
|
@ -108,7 +108,7 @@ void wifi_monitor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to force a full reconnect to Wi-Fi
|
// Function to force a full reconnect to Wi-Fi
|
||||||
static void FullReconnectToWiFi() {
|
void FullReconnectToWiFi() {
|
||||||
|
|
||||||
// Increase the current reconnect interval if it's not at the maximum
|
// Increase the current reconnect interval if it's not at the maximum
|
||||||
if (current_full_reconnect_interval + STEP_WIFI_FULL_RECONNECT_INTERVAL <= MAX_WIFI_FULL_RECONNECT_INTERVAL) {
|
if (current_full_reconnect_interval + STEP_WIFI_FULL_RECONNECT_INTERVAL <= MAX_WIFI_FULL_RECONNECT_INTERVAL) {
|
||||||
|
@ -120,7 +120,7 @@ static void FullReconnectToWiFi() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to handle Wi-Fi connection
|
// Function to handle Wi-Fi connection
|
||||||
static void connectToWiFi() {
|
void connectToWiFi() {
|
||||||
if (WiFi.status() != WL_CONNECTED) {
|
if (WiFi.status() != WL_CONNECTED) {
|
||||||
lastReconnectAttempt = millis(); // Reset the reconnect attempt timer
|
lastReconnectAttempt = millis(); // Reset the reconnect attempt timer
|
||||||
#ifdef DEBUG_LOG
|
#ifdef DEBUG_LOG
|
||||||
|
@ -135,7 +135,7 @@ static void connectToWiFi() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event handler for successful Wi-Fi connection
|
// Event handler for successful Wi-Fi connection
|
||||||
static void onWifiConnect(WiFiEvent_t event, WiFiEventInfo_t info) {
|
void onWifiConnect(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||||
clear_event(EVENT_WIFI_DISCONNECT);
|
clear_event(EVENT_WIFI_DISCONNECT);
|
||||||
set_event(EVENT_WIFI_CONNECT, 0);
|
set_event(EVENT_WIFI_CONNECT, 0);
|
||||||
connected_once = true;
|
connected_once = true;
|
||||||
|
@ -153,7 +153,7 @@ static void onWifiConnect(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event handler for Wi-Fi Got IP
|
// Event handler for Wi-Fi Got IP
|
||||||
static void onWifiGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
|
void onWifiGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||||
//clear disconnects events if we got a IP
|
//clear disconnects events if we got a IP
|
||||||
clear_event(EVENT_WIFI_DISCONNECT);
|
clear_event(EVENT_WIFI_DISCONNECT);
|
||||||
#ifdef DEBUG_LOG
|
#ifdef DEBUG_LOG
|
||||||
|
@ -164,7 +164,7 @@ static void onWifiGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event handler for Wi-Fi disconnection
|
// Event handler for Wi-Fi disconnection
|
||||||
static void onWifiDisconnect(WiFiEvent_t event, WiFiEventInfo_t info) {
|
void onWifiDisconnect(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||||
if (connected_once)
|
if (connected_once)
|
||||||
set_event(EVENT_WIFI_DISCONNECT, 0);
|
set_event(EVENT_WIFI_DISCONNECT, 0);
|
||||||
#ifdef DEBUG_LOG
|
#ifdef DEBUG_LOG
|
||||||
|
|
|
@ -17,11 +17,11 @@ extern const char* passwordAP;
|
||||||
|
|
||||||
void init_WiFi();
|
void init_WiFi();
|
||||||
void wifi_monitor();
|
void wifi_monitor();
|
||||||
static void connectToWiFi();
|
void connectToWiFi();
|
||||||
static void FullReconnectToWiFi();
|
void FullReconnectToWiFi();
|
||||||
static void onWifiConnect(WiFiEvent_t event, WiFiEventInfo_t info);
|
void onWifiConnect(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||||
static void onWifiDisconnect(WiFiEvent_t event, WiFiEventInfo_t info);
|
void onWifiDisconnect(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||||
static void onWifiGotIP(WiFiEvent_t event, WiFiEventInfo_t info);
|
void onWifiGotIP(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||||
|
|
||||||
#ifdef WIFIAP
|
#ifdef WIFIAP
|
||||||
void init_WiFi_AP();
|
void init_WiFi_AP();
|
||||||
|
|
|
@ -155,8 +155,8 @@ void update_values_can_inverter() { //This function maps all the values fetched
|
||||||
SOLAX_1874.data.u8[1] = (datalayer.battery.status.temperature_max_dC >> 8);
|
SOLAX_1874.data.u8[1] = (datalayer.battery.status.temperature_max_dC >> 8);
|
||||||
SOLAX_1874.data.u8[2] = (int8_t)datalayer.battery.status.temperature_min_dC;
|
SOLAX_1874.data.u8[2] = (int8_t)datalayer.battery.status.temperature_min_dC;
|
||||||
SOLAX_1874.data.u8[3] = (datalayer.battery.status.temperature_min_dC >> 8);
|
SOLAX_1874.data.u8[3] = (datalayer.battery.status.temperature_min_dC >> 8);
|
||||||
SOLAX_1874.data.u8[4] = (uint8_t)(datalayer.battery.status.cell_max_voltage_mV);
|
SOLAX_1874.data.u8[4] = (uint8_t)(datalayer.battery.info.max_cell_voltage_mV);
|
||||||
SOLAX_1874.data.u8[5] = (datalayer.battery.status.cell_max_voltage_mV >> 8);
|
SOLAX_1874.data.u8[5] = (datalayer.battery.info.max_cell_voltage_mV >> 8);
|
||||||
SOLAX_1874.data.u8[6] = (uint8_t)(datalayer.battery.status.cell_min_voltage_mV);
|
SOLAX_1874.data.u8[6] = (uint8_t)(datalayer.battery.status.cell_min_voltage_mV);
|
||||||
SOLAX_1874.data.u8[7] = (datalayer.battery.status.cell_min_voltage_mV >> 8);
|
SOLAX_1874.data.u8[7] = (datalayer.battery.status.cell_min_voltage_mV >> 8);
|
||||||
|
|
||||||
|
@ -167,9 +167,13 @@ void update_values_can_inverter() { //This function maps all the values fetched
|
||||||
SOLAX_1875.data.u8[4] = (uint8_t)0; // Contactor Status 0=off, 1=on.
|
SOLAX_1875.data.u8[4] = (uint8_t)0; // Contactor Status 0=off, 1=on.
|
||||||
|
|
||||||
//BMS_PackTemps (strange name, since it has voltages?)
|
//BMS_PackTemps (strange name, since it has voltages?)
|
||||||
|
SOLAX_1876.data.u8[0] = (int8_t)datalayer.battery.status.temperature_max_dC;
|
||||||
|
SOLAX_1876.data.u8[1] = (datalayer.battery.status.temperature_max_dC >> 8);
|
||||||
SOLAX_1876.data.u8[2] = (uint8_t)datalayer.battery.status.cell_max_voltage_mV;
|
SOLAX_1876.data.u8[2] = (uint8_t)datalayer.battery.status.cell_max_voltage_mV;
|
||||||
SOLAX_1876.data.u8[3] = (datalayer.battery.status.cell_max_voltage_mV >> 8);
|
SOLAX_1876.data.u8[3] = (datalayer.battery.status.cell_max_voltage_mV >> 8);
|
||||||
|
|
||||||
|
SOLAX_1876.data.u8[4] = (int8_t)datalayer.battery.status.temperature_min_dC;
|
||||||
|
SOLAX_1876.data.u8[5] = (datalayer.battery.status.temperature_min_dC >> 8);
|
||||||
SOLAX_1876.data.u8[6] = (uint8_t)datalayer.battery.status.cell_min_voltage_mV;
|
SOLAX_1876.data.u8[6] = (uint8_t)datalayer.battery.status.cell_min_voltage_mV;
|
||||||
SOLAX_1876.data.u8[7] = (datalayer.battery.status.cell_min_voltage_mV >> 8);
|
SOLAX_1876.data.u8[7] = (datalayer.battery.status.cell_min_voltage_mV >> 8);
|
||||||
|
|
||||||
|
@ -183,8 +187,10 @@ void update_values_can_inverter() { //This function maps all the values fetched
|
||||||
SOLAX_1878.data.u8[0] = (uint8_t)(datalayer.battery.status.voltage_dV);
|
SOLAX_1878.data.u8[0] = (uint8_t)(datalayer.battery.status.voltage_dV);
|
||||||
SOLAX_1878.data.u8[1] = ((datalayer.battery.status.voltage_dV) >> 8);
|
SOLAX_1878.data.u8[1] = ((datalayer.battery.status.voltage_dV) >> 8);
|
||||||
|
|
||||||
SOLAX_1878.data.u8[4] = (uint8_t)capped_capacity_Wh;
|
SOLAX_1878.data.u8[4] = (uint8_t)datalayer.battery.info.total_capacity_Wh;
|
||||||
SOLAX_1878.data.u8[5] = (capped_capacity_Wh >> 8);
|
SOLAX_1878.data.u8[5] = (datalayer.battery.info.total_capacity_Wh >> 8);
|
||||||
|
SOLAX_1878.data.u8[6] = (datalayer.battery.info.total_capacity_Wh >> 16);
|
||||||
|
SOLAX_1878.data.u8[7] = (datalayer.battery.info.total_capacity_Wh >> 24);
|
||||||
|
|
||||||
// BMS_Answer
|
// BMS_Answer
|
||||||
SOLAX_1801.data.u8[0] = 2;
|
SOLAX_1801.data.u8[0] = 2;
|
||||||
|
@ -192,10 +198,10 @@ void update_values_can_inverter() { //This function maps all the values fetched
|
||||||
SOLAX_1801.data.u8[4] = 1;
|
SOLAX_1801.data.u8[4] = 1;
|
||||||
|
|
||||||
//Ultra messages
|
//Ultra messages
|
||||||
SOLAX_187E.data.u8[0] = (uint8_t)capped_remaining_capacity_Wh;
|
SOLAX_187E.data.u8[0] = (uint8_t)datalayer.battery.status.reported_remaining_capacity_Wh;
|
||||||
SOLAX_187E.data.u8[1] = (capped_remaining_capacity_Wh >> 8);
|
SOLAX_187E.data.u8[1] = (datalayer.battery.status.reported_remaining_capacity_Wh >> 8);
|
||||||
SOLAX_187E.data.u8[2] = 0;
|
SOLAX_187E.data.u8[2] = (datalayer.battery.status.reported_remaining_capacity_Wh >> 16);
|
||||||
SOLAX_187E.data.u8[3] = 0;
|
SOLAX_187E.data.u8[3] = (datalayer.battery.status.reported_remaining_capacity_Wh >> 24);
|
||||||
SOLAX_187E.data.u8[5] = (uint8_t)(datalayer.battery.status.reported_soc / 100);
|
SOLAX_187E.data.u8[5] = (uint8_t)(datalayer.battery.status.reported_soc / 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue