diff --git a/.github/workflows/compile-all-batteries.yml b/.github/workflows/compile-all-batteries.yml index a3e2d7df..f4be1c58 100644 --- a/.github/workflows/compile-all-batteries.yml +++ b/.github/workflows/compile-all-batteries.yml @@ -112,4 +112,4 @@ jobs: # in the build matrix, and using build flags to define the # battery and inverter set in the build matrix. - 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 diff --git a/.github/workflows/compile-all-combinations-part1-batteries-A-to-M.yml b/.github/workflows/compile-all-combinations-part1-batteries-A-to-M.yml index 2aed0464..1606e334 100644 --- a/.github/workflows/compile-all-combinations-part1-batteries-A-to-M.yml +++ b/.github/workflows/compile-all-combinations-part1-batteries-A-to-M.yml @@ -118,4 +118,4 @@ jobs: # in the build matrix, and using build flags to define the # battery and inverter set in the build matrix. - 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 diff --git a/.github/workflows/compile-all-combinations-part2-batteries-N-to-Z.yml b/.github/workflows/compile-all-combinations-part2-batteries-N-to-Z.yml index c1233dd0..8a4f76e2 100644 --- a/.github/workflows/compile-all-combinations-part2-batteries-N-to-Z.yml +++ b/.github/workflows/compile-all-combinations-part2-batteries-N-to-Z.yml @@ -118,4 +118,4 @@ jobs: # in the build matrix, and using build flags to define the # battery and inverter set in the build matrix. - 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 diff --git a/.github/workflows/compile-all-hardware.yml b/.github/workflows/compile-all-hardware.yml index 473e0fb2..e55aeb32 100644 --- a/.github/workflows/compile-all-hardware.yml +++ b/.github/workflows/compile-all-hardware.yml @@ -90,4 +90,4 @@ jobs: # in the build matrix, and using build flags to define the # battery and inverter set in the build matrix. - 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 diff --git a/.github/workflows/compile-all-inverters.yml b/.github/workflows/compile-all-inverters.yml index 62e2a217..ad46efc8 100644 --- a/.github/workflows/compile-all-inverters.yml +++ b/.github/workflows/compile-all-inverters.yml @@ -105,4 +105,4 @@ jobs: # in the build matrix, and using build flags to define the # battery and inverter set in the build matrix. - 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 diff --git a/Software/Software.ino b/Software/Software.ino index d3c9c9ec..92f5a8a2 100644 --- a/Software/Software.ino +++ b/Software/Software.ino @@ -46,7 +46,7 @@ #endif // WIFI // The current software version, shown on webserver -const char* version_number = "8.3.dev"; +const char* version_number = "8.3.0"; // Interval settings uint16_t intervalUpdateValues = INTERVAL_1_S; // Interval at which to update inverter values / Modbus registers diff --git a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp index 4555cd45..af621981 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp @@ -39,6 +39,38 @@ static int8_t heatertemp = 0; static int8_t powerRelayTemperature = 0; 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, .ext_ID = false, .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( + (static_cast(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() { unsigned long currentMillis = millis(); @@ -509,6 +932,13 @@ void transmit_can_battery() { transmit_can_frame(&KIA64_553, can_config.battery); transmit_can_frame(&KIA64_57F, 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 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_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.max_cell_voltage_mV = MAX_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 diff --git a/Software/src/battery/NISSAN-LEAF-BATTERY.cpp b/Software/src/battery/NISSAN-LEAF-BATTERY.cpp index 747342c7..ddd7c91e 100644 --- a/Software/src/battery/NISSAN-LEAF-BATTERY.cpp +++ b/Software/src/battery/NISSAN-LEAF-BATTERY.cpp @@ -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 + //Allow contactors to close + if (battery_can_alive) { + datalayer.system.status.battery_allows_contactor_closing = true; + } + /*Extra safety functions below*/ if (battery_GIDS < 10) //700Wh left in battery! { //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_Failsafe_Status = (rx_frame.data.u8[1] & 0x07); 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_Interlock = (bool)((rx_frame.data.u8[3] & 0x08) >> 3); break; @@ -1064,9 +1064,19 @@ void handle_incoming_can_frame_battery(CAN_frame rx_frame) { } } 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 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 strncpy(datalayer.system.info.battery_protocol, "Nissan LEAF battery", 63); datalayer.system.info.battery_protocol[63] = '\0'; - datalayer.battery.info.number_of_cells = 96; datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_DV; datalayer.battery.info.min_design_voltage_dV = MIN_PACK_VOLTAGE_DV; diff --git a/Software/src/communication/can/comm_can.cpp b/Software/src/communication/can/comm_can.cpp index 7aded133..51c7e88f 100644 --- a/Software/src/communication/can/comm_can.cpp +++ b/Software/src/communication/can/comm_can.cpp @@ -105,8 +105,9 @@ void init_CAN() { // Transmit functions void transmit_can() { if (!allowed_to_send_CAN) { - return; + return; //Global block of CAN messages } + transmit_can_battery(); #ifdef CAN_INVERTER_SELECTED diff --git a/Software/src/communication/contactorcontrol/comm_contactorcontrol.cpp b/Software/src/communication/contactorcontrol/comm_contactorcontrol.cpp index 8f8050d7..6a828983 100644 --- a/Software/src/communication/contactorcontrol/comm_contactorcontrol.cpp +++ b/Software/src/communication/contactorcontrol/comm_contactorcontrol.cpp @@ -43,7 +43,6 @@ unsigned long currentTime = 0; unsigned long lastPowerRemovalTime = 0; const unsigned long powerRemovalInterval = 24 * 60 * 60 * 1000; // 24 hours 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) { #ifdef PWM_CONTACTOR_CONTROL @@ -256,48 +255,38 @@ void handle_BMSpower() { #endif //PERIODIC_BMS_RESET // 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 - 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) { + if (datalayer.system.status.BMS_reset_in_progress && currentTime - lastPowerRemovalTime >= powerRemovalDuration) { // Reapply power to the BMS digitalWrite(BMS_POWER, HIGH); #ifdef BMS_2_POWER digitalWrite(BMS_2_POWER, HIGH); // Same for battery 2 #endif - //Resume the battery pause and CAN communication + //Resume from the power pause 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) } diff --git a/Software/src/datalayer/datalayer.h b/Software/src/datalayer/datalayer.h index 1b26f56d..f7bab4cb 100644 --- a/Software/src/datalayer/datalayer.h +++ b/Software/src/datalayer/datalayer.h @@ -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 */ bool contactors_battery2_engaged = false; #endif + /** True if the BMS is being reset, by cutting power towards it */ + bool BMS_reset_in_progress = false; } DATALAYER_SYSTEM_STATUS_TYPE; typedef struct { diff --git a/Software/src/datalayer/datalayer_extended.h b/Software/src/datalayer/datalayer_extended.h index 27a86131..9b6b1649 100644 --- a/Software/src/datalayer/datalayer_extended.h +++ b/Software/src/datalayer/datalayer_extended.h @@ -259,6 +259,16 @@ typedef struct { uint8_t batteryManagementMode = 0; uint8_t BMS_ign = 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; typedef struct { diff --git a/Software/src/devboard/safety/safety.cpp b/Software/src/devboard/safety/safety.cpp index b5393645..8e62dd3f 100644 --- a/Software/src/devboard/safety/safety.cpp +++ b/Software/src/devboard/safety/safety.cpp @@ -237,7 +237,7 @@ void update_machineryprotection() { } 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 { clear_event(EVENT_SOH_DIFFERENCE); } diff --git a/Software/src/devboard/webserver/advanced_battery_html.cpp b/Software/src/devboard/webserver/advanced_battery_html.cpp index c8dba352..571884df 100644 --- a/Software/src/devboard/webserver/advanced_battery_html.cpp +++ b/Software/src/devboard/webserver/advanced_battery_html.cpp @@ -443,6 +443,22 @@ String advanced_battery_processor(const String& var) { content += "

