diff --git a/Software/USER_SETTINGS.h b/Software/USER_SETTINGS.h index f6707e5e..a73799c5 100644 --- a/Software/USER_SETTINGS.h +++ b/Software/USER_SETTINGS.h @@ -11,6 +11,7 @@ /* Select battery used */ //#define BMW_I3_BATTERY //#define BMW_IX_BATTERY +//#define BOLT_AMPERA_BATTERY //#define BYD_ATTO_3_BATTERY //#define CELLPOWER_BMS //#define CHADEMO_BATTERY //NOTE: inherently enables CONTACTOR_CONTROL below diff --git a/Software/src/battery/BATTERIES.h b/Software/src/battery/BATTERIES.h index c2c0bdac..08413b00 100644 --- a/Software/src/battery/BATTERIES.h +++ b/Software/src/battery/BATTERIES.h @@ -10,6 +10,10 @@ #include "BMW-IX-BATTERY.h" #endif +#ifdef BOLT_AMPERA_BATTERY +#include "BOLT-AMPERA-BATTERY.h" +#endif + #ifdef BYD_ATTO_3_BATTERY #include "BYD-ATTO-3-BATTERY.h" #endif diff --git a/Software/src/battery/BOLT-AMPERA-BATTERY.cpp b/Software/src/battery/BOLT-AMPERA-BATTERY.cpp new file mode 100644 index 00000000..90d85eb5 --- /dev/null +++ b/Software/src/battery/BOLT-AMPERA-BATTERY.cpp @@ -0,0 +1,789 @@ +#include "../include.h" +#ifdef BOLT_AMPERA_BATTERY +#include "../datalayer/datalayer.h" +#include "../datalayer/datalayer_extended.h" +#include "../devboard/utils/events.h" +#include "BOLT-AMPERA-BATTERY.h" + +/* +TODOs left for this implementation +- The battery has 3 CAN ports. One of them is responsible for the 7E4 polls, the other for the 7E7 polls +- Current implementation only seems to get the 7E7 polls working. +- Could on of the CAN channels be GMLAN? + +- The values missing for a working implementation is: +- SOC% missing! This is absolutely mandatory to fix before starting to use this! +- Capacity (kWh) (can be estimated) +- Charge max power (can be estimated) +- Discharge max power (can be estimated) +- SOH% (low prio)) +*/ + +/* Do not change code below unless you are sure what you are doing */ +static unsigned long previousMillis20ms = 0; // will store last time a 20ms CAN Message was send +static unsigned long previousMillis100ms = 0; // will store last time a 100ms CAN Message was send +static unsigned long previousMillis120ms = 0; // will store last time a 120ms CAN Message was send + +CAN_frame BOLT_778 = {.FD = false, // Unsure of what this message is, added only as example + .ext_ID = false, + .DLC = 7, + .ID = 0x778, + .data = {0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00}}; +CAN_frame BOLT_POLL_7E4 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x7E4, + .data = {0x03, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; +CAN_frame BOLT_ACK_7E4 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x7E4, + .data = {0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; +CAN_frame BOLT_POLL_7E7 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x7E7, + .data = {0x03, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; +CAN_frame BOLT_ACK_7E7 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x7E7, + .data = {0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + +// 7E4 Battery , reply 000007EC +// 7E7 Battery (Cell voltages), reply 000007EF + +static uint16_t battery_cell_voltages[96]; //array with all the cellvoltages +static uint16_t battery_capacity_my17_18 = 0; +static uint16_t battery_capacity_my19plus = 0; +static uint16_t battery_SOC_display = 0; +static uint16_t battery_SOC_raw_highprec = 0; +static uint16_t battery_max_temperature = 0; +static uint16_t battery_min_temperature = 0; +static uint16_t battery_min_cell_voltage = 0; +static uint16_t battery_max_cell_voltage = 0; +static uint16_t battery_internal_resistance = 0; +static uint16_t battery_lowest_cell = 0; +static uint16_t battery_highest_cell = 0; +static uint16_t battery_voltage_polled = 0; +static uint16_t battery_voltage_periodic = 0; +static uint16_t battery_vehicle_isolation = 0; +static uint16_t battery_isolation_kohm = 0; +static uint16_t battery_HV_locked = 0; +static uint16_t battery_crash_event = 0; +static uint16_t battery_HVIL = 0; +static uint16_t battery_HVIL_status = 0; +static uint16_t battery_5V_ref = 0; +static int16_t battery_current_7E4 = 0; +static int16_t battery_module_temp_1 = 0; +static int16_t battery_module_temp_2 = 0; +static int16_t battery_module_temp_3 = 0; +static int16_t battery_module_temp_4 = 0; +static int16_t battery_module_temp_5 = 0; +static int16_t battery_module_temp_6 = 0; +static uint16_t battery_cell_average_voltage = 0; +static uint16_t battery_cell_average_voltage_2 = 0; +static uint16_t battery_terminal_voltage = 0; +static uint16_t battery_ignition_power_mode = 0; +static int16_t battery_current_7E7 = 0; +static int16_t temperature_1 = 0; +static int16_t temperature_2 = 0; +static int16_t temperature_3 = 0; +static int16_t temperature_4 = 0; +static int16_t temperature_5 = 0; +static int16_t temperature_6 = 0; +static int16_t temperature_highest = 0; +static int16_t temperature_lowest = 0; +static uint8_t mux = 0; +static uint8_t poll_index_7E4 = 0; +static uint16_t currentpoll_7E4 = POLL_7E4_CAPACITY_EST_GEN1; +static uint16_t reply_poll_7E4 = 0; +static uint8_t poll_index_7E7 = 0; +static uint16_t currentpoll_7E7 = POLL_7E7_CURRENT; +static uint16_t reply_poll_7E7 = 0; + +const uint16_t poll_commands_7E4[19] = {POLL_7E4_CAPACITY_EST_GEN1, + POLL_7E4_CAPACITY_EST_GEN2, + POLL_7E4_SOC_DISPLAY, + POLL_7E4_SOC_RAW_HIGHPREC, + POLL_7E4_MAX_TEMPERATURE, + POLL_7E4_MIN_TEMPERATURE, + POLL_7E4_MIN_CELL_V, + POLL_7E4_MAX_CELL_V, + POLL_7E4_INTERNAL_RES, + POLL_7E4_LOWEST_CELL_NUMBER, + POLL_7E4_HIGHEST_CELL_NUMBER, + POLL_7E4_VOLTAGE, + POLL_7E4_VEHICLE_ISOLATION, + POLL_7E4_ISOLATION_TEST_KOHM, + POLL_7E4_HV_LOCKED_OUT, + POLL_7E4_CRASH_EVENT, + POLL_7E4_HVIL, + POLL_7E4_HVIL_STATUS, + POLL_7E4_CURRENT}; + +const uint16_t poll_commands_7E7[108] = {POLL_7E7_CURRENT, POLL_7E7_5V_REF, + POLL_7E7_MODULE_TEMP_1, POLL_7E7_MODULE_TEMP_2, + POLL_7E7_MODULE_TEMP_3, POLL_7E7_MODULE_TEMP_4, + POLL_7E7_MODULE_TEMP_5, POLL_7E7_MODULE_TEMP_6, + POLL_7E7_CELL_AVG_VOLTAGE, POLL_7E7_CELL_AVG_VOLTAGE_2, + POLL_7E7_TERMINAL_VOLTAGE, POLL_7E7_IGNITION_POWER_MODE, + POLL_7E7_CELL_01, POLL_7E7_CELL_02, + POLL_7E7_CELL_03, POLL_7E7_CELL_04, + POLL_7E7_CELL_05, POLL_7E7_CELL_06, + POLL_7E7_CELL_07, POLL_7E7_CELL_08, + POLL_7E7_CELL_09, POLL_7E7_CELL_10, + POLL_7E7_CELL_11, POLL_7E7_CELL_12, + POLL_7E7_CELL_13, POLL_7E7_CELL_14, + POLL_7E7_CELL_15, POLL_7E7_CELL_16, + POLL_7E7_CELL_17, POLL_7E7_CELL_18, + POLL_7E7_CELL_19, POLL_7E7_CELL_20, + POLL_7E7_CELL_21, POLL_7E7_CELL_22, + POLL_7E7_CELL_23, POLL_7E7_CELL_24, + POLL_7E7_CELL_25, POLL_7E7_CELL_26, + POLL_7E7_CELL_27, POLL_7E7_CELL_28, + POLL_7E7_CELL_29, POLL_7E7_CELL_30, + POLL_7E7_CELL_31, POLL_7E7_CELL_32, + POLL_7E7_CELL_33, POLL_7E7_CELL_34, + POLL_7E7_CELL_35, POLL_7E7_CELL_36, + POLL_7E7_CELL_37, POLL_7E7_CELL_38, + POLL_7E7_CELL_39, POLL_7E7_CELL_40, + POLL_7E7_CELL_41, POLL_7E7_CELL_42, + POLL_7E7_CELL_43, POLL_7E7_CELL_44, + POLL_7E7_CELL_45, POLL_7E7_CELL_46, + POLL_7E7_CELL_47, POLL_7E7_CELL_48, + POLL_7E7_CELL_49, POLL_7E7_CELL_50, + POLL_7E7_CELL_51, POLL_7E7_CELL_52, + POLL_7E7_CELL_53, POLL_7E7_CELL_54, + POLL_7E7_CELL_55, POLL_7E7_CELL_56, + POLL_7E7_CELL_57, POLL_7E7_CELL_58, + POLL_7E7_CELL_59, POLL_7E7_CELL_60, + POLL_7E7_CELL_61, POLL_7E7_CELL_62, + POLL_7E7_CELL_63, POLL_7E7_CELL_64, + POLL_7E7_CELL_65, POLL_7E7_CELL_66, + POLL_7E7_CELL_67, POLL_7E7_CELL_68, + POLL_7E7_CELL_69, POLL_7E7_CELL_70, + POLL_7E7_CELL_71, POLL_7E7_CELL_72, + POLL_7E7_CELL_73, POLL_7E7_CELL_74, + POLL_7E7_CELL_75, POLL_7E7_CELL_76, + POLL_7E7_CELL_77, POLL_7E7_CELL_78, + POLL_7E7_CELL_79, POLL_7E7_CELL_80, + POLL_7E7_CELL_81, POLL_7E7_CELL_82, + POLL_7E7_CELL_83, POLL_7E7_CELL_84, + POLL_7E7_CELL_85, POLL_7E7_CELL_86, + POLL_7E7_CELL_87, POLL_7E7_CELL_88, + POLL_7E7_CELL_89, POLL_7E7_CELL_90, + POLL_7E7_CELL_91, POLL_7E7_CELL_92, + POLL_7E7_CELL_93, POLL_7E7_CELL_94, + POLL_7E7_CELL_95, POLL_7E7_CELL_96}; + +void update_values_battery() { //This function maps all the values fetched via CAN to the battery datalayer + + datalayer.battery.status.real_soc = battery_SOC_display; + + //datalayer.battery.status.voltage_dV = battery_voltage * 0.52; + datalayer.battery.status.voltage_dV = (battery_voltage_periodic / 8) * 10; + + datalayer.battery.status.current_dA = battery_current_7E7; + + datalayer.battery.info.total_capacity_Wh; + + datalayer.battery.status.remaining_capacity_Wh; + + datalayer.battery.status.soh_pptt; + + datalayer.battery.status.max_discharge_power_W; + + datalayer.battery.status.max_charge_power_W; + + // Store temperatures in an array + int16_t temperatures[] = {temperature_1, temperature_2, temperature_3, temperature_4, temperature_5, temperature_6}; + + // Initialize highest and lowest to the first element + temperature_highest = temperatures[0]; + temperature_lowest = temperatures[0]; + + // Iterate through the array to find the highest and lowest values + for (uint8_t i = 1; i < 6; ++i) { + if (temperatures[i] > temperature_highest) { + temperature_highest = temperatures[i]; + } + if (temperatures[i] < temperature_lowest) { + temperature_lowest = temperatures[i]; + } + } + + datalayer.battery.status.temperature_min_dC = temperature_lowest * 10; + + datalayer.battery.status.temperature_max_dC = temperature_highest * 10; + + //Map all cell voltages to the global array + memcpy(datalayer.battery.status.cell_voltages_mV, battery_cell_voltages, 96 * sizeof(uint16_t)); + + // Update webserver datalayer + datalayer_extended.boltampera.battery_5V_ref = battery_5V_ref; + datalayer_extended.boltampera.battery_module_temp_1 = battery_module_temp_1; + datalayer_extended.boltampera.battery_module_temp_2 = battery_module_temp_2; + datalayer_extended.boltampera.battery_module_temp_3 = battery_module_temp_3; + datalayer_extended.boltampera.battery_module_temp_4 = battery_module_temp_4; + datalayer_extended.boltampera.battery_module_temp_5 = battery_module_temp_5; + datalayer_extended.boltampera.battery_module_temp_6 = battery_module_temp_6; + datalayer_extended.boltampera.battery_cell_average_voltage = battery_cell_average_voltage; + datalayer_extended.boltampera.battery_cell_average_voltage_2 = battery_cell_average_voltage_2; + datalayer_extended.boltampera.battery_terminal_voltage = battery_terminal_voltage; + datalayer_extended.boltampera.battery_ignition_power_mode = battery_ignition_power_mode; + datalayer_extended.boltampera.battery_current_7E7 = battery_current_7E7; + datalayer_extended.boltampera.battery_capacity_my17_18 = battery_capacity_my17_18; + datalayer_extended.boltampera.battery_capacity_my19plus = battery_capacity_my19plus; + datalayer_extended.boltampera.battery_SOC_display = battery_SOC_display; + datalayer_extended.boltampera.battery_SOC_raw_highprec = battery_SOC_raw_highprec; + datalayer_extended.boltampera.battery_max_temperature = battery_max_temperature; + datalayer_extended.boltampera.battery_min_temperature = battery_min_temperature; + datalayer_extended.boltampera.battery_min_cell_voltage = battery_min_cell_voltage; + datalayer_extended.boltampera.battery_max_cell_voltage = battery_max_cell_voltage; + datalayer_extended.boltampera.battery_lowest_cell = battery_lowest_cell; + datalayer_extended.boltampera.battery_highest_cell = battery_highest_cell; + datalayer_extended.boltampera.battery_internal_resistance = battery_internal_resistance; + datalayer_extended.boltampera.battery_voltage_polled = battery_voltage_polled; + datalayer_extended.boltampera.battery_vehicle_isolation = battery_vehicle_isolation; + datalayer_extended.boltampera.battery_isolation_kohm = battery_isolation_kohm; + datalayer_extended.boltampera.battery_HV_locked = battery_HV_locked; + datalayer_extended.boltampera.battery_crash_event = battery_crash_event; + datalayer_extended.boltampera.battery_HVIL = battery_HVIL; + datalayer_extended.boltampera.battery_HVIL_status = battery_HVIL_status; + datalayer_extended.boltampera.battery_current_7E4 = battery_current_7E4; +} + +void receive_can_battery(CAN_frame rx_frame) { + switch (rx_frame.ID) { + case 0x200: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + mux = ((rx_frame.data.u8[6] & 0xE0) >> 5); //goes from 0-7 + break; + case 0x202: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + mux = ((rx_frame.data.u8[6] & 0xE0) >> 5); //goes from 0-7 + break; + case 0x204: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + mux = ((rx_frame.data.u8[6] & 0xE0) >> 5); //goes from 0-7 + break; + case 0x206: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + mux = ((rx_frame.data.u8[6] & 0xE0) >> 5); //goes from 0-7 + break; + case 0x208: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + mux = ((rx_frame.data.u8[6] & 0xE0) >> 5); //goes from 0-7 + break; + case 0x20C: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + break; + case 0x216: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + break; + case 0x2C7: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + battery_voltage_periodic = (rx_frame.data.u8[3] << 4) | (rx_frame.data.u8[4] >> 4); + break; + case 0x260: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + break; + case 0x270: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + break; + case 0x272: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + break; + case 0x274: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + break; + case 0x302: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + temperature_1 = ((rx_frame.data.u8[1] / 2) - 40); //Module 1 Temperature + temperature_2 = ((rx_frame.data.u8[2] / 2) - 40); //Module 2 Temperature + temperature_3 = ((rx_frame.data.u8[3] / 2) - 40); //Module 3 Temperature + temperature_4 = ((rx_frame.data.u8[4] / 2) - 40); //Module 4 Temperature + temperature_5 = ((rx_frame.data.u8[5] / 2) - 40); //Module 5 Temperature + temperature_6 = ((rx_frame.data.u8[6] / 2) - 40); //Module 6 Temperature + break; + case 0x3E3: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + break; + case 0x460: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + break; + case 0x5EF: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + break; + case 0x7EC: //When polling 7E4 BMS replies with 7EC ?? + + if (rx_frame.data.u8[0] == 0x10) { //"PID Header" + transmit_can(&BOLT_ACK_7E4, can_config.battery); + } + + //Frame 2 & 3 contains reply + reply_poll_7E4 = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + + switch (reply_poll_7E4) { + case POLL_7E4_CAPACITY_EST_GEN1: + battery_capacity_my17_18 = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]); + break; + case POLL_7E4_CAPACITY_EST_GEN2: + battery_capacity_my19plus = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]); + break; + case POLL_7E4_SOC_DISPLAY: + battery_SOC_display = ((rx_frame.data.u8[4] * 100) / 255); + break; + case POLL_7E4_SOC_RAW_HIGHPREC: + battery_SOC_raw_highprec = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 100) / 65535); + break; + case POLL_7E4_MAX_TEMPERATURE: + battery_max_temperature = (rx_frame.data.u8[4] - 40); + break; + case POLL_7E4_MIN_TEMPERATURE: + battery_min_temperature = (rx_frame.data.u8[4] - 40); + break; + case POLL_7E4_MIN_CELL_V: + battery_min_cell_voltage = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) / 1666; + break; + case POLL_7E4_MAX_CELL_V: + battery_max_cell_voltage = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) / 1666; + break; + case POLL_7E4_INTERNAL_RES: + battery_internal_resistance = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) / 2; + break; + case POLL_7E4_LOWEST_CELL_NUMBER: + battery_lowest_cell = rx_frame.data.u8[4]; + break; + case POLL_7E4_HIGHEST_CELL_NUMBER: + battery_highest_cell = rx_frame.data.u8[4]; + break; + case POLL_7E4_VOLTAGE: + battery_voltage_polled = (((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 0.52); + break; + case POLL_7E4_VEHICLE_ISOLATION: + battery_vehicle_isolation = ((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]); + break; + case POLL_7E4_ISOLATION_TEST_KOHM: + battery_isolation_kohm = (rx_frame.data.u8[4] * 25); + break; + case POLL_7E4_HV_LOCKED_OUT: + battery_HV_locked = rx_frame.data.u8[4]; + break; + case POLL_7E4_CRASH_EVENT: + battery_crash_event = rx_frame.data.u8[4]; + break; + case POLL_7E4_HVIL: + battery_HVIL = rx_frame.data.u8[4]; + break; + case POLL_7E4_HVIL_STATUS: + battery_HVIL_status = rx_frame.data.u8[4]; + break; + case POLL_7E4_CURRENT: + battery_current_7E4 = (((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) / (-6.675)); + break; + default: + break; + } + + break; + case 0x7EF: //When polling 7E7 BMS replies with 7EF + + if (rx_frame.data.u8[0] == 0x10) { //"PID Header" + transmit_can(&BOLT_ACK_7E7, can_config.battery); + } + + //Frame 2 & 3 contains reply + reply_poll_7E7 = (rx_frame.data.u8[2] << 8) | rx_frame.data.u8[3]; + + switch (reply_poll_7E7) { + case POLL_7E7_CURRENT: + battery_current_7E7 = (rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]; + break; + case POLL_7E7_5V_REF: + battery_5V_ref = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5) / 65535); + break; + case POLL_7E7_MODULE_TEMP_1: + battery_module_temp_1 = (rx_frame.data.u8[4] - 40); + break; + case POLL_7E7_MODULE_TEMP_2: + battery_module_temp_2 = (rx_frame.data.u8[4] - 40); + break; + case POLL_7E7_MODULE_TEMP_3: + battery_module_temp_3 = (rx_frame.data.u8[4] - 40); + break; + case POLL_7E7_MODULE_TEMP_4: + battery_module_temp_4 = (rx_frame.data.u8[4] - 40); + break; + case POLL_7E7_MODULE_TEMP_5: + battery_module_temp_5 = (rx_frame.data.u8[4] - 40); + break; + case POLL_7E7_MODULE_TEMP_6: + battery_module_temp_6 = (rx_frame.data.u8[4] - 40); + break; + case POLL_7E7_CELL_AVG_VOLTAGE: + battery_cell_average_voltage = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_AVG_VOLTAGE_2: + battery_cell_average_voltage_2 = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) / 8000) * 1000); + break; + case POLL_7E7_TERMINAL_VOLTAGE: + battery_terminal_voltage = rx_frame.data.u8[4] * 2; + break; + case POLL_7E7_IGNITION_POWER_MODE: + battery_ignition_power_mode = rx_frame.data.u8[4]; + break; + case POLL_7E7_CELL_01: + battery_cell_voltages[0] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_02: + battery_cell_voltages[1] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_03: + battery_cell_voltages[2] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_04: + battery_cell_voltages[3] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_05: + battery_cell_voltages[4] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_06: + battery_cell_voltages[5] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_07: + battery_cell_voltages[6] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_08: + battery_cell_voltages[7] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_09: + battery_cell_voltages[8] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_10: + battery_cell_voltages[9] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_11: + battery_cell_voltages[10] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_12: + battery_cell_voltages[11] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_13: + battery_cell_voltages[12] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_14: + battery_cell_voltages[13] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_15: + battery_cell_voltages[14] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_16: + battery_cell_voltages[15] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_17: + battery_cell_voltages[16] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_18: + battery_cell_voltages[17] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_19: + battery_cell_voltages[18] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_20: + battery_cell_voltages[19] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_21: + battery_cell_voltages[20] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_22: + battery_cell_voltages[21] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_23: + battery_cell_voltages[22] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_24: + battery_cell_voltages[23] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_25: + battery_cell_voltages[24] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_26: + battery_cell_voltages[25] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_27: + battery_cell_voltages[26] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_28: + battery_cell_voltages[27] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_29: + battery_cell_voltages[28] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_30: + battery_cell_voltages[29] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_31: + battery_cell_voltages[30] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_32: + battery_cell_voltages[31] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_33: + battery_cell_voltages[32] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_34: + battery_cell_voltages[33] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_35: + battery_cell_voltages[34] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_36: + battery_cell_voltages[35] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_37: + battery_cell_voltages[36] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_38: + battery_cell_voltages[37] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_39: + battery_cell_voltages[38] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_40: + battery_cell_voltages[39] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_41: + battery_cell_voltages[40] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_42: + battery_cell_voltages[41] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_43: + battery_cell_voltages[42] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_44: + battery_cell_voltages[43] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_45: + battery_cell_voltages[44] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_46: + battery_cell_voltages[45] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_47: + battery_cell_voltages[46] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_48: + battery_cell_voltages[47] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_49: + battery_cell_voltages[48] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_50: + battery_cell_voltages[49] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_51: + battery_cell_voltages[50] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_52: + battery_cell_voltages[51] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_53: + battery_cell_voltages[52] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_54: + battery_cell_voltages[53] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_55: + battery_cell_voltages[54] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_56: + battery_cell_voltages[55] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_57: + battery_cell_voltages[56] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_58: + battery_cell_voltages[57] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_59: + battery_cell_voltages[58] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_60: + battery_cell_voltages[59] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_61: + battery_cell_voltages[60] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_62: + battery_cell_voltages[61] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_63: + battery_cell_voltages[62] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_64: + battery_cell_voltages[63] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_65: + battery_cell_voltages[64] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_66: + battery_cell_voltages[65] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_67: + battery_cell_voltages[66] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_68: + battery_cell_voltages[67] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_69: + battery_cell_voltages[68] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_70: + battery_cell_voltages[69] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_71: + battery_cell_voltages[70] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_72: + battery_cell_voltages[71] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_73: + battery_cell_voltages[72] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_74: + battery_cell_voltages[73] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_75: + battery_cell_voltages[74] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_76: + battery_cell_voltages[75] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_77: + battery_cell_voltages[76] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_78: + battery_cell_voltages[77] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_79: + battery_cell_voltages[78] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_80: + battery_cell_voltages[79] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_81: + battery_cell_voltages[80] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_82: + battery_cell_voltages[81] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_83: + battery_cell_voltages[82] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_84: + battery_cell_voltages[83] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_85: + battery_cell_voltages[84] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_86: + battery_cell_voltages[85] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_87: + battery_cell_voltages[86] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_88: + battery_cell_voltages[87] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_89: + battery_cell_voltages[88] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_90: + battery_cell_voltages[89] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_91: + battery_cell_voltages[90] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_92: + battery_cell_voltages[91] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_93: + battery_cell_voltages[92] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_94: + battery_cell_voltages[93] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_95: + battery_cell_voltages[94] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + case POLL_7E7_CELL_96: + battery_cell_voltages[95] = ((((rx_frame.data.u8[4] << 8) | rx_frame.data.u8[5]) * 5000) / 65535); + break; + default: + break; + } + default: + break; + } +} + +void send_can_battery() { + unsigned long currentMillis = millis(); + + //Send 20ms message + if (currentMillis - previousMillis20ms >= INTERVAL_20_MS) { + // Check if sending of CAN messages has been delayed too much. + if ((currentMillis - previousMillis20ms >= INTERVAL_20_MS_DELAYED) && (currentMillis > BOOTUP_TIME)) { + set_event(EVENT_CAN_OVERRUN, (currentMillis - previousMillis20ms)); + } else { + clear_event(EVENT_CAN_OVERRUN); + } + previousMillis20ms = currentMillis; + transmit_can(&BOLT_778, can_config.battery); + } + + //Send 100ms message + if (currentMillis - previousMillis100ms >= INTERVAL_100_MS) { + previousMillis100ms = currentMillis; + + // Update current poll from the 7E7 array + currentpoll_7E7 = poll_commands_7E7[poll_index_7E7]; + poll_index_7E7 = (poll_index_7E7 + 1) % 108; + + BOLT_POLL_7E7.data.u8[2] = (uint8_t)((currentpoll_7E7 & 0xFF00) >> 8); + BOLT_POLL_7E7.data.u8[3] = (uint8_t)(currentpoll_7E7 & 0x00FF); + + transmit_can(&BOLT_POLL_7E7, can_config.battery); + } + + //Send 120ms message + if (currentMillis - previousMillis120ms >= 120) { + previousMillis120ms = currentMillis; + + // Update current poll from the 7E4 array + currentpoll_7E4 = poll_commands_7E4[poll_index_7E4]; + poll_index_7E4 = (poll_index_7E4 + 1) % 19; + + BOLT_POLL_7E4.data.u8[2] = (uint8_t)((currentpoll_7E4 & 0xFF00) >> 8); + BOLT_POLL_7E4.data.u8[3] = (uint8_t)(currentpoll_7E4 & 0x00FF); + + transmit_can(&BOLT_POLL_7E4, can_config.battery); + } +} + +void setup_battery(void) { // Performs one time setup at startup + strncpy(datalayer.system.info.battery_protocol, "Chevrolet Bolt EV/Opel Ampera-e", 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; + datalayer.battery.info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV; + datalayer.battery.info.min_cell_voltage_mV = MIN_CELL_VOLTAGE_MV; + datalayer.battery.info.max_cell_voltage_deviation_mV = MAX_CELL_DEVIATION_MV; + datalayer.system.status.battery_allows_contactor_closing = true; +} + +#endif diff --git a/Software/src/battery/BOLT-AMPERA-BATTERY.h b/Software/src/battery/BOLT-AMPERA-BATTERY.h new file mode 100644 index 00000000..7d877220 --- /dev/null +++ b/Software/src/battery/BOLT-AMPERA-BATTERY.h @@ -0,0 +1,146 @@ +#ifndef BOLT_AMPERA_BATTERY_H +#define BOLT_AMPERA_BATTERY_H +#include +#include "../include.h" + +#define BATTERY_SELECTED + +#define MAX_PACK_VOLTAGE_DV 4150 //5000 = 500.0V +#define MIN_PACK_VOLTAGE_DV 2500 +#define MAX_CELL_DEVIATION_MV 500 +#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 POLL_7E4_CAPACITY_EST_GEN1 0x41A3 +#define POLL_7E4_CAPACITY_EST_GEN2 0x45F9 +#define POLL_7E4_SOC_DISPLAY 0x8334 +#define POLL_7E4_SOC_RAW_HIGHPREC 0x43AF +#define POLL_7E4_MAX_TEMPERATURE 0x4349 +#define POLL_7E4_MIN_TEMPERATURE 0x434A +#define POLL_7E4_MIN_CELL_V 0x4329 +#define POLL_7E4_MAX_CELL_V 0x432B +#define POLL_7E4_INTERNAL_RES 0x40E9 +#define POLL_7E4_LOWEST_CELL_NUMBER 0x433B +#define POLL_7E4_HIGHEST_CELL_NUMBER 0x433C +#define POLL_7E4_VOLTAGE 0x432D +#define POLL_7E4_VEHICLE_ISOLATION 0x41EC +#define POLL_7E4_ISOLATION_TEST_KOHM 0x43A6 +#define POLL_7E4_HV_LOCKED_OUT 0x44F8 +#define POLL_7E4_CRASH_EVENT 0x4522 +#define POLL_7E4_HVIL 0x4310 +#define POLL_7E4_HVIL_STATUS 0x4311 +#define POLL_7E4_CURRENT 0x4356 + +#define POLL_7E7_CURRENT 0x40D4 +#define POLL_7E7_5V_REF 0x40D3 +#define POLL_7E7_MODULE_TEMP_1 0x40D7 +#define POLL_7E7_MODULE_TEMP_2 0x40D9 +#define POLL_7E7_MODULE_TEMP_3 0x40DB +#define POLL_7E7_MODULE_TEMP_4 0x40DD +#define POLL_7E7_MODULE_TEMP_5 0x40DF +#define POLL_7E7_MODULE_TEMP_6 0x40E1 +#define POLL_7E7_CELL_AVG_VOLTAGE 0xC218 +#define POLL_7E7_CELL_AVG_VOLTAGE_2 0x44B9 +#define POLL_7E7_TERMINAL_VOLTAGE 0x82A3 +#define POLL_7E7_IGNITION_POWER_MODE 0x8002 +#define POLL_7E7_CELL_01 0x4181 +#define POLL_7E7_CELL_02 0x4182 +#define POLL_7E7_CELL_03 0x4183 +#define POLL_7E7_CELL_04 0x4184 +#define POLL_7E7_CELL_05 0x4185 +#define POLL_7E7_CELL_06 0x4186 +#define POLL_7E7_CELL_07 0x4187 +#define POLL_7E7_CELL_08 0x4188 +#define POLL_7E7_CELL_09 0x4189 +#define POLL_7E7_CELL_10 0x418A +#define POLL_7E7_CELL_11 0x418B +#define POLL_7E7_CELL_12 0x418C +#define POLL_7E7_CELL_13 0x418D +#define POLL_7E7_CELL_14 0x418E +#define POLL_7E7_CELL_15 0x418F +#define POLL_7E7_CELL_16 0x4190 +#define POLL_7E7_CELL_17 0x4191 +#define POLL_7E7_CELL_18 0x4192 +#define POLL_7E7_CELL_19 0x4193 +#define POLL_7E7_CELL_20 0x4194 +#define POLL_7E7_CELL_21 0x4195 +#define POLL_7E7_CELL_22 0x4196 +#define POLL_7E7_CELL_23 0x4197 +#define POLL_7E7_CELL_24 0x4198 +#define POLL_7E7_CELL_25 0x4199 +#define POLL_7E7_CELL_26 0x419A +#define POLL_7E7_CELL_27 0x419B +#define POLL_7E7_CELL_28 0x419C +#define POLL_7E7_CELL_29 0x419D +#define POLL_7E7_CELL_30 0x419E +#define POLL_7E7_CELL_31 0x419F +#define POLL_7E7_CELL_32 0x4200 +#define POLL_7E7_CELL_33 0x4201 +#define POLL_7E7_CELL_34 0x4202 +#define POLL_7E7_CELL_35 0x4203 +#define POLL_7E7_CELL_36 0x4204 +#define POLL_7E7_CELL_37 0x4205 +#define POLL_7E7_CELL_38 0x4206 +#define POLL_7E7_CELL_39 0x4207 +#define POLL_7E7_CELL_40 0x4208 +#define POLL_7E7_CELL_41 0x4209 +#define POLL_7E7_CELL_42 0x420A +#define POLL_7E7_CELL_43 0x420B +#define POLL_7E7_CELL_44 0x420C +#define POLL_7E7_CELL_45 0x420D +#define POLL_7E7_CELL_46 0x420E +#define POLL_7E7_CELL_47 0x420F +#define POLL_7E7_CELL_48 0x4210 +#define POLL_7E7_CELL_49 0x4211 +#define POLL_7E7_CELL_50 0x4212 +#define POLL_7E7_CELL_51 0x4213 +#define POLL_7E7_CELL_52 0x4214 +#define POLL_7E7_CELL_53 0x4215 +#define POLL_7E7_CELL_54 0x4216 +#define POLL_7E7_CELL_55 0x4217 +#define POLL_7E7_CELL_56 0x4218 +#define POLL_7E7_CELL_57 0x4219 +#define POLL_7E7_CELL_58 0x421A +#define POLL_7E7_CELL_59 0x421B +#define POLL_7E7_CELL_60 0x421C +#define POLL_7E7_CELL_61 0x421D +#define POLL_7E7_CELL_62 0x421E +#define POLL_7E7_CELL_63 0x421F +#define POLL_7E7_CELL_64 0x4220 +#define POLL_7E7_CELL_65 0x4221 +#define POLL_7E7_CELL_66 0x4222 +#define POLL_7E7_CELL_67 0x4223 +#define POLL_7E7_CELL_68 0x4224 +#define POLL_7E7_CELL_69 0x4225 +#define POLL_7E7_CELL_70 0x4226 +#define POLL_7E7_CELL_71 0x4227 +#define POLL_7E7_CELL_72 0x4228 +#define POLL_7E7_CELL_73 0x4229 +#define POLL_7E7_CELL_74 0x422A +#define POLL_7E7_CELL_75 0x422B +#define POLL_7E7_CELL_76 0x422C +#define POLL_7E7_CELL_77 0x422D +#define POLL_7E7_CELL_78 0x422E +#define POLL_7E7_CELL_79 0x422F +#define POLL_7E7_CELL_80 0x4230 +#define POLL_7E7_CELL_81 0x4231 +#define POLL_7E7_CELL_82 0x4232 +#define POLL_7E7_CELL_83 0x4233 +#define POLL_7E7_CELL_84 0x4234 +#define POLL_7E7_CELL_85 0x4235 +#define POLL_7E7_CELL_86 0x4236 +#define POLL_7E7_CELL_87 0x4237 +#define POLL_7E7_CELL_88 0x4238 +#define POLL_7E7_CELL_89 0x4239 +#define POLL_7E7_CELL_90 0x423A +#define POLL_7E7_CELL_91 0x423B +#define POLL_7E7_CELL_92 0x423C +#define POLL_7E7_CELL_93 0x423D +#define POLL_7E7_CELL_94 0x423E +#define POLL_7E7_CELL_95 0x423F +#define POLL_7E7_CELL_96 0x4240 + +void setup_battery(void); +void transmit_can(CAN_frame* tx_frame, int interface); + +#endif diff --git a/Software/src/datalayer/datalayer_extended.h b/Software/src/datalayer/datalayer_extended.h index 0d9b2d3f..3b6e57b1 100644 --- a/Software/src/datalayer/datalayer_extended.h +++ b/Software/src/datalayer/datalayer_extended.h @@ -3,6 +3,42 @@ #include "../include.h" +typedef struct { + /** uint16_t */ + /** PID polling parameters */ + uint16_t battery_5V_ref = 0; + int16_t battery_module_temp_1 = 0; + int16_t battery_module_temp_2 = 0; + int16_t battery_module_temp_3 = 0; + int16_t battery_module_temp_4 = 0; + int16_t battery_module_temp_5 = 0; + int16_t battery_module_temp_6 = 0; + uint16_t battery_cell_average_voltage = 0; + uint16_t battery_cell_average_voltage_2 = 0; + uint16_t battery_terminal_voltage = 0; + uint16_t battery_ignition_power_mode = 0; + int16_t battery_current_7E7 = 0; + uint16_t battery_capacity_my17_18 = 0; + uint16_t battery_capacity_my19plus = 0; + uint16_t battery_SOC_display = 0; + uint16_t battery_SOC_raw_highprec = 0; + uint16_t battery_max_temperature = 0; + uint16_t battery_min_temperature = 0; + uint16_t battery_max_cell_voltage = 0; + uint16_t battery_min_cell_voltage = 0; + uint16_t battery_lowest_cell = 0; + uint16_t battery_highest_cell = 0; + uint16_t battery_internal_resistance = 0; + uint16_t battery_voltage_polled = 0; + uint16_t battery_vehicle_isolation = 0; + uint16_t battery_isolation_kohm = 0; + uint16_t battery_HV_locked = 0; + uint16_t battery_crash_event = 0; + uint16_t battery_HVIL = 0; + uint16_t battery_HVIL_status = 0; + int16_t battery_current_7E4 = 0; +} DATALAYER_INFO_BOLTAMPERA; + typedef struct { /** uint16_t */ /** Terminal 30 - 12V SME Supply Voltage */ @@ -403,6 +439,7 @@ typedef struct { class DataLayerExtended { public: + DATALAYER_INFO_BOLTAMPERA boltampera; DATALAYER_INFO_BMWIX bmwix; DATALAYER_INFO_BMWI3 bmwi3; DATALAYER_INFO_BYDATTO3 bydAtto3; diff --git a/Software/src/devboard/webserver/advanced_battery_html.cpp b/Software/src/devboard/webserver/advanced_battery_html.cpp index 3f7eec4e..a634ef7c 100644 --- a/Software/src/devboard/webserver/advanced_battery_html.cpp +++ b/Software/src/devboard/webserver/advanced_battery_html.cpp @@ -20,6 +20,44 @@ String advanced_battery_processor(const String& var) { // Start a new block with a specific background color content += "
"; +#ifdef BOLT_AMPERA_BATTERY + content += "

