From 806123038097bab4cfb0842c2d130b18dff57454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Nagy?= <124464165+NJbubo@users.noreply.github.com> Date: Sun, 20 Oct 2024 20:06:35 +0200 Subject: [PATCH 1/7] Update Software.ino I added the CHAdeMO GPIO configuration. I thought it was fine that way, but the inputs still didn't work. --- Software/Software.ino | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Software/Software.ino b/Software/Software.ino index babef4dd..852d576e 100644 --- a/Software/Software.ino +++ b/Software/Software.ino @@ -574,6 +574,14 @@ void init_battery() { #ifdef CHADEMO_BATTERY intervalUpdateValues = 800; // This mode requires the values to be updated faster + pinMode(CHADEMO_PIN_2, OUTPUT); + digitalWrite(CHADEMO_PIN_2, LOW); + pinMode(CHADEMO_PIN_10, OUTPUT); + digitalWrite(CHADEMO_PIN_10, LOW); + pinMode(CHADEMO_LOCK, OUTPUT); + digitalWrite(CHADEMO_LOCK, LOW); + pinMode(CHADEMO_PIN_4, INPUT); + pinMode(CHADEMO_PIN_7, INPUT); #endif } From e65686950870ab15b8d84d1466c899f9d0427255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Nagy?= <124464165+NJbubo@users.noreply.github.com> Date: Sun, 20 Oct 2024 21:02:35 +0200 Subject: [PATCH 2/7] Update CHADEMO-BATTERY.cpp Add GPIO INPUT config. --- Software/src/battery/CHADEMO-BATTERY.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Software/src/battery/CHADEMO-BATTERY.cpp b/Software/src/battery/CHADEMO-BATTERY.cpp index 90ecd950..de97532a 100644 --- a/Software/src/battery/CHADEMO-BATTERY.cpp +++ b/Software/src/battery/CHADEMO-BATTERY.cpp @@ -164,6 +164,7 @@ inline void process_vehicle_charging_maximums(CAN_frame rx_frame) { } inline void process_vehicle_charging_session(CAN_frame rx_frame) { + pinMode(CHADEMO_PIN_4, INPUT); uint16_t newTargetBatteryVoltage = ((rx_frame.data.u8[1] << 8) | rx_frame.data.u8[2]); uint16_t priorChargingCurrentRequest = x102_chg_session.ChargingCurrentRequest; @@ -770,6 +771,7 @@ void handle_chademo_sequence() { switch (CHADEMO_Status) { case CHADEMO_IDLE: /* this is where we can unlock connector */ + pinMode(CHADEMO_PIN_7, INPUT); digitalWrite(CHADEMO_LOCK, LOW); plug_inserted = digitalRead(CHADEMO_PIN_7); From 74727c8992a2f94d2fa7abd32dd05f7e101997e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Nagy?= <124464165+NJbubo@users.noreply.github.com> Date: Wed, 23 Oct 2024 22:12:36 +0200 Subject: [PATCH 3/7] Fix CHADEMO-BATTERY.cpp I fixed a lot of faults. - lowByte <-> highByte replace, - variable declaration uint16_t <-> uint8_t replace (Voltage, Current), - Added x102_chg_session.s.status.StatusVehicleDischargeCompatible = bitRead(rx_frame.data.u8[5], 7), - changed the direction of a relationship (x100_chg_lim.MaximumBatteryVoltage < x108_evse_cap.threshold_voltage), - Separate lowByte / highByte x209_evse_dischg_est.remaining_discharge_time, - Park position not invertd. --- Software/src/battery/CHADEMO-BATTERY.cpp | 37 ++++++++++++------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/Software/src/battery/CHADEMO-BATTERY.cpp b/Software/src/battery/CHADEMO-BATTERY.cpp index de97532a..a3dc15ce 100644 --- a/Software/src/battery/CHADEMO-BATTERY.cpp +++ b/Software/src/battery/CHADEMO-BATTERY.cpp @@ -120,7 +120,7 @@ void update_values_battery() { datalayer.battery.status.voltage_dV = get_measured_voltage() * 10; datalayer.battery.info.total_capacity_Wh = - ((x101_chg_est.RatedBatteryCapacity / 0.11) * + ((x101_chg_est.RatedBatteryCapacity / 0.1) * 1000); //(Added in CHAdeMO v1.0.1), maybe handle hardcoded on lower protocol version? /* TODO max charging rate = @@ -151,8 +151,8 @@ void update_values_battery() { inline void process_vehicle_charging_minimums(CAN_frame rx_frame) { x100_chg_lim.MinimumChargeCurrent = rx_frame.data.u8[0]; - x100_chg_lim.MinimumBatteryVoltage = ((rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]); - x100_chg_lim.MaximumBatteryVoltage = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]); + x100_chg_lim.MinimumBatteryVoltage = ((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[2]); + x100_chg_lim.MaximumBatteryVoltage = ((rx_frame.data.u8[5] << 8) | rx_frame.data.u8[4]); x100_chg_lim.ConstantOfChargingRateIndication = rx_frame.data.u8[6]; } @@ -160,16 +160,16 @@ inline void process_vehicle_charging_maximums(CAN_frame rx_frame) { x101_chg_est.MaxChargingTime10sBit = rx_frame.data.u8[1]; x101_chg_est.MaxChargingTime1minBit = rx_frame.data.u8[2]; x101_chg_est.EstimatedChargingTime = rx_frame.data.u8[3]; - x101_chg_est.RatedBatteryCapacity = ((rx_frame.data.u8[5] << 8) | rx_frame.data.u8[6]); + x101_chg_est.RatedBatteryCapacity = ((rx_frame.data.u8[6] << 8) | rx_frame.data.u8[5]); } inline void process_vehicle_charging_session(CAN_frame rx_frame) { pinMode(CHADEMO_PIN_4, INPUT); - uint16_t newTargetBatteryVoltage = ((rx_frame.data.u8[1] << 8) | rx_frame.data.u8[2]); - uint16_t priorChargingCurrentRequest = x102_chg_session.ChargingCurrentRequest; - uint8_t priorTargetBatteryVoltage = x102_chg_session.TargetBatteryVoltage; + uint16_t newTargetBatteryVoltage = ((rx_frame.data.u8[2] << 8) | rx_frame.data.u8[1]); + uint16_t priorTargetBatteryVoltage = x102_chg_session.TargetBatteryVoltage; uint8_t newChargingCurrentRequest = rx_frame.data.u8[3]; + uint8_t priorChargingCurrentRequest = x102_chg_session.ChargingCurrentRequest; vehicle_can_initialized = true; @@ -188,6 +188,7 @@ inline void process_vehicle_charging_session(CAN_frame rx_frame) { x102_chg_session.s.status.StatusChargingError = bitRead(rx_frame.data.u8[5], 2); x102_chg_session.s.status.StatusVehicle = bitRead(rx_frame.data.u8[5], 3); x102_chg_session.s.status.StatusNormalStopRequest = bitRead(rx_frame.data.u8[5], 4); + x102_chg_session.s.status.StatusVehicleDischargeCompatible = bitRead(rx_frame.data.u8[5], 7); x102_chg_session.StateOfCharge = rx_frame.data.u8[6]; @@ -203,7 +204,7 @@ inline void process_vehicle_charging_session(CAN_frame rx_frame) { uint8_t chargingrate = 0; if (x100_chg_lim.ConstantOfChargingRateIndication > 0) { chargingrate = x102_chg_session.StateOfCharge / x100_chg_lim.ConstantOfChargingRateIndication * 100; - Serial.print("Charge Rate (kW):"); + Serial.print("Charge Rate (kW): "); Serial.println(chargingrate); } #endif @@ -309,7 +310,7 @@ inline void process_vehicle_charging_session(CAN_frame rx_frame) { inline void process_vehicle_charging_limits(CAN_frame rx_frame) { x200_discharge_limits.MaximumDischargeCurrent = rx_frame.data.u8[0]; - x200_discharge_limits.MinimumDischargeVoltage = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]); + x200_discharge_limits.MinimumDischargeVoltage = ((rx_frame.data.u8[5] << 8) | rx_frame.data.u8[4]); x200_discharge_limits.MinimumBatteryDischargeLevel = rx_frame.data.u8[6]; x200_discharge_limits.MaxRemainingCapacityForCharging = rx_frame.data.u8[7]; @@ -339,15 +340,15 @@ inline void process_vehicle_discharge_estimate(CAN_frame rx_frame) { unsigned long currentMillis = millis(); x201_discharge_estimate.V2HchargeDischargeSequenceNum = rx_frame.data.u8[0]; - x201_discharge_estimate.ApproxDischargeCompletionTime = ((rx_frame.data.u8[1] << 8) | rx_frame.data.u8[2]); - x201_discharge_estimate.AvailableVehicleEnergy = ((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[4]); + x201_discharge_estimate.ApproxDischargeCompletionTime = ((rx_frame.data.u8[2] << 8) | rx_frame.data.u8[1]); + x201_discharge_estimate.AvailableVehicleEnergy = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[3]); #ifdef DEBUG_VIA_USB if (currentMillis - previousMillis5000 >= INTERVAL_5_S) { previousMillis5000 = currentMillis; - Serial.println("x201 availabile vehicle energy, completion time"); + Serial.println("x201 availabile vehicle energy, completion time: "); Serial.println(x201_discharge_estimate.AvailableVehicleEnergy); - Serial.println("x201 approx vehicle completion time"); + Serial.println("x201 approx vehicle completion time: "); Serial.println(x201_discharge_estimate.ApproxDischargeCompletionTime); } #endif @@ -365,7 +366,7 @@ inline void process_vehicle_dynamic_control(CAN_frame rx_frame) { inline void process_vehicle_vendor_ID(CAN_frame rx_frame) { x700_vendor_id.AutomakerCode = rx_frame.data.u8[0]; x700_vendor_id.OptionalContent = - ((rx_frame.data.u8[1] << 8) | rx_frame.data.u8[2]); //Actually more bytes, but not needed for our purpose + ((rx_frame.data.u8[2] << 8) | rx_frame.data.u8[1]); //Actually more bytes, but not needed for our purpose } void receive_can_battery(CAN_frame rx_frame) { @@ -558,7 +559,7 @@ void update_evse_status(CAN_frame& f) { * */ if ((x102_chg_session.TargetBatteryVoltage > x108_evse_cap.available_output_voltage) || - (x100_chg_lim.MaximumBatteryVoltage > x108_evse_cap.threshold_voltage)) { + (x100_chg_lim.MaximumBatteryVoltage < x108_evse_cap.threshold_voltage)) { //Toggle battery incompatibility flag 109.5.3 x109_evse_state.s.status.EVSE_error = 1; x109_evse_state.s.status.battery_incompatible = 1; @@ -603,7 +604,8 @@ void update_evse_discharge_estimate(CAN_frame& f) { */ CHADEMO_209.data.u8[0] = x209_evse_dischg_est.sequence_control_number; - CHADEMO_209.data.u8[1] = x209_evse_dischg_est.remaining_discharge_time; + CHADEMO_209.data.u8[1] = lowByte(x209_evse_dischg_est.remaining_discharge_time); + CHADEMO_209.data.u8[2] = highByte(x209_evse_dischg_est.remaining_discharge_time); } /* x208 EVSE, peer to 0x200 Vehicle */ @@ -752,7 +754,7 @@ void handle_chademo_sequence() { /* ------------------- State override conditions checks ------------------- */ /* ------------------------------------------------------------------------------ */ - if (CHADEMO_Status >= CHADEMO_EV_ALLOWED && !x102_chg_session.s.status.StatusVehicleShifterPosition) { + if (CHADEMO_Status >= CHADEMO_EV_ALLOWED && x102_chg_session.s.status.StatusVehicleShifterPosition) { #ifdef DEBUG_VIA_USB Serial.println("Vehicle is not parked, abort."); #endif @@ -779,7 +781,6 @@ void handle_chademo_sequence() { #ifdef DEBUG_VIA_USB // Commented unless needed for debug // Serial.println("CHADEMO plug is not inserted."); -// #endif return; } From 8657983570bb755cafdb381756678e9b3815c675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Nagy?= <124464165+NJbubo@users.noreply.github.com> Date: Wed, 23 Oct 2024 22:15:29 +0200 Subject: [PATCH 4/7] Update CHADEMO-BATTERY.cpp --- Software/src/battery/CHADEMO-BATTERY.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Software/src/battery/CHADEMO-BATTERY.cpp b/Software/src/battery/CHADEMO-BATTERY.cpp index a3dc15ce..882a1b52 100644 --- a/Software/src/battery/CHADEMO-BATTERY.cpp +++ b/Software/src/battery/CHADEMO-BATTERY.cpp @@ -346,9 +346,9 @@ inline void process_vehicle_discharge_estimate(CAN_frame rx_frame) { #ifdef DEBUG_VIA_USB if (currentMillis - previousMillis5000 >= INTERVAL_5_S) { previousMillis5000 = currentMillis; - Serial.println("x201 availabile vehicle energy, completion time: "); + Serial.print("x201 availabile vehicle energy, completion time: "); Serial.println(x201_discharge_estimate.AvailableVehicleEnergy); - Serial.println("x201 approx vehicle completion time: "); + Serial.print("x201 approx vehicle completion time: "); Serial.println(x201_discharge_estimate.ApproxDischargeCompletionTime); } #endif From af191b3606186a28b0787dcfc15825ea63877aad Mon Sep 17 00:00:00 2001 From: NJbubo Date: Sun, 17 Nov 2024 07:23:44 +0100 Subject: [PATCH 5/7] Fixed CHAdeMO GPIO, Added CAN message to ISA SHUNT --- .github/workflows/compile-all-batteries.yml | 13 +- .github/workflows/compile-all-inverters.yml | 2 + Software/Software.ino | 49 +-- Software/src/battery/BATTERIES.h | 1 + Software/src/battery/BMW-I3-BATTERY.cpp | 8 +- Software/src/battery/BMW-IX-BATTERY.cpp | 5 +- Software/src/battery/BYD-ATTO-3-BATTERY.cpp | 5 +- Software/src/battery/CELLPOWER-BMS.cpp | 5 +- Software/src/battery/CHADEMO-BATTERY.cpp | 22 +- Software/src/battery/CHADEMO-SHUNTS.cpp | 294 +++++++++++------- Software/src/battery/CHADEMO-SHUNTS.h | 12 +- .../src/battery/IMIEV-CZERO-ION-BATTERY.cpp | 5 +- Software/src/battery/JAGUAR-IPACE-BATTERY.cpp | 6 +- Software/src/battery/KIA-E-GMP-BATTERY.cpp | 6 +- .../src/battery/KIA-HYUNDAI-64-BATTERY.cpp | 5 +- .../battery/KIA-HYUNDAI-HYBRID-BATTERY.cpp | 6 +- Software/src/battery/MG-5-BATTERY.cpp | 5 +- Software/src/battery/NISSAN-LEAF-BATTERY.cpp | 244 +++++++++++++-- Software/src/battery/NISSAN-LEAF-BATTERY.h | 8 + Software/src/battery/PYLON-BATTERY.cpp | 6 +- .../src/battery/RANGE-ROVER-PHEV-BATTERY.cpp | 6 +- .../src/battery/RENAULT-KANGOO-BATTERY.cpp | 6 +- Software/src/battery/RENAULT-TWIZY.cpp | 6 +- .../src/battery/RENAULT-ZOE-GEN1-BATTERY.cpp | 5 +- .../src/battery/RENAULT-ZOE-GEN2-BATTERY.cpp | 5 +- Software/src/battery/RJXZS-BMS.cpp | 6 +- .../src/battery/SANTA-FE-PHEV-BATTERY.cpp | 5 +- .../SERIAL-LINK-RECEIVER-FROM-BATTERY.cpp | 3 +- Software/src/battery/TESLA-BATTERY.cpp | 8 +- Software/src/battery/TEST-FAKE-BATTERY.cpp | 5 +- Software/src/battery/VOLVO-SPA-BATTERY.cpp | 6 +- Software/src/datalayer/datalayer.h | 5 +- Software/src/datalayer/datalayer_extended.h | 15 + .../webserver/advanced_battery_html.cpp | 14 + Software/src/devboard/webserver/webserver.cpp | 117 +------ Software/src/include.h | 6 - Software/src/inverter/AFORE-CAN.cpp | 4 + Software/src/inverter/AFORE-CAN.h | 3 +- Software/src/inverter/BYD-CAN.cpp | 47 ++- Software/src/inverter/BYD-CAN.h | 1 + Software/src/inverter/BYD-MODBUS.cpp | 4 + Software/src/inverter/BYD-MODBUS.h | 1 + Software/src/inverter/BYD-SMA.cpp | 6 + Software/src/inverter/BYD-SMA.h | 1 + Software/src/inverter/FOXESS-CAN.cpp | 4 + Software/src/inverter/FOXESS-CAN.h | 1 + Software/src/inverter/PYLON-CAN.cpp | 4 + Software/src/inverter/PYLON-CAN.h | 1 + Software/src/inverter/PYLON-LV-CAN.cpp | 4 + Software/src/inverter/PYLON-LV-CAN.h | 1 + .../SERIAL-LINK-TRANSMITTER-INVERTER.cpp | 2 + .../SERIAL-LINK-TRANSMITTER-INVERTER.h | 1 + Software/src/inverter/SMA-CAN.cpp | 5 + Software/src/inverter/SMA-CAN.h | 1 + Software/src/inverter/SMA-TRIPOWER-CAN.cpp | 5 + Software/src/inverter/SMA-TRIPOWER-CAN.h | 1 + Software/src/inverter/SOFAR-CAN.cpp | 5 + Software/src/inverter/SOFAR-CAN.h | 1 + Software/src/inverter/SOLAX-CAN.cpp | 5 + Software/src/inverter/SOLAX-CAN.h | 1 + 60 files changed, 642 insertions(+), 392 deletions(-) diff --git a/.github/workflows/compile-all-batteries.yml b/.github/workflows/compile-all-batteries.yml index 1cd8955e..287b75f2 100644 --- a/.github/workflows/compile-all-batteries.yml +++ b/.github/workflows/compile-all-batteries.yml @@ -34,19 +34,25 @@ jobs: # These are the batteries for which the code will be compiled. battery: - BMW_I3_BATTERY + - BMW_IX_BATTERY - BYD_ATTO_3_BATTERY - CELLPOWER_BMS - CHADEMO_BATTERY - IMIEV_CZERO_ION_BATTERY - JAGUAR_IPACE_BATTERY - KIA_HYUNDAI_64_BATTERY + - KIA_E_GMP_BATTERY - KIA_HYUNDAI_HYBRID_BATTERY + - MG_5_BATTERY - NISSAN_LEAF_BATTERY - PYLON_BATTERY - RJXZS_BMS + - RANGE_ROVER_PHEV_BATTERY - RENAULT_KANGOO_BATTERY + - RENAULT_TWIZY_BATTERY - RENAULT_ZOE_GEN1_BATTERY - RENAULT_ZOE_GEN2_BATTERY + - SANTA_FE_PHEV_BATTERY - TESLA_MODEL_3Y_BATTERY - VOLVO_SPA_BATTERY - TEST_FAKE_BATTERY @@ -54,13 +60,6 @@ jobs: # These are the emulated inverter communication protocols for which the code will be compiled. inverter: - BYD_CAN -# - BYD_MODBUS -# - PYLON_CAN -# - SMA_CAN -# - SMA_TRIPOWER_CAN -# - SOFAR_CAN -# - SOLAX_CAN - # This is the platform GitHub will use to run our workflow. runs-on: ubuntu-latest diff --git a/.github/workflows/compile-all-inverters.yml b/.github/workflows/compile-all-inverters.yml index 85beb384..deb0ccc9 100644 --- a/.github/workflows/compile-all-inverters.yml +++ b/.github/workflows/compile-all-inverters.yml @@ -42,10 +42,12 @@ jobs: # - TESLA_MODEL_3Y_BATTERY # These are the emulated inverter communication protocols for which the code will be compiled. inverter: + - AFORE_CAN - BYD_CAN - BYD_SMA - BYD_MODBUS - FOXESS_CAN + - PYLON_LV_CAN - PYLON_CAN - SMA_CAN - SMA_TRIPOWER_CAN diff --git a/Software/Software.ino b/Software/Software.ino index 852d576e..015c6b08 100644 --- a/Software/Software.ino +++ b/Software/Software.ino @@ -70,13 +70,11 @@ volatile bool send_ok = 0; static const uint32_t QUARTZ_FREQUENCY = CRYSTAL_FREQUENCY_MHZ * 1000000UL; //MHZ configured in USER_SETTINGS.h ACAN2515 can(MCP2515_CS, SPI, MCP2515_INT); static ACAN2515_Buffer16 gBuffer; -#endif +#endif //DUAL_CAN #ifdef CAN_FD #include "src/lib/pierremolinaro-ACAN2517FD/ACAN2517FD.h" ACAN2517FD canfd(MCP2517_CS, SPI, MCP2517_INT); -#else -typedef char CANFDMessage; -#endif +#endif //CAN_FD // ModbusRTU parameters #ifdef MODBUS_INVERTER_SELECTED @@ -172,11 +170,10 @@ void setup() { init_rs485(); init_serialDataLink(); - - init_inverter(); - - init_battery(); - +#if defined(CAN_INVERTER_SELECTED) || defined(MODBUS_INVERTER_SELECTED) + setup_inverter(); +#endif + setup_battery(); #ifdef EQUIPMENT_STOP_BUTTON init_equipment_stop_button(); #endif @@ -554,37 +551,6 @@ void init_rs485() { #endif } -void init_inverter() { -#ifdef SOLAX_CAN - datalayer.system.status.inverter_allows_contactor_closing = false; // The inverter needs to allow first - intervalUpdateValues = 800; // This protocol also requires the values to be updated faster -#endif -#ifdef FOXESS_CAN - intervalUpdateValues = 950; // This protocol also requires the values to be updated faster -#endif -#ifdef BYD_SMA - datalayer.system.status.inverter_allows_contactor_closing = false; // The inverter needs to allow first - pinMode(INVERTER_CONTACTOR_ENABLE_PIN, INPUT); -#endif -} - -void init_battery() { - // Inform user what battery is used and perform setup - setup_battery(); - -#ifdef CHADEMO_BATTERY - intervalUpdateValues = 800; // This mode requires the values to be updated faster - pinMode(CHADEMO_PIN_2, OUTPUT); - digitalWrite(CHADEMO_PIN_2, LOW); - pinMode(CHADEMO_PIN_10, OUTPUT); - digitalWrite(CHADEMO_PIN_10, LOW); - pinMode(CHADEMO_LOCK, OUTPUT); - digitalWrite(CHADEMO_LOCK, LOW); - pinMode(CHADEMO_PIN_4, INPUT); - pinMode(CHADEMO_PIN_7, INPUT); -#endif -} - #ifdef EQUIPMENT_STOP_BUTTON void monitor_equipment_stop_button() { @@ -1156,6 +1122,9 @@ void receive_can(CAN_frame* rx_frame, int interface) { if (interface == can_config.battery) { receive_can_battery(*rx_frame); +#ifdef CHADEMO_BATTERY + ISA_handleFrame(rx_frame); +#endif } if (interface == can_config.inverter) { #ifdef CAN_INVERTER_SELECTED diff --git a/Software/src/battery/BATTERIES.h b/Software/src/battery/BATTERIES.h index 3bc65189..e17d1c06 100644 --- a/Software/src/battery/BATTERIES.h +++ b/Software/src/battery/BATTERIES.h @@ -20,6 +20,7 @@ #ifdef CHADEMO_BATTERY #include "CHADEMO-BATTERY.h" +#include "CHADEMO-SHUNTS.h" #endif #ifdef IMIEV_CZERO_ION_BATTERY diff --git a/Software/src/battery/BMW-I3-BATTERY.cpp b/Software/src/battery/BMW-I3-BATTERY.cpp index a1b576d4..b15cb31e 100644 --- a/Software/src/battery/BMW-I3-BATTERY.cpp +++ b/Software/src/battery/BMW-I3-BATTERY.cpp @@ -1118,9 +1118,8 @@ void send_can_battery() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("BMW i3 battery selected"); -#endif //DEBUG_VIA_USB + strncpy(datalayer.system.info.battery_protocol, "BMW i3", 63); + datalayer.system.info.battery_protocol[63] = '\0'; //Before we have started up and detected which battery is in use, use 60AH values datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_60AH; @@ -1129,9 +1128,6 @@ void setup_battery(void) { // Performs one time setup at startup datalayer.system.status.battery_allows_contactor_closing = true; #ifdef DOUBLE_BATTERY -#ifdef DEBUG_VIA_USB - Serial.println("Another BMW i3 battery also selected!"); -#endif //DEBUG_VIA_USB 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_deviation_mV = datalayer.battery.info.max_cell_voltage_deviation_mV; diff --git a/Software/src/battery/BMW-IX-BATTERY.cpp b/Software/src/battery/BMW-IX-BATTERY.cpp index a994e27d..8d9f358d 100644 --- a/Software/src/battery/BMW-IX-BATTERY.cpp +++ b/Software/src/battery/BMW-IX-BATTERY.cpp @@ -778,9 +778,8 @@ void send_can_battery() { //} //We can always send CAN as the iX BMS will wake up on vehicle comms void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("BMW iX battery selected"); -#endif //DEBUG_VIA_USB + strncpy(datalayer.system.info.battery_protocol, "BMW iX and i4-7 platform", 63); + datalayer.system.info.battery_protocol[63] = '\0'; //Before we have started up and detected which battery is in use, use 108S values datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_DV; diff --git a/Software/src/battery/BYD-ATTO-3-BATTERY.cpp b/Software/src/battery/BYD-ATTO-3-BATTERY.cpp index 9a1e1f9b..bfbc92f3 100644 --- a/Software/src/battery/BYD-ATTO-3-BATTERY.cpp +++ b/Software/src/battery/BYD-ATTO-3-BATTERY.cpp @@ -399,9 +399,8 @@ void send_can_battery() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("BYD Atto 3 battery selected"); -#endif + strncpy(datalayer.system.info.battery_protocol, "BYD Atto 3", 63); + datalayer.system.info.battery_protocol[63] = '\0'; datalayer.battery.info.number_of_cells = 126; datalayer.battery.info.chemistry = battery_chemistry_enum::LFP; datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_DV; diff --git a/Software/src/battery/CELLPOWER-BMS.cpp b/Software/src/battery/CELLPOWER-BMS.cpp index ec448312..80c981c6 100644 --- a/Software/src/battery/CELLPOWER-BMS.cpp +++ b/Software/src/battery/CELLPOWER-BMS.cpp @@ -333,9 +333,8 @@ void send_can_battery() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("Cellpower BMS selected"); -#endif + strncpy(datalayer.system.info.battery_protocol, "Cellpower BMS", 63); + datalayer.system.info.battery_protocol[63] = '\0'; datalayer.system.status.battery_allows_contactor_closing = true; 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/battery/CHADEMO-BATTERY.cpp b/Software/src/battery/CHADEMO-BATTERY.cpp index 882a1b52..f445724d 100644 --- a/Software/src/battery/CHADEMO-BATTERY.cpp +++ b/Software/src/battery/CHADEMO-BATTERY.cpp @@ -164,8 +164,6 @@ inline void process_vehicle_charging_maximums(CAN_frame rx_frame) { } inline void process_vehicle_charging_session(CAN_frame rx_frame) { - pinMode(CHADEMO_PIN_4, INPUT); - uint16_t newTargetBatteryVoltage = ((rx_frame.data.u8[2] << 8) | rx_frame.data.u8[1]); uint16_t priorTargetBatteryVoltage = x102_chg_session.TargetBatteryVoltage; uint8_t newChargingCurrentRequest = rx_frame.data.u8[3]; @@ -773,7 +771,6 @@ void handle_chademo_sequence() { switch (CHADEMO_Status) { case CHADEMO_IDLE: /* this is where we can unlock connector */ - pinMode(CHADEMO_PIN_7, INPUT); digitalWrite(CHADEMO_LOCK, LOW); plug_inserted = digitalRead(CHADEMO_PIN_7); @@ -1034,9 +1031,19 @@ void handle_chademo_sequence() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("Chademo battery selected"); -#endif + + intervalUpdateValues = 800; // This mode requires the values to be updated faster + pinMode(CHADEMO_PIN_2, OUTPUT); + digitalWrite(CHADEMO_PIN_2, LOW); + pinMode(CHADEMO_PIN_10, OUTPUT); + digitalWrite(CHADEMO_PIN_10, LOW); + pinMode(CHADEMO_LOCK, OUTPUT); + digitalWrite(CHADEMO_LOCK, LOW); + pinMode(CHADEMO_PIN_4, INPUT); + pinMode(CHADEMO_PIN_7, INPUT); + + strncpy(datalayer.system.info.battery_protocol, "Chademo V2X mode", 63); + datalayer.system.info.battery_protocol[63] = '\0'; CHADEMO_Status = CHADEMO_IDLE; @@ -1078,6 +1085,9 @@ void setup_battery(void) { // Performs one time setup at startup x109_evse_state.s.status.ChgDischStopControl = 1; handle_chademo_sequence(); +// ISA_deFAULT(); // ISA Setup - it is sufficient to set it once, because it is saved in SUNT +// ISA_initialize(); // ISA Setup - it is sufficient to set it once, because it is saved in SUNT +// ISA_RESTART(); setupMillis = millis(); } diff --git a/Software/src/battery/CHADEMO-SHUNTS.cpp b/Software/src/battery/CHADEMO-SHUNTS.cpp index ec78e616..34dfb734 100644 --- a/Software/src/battery/CHADEMO-SHUNTS.cpp +++ b/Software/src/battery/CHADEMO-SHUNTS.cpp @@ -12,6 +12,11 @@ * * 2024 - Modified to make use of ESP32-Arduino-CAN by miwagner * + * 2024.11 - Modified byte sequence to Big Endian (this is the default for IVT) and the same as CHAdeMO + * - Fixed and Added send functions + * - Added some GET functions + * by NJbubo + * */ #include "../include.h" #ifdef CHADEMO_BATTERY @@ -74,16 +79,29 @@ uint16_t get_measured_current() { } //This is our CAN interrupt service routine to catch inbound frames -inline void ISA_handleFrame(CAN_frame* frame) { +void ISA_handleFrame(CAN_frame* frame) { - if (frame->ID < 0x521 || frame->ID > 0x528) { + if (frame->ID < 0x510 || frame->ID > 0x528) { return; } framecount++; switch (frame->ID) { + + case 0x510: case 0x511: + Serial.print(millis()); // Example printout, time, ID, length, data: 7553 1DB 8 FF C0 B9 EA 0 0 2 5D + Serial.print(" "); + Serial.print(frame->ID, HEX); + Serial.print(" "); + Serial.print(frame->DLC); + Serial.print(" "); + for (int i = 0; i < frame->DLC; ++i) { + Serial.print(frame->data.u8[i], HEX); + Serial.print(" "); + } + Serial.println(""); break; case 0x521: @@ -118,7 +136,6 @@ inline void ISA_handleFrame(CAN_frame* frame) { ISA_handle528(frame); break; } - return; } @@ -126,7 +143,7 @@ inline void ISA_handleFrame(CAN_frame* frame) { inline void ISA_handle521(CAN_frame* frame) { long current = 0; current = - (long)((frame->data.u8[5] << 24) | (frame->data.u8[4] << 16) | (frame->data.u8[3] << 8) | (frame->data.u8[2])); + (long)((frame->data.u8[2] << 24) | (frame->data.u8[3] << 16) | (frame->data.u8[4] << 8) | (frame->data.u8[5])); milliamps = current; Amperes = current / 1000.0f; @@ -135,7 +152,7 @@ inline void ISA_handle521(CAN_frame* frame) { //handle frame for Voltage inline void ISA_handle522(CAN_frame* frame) { long volt = - (long)((frame->data.u8[5] << 24) | (frame->data.u8[4] << 16) | (frame->data.u8[3] << 8) | (frame->data.u8[2])); + (long)((frame->data.u8[2] << 24) | (frame->data.u8[3] << 16) | (frame->data.u8[4] << 8) | (frame->data.u8[5])); Voltage = volt / 1000.0f; Voltage1 = Voltage - (Voltage2 + Voltage3); @@ -158,7 +175,7 @@ inline void ISA_handle522(CAN_frame* frame) { //handle frame for Voltage 2 inline void ISA_handle523(CAN_frame* frame) { long volt = - (long)((frame->data.u8[5] << 24) | (frame->data.u8[4] << 16) | (frame->data.u8[3] << 8) | (frame->data.u8[2])); + (long)((frame->data.u8[2] << 24) | (frame->data.u8[3] << 16) | (frame->data.u8[4] << 8) | (frame->data.u8[5])); Voltage2 = volt / 1000.0f; if (Voltage2 > 3) @@ -177,7 +194,7 @@ inline void ISA_handle523(CAN_frame* frame) { //handle frame for Voltage3 inline void ISA_handle524(CAN_frame* frame) { long volt = - (long)((frame->data.u8[5] << 24) | (frame->data.u8[4] << 16) | (frame->data.u8[3] << 8) | (frame->data.u8[2])); + (long)((frame->data.u8[2] << 24) | (frame->data.u8[3] << 16) | (frame->data.u8[4] << 8) | (frame->data.u8[5])); Voltage3 = volt / 1000.0f; @@ -194,7 +211,7 @@ inline void ISA_handle524(CAN_frame* frame) { //handle frame for Temperature inline void ISA_handle525(CAN_frame* frame) { long temp = 0; - temp = (long)((frame->data.u8[5] << 24) | (frame->data.u8[4] << 16) | (frame->data.u8[3] << 8) | (frame->data.u8[2])); + temp = (long)((frame->data.u8[2] << 24) | (frame->data.u8[3] << 16) | (frame->data.u8[4] << 8) | (frame->data.u8[5])); Temperature = temp / 10; } @@ -202,14 +219,15 @@ inline void ISA_handle525(CAN_frame* frame) { //handle frame for Kilowatts inline void ISA_handle526(CAN_frame* frame) { watt = 0; - watt = (long)((frame->data.u8[5] << 24) | (frame->data.u8[4] << 16) | (frame->data.u8[3] << 8) | (frame->data.u8[2])); + watt = (long)((frame->data.u8[2] << 24) | (frame->data.u8[3] << 16) | (frame->data.u8[4] << 8) | (frame->data.u8[5])); + KW = watt / 1000.0f; } //handle frame for Ampere-Hours inline void ISA_handle527(CAN_frame* frame) { As = 0; - As = (frame->data.u8[5] << 24) | (frame->data.u8[4] << 16) | (frame->data.u8[3] << 8) | (frame->data.u8[2]); + As = (long)(frame->data.u8[2] << 24) | (frame->data.u8[3] << 16) | (frame->data.u8[4] << 8) | (frame->data.u8[5]); AH += (As - lastAs) / 3600.0f; lastAs = As; @@ -217,133 +235,199 @@ inline void ISA_handle527(CAN_frame* frame) { //handle frame for kiloWatt-hours inline void ISA_handle528(CAN_frame* frame) { - wh = (long)((frame->data.u8[5] << 24) | (frame->data.u8[4] << 16) | (frame->data.u8[3] << 8) | (frame->data.u8[2])); + wh = (long)((frame->data.u8[2] << 24) | (frame->data.u8[3] << 16) | (frame->data.u8[4] << 8) | (frame->data.u8[5])); KWH += (wh - lastWh) / 1000.0f; lastWh = wh; } -/* void ISA_initialize() { - firstframe=false; - STOP(); - delay(700); - for(int i=0;i<9;i++) { - Serial.println("initialization \n"); + firstframe=false; + ISA_STOP(); + delay(500); + for(int i=0;i<8;i++) { + Serial.print("ISA Initialization "); + Serial.println(i); - outframe.data.u8[0]=(0x20+i); - outframe.data.u8[1]=0x42; - outframe.data.u8[2]=0x02; - outframe.data.u8[3]=(0x60+(i*18)); - outframe.data.u8[4]=0x00; - outframe.data.u8[5]=0x00; - outframe.data.u8[6]=0x00; - outframe.data.u8[7]=0x00; + outframe.data.u8[0]=(0x20+i); + outframe.data.u8[1]=0x02; + outframe.data.u8[2]=0x02; + outframe.data.u8[3]=(0x60+(i*18)); + outframe.data.u8[4]=0x00; + outframe.data.u8[5]=0x00; + outframe.data.u8[6]=0x00; + outframe.data.u8[7]=0x00; - transmit_can((&outframe, can_config.battery); - - delay(500); - - sendSTORE(); - delay(500); - } - - START(); + transmit_can(&outframe, can_config.battery); delay(500); - lastAs=As; - lastWh=wh; + } + ISA_sendSTORE(); + delay(500); + + ISA_START(); + delay(500); + lastAs=As; + lastWh=wh; } void ISA_STOP() { - outframe.data.u8[0]=0x34; - outframe.data.u8[1]=0x00; - outframe.data.u8[2]=0x01; - outframe.data.u8[3]=0x00; - outframe.data.u8[4]=0x00; - outframe.data.u8[5]=0x00; - outframe.data.u8[6]=0x00; - outframe.data.u8[7]=0x00; - transmit_can((&outframe, can_config.battery); + Serial.println("ISA STOP"); + outframe.data.u8[0] = 0x34; + outframe.data.u8[1] = 0x00; + outframe.data.u8[2] = 0x01; + outframe.data.u8[3] = 0x00; + outframe.data.u8[4] = 0x00; + outframe.data.u8[5] = 0x00; + outframe.data.u8[6] = 0x00; + outframe.data.u8[7] = 0x00; + + transmit_can(&outframe, can_config.battery); } void ISA_sendSTORE() { - outframe.data.u8[0]=0x32; - outframe.data.u8[1]=0x00; - outframe.data.u8[2]=0x00; - outframe.data.u8[3]=0x00; - outframe.data.u8[4]=0x00; - outframe.data.u8[5]=0x00; - outframe.data.u8[6]=0x00; - outframe.data.u8[7]=0x00; - transmit_can((&outframe, can_config.battery); + Serial.println("ISA send STORE"); + + outframe.data.u8[0] = 0x32; + outframe.data.u8[1] = 0x00; + outframe.data.u8[2] = 0x00; + outframe.data.u8[3] = 0x00; + outframe.data.u8[4] = 0x00; + outframe.data.u8[5] = 0x00; + outframe.data.u8[6] = 0x00; + outframe.data.u8[7] = 0x00; + + transmit_can(&outframe, can_config.battery); } void ISA_START() { - outframe.data.u8[0]=0x34; - outframe.data.u8[1]=0x01; - outframe.data.u8[2]=0x01; - outframe.data.u8[3]=0x00; - outframe.data.u8[4]=0x00; - outframe.data.u8[5]=0x00; - outframe.data.u8[6]=0x00; - outframe.data.u8[7]=0x00; - transmit_can((&outframe, can_config.battery); + Serial.println("ISA START"); + + outframe.data.u8[0] = 0x34; + outframe.data.u8[1] = 0x01; + outframe.data.u8[2] = 0x01; + outframe.data.u8[3] = 0x00; + outframe.data.u8[4] = 0x00; + outframe.data.u8[5] = 0x00; + outframe.data.u8[6] = 0x00; + outframe.data.u8[7] = 0x00; + + transmit_can(&outframe, can_config.battery); } void ISA_RESTART() { - //Has the effect of zeroing AH and KWH - outframe.data.u8[0]=0x3F; - outframe.data.u8[1]=0x00; - outframe.data.u8[2]=0x00; - outframe.data.u8[3]=0x00; - outframe.data.u8[4]=0x00; - outframe.data.u8[5]=0x00; - outframe.data.u8[6]=0x00; - outframe.data.u8[7]=0x00; - transmit_can((&outframe, can_config.battery); + //Has the effect of zeroing AH and KWH + Serial.println("ISA RESTART"); + + outframe.data.u8[0] = 0x3F; + outframe.data.u8[1] = 0x00; + outframe.data.u8[2] = 0x00; + outframe.data.u8[3] = 0x00; + outframe.data.u8[4] = 0x00; + outframe.data.u8[5] = 0x00; + outframe.data.u8[6] = 0x00; + outframe.data.u8[7] = 0x00; + + transmit_can(&outframe, can_config.battery); } void ISA_deFAULT() { - //Returns module to original defaults - outframe.data.u8[0]=0x3D; - outframe.data.u8[1]=0x00; - outframe.data.u8[2]=0x00; - outframe.data.u8[3]=0x00; - outframe.data.u8[4]=0x00; - outframe.data.u8[5]=0x00; - outframe.data.u8[6]=0x00; - outframe.data.u8[7]=0x00; - transmit_can((&outframe, can_config.battery); + //Returns module to original defaults + ISA_STOP(); + delay(500); + + Serial.println("ISA RESTART to default"); + + outframe.data.u8[0]=0x3D; + outframe.data.u8[1]=0x00; + outframe.data.u8[2]=0x00; + outframe.data.u8[3]=0x00; + outframe.data.u8[4]=0x00; + outframe.data.u8[5]=0x00; + outframe.data.u8[6]=0x00; + outframe.data.u8[7]=0x00; + + transmit_can(&outframe, can_config.battery); + delay(500); + + ISA_START(); + delay(500); } void ISA_initCurrent() { - STOP(); - delay(500); + ISA_STOP(); + delay(500); - Serial.println("initialization \n"); - - outframe.data.u8[0]=0x21; - outframe.data.u8[1]=0x42; - outframe.data.u8[2]=0x01; - outframe.data.u8[3]=0x61; - outframe.data.u8[4]=0x00; - outframe.data.u8[5]=0x00; - outframe.data.u8[6]=0x00; - outframe.data.u8[7]=0x00; + Serial.println("ISA Initialization Current"); - transmit_can((&outframe, can_config.battery); + outframe.data.u8[0]=0x21; + outframe.data.u8[1]=0x02; + outframe.data.u8[2]=0x01; + outframe.data.u8[3]=0x61; + outframe.data.u8[4]=0x00; + outframe.data.u8[5]=0x00; + outframe.data.u8[6]=0x00; + outframe.data.u8[7]=0x00; - delay(500); + transmit_can(&outframe, can_config.battery); + delay(500); - sendSTORE(); - delay(500); + ISA_sendSTORE(); + delay(500); - START(); - delay(500); - lastAs=As; - lastWh=wh; + ISA_START(); + delay(500); + lastAs=As; + lastWh=wh; } -*/ -#endif +void ISA_getCONFIG(uint8_t i) { + Serial.print("ISA Get Config "); + Serial.println(i); + + outframe.data.u8[0] = (0x60+i); + outframe.data.u8[1] = 0x00; + outframe.data.u8[2] = 0x00; + outframe.data.u8[3] = 0x00; + outframe.data.u8[4] = 0x00; + outframe.data.u8[5] = 0x00; + outframe.data.u8[6] = 0x00; + outframe.data.u8[7] = 0x00; + + transmit_can(&outframe, can_config.battery); +} + +void ISA_getCAN_ID(uint8_t i) { + Serial.print("ISA Get CAN ID "); + Serial.println(i); + + outframe.data.u8[0] = (0x50+i); + if (i == 8) outframe.data.u8[0] = 0x5D; + if (i == 9) outframe.data.u8[0] = 0x5F; + outframe.data.u8[1] = 0x00; + outframe.data.u8[2] = 0x00; + outframe.data.u8[3] = 0x00; + outframe.data.u8[4] = 0x00; + outframe.data.u8[5] = 0x00; + outframe.data.u8[6] = 0x00; + outframe.data.u8[7] = 0x00; + + transmit_can(&outframe, can_config.battery); +} + +void ISA_getINFO(uint8_t i) { + Serial.print("ISA Get INFO "); + Serial.println(i,HEX); + + outframe.data.u8[0] = (0x70+i); + outframe.data.u8[1] = 0x00; + outframe.data.u8[2] = 0x00; + outframe.data.u8[3] = 0x00; + outframe.data.u8[4] = 0x00; + outframe.data.u8[5] = 0x00; + outframe.data.u8[6] = 0x00; + outframe.data.u8[7] = 0x00; + + transmit_can(&outframe, can_config.battery); +} +#endif \ No newline at end of file diff --git a/Software/src/battery/CHADEMO-SHUNTS.h b/Software/src/battery/CHADEMO-SHUNTS.h index 1abd9354..b4ebe3cb 100644 --- a/Software/src/battery/CHADEMO-SHUNTS.h +++ b/Software/src/battery/CHADEMO-SHUNTS.h @@ -5,7 +5,7 @@ uint16_t get_measured_voltage(); uint16_t get_measured_current(); -inline void ISA_handler(CAN_frame* frame); +void ISA_handleFrame(CAN_frame* frame); inline void ISA_handle521(CAN_frame* frame); inline void ISA_handle522(CAN_frame* frame); inline void ISA_handle523(CAN_frame* frame); @@ -14,6 +14,16 @@ inline void ISA_handle525(CAN_frame* frame); inline void ISA_handle526(CAN_frame* frame); inline void ISA_handle527(CAN_frame* frame); inline void ISA_handle528(CAN_frame* frame); +void ISA_initialize(); +void ISA_STOP(); +void ISA_sendSTORE(); +void ISA_START(); +void ISA_RESTART(); +void ISA_deFAULT(); +void ISA_initCurrent(); +void ISA_getCONFIG(uint8_t i); +void ISA_getCAN_ID(uint8_t i); +void ISA_getINFO(uint8_t i); void transmit_can(CAN_frame* tx_frame, int interface); diff --git a/Software/src/battery/IMIEV-CZERO-ION-BATTERY.cpp b/Software/src/battery/IMIEV-CZERO-ION-BATTERY.cpp index 43ef0b07..05e6e7c6 100644 --- a/Software/src/battery/IMIEV-CZERO-ION-BATTERY.cpp +++ b/Software/src/battery/IMIEV-CZERO-ION-BATTERY.cpp @@ -224,9 +224,8 @@ void send_can_battery() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("Mitsubishi i-MiEV / Citroen C-Zero / Peugeot Ion battery selected"); -#endif + strncpy(datalayer.system.info.battery_protocol, "I-Miev / C-Zero / Ion Triplet", 63); + datalayer.system.info.battery_protocol[63] = '\0'; 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.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV; diff --git a/Software/src/battery/JAGUAR-IPACE-BATTERY.cpp b/Software/src/battery/JAGUAR-IPACE-BATTERY.cpp index a083a8ce..eb13017c 100644 --- a/Software/src/battery/JAGUAR-IPACE-BATTERY.cpp +++ b/Software/src/battery/JAGUAR-IPACE-BATTERY.cpp @@ -254,10 +254,8 @@ void send_can_battery() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("Jaguar iPace 90kWh battery selected"); -#endif - + strncpy(datalayer.system.info.battery_protocol, "Jaguar I-PACE", 63); + datalayer.system.info.battery_protocol[63] = '\0'; datalayer.battery.info.number_of_cells = 108; 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/battery/KIA-E-GMP-BATTERY.cpp b/Software/src/battery/KIA-E-GMP-BATTERY.cpp index 19db7992..a0715a26 100644 --- a/Software/src/battery/KIA-E-GMP-BATTERY.cpp +++ b/Software/src/battery/KIA-E-GMP-BATTERY.cpp @@ -1037,14 +1037,12 @@ void send_can_battery() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("Hyundai E-GMP (Electric Global Modular Platform) battery selected"); -#endif + strncpy(datalayer.system.info.battery_protocol, "Kia/Hyundai EGMP platform", 63); + datalayer.system.info.battery_protocol[63] = '\0'; startMillis = millis(); // Record the starting time datalayer.system.status.battery_allows_contactor_closing = true; - datalayer.battery.info.number_of_cells = 192; // TODO: will vary depending on battery 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/battery/KIA-HYUNDAI-64-BATTERY.cpp b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp index b3f935a6..3a6663c6 100644 --- a/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp +++ b/Software/src/battery/KIA-HYUNDAI-64-BATTERY.cpp @@ -534,9 +534,8 @@ void send_can_battery() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("Kia Niro / Hyundai Kona 64kWh battery selected"); -#endif + strncpy(datalayer.system.info.battery_protocol, "Kia/Hyundai 64/40kWh battery", 63); + datalayer.system.info.battery_protocol[63] = '\0'; datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_98S_DV; //Start with 98S 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; diff --git a/Software/src/battery/KIA-HYUNDAI-HYBRID-BATTERY.cpp b/Software/src/battery/KIA-HYUNDAI-HYBRID-BATTERY.cpp index 49a8dae6..c37fcb15 100644 --- a/Software/src/battery/KIA-HYUNDAI-HYBRID-BATTERY.cpp +++ b/Software/src/battery/KIA-HYUNDAI-HYBRID-BATTERY.cpp @@ -257,9 +257,9 @@ void send_can_battery() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("Kia/Hyundai Hybrid battery selected"); -#endif + strncpy(datalayer.system.info.battery_protocol, "Kia/Hyundai Hybrid", 63); + datalayer.system.info.battery_protocol[63] = '\0'; + datalayer.battery.info.number_of_cells = 56; // HEV , TODO: Make dynamic according to HEV/PHEV 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/battery/MG-5-BATTERY.cpp b/Software/src/battery/MG-5-BATTERY.cpp index 8da1b9a2..35c8ee96 100644 --- a/Software/src/battery/MG-5-BATTERY.cpp +++ b/Software/src/battery/MG-5-BATTERY.cpp @@ -135,9 +135,8 @@ void send_can_battery() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("MG 5 battery selected"); -#endif + strncpy(datalayer.system.info.battery_protocol, "MG 5 battery", 63); + datalayer.system.info.battery_protocol[63] = '\0'; 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/battery/NISSAN-LEAF-BATTERY.cpp b/Software/src/battery/NISSAN-LEAF-BATTERY.cpp index f32a9ba6..429d8681 100644 --- a/Software/src/battery/NISSAN-LEAF-BATTERY.cpp +++ b/Software/src/battery/NISSAN-LEAF-BATTERY.cpp @@ -174,11 +174,17 @@ static int16_t battery2_temp_polled_max = 0; static int16_t battery2_temp_polled_min = 0; #endif // DOUBLE_BATTERY -void print_with_units(char* header, int value, char* units) { - Serial.print(header); - Serial.print(value); - Serial.print(units); -} +// Clear SOH values +static uint8_t stateMachineClearSOH = 0xFF; +static uint32_t incomingChallenge = 0xFFFFFFFF; +static uint8_t solvedChallenge[8]; +static bool challengeFailed = false; + +CAN_frame LEAF_CLEAR_SOH = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x79B, + .data = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; void update_values_battery() { /* This function maps all the values fetched via CAN to the correct parameters used for modbus */ /* Start with mapping all values */ @@ -334,17 +340,18 @@ void update_values_battery() { /* This function maps all the values fetched via datalayer_extended.nissanleaf.HeatingStop = battery_Heating_Stop; datalayer_extended.nissanleaf.HeatingStart = battery_Heating_Start; datalayer_extended.nissanleaf.HeaterSendRequest = battery_Batt_Heater_Mail_Send_Request; + datalayer_extended.nissanleaf.CryptoChallenge = incomingChallenge; + datalayer_extended.nissanleaf.SolvedChallengeMSB = + ((solvedChallenge[7] << 24) | (solvedChallenge[6] << 16) | (solvedChallenge[5] << 8) | solvedChallenge[4]); + datalayer_extended.nissanleaf.SolvedChallengeLSB = + ((solvedChallenge[3] << 24) | (solvedChallenge[2] << 16) | (solvedChallenge[1] << 8) | solvedChallenge[0]); + datalayer_extended.nissanleaf.challengeFailed = challengeFailed; -/*Finally print out values to serial if configured to do so*/ -#ifdef DEBUG_VIA_USB - Serial.println("Values from battery"); - print_with_units("Real SOC%: ", (battery_SOC * 0.1), "% "); - print_with_units(", GIDS: ", battery_GIDS, " (x77Wh) "); - print_with_units(", Battery gen: ", LEAF_battery_Type, " "); - print_with_units(", Has heater: ", battery_HeatExist, " "); - print_with_units(", Max cell voltage: ", battery_min_max_voltage[1], "mV "); - print_with_units(", Min cell voltage: ", battery_min_max_voltage[0], "mV "); -#endif + // Update requests from webserver datalayer + if (datalayer_extended.nissanleaf.UserRequestSOHreset) { + stateMachineClearSOH = 0; //Start the statemachine + datalayer_extended.nissanleaf.UserRequestSOHreset = false; + } } #ifdef DOUBLE_BATTERY @@ -603,7 +610,7 @@ void receive_can_battery2(CAN_frame rx_frame) { } } - if (stop_battery_query) { //Leafspy is active, stop our own polling + if (stop_battery_query) { //Leafspy/Service request is active, stop our own polling break; } @@ -840,6 +847,22 @@ void receive_can_battery(CAN_frame rx_frame) { hold_off_with_polling_10seconds = 10; //Polling is paused for 100s break; case 0x7BB: + + // This section checks if we are doing a SOH reset towards BMS + if (stateMachineClearSOH < 255) { + //Intercept the messages based on state machine + if (rx_frame.data.u8[0] == 0x06) { // Incoming challenge data! + // BMS should reply with (challenge) 06 67 65 (02 DD 86 43) FF + incomingChallenge = ((rx_frame.data.u8[3] << 24) | (rx_frame.data.u8[4] << 16) | (rx_frame.data.u8[5] << 8) | + rx_frame.data.u8[6]); + } + //Error checking + if ((rx_frame.data.u8[0] == 0x03) && (rx_frame.data.u8[1] == 0x7F)) { + challengeFailed = true; + } + break; + } + //First check which group data we are getting if (rx_frame.data.u8[0] == 0x10) { //First message of a group group_7bb = rx_frame.data.u8[3]; @@ -1120,6 +1143,10 @@ void send_can_battery() { if (currentMillis - previousMillis100 >= INTERVAL_100_MS) { previousMillis100 = currentMillis; + if (stateMachineClearSOH < 255) { // Enter the ClearSOH statemachine only if we request it + clearSOH(); + } + //When battery requests heating pack status change, ack this if (battery_Batt_Heater_Mail_Send_Request) { LEAF_50B.data.u8[6] = 0x20; //Batt_Heater_Mail_Send_OK @@ -1223,10 +1250,189 @@ uint16_t Temp_fromRAW_to_F(uint16_t temperature) { //This function feels horrib return static_cast(1094 + (309 - temperature) * 2.5714285714285715); } +void clearSOH(void) { + stop_battery_query = true; + hold_off_with_polling_10seconds = 10; // Active battery polling is paused for 100 seconds + + switch (stateMachineClearSOH) { + case 0: // Wait until polling actually stops + challengeFailed = false; + stateMachineClearSOH = 1; + break; + case 1: // Set CAN_PROCESS_FLAG to 0xC0 + LEAF_CLEAR_SOH.data = {0x02, 0x10, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00}; + transmit_can(&LEAF_CLEAR_SOH, can_config.battery); + // BMS should reply 02 50 C0 FF FF FF FF FF + stateMachineClearSOH = 2; + break; + case 2: // Set something ? + LEAF_CLEAR_SOH.data = {0x02, 0x3E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; + transmit_can(&LEAF_CLEAR_SOH, can_config.battery); + // BMS should reply 7E FF FF FF FF FF FF + stateMachineClearSOH = 3; + break; + case 3: // Request challenge to solve + LEAF_CLEAR_SOH.data = {0x02, 0x27, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00}; + transmit_can(&LEAF_CLEAR_SOH, can_config.battery); + // BMS should reply with (challenge) 06 67 65 (02 DD 86 43) FF + stateMachineClearSOH = 4; + break; + case 4: // Send back decoded challenge data + decodeChallengeData(incomingChallenge, solvedChallenge); + LEAF_CLEAR_SOH.data = { + 0x10, 0x0A, 0x27, 0x66, solvedChallenge[0], solvedChallenge[1], solvedChallenge[2], solvedChallenge[3]}; + transmit_can(&LEAF_CLEAR_SOH, can_config.battery); + // BMS should reply 7BB 8 30 01 00 FF FF FF FF FF // Proceed with more data (PID ACK) + stateMachineClearSOH = 5; + break; + case 5: // Reply with even more decoded challenge data + LEAF_CLEAR_SOH.data = { + 0x21, solvedChallenge[4], solvedChallenge[5], solvedChallenge[6], solvedChallenge[7], 0x00, 0x00, 0x00}; + transmit_can(&LEAF_CLEAR_SOH, can_config.battery); + // BMS should reply 02 67 66 FF FF FF FF FF // Thank you for the data + stateMachineClearSOH = 6; + break; + case 6: // Check if solved data was OK + LEAF_CLEAR_SOH.data = {0x03, 0x31, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}; + transmit_can(&LEAF_CLEAR_SOH, can_config.battery); + //7BB 8 03 71 03 01 FF FF FF FF // If all is well, BMS replies with 03 71 03 01. + //Incase you sent wrong challenge, you get 03 7f 31 12 + stateMachineClearSOH = 7; + break; + case 7: // Reset SOH% request + LEAF_CLEAR_SOH.data = {0x03, 0x31, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00}; + transmit_can(&LEAF_CLEAR_SOH, can_config.battery); + //7BB 8 03 71 03 02 FF FF FF FF // 03 71 03 02 means that BMS accepted command. + //7BB 03 7f 31 12 means your challenge was wrong, so command ignored + stateMachineClearSOH = 8; + break; + case 8: // Please proceed with resetting SOH + LEAF_CLEAR_SOH.data = {0x02, 0x10, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00}; + transmit_can(&LEAF_CLEAR_SOH, can_config.battery); + // 7BB 8 02 50 81 FF FF FF FF FF // SOH reset OK + stateMachineClearSOH = 255; + break; + default: + break; + } +} + +unsigned int CyclicXorHash16Bit(unsigned int param_1, unsigned int param_2) { + bool bVar1; + unsigned int uVar2, uVar3, uVar4, uVar5, uVar6, uVar7, uVar8, uVar9, uVar10, uVar11, iVar12; + + param_1 = param_1 & 0xffff; + param_2 = param_2 & 0xffff; + uVar10 = 0xffff; + iVar12 = 2; + do { + uVar2 = param_2; + if ((param_1 & 1) == 1) { + uVar2 = param_1 >> 1; + } + uVar3 = param_2; + if ((param_1 >> 1 & 1) == 1) { + uVar3 = param_1 >> 2; + } + uVar4 = param_2; + if ((param_1 >> 2 & 1) == 1) { + uVar4 = param_1 >> 3; + } + uVar5 = param_2; + if ((param_1 >> 3 & 1) == 1) { + uVar5 = param_1 >> 4; + } + uVar6 = param_2; + if ((param_1 >> 4 & 1) == 1) { + uVar6 = param_1 >> 5; + } + uVar7 = param_2; + if ((param_1 >> 5 & 1) == 1) { + uVar7 = param_1 >> 6; + } + uVar11 = param_1 >> 7; + uVar8 = param_2; + if ((param_1 >> 6 & 1) == 1) { + uVar8 = uVar11; + } + param_1 = param_1 >> 8; + uVar9 = param_2; + if ((uVar11 & 1) == 1) { + uVar9 = param_1; + } + uVar10 = + (((((((((((((((uVar10 & 0x7fff) << 1 ^ uVar2) & 0x7fff) << 1 ^ uVar3) & 0x7fff) << 1 ^ uVar4) & 0x7fff) << 1 ^ + uVar5) & + 0x7fff) + << 1 ^ + uVar6) & + 0x7fff) + << 1 ^ + uVar7) & + 0x7fff) + << 1 ^ + uVar8) & + 0x7fff) + << 1 ^ + uVar9; + bVar1 = iVar12 != 1; + iVar12 = iVar12 + -1; + } while (bVar1); + return uVar10; +} +unsigned int ComputeMaskedXorProduct(unsigned int param_1, unsigned int param_2, unsigned int param_3) { + return (param_3 ^ 0x7F88 | param_2 ^ 0x8FE7) * ((param_1 & 0xffff) >> 8 ^ param_1 & 0xff) & 0xffff; +} + +short ShortMaskedSumAndProduct(short param_1, short param_2) { + unsigned short uVar1; + + uVar1 = param_2 + param_1 * 0x0006 & 0xff; + return (uVar1 + param_1) * (uVar1 + param_2); +} + +unsigned int MaskedBitwiseRotateMultiply(unsigned int param_1, unsigned int param_2) { + unsigned int uVar1; + + param_1 = param_1 & 0xffff; + param_2 = param_2 & 0xffff; + uVar1 = param_2 & (param_1 | 0x0006) & 0xf; + return ((unsigned int)param_1 >> uVar1 | param_1 << (0x10 - uVar1 & 0x1f)) * + (param_2 << uVar1 | (unsigned int)param_2 >> (0x10 - uVar1 & 0x1f)) & + 0xffff; +} + +unsigned int CryptAlgo(unsigned int param_1, unsigned int param_2, unsigned int param_3) { + unsigned int uVar1, uVar2, iVar3, iVar4; + + uVar1 = MaskedBitwiseRotateMultiply(param_2, param_3); + uVar2 = ShortMaskedSumAndProduct(param_2, param_3); + uVar1 = ComputeMaskedXorProduct(param_1, uVar1, uVar2); + uVar2 = ComputeMaskedXorProduct(param_1, uVar2, uVar1); + iVar3 = CyclicXorHash16Bit(uVar1, 0x8421); + iVar4 = CyclicXorHash16Bit(uVar2, 0x8421); + return iVar4 + iVar3 * 0x10000; +} + +void decodeChallengeData(unsigned int incomingChallenge, unsigned char* solvedChallenge) { + unsigned int uVar1, uVar2; + + uVar1 = CryptAlgo(0x54e9, 0x3afd, incomingChallenge >> 0x10); + uVar2 = CryptAlgo(incomingChallenge & 0xffff, incomingChallenge >> 0x10, 0x54e9); + *solvedChallenge = (unsigned char)uVar1; + solvedChallenge[1] = (unsigned char)uVar2; + solvedChallenge[2] = (unsigned char)((unsigned int)uVar2 >> 8); + solvedChallenge[3] = (unsigned char)((unsigned int)uVar1 >> 8); + solvedChallenge[4] = (unsigned char)((unsigned int)uVar2 >> 0x10); + solvedChallenge[5] = (unsigned char)((unsigned int)uVar1 >> 0x10); + solvedChallenge[6] = (unsigned char)((unsigned int)uVar2 >> 0x18); + solvedChallenge[7] = (unsigned char)((unsigned int)uVar1 >> 0x18); + return; +} + void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("Nissan LEAF battery selected"); -#endif + 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; diff --git a/Software/src/battery/NISSAN-LEAF-BATTERY.h b/Software/src/battery/NISSAN-LEAF-BATTERY.h index 89ff4443..245f0f39 100644 --- a/Software/src/battery/NISSAN-LEAF-BATTERY.h +++ b/Software/src/battery/NISSAN-LEAF-BATTERY.h @@ -14,5 +14,13 @@ uint16_t Temp_fromRAW_to_F(uint16_t temperature); bool is_message_corrupt(CAN_frame rx_frame); void setup_battery(void); void transmit_can(CAN_frame* tx_frame, int interface); +void clearSOH(void); +//Cryptographic functions +void decodeChallengeData(unsigned int SeedInput, unsigned char* Crypt_Output_Buffer); +unsigned int CyclicXorHash16Bit(unsigned int param_1, unsigned int param_2); +unsigned int ComputeMaskedXorProduct(unsigned int param_1, unsigned int param_2, unsigned int param_3); +short ShortMaskedSumAndProduct(short param_1, short param_2); +unsigned int MaskedBitwiseRotateMultiply(unsigned int param_1, unsigned int param_2); +unsigned int CryptAlgo(unsigned int param_1, unsigned int param_2, unsigned int param_3); #endif diff --git a/Software/src/battery/PYLON-BATTERY.cpp b/Software/src/battery/PYLON-BATTERY.cpp index 16906722..ec61901d 100644 --- a/Software/src/battery/PYLON-BATTERY.cpp +++ b/Software/src/battery/PYLON-BATTERY.cpp @@ -175,10 +175,8 @@ void send_can_battery() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("Pylon battery selected"); -#endif - + strncpy(datalayer.system.info.battery_protocol, "Pylon compatible battery", 63); + datalayer.system.info.battery_protocol[63] = '\0'; 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.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV; diff --git a/Software/src/battery/RANGE-ROVER-PHEV-BATTERY.cpp b/Software/src/battery/RANGE-ROVER-PHEV-BATTERY.cpp index 4f6eb16c..4ca3a330 100644 --- a/Software/src/battery/RANGE-ROVER-PHEV-BATTERY.cpp +++ b/Software/src/battery/RANGE-ROVER-PHEV-BATTERY.cpp @@ -313,10 +313,8 @@ void send_can_battery() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("Range Rover PHEV battery (L494 / L405) selected"); -#endif //DEBUG_VIA_USB - + strncpy(datalayer.system.info.battery_protocol, "Range Rover 13kWh PHEV battery (L494/L405)", 63); + datalayer.system.info.battery_protocol[63] = '\0'; 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.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV; diff --git a/Software/src/battery/RENAULT-KANGOO-BATTERY.cpp b/Software/src/battery/RENAULT-KANGOO-BATTERY.cpp index 00b4e12b..096cb629 100644 --- a/Software/src/battery/RENAULT-KANGOO-BATTERY.cpp +++ b/Software/src/battery/RENAULT-KANGOO-BATTERY.cpp @@ -234,9 +234,9 @@ void send_can_battery() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("Renault Kangoo battery selected"); -#endif + + strncpy(datalayer.system.info.battery_protocol, "Renault Kangoo", 63); + datalayer.system.info.battery_protocol[63] = '\0'; 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/battery/RENAULT-TWIZY.cpp b/Software/src/battery/RENAULT-TWIZY.cpp index 69a83316..b0140eff 100644 --- a/Software/src/battery/RENAULT-TWIZY.cpp +++ b/Software/src/battery/RENAULT-TWIZY.cpp @@ -132,10 +132,8 @@ void send_can_battery() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("Renault Twizy battery selected"); -#endif - + strncpy(datalayer.system.info.battery_protocol, "Renault Twizy", 63); + datalayer.system.info.battery_protocol[63] = '\0'; datalayer.battery.info.number_of_cells = 14; 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/battery/RENAULT-ZOE-GEN1-BATTERY.cpp b/Software/src/battery/RENAULT-ZOE-GEN1-BATTERY.cpp index 1044729f..ef9f54f8 100644 --- a/Software/src/battery/RENAULT-ZOE-GEN1-BATTERY.cpp +++ b/Software/src/battery/RENAULT-ZOE-GEN1-BATTERY.cpp @@ -518,9 +518,8 @@ void send_can_battery() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("Renault Zoe 22/40kWh battery selected"); -#endif + strncpy(datalayer.system.info.battery_protocol, "Renault Zoe Gen1 22/40kWh", 63); + datalayer.system.info.battery_protocol[63] = '\0'; datalayer.system.status.battery_allows_contactor_closing = true; datalayer.battery.info.number_of_cells = 96; datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_DV; diff --git a/Software/src/battery/RENAULT-ZOE-GEN2-BATTERY.cpp b/Software/src/battery/RENAULT-ZOE-GEN2-BATTERY.cpp index 50b09d2e..08ac57bf 100644 --- a/Software/src/battery/RENAULT-ZOE-GEN2-BATTERY.cpp +++ b/Software/src/battery/RENAULT-ZOE-GEN2-BATTERY.cpp @@ -385,9 +385,8 @@ void send_can_battery() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("Renault Zoe 50kWh battery selected"); -#endif + strncpy(datalayer.system.info.battery_protocol, "Renault Zoe Gen2 50kWh", 63); + datalayer.system.info.battery_protocol[63] = '\0'; datalayer.system.status.battery_allows_contactor_closing = true; datalayer.battery.info.number_of_cells = 96; datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_DV; diff --git a/Software/src/battery/RJXZS-BMS.cpp b/Software/src/battery/RJXZS-BMS.cpp index b75934c8..85b96434 100644 --- a/Software/src/battery/RJXZS-BMS.cpp +++ b/Software/src/battery/RJXZS-BMS.cpp @@ -570,10 +570,8 @@ void send_can_battery() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("RJXZS BMS selected"); -#endif - + strncpy(datalayer.system.info.battery_protocol, "RJXZS BMS, DIY battery", 63); + datalayer.system.info.battery_protocol[63] = '\0'; 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.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV; diff --git a/Software/src/battery/SANTA-FE-PHEV-BATTERY.cpp b/Software/src/battery/SANTA-FE-PHEV-BATTERY.cpp index 36b1a649..e6f27acc 100644 --- a/Software/src/battery/SANTA-FE-PHEV-BATTERY.cpp +++ b/Software/src/battery/SANTA-FE-PHEV-BATTERY.cpp @@ -402,9 +402,8 @@ uint8_t CalculateCRC8(CAN_frame rx_frame) { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("Hyundai Santa Fe PHEV battery selected"); -#endif + strncpy(datalayer.system.info.battery_protocol, "Santa Fe PHEV", 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/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.cpp b/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.cpp index 0f4ac135..41697c33 100644 --- a/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.cpp +++ b/Software/src/battery/SERIAL-LINK-RECEIVER-FROM-BATTERY.cpp @@ -219,7 +219,8 @@ void update_values_serial_link() { } void setup_battery(void) { - Serial.println("SERIAL_DATA_LINK_RECEIVER selected"); + strncpy(datalayer.system.info.battery_protocol, "Serial link to another LilyGo board", 63); + datalayer.system.info.battery_protocol[63] = '\0'; } // Needed to make the compiler happy void update_values_battery() {} diff --git a/Software/src/battery/TESLA-BATTERY.cpp b/Software/src/battery/TESLA-BATTERY.cpp index eaa01e1b..6e4ea6b1 100644 --- a/Software/src/battery/TESLA-BATTERY.cpp +++ b/Software/src/battery/TESLA-BATTERY.cpp @@ -1249,13 +1249,11 @@ void printDebugIfActive(uint8_t symbol, const char* message) { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("Tesla Model S/3/X/Y battery selected"); -#endif - datalayer.system.status.battery_allows_contactor_closing = true; #ifdef TESLA_MODEL_SX_BATTERY // Always use NCM/A mode on S/X packs + strncpy(datalayer.system.info.battery_protocol, "Tesla Model S/X", 63); + datalayer.system.info.battery_protocol[63] = '\0'; datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_SX_NCMA; datalayer.battery.info.min_design_voltage_dV = MIN_PACK_VOLTAGE_SX_NCMA; datalayer.battery.info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_NCA_NCM; @@ -1271,6 +1269,8 @@ void setup_battery(void) { // Performs one time setup at startup #endif // TESLA_MODEL_SX_BATTERY #ifdef TESLA_MODEL_3Y_BATTERY // Model 3/Y can be either LFP or NCM/A + strncpy(datalayer.system.info.battery_protocol, "Tesla Model 3/Y", 63); + datalayer.system.info.battery_protocol[63] = '\0'; #ifdef LFP_CHEMISTRY datalayer.battery.info.chemistry = battery_chemistry_enum::LFP; datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_3Y_LFP; diff --git a/Software/src/battery/TEST-FAKE-BATTERY.cpp b/Software/src/battery/TEST-FAKE-BATTERY.cpp index fdc35294..e69ddfb2 100644 --- a/Software/src/battery/TEST-FAKE-BATTERY.cpp +++ b/Software/src/battery/TEST-FAKE-BATTERY.cpp @@ -145,9 +145,8 @@ void send_can_battery() { void setup_battery(void) { // Performs one time setup at startup randomSeed(analogRead(0)); -#ifdef DEBUG_VIA_USB - Serial.println("Test mode with fake battery selected"); -#endif + strncpy(datalayer.system.info.battery_protocol, "Fake battery for testing purposes", 63); + datalayer.system.info.battery_protocol[63] = '\0'; datalayer.battery.info.max_design_voltage_dV = 4040; // 404.4V, over this, charging is not possible (goes into forced discharge) diff --git a/Software/src/battery/VOLVO-SPA-BATTERY.cpp b/Software/src/battery/VOLVO-SPA-BATTERY.cpp index efdbc0a0..839665c8 100644 --- a/Software/src/battery/VOLVO-SPA-BATTERY.cpp +++ b/Software/src/battery/VOLVO-SPA-BATTERY.cpp @@ -332,10 +332,8 @@ void send_can_battery() { } void setup_battery(void) { // Performs one time setup at startup -#ifdef DEBUG_VIA_USB - Serial.println("Volvo SPA XC40 Recharge / Polestar2 78kWh battery selected"); -#endif - + strncpy(datalayer.system.info.battery_protocol, "Volvo / Polestar 78kWh battery", 63); + datalayer.system.info.battery_protocol[63] = '\0'; datalayer.battery.info.number_of_cells = 108; 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/datalayer/datalayer.h b/Software/src/datalayer/datalayer.h index 5b198158..f925d30c 100644 --- a/Software/src/datalayer/datalayer.h +++ b/Software/src/datalayer/datalayer.h @@ -127,7 +127,10 @@ typedef struct { } DATALAYER_SHUNT_TYPE; typedef struct { - // TODO + /** array with type of battery used, for displaying on webserver */ + char battery_protocol[64] = {0}; + /** array with type of inverter used, for displaying on webserver */ + char inverter_protocol[64] = {0}; } DATALAYER_SYSTEM_INFO_TYPE; typedef struct { diff --git a/Software/src/datalayer/datalayer_extended.h b/Software/src/datalayer/datalayer_extended.h index 2009d60b..5370637c 100644 --- a/Software/src/datalayer/datalayer_extended.h +++ b/Software/src/datalayer/datalayer_extended.h @@ -223,6 +223,21 @@ typedef struct { /** bool */ /** Heat request sent*/ bool HeaterSendRequest = false; + /** bool */ + /** User requesting SOH reset via WebUI*/ + bool UserRequestSOHreset = false; + /** bool */ + /** True if the crypto challenge response from BMS is signalling a failed attempt*/ + bool challengeFailed = false; + /** uint32_t */ + /** Cryptographic challenge to be solved */ + uint32_t CryptoChallenge = 0; + /** uint32_t */ + /** Solution for crypto challenge, MSBs */ + uint32_t SolvedChallengeMSB = 0; + /** uint32_t */ + /** Solution for crypto challenge, LSBs */ + uint32_t SolvedChallengeLSB = 0; } DATALAYER_INFO_NISSAN_LEAF; diff --git a/Software/src/devboard/webserver/advanced_battery_html.cpp b/Software/src/devboard/webserver/advanced_battery_html.cpp index 5db01127..2a301a07 100644 --- a/Software/src/devboard/webserver/advanced_battery_html.cpp +++ b/Software/src/devboard/webserver/advanced_battery_html.cpp @@ -331,6 +331,11 @@ String advanced_battery_processor(const String& var) { content += "