Batterymanagement mode: " + String(datalayer_extended.KiaHyundai64.batteryManagementMode) + "

"; content += "

BMS ignition: " + String(datalayer_extended.KiaHyundai64.BMS_ign) + "

"; content += "

Battery relay: " + String(datalayer_extended.KiaHyundai64.batteryRelay) + "

"; +#ifdef DOUBLE_BATTERY + content += "

Values from battery 2

"; + content += "

Cells: " + String(datalayer_extended.KiaHyundai64.battery2_total_cell_count) + "S

"; + content += "

12V voltage: " + String(datalayer_extended.KiaHyundai64.battery2_battery_12V / 10.0, 1) + "

"; + content += "

Waterleakage: " + String(datalayer_extended.KiaHyundai64.battery2_waterleakageSensor) + "

"; + content += + "

Temperature, water inlet: " + String(datalayer_extended.KiaHyundai64.battery2_temperature_water_inlet) + + "

"; + content += + "

Temperature, power relay: " + String(datalayer_extended.KiaHyundai64.battery2_powerRelayTemperature) + + "

"; + content += "

Batterymanagement mode: " + String(datalayer_extended.KiaHyundai64.battery2_batteryManagementMode) + + "

"; + content += "

BMS ignition: " + String(datalayer_extended.KiaHyundai64.battery2_BMS_ign) + "

"; + content += "

Battery relay: " + String(datalayer_extended.KiaHyundai64.battery2_batteryRelay) + "