5V Reference: " + String(datalayer_extended.boltampera.battery_5V_ref) + "

"; + content += "

Module 1 temp: " + String(datalayer_extended.boltampera.battery_module_temp_1) + "

"; + content += "

Module 2 temp: " + String(datalayer_extended.boltampera.battery_module_temp_2) + "

"; + content += "

Module 3 temp: " + String(datalayer_extended.boltampera.battery_module_temp_3) + "

"; + content += "

Module 4 temp: " + String(datalayer_extended.boltampera.battery_module_temp_4) + "

"; + content += "

Module 5 temp: " + String(datalayer_extended.boltampera.battery_module_temp_5) + "

"; + content += "

Module 6 temp: " + String(datalayer_extended.boltampera.battery_module_temp_6) + "

"; + content += + "

Cell average voltage: " + String(datalayer_extended.boltampera.battery_cell_average_voltage) + "

"; + content += + "

Cell average voltage 2: " + String(datalayer_extended.boltampera.battery_cell_average_voltage_2) + "

"; + content += "

Terminal voltage: " + String(datalayer_extended.boltampera.battery_terminal_voltage) + "

"; + content += + "

Ignition power mode: " + String(datalayer_extended.boltampera.battery_ignition_power_mode) + "

"; + content += "

Battery current (7E7): " + String(datalayer_extended.boltampera.battery_current_7E7) + "

