From d5d42291695e4ebc7706d49bff6ea6f90d63b72c Mon Sep 17 00:00:00 2001 From: Jaakko Haakana Date: Mon, 19 May 2025 23:12:44 +0300 Subject: [PATCH] Use base class for MEB battery --- Software/src/battery/MEB-BATTERY.cpp | 376 +--------------- Software/src/battery/MEB-BATTERY.h | 639 +++++++++++++++++++++------ 2 files changed, 511 insertions(+), 504 deletions(-) diff --git a/Software/src/battery/MEB-BATTERY.cpp b/Software/src/battery/MEB-BATTERY.cpp index 8d9e4f8c..6dac2b9b 100644 --- a/Software/src/battery/MEB-BATTERY.cpp +++ b/Software/src/battery/MEB-BATTERY.cpp @@ -15,359 +15,20 @@ TODO list - remaining_capacity_Wh is based on a lower limit of 5% soc. This means that at 5% soc, remaining_capacity_Wh returns 0. */ -/* Do not change code below unless you are sure what you are doing */ -static unsigned long previousMillis10ms = 0; // will store last time a 10ms CAN Message was send -static unsigned long previousMillis20ms = 0; // will store last time a 20ms CAN Message was send -static unsigned long previousMillis40ms = 0; // will store last time a 40ms CAN Message was send -static unsigned long previousMillis50ms = 0; // will store last time a 50ms CAN Message was send -static unsigned long previousMillis100ms = 0; // will store last time a 100ms CAN Message was send -static unsigned long previousMillis200ms = 0; // will store last time a 200ms CAN Message was send -static unsigned long previousMillis500ms = 0; // will store last time a 200ms CAN Message was send -static unsigned long previousMillis1s = 0; // will store last time a 1s CAN Message was send - -static bool toggle = false; -static uint8_t counter_1000ms = 0; -static uint8_t counter_200ms = 0; -static uint8_t counter_100ms = 0; -static uint8_t counter_50ms = 0; -static uint8_t counter_40ms = 0; -static uint8_t counter_20ms = 0; -static uint8_t counter_10ms = 0; -static uint8_t counter_040 = 0; -static uint8_t counter_0F7 = 0; -static uint8_t counter_3b5 = 0; - -static uint32_t poll_pid = PID_CELLVOLTAGE_CELL_85; // We start here to quickly determine the cell size of the pack. -static bool nof_cells_determined = false; -static uint32_t pid_reply = 0; -static uint16_t battery_soc_polled = 0; -static uint16_t battery_voltage_polled = 1480; -static int16_t battery_current_polled = 0; -static int16_t battery_max_temp = 600; -static int16_t battery_min_temp = 600; -static uint16_t battery_max_charge_voltage = 0; -static uint16_t battery_min_discharge_voltage = 0; -static uint16_t battery_allowed_charge_power = 0; -static uint16_t battery_allowed_discharge_power = 0; -static uint16_t cellvoltages_polled[108]; -static uint16_t tempval = 0; -static uint8_t BMS_16A954A6_CRC = 0; -static uint8_t BMS_5A2_counter = 0; -static uint8_t BMS_5CA_counter = 0; -static uint8_t BMS_0CF_counter = 0; -static uint8_t BMS_0C0_counter = 0; -static uint8_t BMS_578_counter = 0; -static uint8_t BMS_16A954A6_counter = 0; -static bool BMS_ext_limits_active = - false; //The current current limits of the HV battery are expanded to start the combustion engine / confirmation of the request -static uint8_t BMS_mode = - 0x07; //0: standby; Gates open; Communication active 1: Main contactor closed / HV network activated / normal driving operation -//2: assigned depending on the project (e.g. balancing, extended DC fast charging) //3: external charging -static uint8_t BMS_HVIL_status = 0; //0 init, 1 seated, 2 open, 3 fault -static bool BMS_fault_performance = false; //Error: Battery performance is limited (e.g. due to sensor or fan failure) -static uint16_t BMS_current = 16300; -static bool BMS_fault_emergency_shutdown_crash = - false; //Error: Safety-critical error (crash detection) Battery contactors are already opened / will be opened immediately Signal is read directly by the EMS and initiates an AKS of the PWR and an active discharge of the DC link -static uint32_t BMS_voltage_intermediate = 2000; -static uint32_t BMS_voltage = 1480; -static uint8_t BMS_status_voltage_free = - 0; //0=Init, 1=BMS intermediate circuit voltage-free (U_Zwkr < 20V), 2=BMS intermediate circuit not voltage-free (U_Zwkr >/= 25V, hysteresis), 3=Error -static bool BMS_OBD_MIL = false; -static uint8_t BMS_error_status = - 0x7; //0 Component_IO, 1 Restricted_CompFkt_Isoerror_I, 2 Restricted_CompFkt_Isoerror_II, 3 Restricted_CompFkt_Interlock, 4 Restricted_CompFkt_SD, 5 Restricted_CompFkt_Performance red, 6 = No component function, 7 = Init -static uint16_t BMS_capacity_ah = 0; -static bool BMS_error_lamp_req = false; -static bool BMS_warning_lamp_req = false; -static uint8_t BMS_Kl30c_Status = 0; // 0 init, 1 closed, 2 open, 3 fault -static bool service_disconnect_switch_missing = false; -static bool pilotline_open = false; -static bool balancing_request = false; -static uint8_t battery_diagnostic = 0; -static uint16_t battery_Wh_left = 0; -static uint16_t battery_Wh_max = 1000; -static uint8_t battery_potential_status = 0; -static uint8_t battery_temperature_warning = 0; -static uint16_t max_discharge_power_watt = 0; -static uint16_t max_discharge_current_amp = 0; -static uint16_t max_charge_power_watt = 0; -static uint16_t max_charge_current_amp = 0; -static uint16_t battery_SOC = 1; -static uint16_t usable_energy_amount_Wh = 0; -static uint8_t status_HV_line = 0; //0 init, 1 No open HV line, 2 open HV line detected, 3 fault -static uint8_t warning_support = 0; -static bool battery_heating_active = false; -static uint16_t power_discharge_percentage = 0; -static uint16_t power_charge_percentage = 0; -static uint16_t actual_battery_voltage = 0; -static uint16_t regen_battery = 0; -static uint16_t energy_extracted_from_battery = 0; -static uint16_t max_fastcharging_current_amp = 0; //maximum DC charging current allowed -static uint8_t BMS_Status_DCLS = - 0; //Status of the voltage monitoring on the DC charging interface. 0 inactive, 1 I_O , 2 N_I_O , 3 active -static uint16_t DC_voltage_DCLS = - 0; //Factor 1, DC voltage of the charging station. Measurement between the DC HV lines. -static uint16_t DC_voltage_chargeport = - 0; //Factor 0.5, Current voltage at the HV battery DC charging terminals; Outlet to the DC charging plug. -static uint8_t BMS_welded_contactors_status = - 0; //0: Init no diagnostic result, 1: no contactor welded, 2: at least 1 contactor welded, 3: Protection status detection error -static bool BMS_error_shutdown_request = - false; // Fault: Fault condition, requires battery contactors to be opened internal battery error; Advance notification of an impending opening of the battery contactors by the BMS -static bool BMS_error_shutdown = - false; // Fault: Fault condition, requires battery contactors to be opened Internal battery error, battery contactors opened without notice by the BMS -static uint16_t power_battery_heating_watt = 0; -static uint16_t power_battery_heating_req_watt = 0; -static uint8_t cooling_request = - 0; //0 = No cooling, 1 = Light cooling, cabin prio, 2= higher cooling, 3 = immediate cooling, 4 = emergency cooling -static uint8_t heating_request = 0; //0 = init, 1= maintain temp, 2=higher demand, 3 = immediate heat demand -static uint8_t balancing_active = false; //0 = init, 1 active, 2 not active -static bool charging_active = false; -static uint16_t max_energy_Wh = 0; -static uint16_t max_charge_percent = 0; -static uint16_t min_charge_percent = 0; -static uint16_t isolation_resistance_kOhm = 0; -static bool battery_heating_installed = false; -static bool error_NT_circuit = false; -static uint8_t pump_1_control = 0; //0x0D not installed, 0x0E init, 0x0F fault -static uint8_t pump_2_control = 0; //0x0D not installed, 0x0E init, 0x0F fault -static uint8_t target_flow_temperature_C = 0; //*0,5 -40 -static uint8_t return_temperature_C = 0; //*0,5 -40 -static uint8_t status_valve_1 = 0; //0 not active, 1 active, 5 not installed, 6 init, 7 fault -static uint8_t status_valve_2 = 0; //0 not active, 1 active, 5 not installed, 6 init, 7 fault -static uint8_t temperature_request = - 0; //0 high cooling, 1 medium cooling, 2 low cooling, 3 no temp requirement init, 4 low heating , 5 medium heating, 6 high heating, 7 circulation -static uint16_t performance_index_discharge_peak_temperature_percentage = 0; -static uint16_t performance_index_charge_peak_temperature_percentage = 0; -static uint8_t temperature_status_discharge = - 0; //0 init, 1 temp under optimal, 2 temp optimal, 3 temp over optimal, 7 fault -static uint8_t temperature_status_charge = - 0; //0 init, 1 temp under optimal, 2 temp optimal, 3 temp over optimal, 7 fault -static uint8_t isolation_fault = - 0; //0 init, 1 no iso fault, 2 iso fault threshold1, 3 iso fault threshold2, 4 IWU defective -static uint8_t isolation_status = - 0; // 0 init, 1 = larger threshold1, 2 = smaller threshold1 total, 3 = smaller threshold1 intern, 4 = smaller threshold2 total, 5 = smaller threshold2 intern, 6 = no measurement, 7 = measurement active -static uint8_t actual_temperature_highest_C = 0; //*0,5 -40 -static uint8_t actual_temperature_lowest_C = 0; //*0,5 -40 -static uint16_t actual_cellvoltage_highest_mV = 0; //bias 1000 -static uint16_t actual_cellvoltage_lowest_mV = 0; //bias 1000 -static uint16_t predicted_power_dyn_standard_watt = 0; -static uint8_t predicted_time_dyn_standard_minutes = 0; -static uint8_t mux = 0; -static uint16_t cellvoltages[160] = {0}; -static uint16_t duration_discharge_power_watt = 0; -static uint16_t duration_charge_power_watt = 0; -static uint16_t maximum_voltage = 0; -static uint16_t minimum_voltage = 0; -static uint8_t battery_serialnumber[26]; -static uint8_t realtime_overcurrent_monitor = 0; -static uint8_t realtime_CAN_communication_fault = 0; -static uint8_t realtime_overcharge_warning = 0; -static uint8_t realtime_SOC_too_high = 0; -static uint8_t realtime_SOC_too_low = 0; -static uint8_t realtime_SOC_jumping_warning = 0; -static uint8_t realtime_temperature_difference_warning = 0; -static uint8_t realtime_cell_overtemperature_warning = 0; -static uint8_t realtime_cell_undertemperature_warning = 0; -static uint8_t realtime_battery_overvoltage_warning = 0; -static uint8_t realtime_battery_undervoltage_warning = 0; -static uint8_t realtime_cell_overvoltage_warning = 0; -static uint8_t realtime_cell_undervoltage_warning = 0; -static uint8_t realtime_cell_imbalance_warning = 0; -static uint8_t realtime_warning_battery_unathorized = 0; -static bool component_protection_active = false; -static bool shutdown_active = false; -static bool transportation_mode_active = false; -static uint8_t KL15_mode = 0; -static uint8_t bus_knockout_timer = 0; -static uint8_t hybrid_wakeup_reason = 0; -static uint8_t wakeup_type = 0; -static bool instrumentation_cluster_request = false; -static uint8_t seconds = 0; -static uint32_t first_can_msg = 0; -static uint32_t last_can_msg_timestamp = 0; -static bool hv_requested = false; -static int32_t kwh_charge = 0; -static int32_t kwh_discharge = 0; - -#define TIME_YEAR 2024 -#define TIME_MONTH 8 -#define TIME_DAY 20 -#define TIME_HOUR 10 -#define TIME_MINUTE 5 -#define TIME_SECOND 0 - -#define BMS_TARGET_HV_OFF 0 -#define BMS_TARGET_HV_ON 1 -#define BMS_TARGET_AC_CHARGING_EXT 3 //(HS + AC_2 contactors closed) -#define BMS_TARGET_AC_CHARGING 4 //(HS + AC contactors closed) -#define BMS_TARGET_DC_CHARGING 6 //(HS + DC contactors closed) -#define BMS_TARGET_INIT 7 - -#define DC_FASTCHARGE_NO_START_REQUEST 0x00 -#define DC_FASTCHARGE_VEHICLE 0x40 -#define DC_FASTCHARGE_LS1 0x80 -#define DC_FASTCHARGE_LS2 0xC0 - -CAN_frame MEB_POLLING_FRAME = {.FD = true, - .ext_ID = true, - .DLC = 8, - .ID = 0x1C40007B, // SOC 02 8C - .data = {0x03, 0x22, 0x02, 0x8C, 0x55, 0x55, 0x55, 0x55}}; -CAN_frame MEB_ACK_FRAME = {.FD = true, - .ext_ID = true, - .DLC = 8, - .ID = 0x1C40007B, // Ack - .data = {0x30, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55}}; -//Messages needed for contactor closing -CAN_frame MEB_040 = {.FD = true, // Airbag - .ext_ID = false, - .DLC = 8, - .ID = 0x040, //Frame5 has HV deactivate request. Needs to be 0x00 - .data = {0x7E, 0x83, 0x00, 0x01, 0x00, 0x00, 0x15, 0x00}}; -CAN_frame MEB_0C0 = { - .FD = true, // EM1 message - .ext_ID = false, - .DLC = 32, - .ID = 0x0C0, //Frame 5-6 and maybe 7-8 important (external voltage at inverter) - .data = {0x77, 0x0A, 0xFE, 0xE7, 0x7F, 0x10, 0x27, 0x00, 0xE0, 0x7F, 0xFF, 0xF3, 0x3F, 0xFF, 0xF3, 0x3F, - 0xFC, 0x0F, 0x00, 0x00, 0xC0, 0xFF, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame MEB_0FC = { - .FD = true, // - .ext_ID = false, - .DLC = 48, - .ID = 0x0FC, //This message contains emergency regen request?(byte19), battery needs to see this message - .data = {0x07, 0x08, 0x00, 0x00, 0x7E, 0x00, 0x40, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFE, 0xFE, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xF4, 0x01, 0x40, 0xFF, 0xEB, 0x7F, 0x0A, 0x88, 0xE3, 0x81, 0xAF, 0x42}}; -CAN_frame MEB_6B2 = {.FD = true, // Diagnostics - .ext_ID = false, - .DLC = 8, - .ID = 0x6B2, - .data = {0x6A, 0xA7, 0x37, 0x80, 0xC9, 0xBD, 0xF6, 0xC2}}; -CAN_frame MEB_17FC007B_poll = {.FD = true, // Non period request - .ext_ID = true, - .DLC = 8, - .ID = 0x17FC007B, - .data = {0x03, 0x22, 0x1E, 0x3D, 0x55, 0x55, 0x55, 0x55}}; -CAN_frame MEB_1A5555A6 = {.FD = true, - .ext_ID = true, - .DLC = 8, - .ID = 0x1A5555A6, - .data = {0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame MEB_585 = { - .FD = true, - .ext_ID = false, - .DLC = 8, - .ID = 0x585, - .data = {0xCF, 0x38, 0xAF, 0x5B, 0x25, 0x00, 0x00, 0x00}}; // CF 38 AF 5B 25 00 00 00 in start4.log -// .data = {0xCF, 0x38, 0x20, 0x02, 0x25, 0xF7, 0x30, 0x00}}; // CF 38 AF 5B 25 00 00 00 in start4.log -CAN_frame MEB_5F5 = {.FD = true, - .ext_ID = false, - .DLC = 8, - .ID = 0x5F5, - .data = {0x23, 0x02, 0x39, 0xC0, 0x1B, 0x8B, 0xC8, 0x1B}}; -CAN_frame MEB_641 = {.FD = true, - .ext_ID = false, - .DLC = 8, - .ID = 0x641, - .data = {0x37, 0x18, 0x00, 0x00, 0xF0, 0x00, 0xAA, 0x70}}; -CAN_frame MEB_3C0 = {.FD = true, - .ext_ID = false, - .DLC = 4, - .ID = 0x3C0, - .data = {0x66, 0x00, 0x00, 0x00}}; // Klemmen_status_01 -CAN_frame MEB_0FD = {.FD = true, - .ext_ID = false, - .DLC = 8, - .ID = 0x0FD, //CRC and counter, otherwise static - .data = {0x5F, 0xD0, 0x1F, 0x81, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame MEB_16A954FB = {.FD = true, - .ext_ID = true, - .DLC = 8, - .ID = 0x16A954FB, - .data = {0x00, 0xC0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame MEB_1A555548 = {.FD = true, - .ext_ID = true, - .DLC = 8, - .ID = 0x1A555548, - .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame MEB_1A55552B = {.FD = true, - .ext_ID = true, - .DLC = 8, - .ID = 0x1A55552B, - .data = {0x00, 0x00, 0x00, 0xA0, 0x02, 0x04, 0x00, 0x30}}; -CAN_frame MEB_569 = {.FD = true, - .ext_ID = false, - .DLC = 8, - .ID = 0x569, //HVEM - .data = {0x00, 0x00, 0x01, 0x3A, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame MEB_16A954B4 = {.FD = true, - .ext_ID = true, - .DLC = 8, - .ID = 0x16A954B4, //eTM - .data = {0xFE, 0xB6, 0x0D, 0x00, 0x00, 0xD5, 0x48, 0xFD}}; -CAN_frame MEB_1B000046 = {.FD = false, // Not FD - .ext_ID = true, - .DLC = 8, - .ID = 0x1B000046, // Klima - .data = {0x00, 0x40, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame MEB_1B000010 = {.FD = false, // Not FD - .ext_ID = true, - .DLC = 8, - .ID = 0x1B000010, // Gateway - .data = {0x00, 0x50, 0x08, 0x50, 0x01, 0xFF, 0x30, 0x00}}; -CAN_frame MEB_1B0000B9 = {.FD = false, // Not FD - .ext_ID = true, - .DLC = 8, - .ID = 0x1B0000B9, //DC/DC converter - .data = {0x00, 0x40, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00}}; -CAN_frame MEB_153 = {.FD = true, - .ext_ID = false, - .DLC = 8, - .ID = 0x153, // Static content - .data = {0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFE, 0xFF, 0xFF}}; -CAN_frame MEB_5E1 = {.FD = true, - .ext_ID = false, - .DLC = 8, - .ID = 0x5E1, // Static content - .data = {0x7F, 0x2A, 0x00, 0x60, 0xFE, 0x00, 0x00, 0x00}}; -CAN_frame MEB_3BE = {.FD = true, - .ext_ID = false, - .DLC = 8, - .ID = 0x3BE, // CRC, otherwise Static content - .data = {0x57, 0x0D, 0x00, 0x00, 0x00, 0x02, 0x04, 0x40}}; -CAN_frame MEB_272 = {.FD = true, //HVLM_14 - .ext_ID = false, - .DLC = 8, - .ID = 0x272, // Static content - .data = {0x00, 0x00, 0x00, 0x00, 0x48, 0x08, 0x00, 0x94}}; -CAN_frame MEB_503 = {.FD = true, //HVK_01 - .ext_ID = false, - .DLC = 8, - .ID = 0x503, // Content varies. Frame1 & 3 has HV req - .data = {0x5D, 0x61, 0x00, 0xFF, 0x7F, 0x80, 0xE3, 0x03}}; -CAN_frame MEB_14C = { - .FD = true, //Motor message - .ext_ID = false, - .DLC = 32, - .ID = 0x14C, //CRC needed, static content otherwise - .data = {0x38, 0x0A, 0xFF, 0x01, 0x01, 0xFF, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, - 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x25, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE}}; - -uint32_t can_msg_received = 0; -#define RX_0x17F0007B 0x0001 -#define RX_0x12DD54D0 0x0002 -#define RX_0x12DD54D1 0x0004 -#define RX_0x12DD54D2 0x0008 -#define RX_0x1A555550 0x0010 -#define RX_0x1A555551 0x0020 -#define RX_0x1A5555B2 0x0040 -#define RX_0x16A954A6 0x0080 -#define RX_0x1A5555B0 0x0100 -#define RX_0x1A5555B1 0x0200 -#define RX_0x5A2 0x0400 -#define RX_0x5CA 0x0800 -#define RX_0x0CF 0x1000 -#define RX_DEFAULT 0xE000 +const int RX_0x17F0007B = 0x0001; +const int RX_0x12DD54D0 = 0x0002; +const int RX_0x12DD54D1 = 0x0004; +const int RX_0x12DD54D2 = 0x0008; +const int RX_0x1A555550 = 0x0010; +const int RX_0x1A555551 = 0x0020; +const int RX_0x1A5555B2 = 0x0040; +const int RX_0x16A954A6 = 0x0080; +const int RX_0x1A5555B0 = 0x0100; +const int RX_0x1A5555B1 = 0x0200; +const int RX_0x5A2 = 0x0400; +const int RX_0x5CA = 0x0800; +const int RX_0x0CF = 0x1000; +const int RX_DEFAULT = 0xE000; /** Calculate the CRC checksum for VAG CAN Messages * @@ -538,7 +199,8 @@ uint8_t vw_crc_calc(uint8_t* inputBytes, uint8_t length, uint32_t address) { return crc; } -void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus +void MebBattery:: + update_values() { //This function maps all the values fetched via CAN to the correct parameters used for modbus datalayer.battery.status.real_soc = battery_SOC * 5; //*0.05*100 @@ -645,7 +307,7 @@ void update_values_battery() { //This function maps all the values fetched via datalayer_extended.meb.charging_active = charging_active; } -void handle_incoming_can_frame_battery(CAN_frame rx_frame) { +void MebBattery::handle_incoming_can_frame(CAN_frame rx_frame) { last_can_msg_timestamp = millis(); if (first_can_msg == 0) { #ifdef DEBUG_LOG @@ -1627,7 +1289,7 @@ void handle_incoming_can_frame_battery(CAN_frame rx_frame) { } } -void transmit_can_battery(unsigned long currentMillis) { +void MebBattery::transmit_can(unsigned long currentMillis) { if (currentMillis > last_can_msg_timestamp + 500) { #ifdef DEBUG_LOG @@ -2373,7 +2035,7 @@ void transmit_can_battery(unsigned long currentMillis) { } } -void setup_battery(void) { // Performs one time setup at startup +void MebBattery::setup(void) { // Performs one time setup at startup strncpy(datalayer.system.info.battery_protocol, "Volkswagen Group MEB platform via CAN-FD", 63); datalayer.system.info.battery_protocol[63] = '\0'; datalayer.battery.info.number_of_cells = 108; //Startup in 108S mode. We figure out the actual count later. diff --git a/Software/src/battery/MEB-BATTERY.h b/Software/src/battery/MEB-BATTERY.h index dcf6e447..6aff0b87 100644 --- a/Software/src/battery/MEB-BATTERY.h +++ b/Software/src/battery/MEB-BATTERY.h @@ -2,156 +2,501 @@ #define MEB_BATTERY_H #include #include "../include.h" +#include "CanBattery.h" #define BATTERY_SELECTED -#define MAX_PACK_VOLTAGE_84S_DV 3528 //5000 = 500.0V -#define MIN_PACK_VOLTAGE_84S_DV 2520 -#define MAX_PACK_VOLTAGE_96S_DV 4032 -#define MIN_PACK_VOLTAGE_96S_DV 2880 -#define MAX_PACK_VOLTAGE_108S_DV 4536 -#define MIN_PACK_VOLTAGE_108S_DV 3240 -#define MAX_CELL_DEVIATION_MV 150 -#define MAX_CELL_VOLTAGE_MV 4250 //Battery is put into emergency stop if one cell goes over this value -#define MIN_CELL_VOLTAGE_MV 2700 //Battery is put into emergency stop if one cell goes below this value +#define SELECTED_BATTERY_CLASS MebBattery -#define PID_SOC 0x028C -#define PID_VOLTAGE 0x1E3B -#define PID_CURRENT 0x1E3D -#define PID_MAX_TEMP 0x1E0E -#define PID_MIN_TEMP 0x1E0F -#define PID_MAX_CHARGE_VOLTAGE 0x5171 -#define PID_MIN_DISCHARGE_VOLTAGE 0x5170 -#define PID_ENERGY_COUNTERS 0x1E32 -#define PID_ALLOWED_CHARGE_POWER 0x1E1B -#define PID_ALLOWED_DISCHARGE_POWER 0x1E1C -#define PID_CELLVOLTAGE_CELL_1 0x1E40 -#define PID_CELLVOLTAGE_CELL_2 0x1E41 -#define PID_CELLVOLTAGE_CELL_3 0x1E42 -#define PID_CELLVOLTAGE_CELL_4 0x1E43 -#define PID_CELLVOLTAGE_CELL_5 0x1E44 -#define PID_CELLVOLTAGE_CELL_6 0x1E45 -#define PID_CELLVOLTAGE_CELL_7 0x1E46 -#define PID_CELLVOLTAGE_CELL_8 0x1E47 -#define PID_CELLVOLTAGE_CELL_9 0x1E48 -#define PID_CELLVOLTAGE_CELL_10 0x1E49 -#define PID_CELLVOLTAGE_CELL_11 0x1E4A -#define PID_CELLVOLTAGE_CELL_12 0x1E4B -#define PID_CELLVOLTAGE_CELL_13 0x1E4C -#define PID_CELLVOLTAGE_CELL_14 0x1E4D -#define PID_CELLVOLTAGE_CELL_15 0x1E4E -#define PID_CELLVOLTAGE_CELL_16 0x1E4F -#define PID_CELLVOLTAGE_CELL_17 0x1E50 -#define PID_CELLVOLTAGE_CELL_18 0x1E51 -#define PID_CELLVOLTAGE_CELL_19 0x1E52 -#define PID_CELLVOLTAGE_CELL_20 0x1E53 -#define PID_CELLVOLTAGE_CELL_21 0x1E54 -#define PID_CELLVOLTAGE_CELL_22 0x1E55 -#define PID_CELLVOLTAGE_CELL_23 0x1E56 -#define PID_CELLVOLTAGE_CELL_24 0x1E57 -#define PID_CELLVOLTAGE_CELL_25 0x1E58 -#define PID_CELLVOLTAGE_CELL_26 0x1E59 -#define PID_CELLVOLTAGE_CELL_27 0x1E5A -#define PID_CELLVOLTAGE_CELL_28 0x1E5B -#define PID_CELLVOLTAGE_CELL_29 0x1E5C -#define PID_CELLVOLTAGE_CELL_30 0x1E5D -#define PID_CELLVOLTAGE_CELL_31 0x1E5E -#define PID_CELLVOLTAGE_CELL_32 0x1E5F -#define PID_CELLVOLTAGE_CELL_33 0x1E60 -#define PID_CELLVOLTAGE_CELL_34 0x1E61 -#define PID_CELLVOLTAGE_CELL_35 0x1E62 -#define PID_CELLVOLTAGE_CELL_36 0x1E63 -#define PID_CELLVOLTAGE_CELL_37 0x1E64 -#define PID_CELLVOLTAGE_CELL_38 0x1E65 -#define PID_CELLVOLTAGE_CELL_39 0x1E66 -#define PID_CELLVOLTAGE_CELL_40 0x1E67 -#define PID_CELLVOLTAGE_CELL_41 0x1E68 -#define PID_CELLVOLTAGE_CELL_42 0x1E69 -#define PID_CELLVOLTAGE_CELL_43 0x1E6A -#define PID_CELLVOLTAGE_CELL_44 0x1E6B -#define PID_CELLVOLTAGE_CELL_45 0x1E6C -#define PID_CELLVOLTAGE_CELL_46 0x1E6D -#define PID_CELLVOLTAGE_CELL_47 0x1E6E -#define PID_CELLVOLTAGE_CELL_48 0x1E6F -#define PID_CELLVOLTAGE_CELL_49 0x1E70 -#define PID_CELLVOLTAGE_CELL_50 0x1E71 -#define PID_CELLVOLTAGE_CELL_51 0x1E72 -#define PID_CELLVOLTAGE_CELL_52 0x1E73 -#define PID_CELLVOLTAGE_CELL_53 0x1E74 -#define PID_CELLVOLTAGE_CELL_54 0x1E75 -#define PID_CELLVOLTAGE_CELL_55 0x1E76 -#define PID_CELLVOLTAGE_CELL_56 0x1E77 -#define PID_CELLVOLTAGE_CELL_57 0x1E78 -#define PID_CELLVOLTAGE_CELL_58 0x1E79 -#define PID_CELLVOLTAGE_CELL_59 0x1E7A -#define PID_CELLVOLTAGE_CELL_60 0x1E7B -#define PID_CELLVOLTAGE_CELL_61 0x1E7C -#define PID_CELLVOLTAGE_CELL_62 0x1E7D -#define PID_CELLVOLTAGE_CELL_63 0x1E7E -#define PID_CELLVOLTAGE_CELL_64 0x1E7F -#define PID_CELLVOLTAGE_CELL_65 0x1E80 -#define PID_CELLVOLTAGE_CELL_66 0x1E81 -#define PID_CELLVOLTAGE_CELL_67 0x1E82 -#define PID_CELLVOLTAGE_CELL_68 0x1E83 -#define PID_CELLVOLTAGE_CELL_69 0x1E84 -#define PID_CELLVOLTAGE_CELL_70 0x1E85 -#define PID_CELLVOLTAGE_CELL_71 0x1E86 -#define PID_CELLVOLTAGE_CELL_72 0x1E87 -#define PID_CELLVOLTAGE_CELL_73 0x1E88 -#define PID_CELLVOLTAGE_CELL_74 0x1E89 -#define PID_CELLVOLTAGE_CELL_75 0x1E8A -#define PID_CELLVOLTAGE_CELL_76 0x1E8B -#define PID_CELLVOLTAGE_CELL_77 0x1E8C -#define PID_CELLVOLTAGE_CELL_78 0x1E8D -#define PID_CELLVOLTAGE_CELL_79 0x1E8E -#define PID_CELLVOLTAGE_CELL_80 0x1E8F -#define PID_CELLVOLTAGE_CELL_81 0x1E90 -#define PID_CELLVOLTAGE_CELL_82 0x1E91 -#define PID_CELLVOLTAGE_CELL_83 0x1E92 -#define PID_CELLVOLTAGE_CELL_84 0x1E93 -#define PID_CELLVOLTAGE_CELL_85 0x1E94 -#define PID_CELLVOLTAGE_CELL_86 0x1E95 -#define PID_CELLVOLTAGE_CELL_87 0x1E96 -#define PID_CELLVOLTAGE_CELL_88 0x1E97 -#define PID_CELLVOLTAGE_CELL_89 0x1E98 -#define PID_CELLVOLTAGE_CELL_90 0x1E99 -#define PID_CELLVOLTAGE_CELL_91 0x1E9A -#define PID_CELLVOLTAGE_CELL_92 0x1E9B -#define PID_CELLVOLTAGE_CELL_93 0x1E9C -#define PID_CELLVOLTAGE_CELL_94 0x1E9D -#define PID_CELLVOLTAGE_CELL_95 0x1E9E -#define PID_CELLVOLTAGE_CELL_96 0x1E9F -#define PID_CELLVOLTAGE_CELL_97 0x1EA0 -#define PID_CELLVOLTAGE_CELL_98 0x1EA1 -#define PID_CELLVOLTAGE_CELL_99 0x1EA2 -#define PID_CELLVOLTAGE_CELL_100 0x1EA3 -#define PID_CELLVOLTAGE_CELL_101 0x1EA4 -#define PID_CELLVOLTAGE_CELL_102 0x1EA5 -#define PID_CELLVOLTAGE_CELL_103 0x1EA6 -#define PID_CELLVOLTAGE_CELL_104 0x1EA7 -#define PID_CELLVOLTAGE_CELL_105 0x1EA8 -#define PID_CELLVOLTAGE_CELL_106 0x1EA9 -#define PID_CELLVOLTAGE_CELL_107 0x1EAA -#define PID_CELLVOLTAGE_CELL_108 0x1EAB -#define PID_TEMP_POINT_1 0x1EAE -#define PID_TEMP_POINT_2 0x1EAF -#define PID_TEMP_POINT_3 0x1EB0 -#define PID_TEMP_POINT_4 0x1EB1 -#define PID_TEMP_POINT_5 0x1EB2 -#define PID_TEMP_POINT_6 0x1EB3 -#define PID_TEMP_POINT_7 0x1EB4 -#define PID_TEMP_POINT_8 0x1EB5 -#define PID_TEMP_POINT_9 0x1EB6 -#define PID_TEMP_POINT_10 0x1EB7 -#define PID_TEMP_POINT_11 0x1EB8 -#define PID_TEMP_POINT_12 0x1EB9 -#define PID_TEMP_POINT_13 0x1EBA -#define PID_TEMP_POINT_14 0x1EBB -#define PID_TEMP_POINT_15 0x1EBC -#define PID_TEMP_POINT_16 0x1EBD -#define PID_TEMP_POINT_17 0x1EBE -#define PID_TEMP_POINT_18 0x1EBF +class MebBattery : public CanBattery { + public: + virtual void setup(void); + virtual void handle_incoming_can_frame(CAN_frame rx_frame); + virtual void update_values(); + virtual void transmit_can(unsigned long currentMillis); -void setup_battery(void); -void transmit_can_frame(CAN_frame* tx_frame, int interface); + private: + static const int MAX_PACK_VOLTAGE_84S_DV = 3528; //5000 = 500.0V + static const int MIN_PACK_VOLTAGE_84S_DV = 2520; + static const int MAX_PACK_VOLTAGE_96S_DV = 4032; + static const int MIN_PACK_VOLTAGE_96S_DV = 2880; + static const int MAX_PACK_VOLTAGE_108S_DV = 4536; + static const int MIN_PACK_VOLTAGE_108S_DV = 3240; + static const int MAX_CELL_DEVIATION_MV = 150; + static const int MAX_CELL_VOLTAGE_MV = 4250; //Battery is put into emergency stop if one cell goes over this value + static const int MIN_CELL_VOLTAGE_MV = 2700; //Battery is put into emergency stop if one cell goes below this value + static const int PID_SOC = 0x028C; + static const int PID_VOLTAGE = 0x1E3B; + static const int PID_CURRENT = 0x1E3D; + static const int PID_MAX_TEMP = 0x1E0E; + static const int PID_MIN_TEMP = 0x1E0F; + static const int PID_MAX_CHARGE_VOLTAGE = 0x5171; + static const int PID_MIN_DISCHARGE_VOLTAGE = 0x5170; + static const int PID_ENERGY_COUNTERS = 0x1E32; + static const int PID_ALLOWED_CHARGE_POWER = 0x1E1B; + static const int PID_ALLOWED_DISCHARGE_POWER = 0x1E1C; + static const int PID_CELLVOLTAGE_CELL_1 = 0x1E40; + static const int PID_CELLVOLTAGE_CELL_2 = 0x1E41; + static const int PID_CELLVOLTAGE_CELL_3 = 0x1E42; + static const int PID_CELLVOLTAGE_CELL_4 = 0x1E43; + static const int PID_CELLVOLTAGE_CELL_5 = 0x1E44; + static const int PID_CELLVOLTAGE_CELL_6 = 0x1E45; + static const int PID_CELLVOLTAGE_CELL_7 = 0x1E46; + static const int PID_CELLVOLTAGE_CELL_8 = 0x1E47; + static const int PID_CELLVOLTAGE_CELL_9 = 0x1E48; + static const int PID_CELLVOLTAGE_CELL_10 = 0x1E49; + static const int PID_CELLVOLTAGE_CELL_11 = 0x1E4A; + static const int PID_CELLVOLTAGE_CELL_12 = 0x1E4B; + static const int PID_CELLVOLTAGE_CELL_13 = 0x1E4C; + static const int PID_CELLVOLTAGE_CELL_14 = 0x1E4D; + static const int PID_CELLVOLTAGE_CELL_15 = 0x1E4E; + static const int PID_CELLVOLTAGE_CELL_16 = 0x1E4F; + static const int PID_CELLVOLTAGE_CELL_17 = 0x1E50; + static const int PID_CELLVOLTAGE_CELL_18 = 0x1E51; + static const int PID_CELLVOLTAGE_CELL_19 = 0x1E52; + static const int PID_CELLVOLTAGE_CELL_20 = 0x1E53; + static const int PID_CELLVOLTAGE_CELL_21 = 0x1E54; + static const int PID_CELLVOLTAGE_CELL_22 = 0x1E55; + static const int PID_CELLVOLTAGE_CELL_23 = 0x1E56; + static const int PID_CELLVOLTAGE_CELL_24 = 0x1E57; + static const int PID_CELLVOLTAGE_CELL_25 = 0x1E58; + static const int PID_CELLVOLTAGE_CELL_26 = 0x1E59; + static const int PID_CELLVOLTAGE_CELL_27 = 0x1E5A; + static const int PID_CELLVOLTAGE_CELL_28 = 0x1E5B; + static const int PID_CELLVOLTAGE_CELL_29 = 0x1E5C; + static const int PID_CELLVOLTAGE_CELL_30 = 0x1E5D; + static const int PID_CELLVOLTAGE_CELL_31 = 0x1E5E; + static const int PID_CELLVOLTAGE_CELL_32 = 0x1E5F; + static const int PID_CELLVOLTAGE_CELL_33 = 0x1E60; + static const int PID_CELLVOLTAGE_CELL_34 = 0x1E61; + static const int PID_CELLVOLTAGE_CELL_35 = 0x1E62; + static const int PID_CELLVOLTAGE_CELL_36 = 0x1E63; + static const int PID_CELLVOLTAGE_CELL_37 = 0x1E64; + static const int PID_CELLVOLTAGE_CELL_38 = 0x1E65; + static const int PID_CELLVOLTAGE_CELL_39 = 0x1E66; + static const int PID_CELLVOLTAGE_CELL_40 = 0x1E67; + static const int PID_CELLVOLTAGE_CELL_41 = 0x1E68; + static const int PID_CELLVOLTAGE_CELL_42 = 0x1E69; + static const int PID_CELLVOLTAGE_CELL_43 = 0x1E6A; + static const int PID_CELLVOLTAGE_CELL_44 = 0x1E6B; + static const int PID_CELLVOLTAGE_CELL_45 = 0x1E6C; + static const int PID_CELLVOLTAGE_CELL_46 = 0x1E6D; + static const int PID_CELLVOLTAGE_CELL_47 = 0x1E6E; + static const int PID_CELLVOLTAGE_CELL_48 = 0x1E6F; + static const int PID_CELLVOLTAGE_CELL_49 = 0x1E70; + static const int PID_CELLVOLTAGE_CELL_50 = 0x1E71; + static const int PID_CELLVOLTAGE_CELL_51 = 0x1E72; + static const int PID_CELLVOLTAGE_CELL_52 = 0x1E73; + static const int PID_CELLVOLTAGE_CELL_53 = 0x1E74; + static const int PID_CELLVOLTAGE_CELL_54 = 0x1E75; + static const int PID_CELLVOLTAGE_CELL_55 = 0x1E76; + static const int PID_CELLVOLTAGE_CELL_56 = 0x1E77; + static const int PID_CELLVOLTAGE_CELL_57 = 0x1E78; + static const int PID_CELLVOLTAGE_CELL_58 = 0x1E79; + static const int PID_CELLVOLTAGE_CELL_59 = 0x1E7A; + static const int PID_CELLVOLTAGE_CELL_60 = 0x1E7B; + static const int PID_CELLVOLTAGE_CELL_61 = 0x1E7C; + static const int PID_CELLVOLTAGE_CELL_62 = 0x1E7D; + static const int PID_CELLVOLTAGE_CELL_63 = 0x1E7E; + static const int PID_CELLVOLTAGE_CELL_64 = 0x1E7F; + static const int PID_CELLVOLTAGE_CELL_65 = 0x1E80; + static const int PID_CELLVOLTAGE_CELL_66 = 0x1E81; + static const int PID_CELLVOLTAGE_CELL_67 = 0x1E82; + static const int PID_CELLVOLTAGE_CELL_68 = 0x1E83; + static const int PID_CELLVOLTAGE_CELL_69 = 0x1E84; + static const int PID_CELLVOLTAGE_CELL_70 = 0x1E85; + static const int PID_CELLVOLTAGE_CELL_71 = 0x1E86; + static const int PID_CELLVOLTAGE_CELL_72 = 0x1E87; + static const int PID_CELLVOLTAGE_CELL_73 = 0x1E88; + static const int PID_CELLVOLTAGE_CELL_74 = 0x1E89; + static const int PID_CELLVOLTAGE_CELL_75 = 0x1E8A; + static const int PID_CELLVOLTAGE_CELL_76 = 0x1E8B; + static const int PID_CELLVOLTAGE_CELL_77 = 0x1E8C; + static const int PID_CELLVOLTAGE_CELL_78 = 0x1E8D; + static const int PID_CELLVOLTAGE_CELL_79 = 0x1E8E; + static const int PID_CELLVOLTAGE_CELL_80 = 0x1E8F; + static const int PID_CELLVOLTAGE_CELL_81 = 0x1E90; + static const int PID_CELLVOLTAGE_CELL_82 = 0x1E91; + static const int PID_CELLVOLTAGE_CELL_83 = 0x1E92; + static const int PID_CELLVOLTAGE_CELL_84 = 0x1E93; + static const int PID_CELLVOLTAGE_CELL_85 = 0x1E94; + static const int PID_CELLVOLTAGE_CELL_86 = 0x1E95; + static const int PID_CELLVOLTAGE_CELL_87 = 0x1E96; + static const int PID_CELLVOLTAGE_CELL_88 = 0x1E97; + static const int PID_CELLVOLTAGE_CELL_89 = 0x1E98; + static const int PID_CELLVOLTAGE_CELL_90 = 0x1E99; + static const int PID_CELLVOLTAGE_CELL_91 = 0x1E9A; + static const int PID_CELLVOLTAGE_CELL_92 = 0x1E9B; + static const int PID_CELLVOLTAGE_CELL_93 = 0x1E9C; + static const int PID_CELLVOLTAGE_CELL_94 = 0x1E9D; + static const int PID_CELLVOLTAGE_CELL_95 = 0x1E9E; + static const int PID_CELLVOLTAGE_CELL_96 = 0x1E9F; + static const int PID_CELLVOLTAGE_CELL_97 = 0x1EA0; + static const int PID_CELLVOLTAGE_CELL_98 = 0x1EA1; + static const int PID_CELLVOLTAGE_CELL_99 = 0x1EA2; + static const int PID_CELLVOLTAGE_CELL_100 = 0x1EA3; + static const int PID_CELLVOLTAGE_CELL_101 = 0x1EA4; + static const int PID_CELLVOLTAGE_CELL_102 = 0x1EA5; + static const int PID_CELLVOLTAGE_CELL_103 = 0x1EA6; + static const int PID_CELLVOLTAGE_CELL_104 = 0x1EA7; + static const int PID_CELLVOLTAGE_CELL_105 = 0x1EA8; + static const int PID_CELLVOLTAGE_CELL_106 = 0x1EA9; + static const int PID_CELLVOLTAGE_CELL_107 = 0x1EAA; + static const int PID_CELLVOLTAGE_CELL_108 = 0x1EAB; + static const int PID_TEMP_POINT_1 = 0x1EAE; + static const int PID_TEMP_POINT_2 = 0x1EAF; + static const int PID_TEMP_POINT_3 = 0x1EB0; + static const int PID_TEMP_POINT_4 = 0x1EB1; + static const int PID_TEMP_POINT_5 = 0x1EB2; + static const int PID_TEMP_POINT_6 = 0x1EB3; + static const int PID_TEMP_POINT_7 = 0x1EB4; + static const int PID_TEMP_POINT_8 = 0x1EB5; + static const int PID_TEMP_POINT_9 = 0x1EB6; + static const int PID_TEMP_POINT_10 = 0x1EB7; + static const int PID_TEMP_POINT_11 = 0x1EB8; + static const int PID_TEMP_POINT_12 = 0x1EB9; + static const int PID_TEMP_POINT_13 = 0x1EBA; + static const int PID_TEMP_POINT_14 = 0x1EBB; + static const int PID_TEMP_POINT_15 = 0x1EBC; + static const int PID_TEMP_POINT_16 = 0x1EBD; + static const int PID_TEMP_POINT_17 = 0x1EBE; + static const int PID_TEMP_POINT_18 = 0x1EBF; + + unsigned long previousMillis10ms = 0; // will store last time a 10ms CAN Message was send + unsigned long previousMillis20ms = 0; // will store last time a 20ms CAN Message was send + unsigned long previousMillis40ms = 0; // will store last time a 40ms CAN Message was send + unsigned long previousMillis50ms = 0; // will store last time a 50ms CAN Message was send + unsigned long previousMillis100ms = 0; // will store last time a 100ms CAN Message was send + unsigned long previousMillis200ms = 0; // will store last time a 200ms CAN Message was send + unsigned long previousMillis500ms = 0; // will store last time a 200ms CAN Message was send + unsigned long previousMillis1s = 0; // will store last time a 1s CAN Message was send + + bool toggle = false; + uint8_t counter_1000ms = 0; + uint8_t counter_200ms = 0; + uint8_t counter_100ms = 0; + uint8_t counter_50ms = 0; + uint8_t counter_40ms = 0; + uint8_t counter_20ms = 0; + uint8_t counter_10ms = 0; + uint8_t counter_040 = 0; + uint8_t counter_0F7 = 0; + uint8_t counter_3b5 = 0; + + uint32_t poll_pid = PID_CELLVOLTAGE_CELL_85; // We start here to quickly determine the cell size of the pack. + bool nof_cells_determined = false; + uint32_t pid_reply = 0; + uint16_t battery_soc_polled = 0; + uint16_t battery_voltage_polled = 1480; + int16_t battery_current_polled = 0; + int16_t battery_max_temp = 600; + int16_t battery_min_temp = 600; + uint16_t battery_max_charge_voltage = 0; + uint16_t battery_min_discharge_voltage = 0; + uint16_t battery_allowed_charge_power = 0; + uint16_t battery_allowed_discharge_power = 0; + uint16_t cellvoltages_polled[108]; + uint16_t tempval = 0; + uint8_t BMS_16A954A6_CRC = 0; + uint8_t BMS_5A2_counter = 0; + uint8_t BMS_5CA_counter = 0; + uint8_t BMS_0CF_counter = 0; + uint8_t BMS_0C0_counter = 0; + uint8_t BMS_578_counter = 0; + uint8_t BMS_16A954A6_counter = 0; + bool BMS_ext_limits_active = + false; //The current current limits of the HV battery are expanded to start the combustion engine / confirmation of the request + uint8_t BMS_mode = + 0x07; //0: standby; Gates open; Communication active 1: Main contactor closed / HV network activated / normal driving operation + //2: assigned depending on the project (e.g. balancing, extended DC fast charging) //3: external charging + uint8_t BMS_HVIL_status = 0; //0 init, 1 seated, 2 open, 3 fault + bool BMS_fault_performance = false; //Error: Battery performance is limited (e.g. due to sensor or fan failure) + uint16_t BMS_current = 16300; + bool BMS_fault_emergency_shutdown_crash = + false; //Error: Safety-critical error (crash detection) Battery contactors are already opened / will be opened immediately Signal is read directly by the EMS and initiates an AKS of the PWR and an active discharge of the DC link + uint32_t BMS_voltage_intermediate = 2000; + uint32_t BMS_voltage = 1480; + uint8_t BMS_status_voltage_free = + 0; //0=Init, 1=BMS intermediate circuit voltage-free (U_Zwkr < 20V), 2=BMS intermediate circuit not voltage-free (U_Zwkr >/= 25V, hysteresis), 3=Error + bool BMS_OBD_MIL = false; + uint8_t BMS_error_status = + 0x7; //0 Component_IO, 1 Restricted_CompFkt_Isoerror_I, 2 Restricted_CompFkt_Isoerror_II, 3 Restricted_CompFkt_Interlock, 4 Restricted_CompFkt_SD, 5 Restricted_CompFkt_Performance red, 6 = No component function, 7 = Init + uint16_t BMS_capacity_ah = 0; + bool BMS_error_lamp_req = false; + bool BMS_warning_lamp_req = false; + uint8_t BMS_Kl30c_Status = 0; // 0 init, 1 closed, 2 open, 3 fault + bool service_disconnect_switch_missing = false; + bool pilotline_open = false; + bool balancing_request = false; + uint8_t battery_diagnostic = 0; + uint16_t battery_Wh_left = 0; + uint16_t battery_Wh_max = 1000; + uint8_t battery_potential_status = 0; + uint8_t battery_temperature_warning = 0; + uint16_t max_discharge_power_watt = 0; + uint16_t max_discharge_current_amp = 0; + uint16_t max_charge_power_watt = 0; + uint16_t max_charge_current_amp = 0; + uint16_t battery_SOC = 1; + uint16_t usable_energy_amount_Wh = 0; + uint8_t status_HV_line = 0; //0 init, 1 No open HV line, 2 open HV line detected, 3 fault + uint8_t warning_support = 0; + bool battery_heating_active = false; + uint16_t power_discharge_percentage = 0; + uint16_t power_charge_percentage = 0; + uint16_t actual_battery_voltage = 0; + uint16_t regen_battery = 0; + uint16_t energy_extracted_from_battery = 0; + uint16_t max_fastcharging_current_amp = 0; //maximum DC charging current allowed + uint8_t BMS_Status_DCLS = + 0; //Status of the voltage monitoring on the DC charging interface. 0 inactive, 1 I_O , 2 N_I_O , 3 active + uint16_t DC_voltage_DCLS = 0; //Factor 1, DC voltage of the charging station. Measurement between the DC HV lines. + uint16_t DC_voltage_chargeport = + 0; //Factor 0.5, Current voltage at the HV battery DC charging terminals; Outlet to the DC charging plug. + uint8_t BMS_welded_contactors_status = + 0; //0: Init no diagnostic result, 1: no contactor welded, 2: at least 1 contactor welded, 3: Protection status detection error + bool BMS_error_shutdown_request = + false; // Fault: Fault condition, requires battery contactors to be opened internal battery error; Advance notification of an impending opening of the battery contactors by the BMS + bool BMS_error_shutdown = + false; // Fault: Fault condition, requires battery contactors to be opened Internal battery error, battery contactors opened without notice by the BMS + uint16_t power_battery_heating_watt = 0; + uint16_t power_battery_heating_req_watt = 0; + uint8_t cooling_request = + 0; //0 = No cooling, 1 = Light cooling, cabin prio, 2= higher cooling, 3 = immediate cooling, 4 = emergency cooling + uint8_t heating_request = 0; //0 = init, 1= maintain temp, 2=higher demand, 3 = immediate heat demand + uint8_t balancing_active = false; //0 = init, 1 active, 2 not active + bool charging_active = false; + uint16_t max_energy_Wh = 0; + uint16_t max_charge_percent = 0; + uint16_t min_charge_percent = 0; + uint16_t isolation_resistance_kOhm = 0; + bool battery_heating_installed = false; + bool error_NT_circuit = false; + uint8_t pump_1_control = 0; //0x0D not installed, 0x0E init, 0x0F fault + uint8_t pump_2_control = 0; //0x0D not installed, 0x0E init, 0x0F fault + uint8_t target_flow_temperature_C = 0; //*0,5 -40 + uint8_t return_temperature_C = 0; //*0,5 -40 + uint8_t status_valve_1 = 0; //0 not active, 1 active, 5 not installed, 6 init, 7 fault + uint8_t status_valve_2 = 0; //0 not active, 1 active, 5 not installed, 6 init, 7 fault + uint8_t temperature_request = + 0; //0 high cooling, 1 medium cooling, 2 low cooling, 3 no temp requirement init, 4 low heating , 5 medium heating, 6 high heating, 7 circulation + uint16_t performance_index_discharge_peak_temperature_percentage = 0; + uint16_t performance_index_charge_peak_temperature_percentage = 0; + uint8_t temperature_status_discharge = + 0; //0 init, 1 temp under optimal, 2 temp optimal, 3 temp over optimal, 7 fault + uint8_t temperature_status_charge = 0; //0 init, 1 temp under optimal, 2 temp optimal, 3 temp over optimal, 7 fault + uint8_t isolation_fault = + 0; //0 init, 1 no iso fault, 2 iso fault threshold1, 3 iso fault threshold2, 4 IWU defective + uint8_t isolation_status = + 0; // 0 init, 1 = larger threshold1, 2 = smaller threshold1 total, 3 = smaller threshold1 intern, 4 = smaller threshold2 total, 5 = smaller threshold2 intern, 6 = no measurement, 7 = measurement active + uint8_t actual_temperature_highest_C = 0; //*0,5 -40 + uint8_t actual_temperature_lowest_C = 0; //*0,5 -40 + uint16_t actual_cellvoltage_highest_mV = 0; //bias 1000 + uint16_t actual_cellvoltage_lowest_mV = 0; //bias 1000 + uint16_t predicted_power_dyn_standard_watt = 0; + uint8_t predicted_time_dyn_standard_minutes = 0; + uint8_t mux = 0; + uint16_t cellvoltages[160] = {0}; + uint16_t duration_discharge_power_watt = 0; + uint16_t duration_charge_power_watt = 0; + uint16_t maximum_voltage = 0; + uint16_t minimum_voltage = 0; + uint8_t battery_serialnumber[26]; + uint8_t realtime_overcurrent_monitor = 0; + uint8_t realtime_CAN_communication_fault = 0; + uint8_t realtime_overcharge_warning = 0; + uint8_t realtime_SOC_too_high = 0; + uint8_t realtime_SOC_too_low = 0; + uint8_t realtime_SOC_jumping_warning = 0; + uint8_t realtime_temperature_difference_warning = 0; + uint8_t realtime_cell_overtemperature_warning = 0; + uint8_t realtime_cell_undertemperature_warning = 0; + uint8_t realtime_battery_overvoltage_warning = 0; + uint8_t realtime_battery_undervoltage_warning = 0; + uint8_t realtime_cell_overvoltage_warning = 0; + uint8_t realtime_cell_undervoltage_warning = 0; + uint8_t realtime_cell_imbalance_warning = 0; + uint8_t realtime_warning_battery_unathorized = 0; + bool component_protection_active = false; + bool shutdown_active = false; + bool transportation_mode_active = false; + uint8_t KL15_mode = 0; + uint8_t bus_knockout_timer = 0; + uint8_t hybrid_wakeup_reason = 0; + uint8_t wakeup_type = 0; + bool instrumentation_cluster_request = false; + uint8_t seconds = 0; + uint32_t first_can_msg = 0; + uint32_t last_can_msg_timestamp = 0; + bool hv_requested = false; + int32_t kwh_charge = 0; + int32_t kwh_discharge = 0; + +#define TIME_YEAR 2024 +#define TIME_MONTH 8 +#define TIME_DAY 20 +#define TIME_HOUR 10 +#define TIME_MINUTE 5 +#define TIME_SECOND 0 + +#define BMS_TARGET_HV_OFF 0 +#define BMS_TARGET_HV_ON 1 +#define BMS_TARGET_AC_CHARGING_EXT 3 //(HS + AC_2 contactors closed) +#define BMS_TARGET_AC_CHARGING 4 //(HS + AC contactors closed) +#define BMS_TARGET_DC_CHARGING 6 //(HS + DC contactors closed) +#define BMS_TARGET_INIT 7 + +#define DC_FASTCHARGE_NO_START_REQUEST 0x00 +#define DC_FASTCHARGE_VEHICLE 0x40 +#define DC_FASTCHARGE_LS1 0x80 +#define DC_FASTCHARGE_LS2 0xC0 + + CAN_frame MEB_POLLING_FRAME = {.FD = true, + .ext_ID = true, + .DLC = 8, + .ID = 0x1C40007B, // SOC 02 8C + .data = {0x03, 0x22, 0x02, 0x8C, 0x55, 0x55, 0x55, 0x55}}; + CAN_frame MEB_ACK_FRAME = {.FD = true, + .ext_ID = true, + .DLC = 8, + .ID = 0x1C40007B, // Ack + .data = {0x30, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55}}; + //Messages needed for contactor closing + CAN_frame MEB_040 = {.FD = true, // Airbag + .ext_ID = false, + .DLC = 8, + .ID = 0x040, //Frame5 has HV deactivate request. Needs to be 0x00 + .data = {0x7E, 0x83, 0x00, 0x01, 0x00, 0x00, 0x15, 0x00}}; + CAN_frame MEB_0C0 = { + .FD = true, // EM1 message + .ext_ID = false, + .DLC = 32, + .ID = 0x0C0, //Frame 5-6 and maybe 7-8 important (external voltage at inverter) + .data = {0x77, 0x0A, 0xFE, 0xE7, 0x7F, 0x10, 0x27, 0x00, 0xE0, 0x7F, 0xFF, 0xF3, 0x3F, 0xFF, 0xF3, 0x3F, + 0xFC, 0x0F, 0x00, 0x00, 0xC0, 0xFF, 0xFE, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + CAN_frame MEB_0FC = { + .FD = true, // + .ext_ID = false, + .DLC = 48, + .ID = 0x0FC, //This message contains emergency regen request?(byte19), battery needs to see this message + .data = {0x07, 0x08, 0x00, 0x00, 0x7E, 0x00, 0x40, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFE, 0xFE, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xF4, 0x01, 0x40, 0xFF, 0xEB, 0x7F, 0x0A, 0x88, 0xE3, 0x81, 0xAF, 0x42}}; + CAN_frame MEB_6B2 = {.FD = true, // Diagnostics + .ext_ID = false, + .DLC = 8, + .ID = 0x6B2, + .data = {0x6A, 0xA7, 0x37, 0x80, 0xC9, 0xBD, 0xF6, 0xC2}}; + CAN_frame MEB_17FC007B_poll = {.FD = true, // Non period request + .ext_ID = true, + .DLC = 8, + .ID = 0x17FC007B, + .data = {0x03, 0x22, 0x1E, 0x3D, 0x55, 0x55, 0x55, 0x55}}; + CAN_frame MEB_1A5555A6 = {.FD = true, + .ext_ID = true, + .DLC = 8, + .ID = 0x1A5555A6, + .data = {0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00}}; + CAN_frame MEB_585 = { + .FD = true, + .ext_ID = false, + .DLC = 8, + .ID = 0x585, + .data = {0xCF, 0x38, 0xAF, 0x5B, 0x25, 0x00, 0x00, 0x00}}; // CF 38 AF 5B 25 00 00 00 in start4.log + // .data = {0xCF, 0x38, 0x20, 0x02, 0x25, 0xF7, 0x30, 0x00}}; // CF 38 AF 5B 25 00 00 00 in start4.log + CAN_frame MEB_5F5 = {.FD = true, + .ext_ID = false, + .DLC = 8, + .ID = 0x5F5, + .data = {0x23, 0x02, 0x39, 0xC0, 0x1B, 0x8B, 0xC8, 0x1B}}; + CAN_frame MEB_641 = {.FD = true, + .ext_ID = false, + .DLC = 8, + .ID = 0x641, + .data = {0x37, 0x18, 0x00, 0x00, 0xF0, 0x00, 0xAA, 0x70}}; + CAN_frame MEB_3C0 = {.FD = true, + .ext_ID = false, + .DLC = 4, + .ID = 0x3C0, + .data = {0x66, 0x00, 0x00, 0x00}}; // Klemmen_status_01 + CAN_frame MEB_0FD = {.FD = true, + .ext_ID = false, + .DLC = 8, + .ID = 0x0FD, //CRC and counter, otherwise static + .data = {0x5F, 0xD0, 0x1F, 0x81, 0x00, 0x00, 0x00, 0x00}}; + CAN_frame MEB_16A954FB = {.FD = true, + .ext_ID = true, + .DLC = 8, + .ID = 0x16A954FB, + .data = {0x00, 0xC0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}}; + CAN_frame MEB_1A555548 = {.FD = true, + .ext_ID = true, + .DLC = 8, + .ID = 0x1A555548, + .data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + CAN_frame MEB_1A55552B = {.FD = true, + .ext_ID = true, + .DLC = 8, + .ID = 0x1A55552B, + .data = {0x00, 0x00, 0x00, 0xA0, 0x02, 0x04, 0x00, 0x30}}; + CAN_frame MEB_569 = {.FD = true, + .ext_ID = false, + .DLC = 8, + .ID = 0x569, //HVEM + .data = {0x00, 0x00, 0x01, 0x3A, 0x00, 0x00, 0x00, 0x00}}; + CAN_frame MEB_16A954B4 = {.FD = true, + .ext_ID = true, + .DLC = 8, + .ID = 0x16A954B4, //eTM + .data = {0xFE, 0xB6, 0x0D, 0x00, 0x00, 0xD5, 0x48, 0xFD}}; + CAN_frame MEB_1B000046 = {.FD = false, // Not FD + .ext_ID = true, + .DLC = 8, + .ID = 0x1B000046, // Klima + .data = {0x00, 0x40, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00}}; + CAN_frame MEB_1B000010 = {.FD = false, // Not FD + .ext_ID = true, + .DLC = 8, + .ID = 0x1B000010, // Gateway + .data = {0x00, 0x50, 0x08, 0x50, 0x01, 0xFF, 0x30, 0x00}}; + CAN_frame MEB_1B0000B9 = {.FD = false, // Not FD + .ext_ID = true, + .DLC = 8, + .ID = 0x1B0000B9, //DC/DC converter + .data = {0x00, 0x40, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00}}; + CAN_frame MEB_153 = {.FD = true, + .ext_ID = false, + .DLC = 8, + .ID = 0x153, // content + .data = {0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFE, 0xFF, 0xFF}}; + CAN_frame MEB_5E1 = {.FD = true, + .ext_ID = false, + .DLC = 8, + .ID = 0x5E1, // content + .data = {0x7F, 0x2A, 0x00, 0x60, 0xFE, 0x00, 0x00, 0x00}}; + CAN_frame MEB_3BE = {.FD = true, + .ext_ID = false, + .DLC = 8, + .ID = 0x3BE, // CRC, otherwise content + .data = {0x57, 0x0D, 0x00, 0x00, 0x00, 0x02, 0x04, 0x40}}; + CAN_frame MEB_272 = {.FD = true, //HVLM_14 + .ext_ID = false, + .DLC = 8, + .ID = 0x272, // content + .data = {0x00, 0x00, 0x00, 0x00, 0x48, 0x08, 0x00, 0x94}}; + CAN_frame MEB_503 = {.FD = true, //HVK_01 + .ext_ID = false, + .DLC = 8, + .ID = 0x503, // Content varies. Frame1 & 3 has HV req + .data = {0x5D, 0x61, 0x00, 0xFF, 0x7F, 0x80, 0xE3, 0x03}}; + CAN_frame MEB_14C = { + .FD = true, //Motor message + .ext_ID = false, + .DLC = 32, + .ID = 0x14C, //CRC needed, content otherwise + .data = {0x38, 0x0A, 0xFF, 0x01, 0x01, 0xFF, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, + 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x25, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE}}; + + uint32_t can_msg_received = 0; +}; #endif