"; +#endif //DOUBLE_BATTERY #endif //KIA_HYUNDAI_64_BATTERY #ifdef BYD_ATTO_3_BATTERY diff --git a/Software/src/devboard/webserver/webserver.cpp b/Software/src/devboard/webserver/webserver.cpp index 976696eb..acfa55c2 100644 --- a/Software/src/devboard/webserver/webserver.cpp +++ b/Software/src/devboard/webserver/webserver.cpp @@ -37,26 +37,26 @@ void init_webserver() { server.on("/GetFirmwareInfo", HTTP_GET, [](AsyncWebServerRequest* request) { if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password)) 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 server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) { if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password)) 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 server.on("/settings", HTTP_GET, [](AsyncWebServerRequest* request) { if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password)) 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 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 @@ -76,7 +76,7 @@ void init_webserver() { // Define the handler to stop can logging server.on("/stop_can_logging", HTTP_GET, [](AsyncWebServerRequest* request) { 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 @@ -119,7 +119,7 @@ void init_webserver() { // Define the handler to delete can log server.on("/delete_can_log", HTTP_GET, [](AsyncWebServerRequest* request) { delete_can_log(); - request->send_P(200, "text/plain", "Log file deleted"); + request->send(200, "text/plain", "Log file deleted"); }); #endif @@ -127,7 +127,7 @@ void init_webserver() { // Define the handler to delete log file server.on("/delete_log", HTTP_GET, [](AsyncWebServerRequest* request) { 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 @@ -171,14 +171,14 @@ void init_webserver() { server.on("/cellmonitor", HTTP_GET, [](AsyncWebServerRequest* request) { if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password)) 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 server.on("/events", HTTP_GET, [](AsyncWebServerRequest* request) { if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password)) 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 diff --git a/Software/src/devboard/wifi/wifi.cpp b/Software/src/devboard/wifi/wifi.cpp index c158b52a..fa8f41ef 100644 --- a/Software/src/devboard/wifi/wifi.cpp +++ b/Software/src/devboard/wifi/wifi.cpp @@ -108,7 +108,7 @@ void wifi_monitor() { } // 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 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 -static void connectToWiFi() { +void connectToWiFi() { if (WiFi.status() != WL_CONNECTED) { lastReconnectAttempt = millis(); // Reset the reconnect attempt timer #ifdef DEBUG_LOG @@ -135,7 +135,7 @@ static void connectToWiFi() { } // 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); set_event(EVENT_WIFI_CONNECT, 0); connected_once = true; @@ -153,7 +153,7 @@ static void onWifiConnect(WiFiEvent_t event, WiFiEventInfo_t info) { } // 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_event(EVENT_WIFI_DISCONNECT); #ifdef DEBUG_LOG @@ -164,7 +164,7 @@ static void onWifiGotIP(WiFiEvent_t event, WiFiEventInfo_t info) { } // 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) set_event(EVENT_WIFI_DISCONNECT, 0); #ifdef DEBUG_LOG diff --git a/Software/src/devboard/wifi/wifi.h b/Software/src/devboard/wifi/wifi.h index 0cf37b23..bed27416 100644 --- a/Software/src/devboard/wifi/wifi.h +++ b/Software/src/devboard/wifi/wifi.h @@ -17,11 +17,11 @@ extern const char* passwordAP; void init_WiFi(); void wifi_monitor(); -static void connectToWiFi(); -static void FullReconnectToWiFi(); -static void onWifiConnect(WiFiEvent_t event, WiFiEventInfo_t info); -static void onWifiDisconnect(WiFiEvent_t event, WiFiEventInfo_t info); -static void onWifiGotIP(WiFiEvent_t event, WiFiEventInfo_t info); +void connectToWiFi(); +void FullReconnectToWiFi(); +void onWifiConnect(WiFiEvent_t event, WiFiEventInfo_t info); +void onWifiDisconnect(WiFiEvent_t event, WiFiEventInfo_t info); +void onWifiGotIP(WiFiEvent_t event, WiFiEventInfo_t info); #ifdef WIFIAP void init_WiFi_AP(); diff --git a/Software/src/inverter/SOLAX-CAN.cpp b/Software/src/inverter/SOLAX-CAN.cpp index e4aa6274..cddc845d 100644 --- a/Software/src/inverter/SOLAX-CAN.cpp +++ b/Software/src/inverter/SOLAX-CAN.cpp @@ -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[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[4] = (uint8_t)(datalayer.battery.status.cell_max_voltage_mV); - SOLAX_1874.data.u8[5] = (datalayer.battery.status.cell_max_voltage_mV >> 8); + SOLAX_1874.data.u8[4] = (uint8_t)(datalayer.battery.info.max_cell_voltage_mV); + 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[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. //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[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[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[1] = ((datalayer.battery.status.voltage_dV) >> 8); - SOLAX_1878.data.u8[4] = (uint8_t)capped_capacity_Wh; - SOLAX_1878.data.u8[5] = (capped_capacity_Wh >> 8); + SOLAX_1878.data.u8[4] = (uint8_t)datalayer.battery.info.total_capacity_Wh; + 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 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; //Ultra messages - SOLAX_187E.data.u8[0] = (uint8_t)capped_remaining_capacity_Wh; - SOLAX_187E.data.u8[1] = (capped_remaining_capacity_Wh >> 8); - SOLAX_187E.data.u8[2] = 0; - SOLAX_187E.data.u8[3] = 0; + SOLAX_187E.data.u8[0] = (uint8_t)datalayer.battery.status.reported_remaining_capacity_Wh; + SOLAX_187E.data.u8[1] = (datalayer.battery.status.reported_remaining_capacity_Wh >> 8); + SOLAX_187E.data.u8[2] = (datalayer.battery.status.reported_remaining_capacity_Wh >> 16); + 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); }