"; + content += "

Capacity MY17-18: " + String(datalayer_extended.boltampera.battery_capacity_my17_18) + "

"; + content += "

Capacity MY19+: " + String(datalayer_extended.boltampera.battery_capacity_my19plus) + "

"; + content += "

SOC Display: " + String(datalayer_extended.boltampera.battery_SOC_display) + "

"; + content += "

SOC Raw highprec: " + String(datalayer_extended.boltampera.battery_SOC_raw_highprec) + "

"; + content += "

Max temp: " + String(datalayer_extended.boltampera.battery_max_temperature) + "

"; + content += "

Min temp: " + String(datalayer_extended.boltampera.battery_min_temperature) + "

"; + content += "

Cell max mV: " + String(datalayer_extended.boltampera.battery_max_cell_voltage) + "

"; + content += "

Cell min mV: " + String(datalayer_extended.boltampera.battery_min_cell_voltage) + "

"; + content += "

Lowest cell: " + String(datalayer_extended.boltampera.battery_lowest_cell) + "

"; + content += "

Highest cell: " + String(datalayer_extended.boltampera.battery_highest_cell) + "

"; + content += + "

Internal resistance: " + String(datalayer_extended.boltampera.battery_internal_resistance) + "

"; + content += "

Voltage: " + String(datalayer_extended.boltampera.battery_voltage_polled) + "