Heating stopped: " + String(datalayer_extended.nissanleaf.HeatingStop) + "

"; content += "

Heating started: " + String(datalayer_extended.nissanleaf.HeatingStart) + "

"; content += "

Heating requested: " + String(datalayer_extended.nissanleaf.HeaterSendRequest) + "

"; + content += ""; + content += "

CryptoChallenge: " + String(datalayer_extended.nissanleaf.CryptoChallenge) + "

"; + content += "

SolvedChallenge: " + String(datalayer_extended.nissanleaf.SolvedChallengeMSB) + + String(datalayer_extended.nissanleaf.SolvedChallengeLSB) + "

"; + content += "

Challenge failed: " + String(datalayer_extended.nissanleaf.challengeFailed) + "

"; #endif #ifdef RENAULT_ZOE_GEN2_BATTERY @@ -388,6 +393,15 @@ String advanced_battery_processor(const String& var) { content += ""; content += ""; return content; diff --git a/Software/src/devboard/webserver/webserver.cpp b/Software/src/devboard/webserver/webserver.cpp index 8eab7631..ce4ec7d4 100644 --- a/Software/src/devboard/webserver/webserver.cpp +++ b/Software/src/devboard/webserver/webserver.cpp @@ -1,6 +1,7 @@ #include "webserver.h" #include #include "../../datalayer/datalayer.h" +#include "../../datalayer/datalayer_extended.h" #include "../../lib/bblanchon-ArduinoJson/ArduinoJson.h" #include "../utils/events.h" #include "../utils/led_handler.h" @@ -231,6 +232,15 @@ void init_webserver() { } }); + // Route for resetting SOH on Nissan LEAF batteries + server.on("/resetSOH", HTTP_GET, [](AsyncWebServerRequest* request) { + if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password)) { + return request->requestAuthentication(); + } + datalayer_extended.nissanleaf.UserRequestSOHreset = true; + request->send(200, "text/plain", "Updated successfully"); + }); + #ifdef TEST_FAKE_BATTERY // Route for editing FakeBatteryVoltage server.on("/updateFakeBatteryVoltage", HTTP_GET, [](AsyncWebServerRequest* request) { @@ -486,117 +496,16 @@ String processor(const String& var) { // Display which components are used content += "

