Merge branch 'dalathegreat:main' into tesla-bugfixes

This commit is contained in:
josiahhiggs 2025-01-26 23:12:31 +13:00 committed by GitHub
commit 87ac87cbf0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 561 additions and 79 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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)
} }

View file

@ -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 {

View file

@ -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 {

View file

@ -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);
} }

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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();

View file

@ -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);
} }