"; + content += "

Isolation Ohm: " + String(datalayer_extended.boltampera.battery_vehicle_isolation) + "

"; + content += "

Isolation kOhm: " + String(datalayer_extended.boltampera.battery_isolation_kohm) + "

"; + content += "

HV locked: " + String(datalayer_extended.boltampera.battery_HV_locked) + "

"; + content += "

Crash event: " + String(datalayer_extended.boltampera.battery_crash_event) + "

"; + content += "

HVIL: " + String(datalayer_extended.boltampera.battery_HVIL) + "

"; + content += "

HVIL status: " + String(datalayer_extended.boltampera.battery_HVIL_status) + "

"; + content += "

Current (7E4): " + String(datalayer_extended.boltampera.battery_current_7E4) + "

"; +#endif //BOLT_AMPERA_BATTERY + #ifdef BMW_IX_BATTERY content += "

Battery Voltage after Contactor: " + String(datalayer_extended.bmwix.battery_voltage_after_contactor) + @@ -680,9 +718,10 @@ String advanced_battery_processor(const String& var) { content += "

soc max: " + String(datalayer_extended.zoePH2.battery_soc_max) + "

"; #endif //RENAULT_ZOE_GEN2_BATTERY -#if !defined(TESLA_BATTERY) && !defined(NISSAN_LEAF_BATTERY) && !defined(BMW_I3_BATTERY) && \ - !defined(BYD_ATTO_3_BATTERY) && !defined(RENAULT_ZOE_GEN2_BATTERY) && !defined(CELLPOWER_BMS) && \ - !defined(MEB_BATTERY) //Only the listed types have extra info +#if !defined(BMW_IX_BATTERY) && !defined(BOLT_AMPERA_BATTERY) && !defined(TESLA_BATTERY) && \ + !defined(NISSAN_LEAF_BATTERY) && !defined(BMW_I3_BATTERY) && !defined(BYD_ATTO_3_BATTERY) && \ + !defined(RENAULT_ZOE_GEN2_BATTERY) && !defined(CELLPOWER_BMS) && \ + !defined(MEB_BATTERY) // Only the listed types have extra info content += "No extra information available for this battery type"; #endif