Inverter protocol: "; -#ifdef BYD_CAN - content += "BYD Battery-Box Premium HVS over CAN Bus"; -#endif // BYD_CAN -#ifdef BYD_MODBUS - content += "BYD 11kWh HVM battery over Modbus RTU"; -#endif // BYD_MODBUS -#ifdef FOXESS_CAN - content += "FoxESS compatible HV2600/ECS4100 battery"; -#endif // FOXESS_CAN -#ifdef PYLON_CAN - content += "Pylontech battery over CAN bus"; -#endif // PYLON_CAN -#ifdef PYLON_LV_CAN - content += "Pylontech LV battery over CAN bus"; -#endif // PYLON_LV_CAN -#ifdef SERIAL_LINK_TRANSMITTER - content += "Serial link to another LilyGo board"; -#endif // SERIAL_LINK_TRANSMITTER -#ifdef SMA_CAN - content += "BYD Battery-Box H 8.9kWh, 7 mod over CAN bus"; -#endif // SMA_CAN -#ifdef SOFAR_CAN - content += "Sofar Energy Storage Inverter High Voltage BMS General Protocol (Extended Frame) over CAN bus"; -#endif // SOFAR_CAN -#ifdef SOLAX_CAN - content += "SolaX Triple Power LFP over CAN bus"; -#endif // SOLAX_CAN + content += datalayer.system.info.inverter_protocol; content += "

"; - content += "

Battery protocol: "; -#ifdef BMW_I3_BATTERY - content += "BMW i3"; -#endif // BMW_I3_BATTERY -#ifdef BMW_IX_BATTERY - content += "BMW iX and i4-7 platform"; -#endif // BMW_IX_BATTERY -#ifdef BYD_ATTO_3_BATTERY - content += "BYD Atto 3"; -#endif // BYD_ATTO_3_BATTERY -#ifdef CELLPOWER_BMS - content += "Cellpower BMS"; -#endif // CELLPOWER_BMS -#ifdef CHADEMO_BATTERY - content += "Chademo V2X mode"; -#endif // CHADEMO_BATTERY -#ifdef IMIEV_CZERO_ION_BATTERY - content += "I-Miev / C-Zero / Ion Triplet"; -#endif // IMIEV_CZERO_ION_BATTERY -#ifdef JAGUAR_IPACE_BATTERY - content += "Jaguar I-PACE"; -#endif // JAGUAR_IPACE_BATTERY -#ifdef KIA_HYUNDAI_64_BATTERY - content += "Kia/Hyundai 64kWh"; -#endif // KIA_HYUNDAI_64_BATTERY -#ifdef KIA_E_GMP_BATTERY - content += "Kia/Hyundai EGMP platform"; -#endif // KIA_E_GMP_BATTERY -#ifdef KIA_HYUNDAI_HYBRID_BATTERY - content += "Kia/Hyundai Hybrid"; -#endif // KIA_HYUNDAI_HYBRID_BATTERY -#ifdef MG_5_BATTERY - content += "MG 5"; -#endif // MG_5_BATTERY -#ifdef NISSAN_LEAF_BATTERY - content += "Nissan LEAF"; -#endif // NISSAN_LEAF_BATTERY -#ifdef PYLON_BATTERY - content += "Pylon compatible battery"; -#endif // PYLON_BATTERY -#ifdef RJXZS_BMS - content += "RJXZS BMS, DIY battery"; -#endif // RJXZS_BMS -#ifdef RANGE_ROVER_PHEV_BATTERY - content += "Range Rover 13kWh PHEV battery (L494/L405)"; -#endif //RANGE_ROVER_PHEV_BATTERY -#ifdef RENAULT_KANGOO_BATTERY - content += "Renault Kangoo"; -#endif // RENAULT_KANGOO_BATTERY -#ifdef RENAULT_TWIZY_BATTERY - content += "Renault Twizy"; -#endif // RENAULT_TWIZY_BATTERY -#ifdef RENAULT_ZOE_GEN1_BATTERY - content += "Renault Zoe Gen1 22/40"; -#endif // RENAULT_ZOE_GEN1_BATTERY -#ifdef RENAULT_ZOE_GEN2_BATTERY - content += "Renault Zoe Gen2 50"; -#endif // RENAULT_ZOE_GEN2_BATTERY -#ifdef SANTA_FE_PHEV_BATTERY - content += "Santa Fe PHEV"; -#endif // SANTA_FE_PHEV_BATTERY -#ifdef SERIAL_LINK_RECEIVER - content += "Serial link to another LilyGo board"; -#endif // SERIAL_LINK_RECEIVER -#ifdef TESLA_MODEL_SX_BATTERY - content += "Tesla Model S/X"; -#endif // TESLA_MODEL_SX_BATTERY -#ifdef TESLA_MODEL_3Y_BATTERY - content += "Tesla Model 3/Y"; -#endif // TESLA_MODEL_3Y_BATTERY -#ifdef VOLVO_SPA_BATTERY - content += "Volvo / Polestar 78kWh battery"; -#endif // VOLVO_SPA_BATTERY -#ifdef TEST_FAKE_BATTERY - content += "Fake battery for testing purposes"; -#endif // TEST_FAKE_BATTERY + content += datalayer.system.info.battery_protocol; #ifdef DOUBLE_BATTERY content += " (Double battery)"; +#endif // DOUBLE_BATTERY if (datalayer.battery.info.chemistry == battery_chemistry_enum::LFP) { content += " (LFP)"; } -#endif // DOUBLE_BATTERY content += "

"; #if defined CHEVYVOLT_CHARGER || defined NISSANLEAF_CHARGER diff --git a/Software/src/include.h b/Software/src/include.h index 83f2290d..b29345e6 100644 --- a/Software/src/include.h +++ b/Software/src/include.h @@ -45,10 +45,4 @@ #error No battery selected! Choose one from the USER_SETTINGS.h file #endif -#ifdef KIA_E_GMP_BATTERY -#ifndef CAN_FD -#error KIA HYUNDAI EGMP BATTERIES CANNOT BE USED WITHOUT CAN FD -#endif -#endif - #endif diff --git a/Software/src/inverter/AFORE-CAN.cpp b/Software/src/inverter/AFORE-CAN.cpp index 74435116..a8d551d7 100644 --- a/Software/src/inverter/AFORE-CAN.cpp +++ b/Software/src/inverter/AFORE-CAN.cpp @@ -233,4 +233,8 @@ void send_can_inverter() { time_to_send_info = false; } } +void setup_inverter(void) { // Performs one time setup at startup over CAN bus + strncpy(datalayer.system.info.inverter_protocol, "Afore battery over CAN", 63); + datalayer.system.info.inverter_protocol[63] = '\0'; +} #endif diff --git a/Software/src/inverter/AFORE-CAN.h b/Software/src/inverter/AFORE-CAN.h index cc9f8548..9829befc 100644 --- a/Software/src/inverter/AFORE-CAN.h +++ b/Software/src/inverter/AFORE-CAN.h @@ -4,8 +4,7 @@ #define CAN_INVERTER_SELECTED -void send_system_data(); -void send_setup_info(); void transmit_can(CAN_frame* tx_frame, int interface); +void setup_inverter(void); #endif diff --git a/Software/src/inverter/BYD-CAN.cpp b/Software/src/inverter/BYD-CAN.cpp index 5cf999a3..4ffa7b20 100644 --- a/Software/src/inverter/BYD-CAN.cpp +++ b/Software/src/inverter/BYD-CAN.cpp @@ -7,13 +7,6 @@ static unsigned long previousMillis2s = 0; // will store last time a 2s CAN Message was send static unsigned long previousMillis10s = 0; // will store last time a 10s CAN Message was send static unsigned long previousMillis60s = 0; // will store last time a 60s CAN Message was send -static uint8_t char1_151 = 0; -static uint8_t char2_151 = 0; -static uint8_t char3_151 = 0; -static uint8_t char4_151 = 0; -static uint8_t char5_151 = 0; -static uint8_t char6_151 = 0; -static uint8_t char7_151 = 0; CAN_frame BYD_250 = {.FD = false, .ext_ID = false, @@ -79,9 +72,12 @@ CAN_frame BYD_210 = {.FD = false, .ID = 0x210, .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; +static uint8_t inverter_name[7] = {0}; static int16_t temperature_average = 0; static uint16_t inverter_voltage = 0; static uint16_t inverter_SOC = 0; +static int16_t inverter_current = 0; +static int16_t inverter_temperature = 0; static uint16_t remaining_capacity_ah = 0; static uint16_t fully_charged_capacity_ah = 0; static long inverter_timestamp = 0; @@ -146,15 +142,12 @@ void update_values_can_inverter() { //This function maps all the values fetched BYD_210.data.u8[3] = (datalayer.battery.status.temperature_min_dC & 0x00FF); #ifdef DEBUG_VIA_USB - if (char1_151 != 0) { + if (inverter_name[0] != 0) { Serial.print("Detected inverter: "); - Serial.print((char)char1_151); - Serial.print((char)char2_151); - Serial.print((char)char3_151); - Serial.print((char)char4_151); - Serial.print((char)char5_151); - Serial.print((char)char6_151); - Serial.println((char)char7_151); + for (uint8_t i = 0; i < 7; i++) { + Serial.print((char)inverter_name[i]); + } + Serial.println(); } #endif } @@ -166,27 +159,25 @@ void receive_can_inverter(CAN_frame rx_frame) { if (rx_frame.data.u8[0] & 0x01) { //Battery requests identification send_intial_data(); } else { // We can identify what inverter type we are connected to - char1_151 = rx_frame.data.u8[1]; - char2_151 = rx_frame.data.u8[2]; - char3_151 = rx_frame.data.u8[3]; - char4_151 = rx_frame.data.u8[4]; - char5_151 = rx_frame.data.u8[5]; - char6_151 = rx_frame.data.u8[6]; - char7_151 = rx_frame.data.u8[7]; + for (uint8_t i = 0; i < 7; i++) { + inverter_name[i] = rx_frame.data.u8[i + 1]; + } } break; case 0x091: datalayer.system.status.CAN_inverter_still_alive = CAN_STILL_ALIVE; - inverter_voltage = ((rx_frame.data.u8[1] << 8) | rx_frame.data.u8[0]) * 0.1; + inverter_voltage = ((rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]) * 0.1; + inverter_current = ((rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]) * 0.1; + inverter_temperature = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 0.1; break; case 0x0D1: datalayer.system.status.CAN_inverter_still_alive = CAN_STILL_ALIVE; - inverter_SOC = ((rx_frame.data.u8[1] << 8) | rx_frame.data.u8[0]) * 0.1; + inverter_SOC = ((rx_frame.data.u8[0] << 8) | rx_frame.data.u8[1]) * 0.1; break; case 0x111: datalayer.system.status.CAN_inverter_still_alive = CAN_STILL_ALIVE; - inverter_timestamp = ((rx_frame.data.u8[3] << 24) | (rx_frame.data.u8[2] << 16) | (rx_frame.data.u8[1] << 8) | - rx_frame.data.u8[0]); + inverter_timestamp = ((rx_frame.data.u8[0] << 24) | (rx_frame.data.u8[1] << 16) | (rx_frame.data.u8[2] << 8) | + rx_frame.data.u8[3]); break; default: break; @@ -232,4 +223,8 @@ void send_intial_data() { transmit_can(&BYD_3D0_2, can_config.inverter); transmit_can(&BYD_3D0_3, can_config.inverter); } +void setup_inverter(void) { // Performs one time setup at startup over CAN bus + strncpy(datalayer.system.info.inverter_protocol, "BYD Battery-Box Premium HVS over CAN Bus", 63); + datalayer.system.info.inverter_protocol[63] = '\0'; +} #endif diff --git a/Software/src/inverter/BYD-CAN.h b/Software/src/inverter/BYD-CAN.h index 6a45317b..5a90d6ba 100644 --- a/Software/src/inverter/BYD-CAN.h +++ b/Software/src/inverter/BYD-CAN.h @@ -8,5 +8,6 @@ void send_intial_data(); void transmit_can(CAN_frame* tx_frame, int interface); +void setup_inverter(void); #endif diff --git a/Software/src/inverter/BYD-MODBUS.cpp b/Software/src/inverter/BYD-MODBUS.cpp index 7cee6b8d..814e24e4 100644 --- a/Software/src/inverter/BYD-MODBUS.cpp +++ b/Software/src/inverter/BYD-MODBUS.cpp @@ -143,4 +143,8 @@ void verify_inverter_modbus() { history_index = (history_index + 1) % HISTORY_LENGTH; } } +void setup_inverter(void) { // Performs one time setup at startup over CAN bus + strncpy(datalayer.system.info.inverter_protocol, "BYD 11kWh HVM battery over Modbus RTU", 63); + datalayer.system.info.inverter_protocol[63] = '\0'; +} #endif diff --git a/Software/src/inverter/BYD-MODBUS.h b/Software/src/inverter/BYD-MODBUS.h index 3d014daa..487c9784 100644 --- a/Software/src/inverter/BYD-MODBUS.h +++ b/Software/src/inverter/BYD-MODBUS.h @@ -14,4 +14,5 @@ void verify_temperature_modbus(); void verify_inverter_modbus(); void handle_update_data_modbusp201_byd(); void handle_update_data_modbusp301_byd(); +void setup_inverter(void); #endif diff --git a/Software/src/inverter/BYD-SMA.cpp b/Software/src/inverter/BYD-SMA.cpp index 230b61e7..34e33063 100644 --- a/Software/src/inverter/BYD-SMA.cpp +++ b/Software/src/inverter/BYD-SMA.cpp @@ -251,4 +251,10 @@ void send_can_inverter() { } } } +void setup_inverter(void) { // Performs one time setup at startup over CAN bus + strncpy(datalayer.system.info.inverter_protocol, "BYD Battery-Box HVS over SMA CAN", 63); + datalayer.system.info.inverter_protocol[63] = '\0'; + datalayer.system.status.inverter_allows_contactor_closing = false; // The inverter needs to allow first + pinMode(INVERTER_CONTACTOR_ENABLE_PIN, INPUT); +} #endif diff --git a/Software/src/inverter/BYD-SMA.h b/Software/src/inverter/BYD-SMA.h index b71a60fa..e787191d 100644 --- a/Software/src/inverter/BYD-SMA.h +++ b/Software/src/inverter/BYD-SMA.h @@ -8,5 +8,6 @@ #define STOP_STATE 0x02 void transmit_can(CAN_frame* tx_frame, int interface); +void setup_inverter(void); #endif diff --git a/Software/src/inverter/FOXESS-CAN.cpp b/Software/src/inverter/FOXESS-CAN.cpp index e4b3b34c..e23f9006 100644 --- a/Software/src/inverter/FOXESS-CAN.cpp +++ b/Software/src/inverter/FOXESS-CAN.cpp @@ -737,4 +737,8 @@ void receive_can_inverter(CAN_frame rx_frame) { } } } +void setup_inverter(void) { // Performs one time setup at startup over CAN bus + strncpy(datalayer.system.info.inverter_protocol, "FoxESS compatible HV2600/ECS4100 battery", 63); + datalayer.system.info.inverter_protocol[63] = '\0'; +} #endif diff --git a/Software/src/inverter/FOXESS-CAN.h b/Software/src/inverter/FOXESS-CAN.h index d9a3da2d..365a559d 100644 --- a/Software/src/inverter/FOXESS-CAN.h +++ b/Software/src/inverter/FOXESS-CAN.h @@ -5,5 +5,6 @@ #define CAN_INVERTER_SELECTED void transmit_can(CAN_frame* tx_frame, int interface); +void setup_inverter(void); #endif diff --git a/Software/src/inverter/PYLON-CAN.cpp b/Software/src/inverter/PYLON-CAN.cpp index 2b8e036c..2145b3e7 100644 --- a/Software/src/inverter/PYLON-CAN.cpp +++ b/Software/src/inverter/PYLON-CAN.cpp @@ -477,4 +477,8 @@ void send_system_data() { //System equipment information transmit_can(&PYLON_4291, can_config.inverter); #endif } +void setup_inverter(void) { // Performs one time setup at startup over CAN bus + strncpy(datalayer.system.info.inverter_protocol, "Pylontech battery over CAN bus", 63); + datalayer.system.info.inverter_protocol[63] = '\0'; +} #endif diff --git a/Software/src/inverter/PYLON-CAN.h b/Software/src/inverter/PYLON-CAN.h index 86bb4afa..6b39afcd 100644 --- a/Software/src/inverter/PYLON-CAN.h +++ b/Software/src/inverter/PYLON-CAN.h @@ -7,5 +7,6 @@ void send_system_data(); void send_setup_info(); void transmit_can(CAN_frame* tx_frame, int interface); +void setup_inverter(void); #endif diff --git a/Software/src/inverter/PYLON-LV-CAN.cpp b/Software/src/inverter/PYLON-LV-CAN.cpp index 458ac7a0..e5eb2e87 100644 --- a/Software/src/inverter/PYLON-LV-CAN.cpp +++ b/Software/src/inverter/PYLON-LV-CAN.cpp @@ -133,4 +133,8 @@ void send_can_inverter() { transmit_can(&PYLON_35E, can_config.inverter); } } +void setup_inverter(void) { // Performs one time setup at startup over CAN bus + strncpy(datalayer.system.info.inverter_protocol, "Pylontech LV battery over CAN bus", 63); + datalayer.system.info.inverter_protocol[63] = '\0'; +} #endif diff --git a/Software/src/inverter/PYLON-LV-CAN.h b/Software/src/inverter/PYLON-LV-CAN.h index 45376d2b..ca6922eb 100644 --- a/Software/src/inverter/PYLON-LV-CAN.h +++ b/Software/src/inverter/PYLON-LV-CAN.h @@ -12,5 +12,6 @@ void send_system_data(); void send_setup_info(); void transmit_can(CAN_frame* tx_frame, int interface); +void setup_inverter(void); #endif diff --git a/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.cpp b/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.cpp index 6d3b5071..a61ea7dc 100644 --- a/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.cpp +++ b/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.cpp @@ -128,6 +128,8 @@ void manageSerialLinkTransmitter() { static unsigned long updateDataTime = 0; if (currentTime - updateDataTime > INTERVAL_1_S) { + strncpy(datalayer.system.info.inverter_protocol, "Serial link to another LilyGo board", 63); + datalayer.system.info.inverter_protocol[63] = '\0'; updateDataTime = currentTime; dataLinkTransmit.updateData(0, datalayer.battery.status.real_soc); dataLinkTransmit.updateData(1, datalayer.battery.status.soh_pptt); diff --git a/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h b/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h index 14ae08d7..1637e6bd 100644 --- a/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h +++ b/Software/src/inverter/SERIAL-LINK-TRANSMITTER-INVERTER.h @@ -6,5 +6,6 @@ #include "../lib/mackelec-SerialDataLink/SerialDataLink.h" void manageSerialLinkTransmitter(); +void setup_inverter(void); #endif diff --git a/Software/src/inverter/SMA-CAN.cpp b/Software/src/inverter/SMA-CAN.cpp index cecae60c..5831406d 100644 --- a/Software/src/inverter/SMA-CAN.cpp +++ b/Software/src/inverter/SMA-CAN.cpp @@ -249,4 +249,9 @@ void send_can_inverter() { } } } + +void setup_inverter(void) { // Performs one time setup at startup over CAN bus + strncpy(datalayer.system.info.inverter_protocol, "SMA CAN", 63); + datalayer.system.info.inverter_protocol[63] = '\0'; +} #endif diff --git a/Software/src/inverter/SMA-CAN.h b/Software/src/inverter/SMA-CAN.h index 73b9f160..111044a4 100644 --- a/Software/src/inverter/SMA-CAN.h +++ b/Software/src/inverter/SMA-CAN.h @@ -8,5 +8,6 @@ #define STOP_STATE 0x02 void transmit_can(CAN_frame* tx_frame, int interface); +void setup_inverter(void); #endif diff --git a/Software/src/inverter/SMA-TRIPOWER-CAN.cpp b/Software/src/inverter/SMA-TRIPOWER-CAN.cpp index 9c0cc279..7a242dae 100644 --- a/Software/src/inverter/SMA-TRIPOWER-CAN.cpp +++ b/Software/src/inverter/SMA-TRIPOWER-CAN.cpp @@ -320,4 +320,9 @@ void send_tripower_init() { transmit_can(&SMA_017, can_config.inverter); // Battery Manufacturer transmit_can(&SMA_018, can_config.inverter); // Battery Name } + +void setup_inverter(void) { // Performs one time setup at startup over CAN bus + strncpy(datalayer.system.info.inverter_protocol, "SMA Tripower CAN", 63); + datalayer.system.info.inverter_protocol[63] = '\0'; +} #endif diff --git a/Software/src/inverter/SMA-TRIPOWER-CAN.h b/Software/src/inverter/SMA-TRIPOWER-CAN.h index e12692da..90967001 100644 --- a/Software/src/inverter/SMA-TRIPOWER-CAN.h +++ b/Software/src/inverter/SMA-TRIPOWER-CAN.h @@ -6,5 +6,6 @@ void send_tripower_init(); void transmit_can(CAN_frame* tx_frame, int interface); +void setup_inverter(void); #endif diff --git a/Software/src/inverter/SOFAR-CAN.cpp b/Software/src/inverter/SOFAR-CAN.cpp index eb13b7c5..838ebf93 100644 --- a/Software/src/inverter/SOFAR-CAN.cpp +++ b/Software/src/inverter/SOFAR-CAN.cpp @@ -263,4 +263,9 @@ void send_can_inverter() { transmit_can(&SOFAR_35A, can_config.inverter); } } + +void setup_inverter(void) { // Performs one time setup at startup over CAN bus + strncpy(datalayer.system.info.inverter_protocol, "Sofar BMS (Extended Frame) over CAN bus", 63); + datalayer.system.info.inverter_protocol[63] = '\0'; +} #endif diff --git a/Software/src/inverter/SOFAR-CAN.h b/Software/src/inverter/SOFAR-CAN.h index 6d43222f..7a80bf62 100644 --- a/Software/src/inverter/SOFAR-CAN.h +++ b/Software/src/inverter/SOFAR-CAN.h @@ -5,5 +5,6 @@ #define CAN_INVERTER_SELECTED void transmit_can(CAN_frame* tx_frame, int interface); +void setup_inverter(void); #endif diff --git a/Software/src/inverter/SOLAX-CAN.cpp b/Software/src/inverter/SOLAX-CAN.cpp index 790c8524..9bef56ec 100644 --- a/Software/src/inverter/SOLAX-CAN.cpp +++ b/Software/src/inverter/SOLAX-CAN.cpp @@ -252,4 +252,9 @@ void receive_can_inverter(CAN_frame rx_frame) { #endif } } +void setup_inverter(void) { // Performs one time setup at startup + strncpy(datalayer.system.info.inverter_protocol, "SolaX Triple Power LFP over CAN bus", 63); + datalayer.system.info.inverter_protocol[63] = '\0'; + datalayer.system.status.inverter_allows_contactor_closing = false; // The inverter needs to allow first +} #endif diff --git a/Software/src/inverter/SOLAX-CAN.h b/Software/src/inverter/SOLAX-CAN.h index 6ad461a7..68373ec2 100644 --- a/Software/src/inverter/SOLAX-CAN.h +++ b/Software/src/inverter/SOLAX-CAN.h @@ -15,5 +15,6 @@ #define UPDATING_FW 4 void transmit_can(CAN_frame* tx_frame, int interface); +void setup_inverter(void); #endif From 18e09918207aee37fcc76380885d9485607dc2e0 Mon Sep 17 00:00:00 2001 From: NJbubo Date: Sun, 17 Nov 2024 21:24:04 +0100 Subject: [PATCH 6/7] =?UTF-8?q?Removed=20the=20intervalUpdateValues=20?= =?UTF-8?q?=E2=80=8B=E2=80=8B=3D=20800=20line=20(commented).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Software/src/battery/CHADEMO-BATTERY.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Software/src/battery/CHADEMO-BATTERY.cpp b/Software/src/battery/CHADEMO-BATTERY.cpp index f445724d..5207806c 100644 --- a/Software/src/battery/CHADEMO-BATTERY.cpp +++ b/Software/src/battery/CHADEMO-BATTERY.cpp @@ -1032,7 +1032,7 @@ void handle_chademo_sequence() { void setup_battery(void) { // Performs one time setup at startup - intervalUpdateValues = 800; // This mode requires the values to be updated faster +// intervalUpdateValues = 800; // This mode requires the values to be updated faster pinMode(CHADEMO_PIN_2, OUTPUT); digitalWrite(CHADEMO_PIN_2, LOW); pinMode(CHADEMO_PIN_10, OUTPUT); From eb850e616c3e4715ad6f3a97ce2d73432954caa1 Mon Sep 17 00:00:00 2001 From: NJbubo Date: Thu, 21 Nov 2024 01:22:11 +0100 Subject: [PATCH 7/7] =?UTF-8?q?I=20use=20pre-commit.=20Removed=20=20interv?= =?UTF-8?q?alUpdateValues=20=E2=80=8B=E2=80=8B=3D=20800=20row.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Software/src/battery/CHADEMO-BATTERY.cpp | 7 +- Software/src/battery/CHADEMO-SHUNTS.cpp | 88 ++++++++++++------------ 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/Software/src/battery/CHADEMO-BATTERY.cpp b/Software/src/battery/CHADEMO-BATTERY.cpp index 5207806c..14720065 100644 --- a/Software/src/battery/CHADEMO-BATTERY.cpp +++ b/Software/src/battery/CHADEMO-BATTERY.cpp @@ -1032,7 +1032,6 @@ void handle_chademo_sequence() { void setup_battery(void) { // Performs one time setup at startup -// intervalUpdateValues = 800; // This mode requires the values to be updated faster pinMode(CHADEMO_PIN_2, OUTPUT); digitalWrite(CHADEMO_PIN_2, LOW); pinMode(CHADEMO_PIN_10, OUTPUT); @@ -1085,9 +1084,9 @@ void setup_battery(void) { // Performs one time setup at startup x109_evse_state.s.status.ChgDischStopControl = 1; handle_chademo_sequence(); -// ISA_deFAULT(); // ISA Setup - it is sufficient to set it once, because it is saved in SUNT -// ISA_initialize(); // ISA Setup - it is sufficient to set it once, because it is saved in SUNT -// ISA_RESTART(); + // ISA_deFAULT(); // ISA Setup - it is sufficient to set it once, because it is saved in SUNT + // ISA_initialize(); // ISA Setup - it is sufficient to set it once, because it is saved in SUNT + // ISA_RESTART(); setupMillis = millis(); } diff --git a/Software/src/battery/CHADEMO-SHUNTS.cpp b/Software/src/battery/CHADEMO-SHUNTS.cpp index 34dfb734..6ca55ca7 100644 --- a/Software/src/battery/CHADEMO-SHUNTS.cpp +++ b/Software/src/battery/CHADEMO-SHUNTS.cpp @@ -241,21 +241,21 @@ inline void ISA_handle528(CAN_frame* frame) { } void ISA_initialize() { - firstframe=false; + firstframe = false; ISA_STOP(); delay(500); - for(int i=0;i<8;i++) { + for (int i = 0; i < 8; i++) { Serial.print("ISA Initialization "); Serial.println(i); - outframe.data.u8[0]=(0x20+i); - outframe.data.u8[1]=0x02; - outframe.data.u8[2]=0x02; - outframe.data.u8[3]=(0x60+(i*18)); - outframe.data.u8[4]=0x00; - outframe.data.u8[5]=0x00; - outframe.data.u8[6]=0x00; - outframe.data.u8[7]=0x00; + outframe.data.u8[0] = (0x20 + i); + outframe.data.u8[1] = 0x02; + outframe.data.u8[2] = 0x02; + outframe.data.u8[3] = (0x60 + (i * 18)); + outframe.data.u8[4] = 0x00; + outframe.data.u8[5] = 0x00; + outframe.data.u8[6] = 0x00; + outframe.data.u8[7] = 0x00; transmit_can(&outframe, can_config.battery); delay(500); @@ -266,8 +266,8 @@ void ISA_initialize() { ISA_START(); delay(500); - lastAs=As; - lastWh=wh; + lastAs = As; + lastWh = wh; } void ISA_STOP() { @@ -316,7 +316,7 @@ void ISA_START() { } void ISA_RESTART() { - //Has the effect of zeroing AH and KWH + //Has the effect of zeroing AH and KWH Serial.println("ISA RESTART"); outframe.data.u8[0] = 0x3F; @@ -332,20 +332,20 @@ void ISA_RESTART() { } void ISA_deFAULT() { - //Returns module to original defaults + //Returns module to original defaults ISA_STOP(); delay(500); Serial.println("ISA RESTART to default"); - outframe.data.u8[0]=0x3D; - outframe.data.u8[1]=0x00; - outframe.data.u8[2]=0x00; - outframe.data.u8[3]=0x00; - outframe.data.u8[4]=0x00; - outframe.data.u8[5]=0x00; - outframe.data.u8[6]=0x00; - outframe.data.u8[7]=0x00; + outframe.data.u8[0] = 0x3D; + outframe.data.u8[1] = 0x00; + outframe.data.u8[2] = 0x00; + outframe.data.u8[3] = 0x00; + outframe.data.u8[4] = 0x00; + outframe.data.u8[5] = 0x00; + outframe.data.u8[6] = 0x00; + outframe.data.u8[7] = 0x00; transmit_can(&outframe, can_config.battery); delay(500); @@ -357,17 +357,17 @@ void ISA_deFAULT() { void ISA_initCurrent() { ISA_STOP(); delay(500); - + Serial.println("ISA Initialization Current"); - outframe.data.u8[0]=0x21; - outframe.data.u8[1]=0x02; - outframe.data.u8[2]=0x01; - outframe.data.u8[3]=0x61; - outframe.data.u8[4]=0x00; - outframe.data.u8[5]=0x00; - outframe.data.u8[6]=0x00; - outframe.data.u8[7]=0x00; + outframe.data.u8[0] = 0x21; + outframe.data.u8[1] = 0x02; + outframe.data.u8[2] = 0x01; + outframe.data.u8[3] = 0x61; + outframe.data.u8[4] = 0x00; + outframe.data.u8[5] = 0x00; + outframe.data.u8[6] = 0x00; + outframe.data.u8[7] = 0x00; transmit_can(&outframe, can_config.battery); delay(500); @@ -377,15 +377,15 @@ void ISA_initCurrent() { ISA_START(); delay(500); - lastAs=As; - lastWh=wh; + lastAs = As; + lastWh = wh; } void ISA_getCONFIG(uint8_t i) { Serial.print("ISA Get Config "); Serial.println(i); - - outframe.data.u8[0] = (0x60+i); + + outframe.data.u8[0] = (0x60 + i); outframe.data.u8[1] = 0x00; outframe.data.u8[2] = 0x00; outframe.data.u8[3] = 0x00; @@ -400,10 +400,12 @@ void ISA_getCONFIG(uint8_t i) { void ISA_getCAN_ID(uint8_t i) { Serial.print("ISA Get CAN ID "); Serial.println(i); - - outframe.data.u8[0] = (0x50+i); - if (i == 8) outframe.data.u8[0] = 0x5D; - if (i == 9) outframe.data.u8[0] = 0x5F; + + outframe.data.u8[0] = (0x50 + i); + if (i == 8) + outframe.data.u8[0] = 0x5D; + if (i == 9) + outframe.data.u8[0] = 0x5F; outframe.data.u8[1] = 0x00; outframe.data.u8[2] = 0x00; outframe.data.u8[3] = 0x00; @@ -417,9 +419,9 @@ void ISA_getCAN_ID(uint8_t i) { void ISA_getINFO(uint8_t i) { Serial.print("ISA Get INFO "); - Serial.println(i,HEX); - - outframe.data.u8[0] = (0x70+i); + Serial.println(i, HEX); + + outframe.data.u8[0] = (0x70 + i); outframe.data.u8[1] = 0x00; outframe.data.u8[2] = 0x00; outframe.data.u8[3] = 0x00; @@ -430,4 +432,4 @@ void ISA_getINFO(uint8_t i) { transmit_can(&outframe, can_config.battery); } -#endif \ No newline at end of file +#endif