diff --git a/Software/src/battery/TESLA-BATTERY.cpp b/Software/src/battery/TESLA-BATTERY.cpp index 43bcb29c..4f3f0624 100644 --- a/Software/src/battery/TESLA-BATTERY.cpp +++ b/Software/src/battery/TESLA-BATTERY.cpp @@ -5,7 +5,9 @@ #include "../devboard/utils/events.h" #include "../include.h" -/* Credits: Most of the code comes from Per Carlen's bms_comms_tesla_model3.py (https://gitlab.com/pelle8/batt2gen24/) */ +/* Credits: */ +/* Some of the original CAN frame parsing code below comes from Per Carlen's bms_comms_tesla_model3.py (https://gitlab.com/pelle8/batt2gen24/) */ +/* Most of the additional CAN frame parsing/information/display comes from Josiah Higgs (https://github.com/josiahhiggs/) */ inline const char* getContactorText(int index) { switch (index) { @@ -326,6 +328,285 @@ inline const char* getFault(bool value) { return value ? "ACTIVE" : "NOT_ACTIVE"; } +// Clamp DLC to 0–8 bytes for classic CAN +inline int getDataLen(uint8_t dlc) { + return std::min(dlc, 8); +} + +// Fast bit‐field writer: writes 'bitLen' bits of 'value' starting at 'startBit' +inline void setBitField(uint8_t* data, int bytes, int startBit, int bitLen, uint64_t value) { + int bit = startBit; + for (int i = 0; i < bitLen && bit < bytes * 8; ++i, ++bit) { + uint8_t* p = data + (bit >> 3); + uint8_t m = uint8_t(1u << (bit & 7)); + *p = (*p & ~m) | (uint8_t((value >> i) & 1) << (bit & 7)); + } +} + +/// Increment a counter field and recompute an 8‑bit checksum as part of a mux +void generateMuxFrameCounterChecksum(CAN_frame& f, + uint8_t frameCounter, // counter value + int ctrStartBit, // bit index of counter LSB + int ctrBitLength, // width of counter in bits + int csumStartBit, // bit index of checksum LSB + int csumBitLength // width of checksum in bits +) { + int bytes = getDataLen(f.DLC); + auto data = f.data.u8; + + // Pack payload into a 64‑bit word + uint64_t w = 0; + for (uint8_t i = 0; i < bytes; ++i) { + w |= uint64_t(data[i]) << (8 * i); + } + + // Increment the counter + { + uint64_t mask = (uint64_t(1) << ctrBitLength) - 1; + uint64_t ctr = frameCounter & mask; // External counter 0-15 + w = (w & ~(mask << ctrStartBit)) | (ctr << ctrStartBit); + } + + // Unpack back into the frame bytes + for (uint8_t i = 0; i < bytes; ++i) { + data[i] = uint8_t((w >> (8 * i)) & 0xFF); + } + + // Build a small buffer and zero out the checksum bits + uint8_t buf[8]; + for (uint8_t i = 0; i < bytes; ++i) { + buf[i] = data[i]; + } + for (int bit = csumStartBit; bit < csumStartBit + csumBitLength; ++bit) { + int b = bit >> 3; + if (b >= bytes) + break; + buf[b] &= uint8_t(~(1u << (bit & 7))); + } + + // Compute checksum offset from most significant hex digit of CAN ID + uint8_t checksum_offset = uint8_t((f.ID >> 8) & 0xF); // high nibble of top byte + + // Sum the low byte of ID + buf[] + uint8_t sum = uint8_t(f.ID & 0xFF); + for (int i = 0; i < bytes; ++i) { + sum = uint8_t(sum + buf[i]); + } + uint8_t checksum = uint8_t(sum + checksum_offset); + + // Write the checksum back into the frame + setBitField(data, bytes, csumStartBit, csumBitLength, checksum); +} + +// Increment a counter field and recompute an 8‑bit checksum +void generateFrameCounterChecksum(CAN_frame& f, + int ctrStartBit, // bit index of counter LSB + int ctrBitLength, // width of counter in bits + int csumStartBit, // bit index of checksum LSB + int csumBitLength // width of checksum in bits +) { + int bytes = getDataLen(f.DLC); + auto data = f.data.u8; + + // Pack payload into a 64‑bit word + uint64_t w = 0; + for (int i = 0; i < bytes; ++i) { + w |= uint64_t(data[i]) << (8 * i); + } + + // Increment the counter by +1 modulo its width + { + uint64_t mask = (uint64_t(1) << ctrBitLength) - 1; + uint64_t ctr = ((w >> ctrStartBit) & mask) + 1; + ctr &= mask; + w = (w & ~(mask << ctrStartBit)) | (ctr << ctrStartBit); + } + + // Unpack back into the frame bytes + for (int i = 0; i < bytes; ++i) { + data[i] = uint8_t((w >> (8 * i)) & 0xFF); + } + + // Build a small buffer and zero out the checksum bits + uint8_t buf[8]; + for (int i = 0; i < bytes; ++i) { + buf[i] = data[i]; + } + for (int bit = csumStartBit; bit < csumStartBit + csumBitLength; ++bit) { + int b = bit >> 3; + if (b >= bytes) + break; + buf[b] &= uint8_t(~(1u << (bit & 7))); + } + + // Compute checksum offset from most significant hex digit of CAN ID + uint8_t checksum_offset = uint8_t((f.ID >> 8) & 0xF); // high nibble of top byte + + // Sum the low byte of ID + buf[] + uint8_t sum = uint8_t(f.ID & 0xFF); + for (int i = 0; i < bytes; ++i) { + sum = uint8_t(sum + buf[i]); + } + uint8_t checksum = uint8_t(sum + checksum_offset); + + // Write the checksum back into the frame + setBitField(data, bytes, csumStartBit, csumBitLength, checksum); +} + +// Function to extract raw bits/values from a given CAN frame signal +inline uint64_t extract_signal_value(const uint8_t* data, uint32_t start_bit, uint32_t bit_length) { + // + // Usage: uint8_t bms_state = static_cast(extract_signal_value(rx_frame.data.u8, 31, 4)); + // + // Calculate the starting byte and bit offset + uint32_t byte_index = start_bit / 8; + uint32_t bit_offset = start_bit % 8; + + // Read up to 8 bytes starting from byte_index (need enough to cover bit_length + bit_offset) + uint64_t raw = 0; + for (int i = 0; i < 8 && (byte_index + i) < 64; ++i) { + raw |= (uint64_t)data[byte_index + i] << (8 * i); + } + + // Shift and mask + raw >>= bit_offset; + if (bit_length == 64) + return raw; + return raw & ((1ULL << bit_length) - 1); +} + +// Function to write a value to a given CAN frame signal +void write_signal_value(CAN_frame* frame, uint16_t start_bit, uint8_t bit_length, int64_t value, bool is_signed) { + if (bit_length == 0 || bit_length > 64 || frame == nullptr) + return; + + uint64_t uvalue; + + if (is_signed) { + int64_t min_val = -(1LL << (bit_length - 1)); + int64_t max_val = (1LL << (bit_length - 1)) - 1; + + // Clamp to valid range + if (value < min_val) + value = min_val; + if (value > max_val) + value = max_val; + + // Two's complement encoding + uvalue = static_cast(value) & ((1ULL << bit_length) - 1); + } else { + uvalue = static_cast(value) & ((1ULL << bit_length) - 1); + } + + // Write value into frame->data.u8 using little-endian bit layout + for (uint8_t i = 0; i < bit_length; ++i) { + uint8_t bit_val = (uvalue >> i) & 1; + uint16_t bit_pos = start_bit + i; + + uint8_t byte_index = bit_pos / 8; + uint8_t bit_index = bit_pos % 8; + + if (byte_index >= frame->DLC) + continue; // Prevent overrun + + if (bit_val) + frame->data.u8[byte_index] |= (1 << bit_index); + else + frame->data.u8[byte_index] &= ~(1 << bit_index); + } +} + +void generateTESLA_229(CAN_frame& f) { + static const uint8_t checksumLookup[16] = {0x46, 0x44, 0x52, 0x6D, 0x43, 0x41, 0xDD, 0xF9, + 0x4C, 0xA5, 0xF6, 0x8C, 0x49, 0x2F, 0x31, 0x3B}; + + // Safety, only run if this is the right ID + if (f.ID != 0x229) + return; + + const int ctrStartBit = 8; + const int ctrBitLength = 4; + const int csumStartBit = 0; + const int csumBitLength = 8; + + int bytes = getDataLen(f.DLC); + auto data = f.data.u8; + + // Pack the first few bytes into a word + uint64_t w = 0; + for (int i = 0; i < bytes; ++i) { + w |= uint64_t(data[i]) << (8 * i); + } + + // Extract current counter + uint64_t mask = (uint64_t(1) << ctrBitLength) - 1; + uint8_t ctr = (w >> ctrStartBit) & mask; + + // Increment counter mod 16 + ctr = (ctr + 1) & 0xF; + + // Write updated counter back + w = (w & ~(mask << ctrStartBit)) | (uint64_t(ctr) << ctrStartBit); + for (int i = 0; i < bytes; ++i) { + data[i] = uint8_t((w >> (8 * i)) & 0xFF); + } + + // Look up and insert checksum + uint8_t checksum = checksumLookup[ctr]; + setBitField(data, bytes, csumStartBit, csumBitLength, checksum); +} + +void generateTESLA_213(CAN_frame& f) { + static uint8_t counter = 0; + + // Increment counter (wrap at 16) + counter = (counter + 1) & 0xF; + + // Safety, only modify if ID is 0x213 and DLC is at least 2 + if (f.ID != 0x213 || f.DLC < 2) + return; + + // Byte 0: counter in high nibble + uint8_t value = counter << 4; + + // Byte 1: checksum = value + 0x15 + uint8_t checksum = (value + 0x15) & 0xFF; + + f.data.u8[0] = value; + f.data.u8[1] = checksum; +} + +// Function to check if a year is a leap year +bool isLeapYear(int year) { + if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) { + return true; + } + return false; +} + +// Function to convert year and day of year (i.e. Julian date) into human readable date +char* dayOfYearToDate(int year, int dayOfYear) { + + // Arrays to hold the number of days in each month for standard/leap years + int daysInMonthStandard[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + int daysInMonthLeap[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + // Select the appropriate array for the given year + int* daysInMonth = isLeapYear(year) ? daysInMonthLeap : daysInMonthStandard; + int month = 0; + + // Find the month and the day within the month + while (dayOfYear > daysInMonth[month]) { + dayOfYear -= daysInMonth[month]; + month++; + } + + static char dateString[11]; // For "YYYY-MM-DD\0" + // Format the date string in "YYYY-MM-DD" format + snprintf(dateString, sizeof(dateString), "%d-%02d-%02d", year, month + 1, dayOfYear); + return dateString; +} + void TeslaBattery:: update_values() { //This function maps all the values fetched via CAN to the correct parameters used for modbus //After values are mapped, we perform some safety checks, and do some serial printouts @@ -435,23 +716,34 @@ void TeslaBattery:: datalayer.battery.settings.user_requests_tesla_isolation_clear = false; } if (datalayer.battery.settings.user_requests_tesla_bms_reset) { - if (battery_contactor == 1 && battery_BMS_a180_SW_ECU_reset_blocked == false) { + if (battery_contactor == 1 && BMS_a180_SW_ECU_reset_blocked == false) { //Start the BMS ECU reset statemachine, only if contactors are OPEN and BMS ECU allows it stateMachineBMSReset = 0; datalayer.battery.settings.user_requests_tesla_bms_reset = false; +#ifdef DEBUG_LOG + logging.println("BMS reset requested"); +#endif //DEBUG_LOG } else { +#ifdef DEBUG_LOG logging.println("ERROR: BMS reset failed due to contactors not being open, or BMS ECU not allowing it"); +#endif //DEBUG_LOG + stateMachineBMSReset = 0; + datalayer.battery.settings.user_requests_tesla_bms_reset = false; } } + //Update 0x333 UI_chargeTerminationPct (bit 16, width 10) value to SOC max value - expose via UI? + //One firmware version this was seen at bit 17 width 11 + write_signal_value(&TESLA_333, 16, 10, static_cast(datalayer.battery.settings.max_percentage / 10), false); + // Update webserver datalayer - //0x20A - datalayer_extended.tesla.status_contactor = battery_contactor; + //datalayer_extended.tesla.BMS_hvilFault = BMS_a036_SW_HvpHvilFault; datalayer_extended.tesla.hvil_status = battery_hvil_status; + //0x20A datalayer_extended.tesla.packContNegativeState = battery_packContNegativeState; datalayer_extended.tesla.packContPositiveState = battery_packContPositiveState; datalayer_extended.tesla.packContactorSetState = battery_packContactorSetState; - datalayer_extended.tesla.packCtrsClosingAllowed = battery_packCtrsClosingAllowed; + datalayer_extended.tesla.packCtrsClosingBlocked = battery_packCtrsClosingBlocked; datalayer_extended.tesla.pyroTestInProgress = battery_pyroTestInProgress; datalayer_extended.tesla.battery_packCtrsOpenNowRequested = battery_packCtrsOpenNowRequested; datalayer_extended.tesla.battery_packCtrsOpenRequested = battery_packCtrsOpenRequested; @@ -459,7 +751,22 @@ void TeslaBattery:: datalayer_extended.tesla.battery_packCtrsResetRequestRequired = battery_packCtrsResetRequestRequired; datalayer_extended.tesla.battery_dcLinkAllowedToEnergize = battery_dcLinkAllowedToEnergize; //0x72A - memcpy(datalayer_extended.tesla.BMS_SerialNumber, BMS_SerialNumber, sizeof(BMS_SerialNumber)); + if (parsed_battery_serialNumber && battery_serialNumber[13] != 0) { + memcpy(datalayer_extended.tesla.battery_serialNumber, battery_serialNumber, sizeof(battery_serialNumber)); + datalayer_extended.tesla.battery_manufactureDate = battery_manufactureDate; + //We have valid data and comms with the battery, attempt to query part number + if (!parsed_battery_partNumber && stateMachineBMSQuery == 0xFF) { + stateMachineBMSQuery = 0; + } + } + //Via UDS + if (parsed_battery_partNumber && battery_partNumber[11] != 0) { + memcpy(datalayer_extended.tesla.battery_partNumber, battery_partNumber, sizeof(battery_partNumber)); + } + //0x3C4 + if (parsed_PCS_partNumber && PCS_partNumber[11] != 0) { + memcpy(datalayer_extended.tesla.PCS_partNumber, PCS_partNumber, sizeof(PCS_partNumber)); + } //0x2B4 datalayer_extended.tesla.battery_dcdcLvBusVolt = battery_dcdcLvBusVolt; datalayer_extended.tesla.battery_dcdcHvBusVolt = battery_dcdcHvBusVolt; @@ -487,8 +794,8 @@ void TeslaBattery:: datalayer_extended.tesla.battery_packMass = battery_packMass; datalayer_extended.tesla.battery_platformMaxBusVoltage = battery_platformMaxBusVoltage; //0x2D2 - datalayer_extended.tesla.battery_bms_min_voltage = battery_bms_min_voltage; - datalayer_extended.tesla.battery_bms_max_voltage = battery_bms_max_voltage; + datalayer_extended.tesla.BMS_min_voltage = BMS_min_voltage; + datalayer_extended.tesla.BMS_max_voltage = BMS_max_voltage; datalayer_extended.tesla.battery_max_charge_current = battery_max_charge_current; datalayer_extended.tesla.battery_max_discharge_current = battery_max_discharge_current; //0x292 @@ -506,30 +813,30 @@ void TeslaBattery:: datalayer_extended.tesla.battery_BrickModelTMax = battery_BrickModelTMax; datalayer_extended.tesla.battery_BrickModelTMin = battery_BrickModelTMin; //0x212 - datalayer_extended.tesla.battery_BMS_isolationResistance = battery_BMS_isolationResistance; - datalayer_extended.tesla.battery_BMS_contactorState = battery_BMS_contactorState; - datalayer_extended.tesla.battery_BMS_state = battery_BMS_state; - datalayer_extended.tesla.battery_BMS_hvState = battery_BMS_hvState; - datalayer_extended.tesla.battery_BMS_uiChargeStatus = battery_BMS_uiChargeStatus; - datalayer_extended.tesla.battery_BMS_diLimpRequest = battery_BMS_diLimpRequest; - datalayer_extended.tesla.battery_BMS_chgPowerAvailable = battery_BMS_chgPowerAvailable; - datalayer_extended.tesla.battery_BMS_pcsPwmEnabled = battery_BMS_pcsPwmEnabled; + datalayer_extended.tesla.BMS_isolationResistance = BMS_isolationResistance; + datalayer_extended.tesla.BMS_contactorState = BMS_contactorState; + datalayer_extended.tesla.BMS_state = BMS_state; + datalayer_extended.tesla.BMS_hvState = BMS_hvState; + datalayer_extended.tesla.BMS_uiChargeStatus = BMS_uiChargeStatus; + datalayer_extended.tesla.BMS_diLimpRequest = BMS_diLimpRequest; + datalayer_extended.tesla.BMS_chgPowerAvailable = BMS_chgPowerAvailable; + datalayer_extended.tesla.BMS_pcsPwmEnabled = BMS_pcsPwmEnabled; //0x224 - datalayer_extended.tesla.battery_PCS_dcdcPrechargeStatus = battery_PCS_dcdcPrechargeStatus; - datalayer_extended.tesla.battery_PCS_dcdc12VSupportStatus = battery_PCS_dcdc12VSupportStatus; - datalayer_extended.tesla.battery_PCS_dcdcHvBusDischargeStatus = battery_PCS_dcdcHvBusDischargeStatus; - datalayer_extended.tesla.battery_PCS_dcdcMainState = battery_PCS_dcdcMainState; - datalayer_extended.tesla.battery_PCS_dcdcSubState = battery_PCS_dcdcSubState; - datalayer_extended.tesla.battery_PCS_dcdcFaulted = battery_PCS_dcdcFaulted; - datalayer_extended.tesla.battery_PCS_dcdcOutputIsLimited = battery_PCS_dcdcOutputIsLimited; - datalayer_extended.tesla.battery_PCS_dcdcMaxOutputCurrentAllowed = battery_PCS_dcdcMaxOutputCurrentAllowed; - datalayer_extended.tesla.battery_PCS_dcdcPrechargeRtyCnt = battery_PCS_dcdcPrechargeRtyCnt; - datalayer_extended.tesla.battery_PCS_dcdc12VSupportRtyCnt = battery_PCS_dcdc12VSupportRtyCnt; - datalayer_extended.tesla.battery_PCS_dcdcDischargeRtyCnt = battery_PCS_dcdcDischargeRtyCnt; - datalayer_extended.tesla.battery_PCS_dcdcPwmEnableLine = battery_PCS_dcdcPwmEnableLine; - datalayer_extended.tesla.battery_PCS_dcdcSupportingFixedLvTarget = battery_PCS_dcdcSupportingFixedLvTarget; - datalayer_extended.tesla.battery_PCS_dcdcPrechargeRestartCnt = battery_PCS_dcdcPrechargeRestartCnt; - datalayer_extended.tesla.battery_PCS_dcdcInitialPrechargeSubState = battery_PCS_dcdcInitialPrechargeSubState; + datalayer_extended.tesla.PCS_dcdcPrechargeStatus = PCS_dcdcPrechargeStatus; + datalayer_extended.tesla.PCS_dcdc12VSupportStatus = PCS_dcdc12VSupportStatus; + datalayer_extended.tesla.PCS_dcdcHvBusDischargeStatus = PCS_dcdcHvBusDischargeStatus; + datalayer_extended.tesla.PCS_dcdcMainState = PCS_dcdcMainState; + datalayer_extended.tesla.PCS_dcdcSubState = PCS_dcdcSubState; + datalayer_extended.tesla.PCS_dcdcFaulted = PCS_dcdcFaulted; + datalayer_extended.tesla.PCS_dcdcOutputIsLimited = PCS_dcdcOutputIsLimited; + datalayer_extended.tesla.PCS_dcdcMaxOutputCurrentAllowed = PCS_dcdcMaxOutputCurrentAllowed; + datalayer_extended.tesla.PCS_dcdcPrechargeRtyCnt = PCS_dcdcPrechargeRtyCnt; + datalayer_extended.tesla.PCS_dcdc12VSupportRtyCnt = PCS_dcdc12VSupportRtyCnt; + datalayer_extended.tesla.PCS_dcdcDischargeRtyCnt = PCS_dcdcDischargeRtyCnt; + datalayer_extended.tesla.PCS_dcdcPwmEnableLine = PCS_dcdcPwmEnableLine; + datalayer_extended.tesla.PCS_dcdcSupportingFixedLvTarget = PCS_dcdcSupportingFixedLvTarget; + datalayer_extended.tesla.PCS_dcdcPrechargeRestartCnt = PCS_dcdcPrechargeRestartCnt; + datalayer_extended.tesla.PCS_dcdcInitialPrechargeSubState = PCS_dcdcInitialPrechargeSubState; //0x252 datalayer_extended.tesla.BMS_maxRegenPower = BMS_maxRegenPower; datalayer_extended.tesla.BMS_maxDischargePower = BMS_maxDischargePower; @@ -538,6 +845,21 @@ void TeslaBattery:: datalayer_extended.tesla.BMS_notEnoughPowerForHeatPump = BMS_notEnoughPowerForHeatPump; datalayer_extended.tesla.BMS_powerLimitState = BMS_powerLimitState; datalayer_extended.tesla.BMS_inverterTQF = BMS_inverterTQF; + //Via UDS + //datalayer_extended.tesla.BMS_info_buildConfigId = BMS_info_buildConfigId; + //0x300 + datalayer_extended.tesla.BMS_info_buildConfigId = BMS_info_buildConfigId; + datalayer_extended.tesla.BMS_info_hardwareId = BMS_info_hardwareId; + datalayer_extended.tesla.BMS_info_componentId = BMS_info_componentId; + datalayer_extended.tesla.BMS_info_pcbaId = BMS_info_pcbaId; + datalayer_extended.tesla.BMS_info_assemblyId = BMS_info_assemblyId; + datalayer_extended.tesla.BMS_info_usageId = BMS_info_usageId; + datalayer_extended.tesla.BMS_info_subUsageId = BMS_info_subUsageId; + datalayer_extended.tesla.BMS_info_platformType = BMS_info_platformType; + datalayer_extended.tesla.BMS_info_appCrc = BMS_info_appCrc; + datalayer_extended.tesla.BMS_info_bootGitHash = BMS_info_bootGitHash; + datalayer_extended.tesla.BMS_info_bootUdsProtoVersion = BMS_info_bootUdsProtoVersion; + datalayer_extended.tesla.BMS_info_bootCrc = BMS_info_bootCrc; //0x312 datalayer_extended.tesla.BMS_powerDissipation = BMS_powerDissipation; datalayer_extended.tesla.BMS_flowRequest = BMS_flowRequest; @@ -548,6 +870,10 @@ void TeslaBattery:: datalayer_extended.tesla.BMS_packTMax = BMS_packTMax; datalayer_extended.tesla.BMS_pcsNoFlowRequest = BMS_pcsNoFlowRequest; datalayer_extended.tesla.BMS_noFlowRequest = BMS_noFlowRequest; + //0x3C4 + datalayer_extended.tesla.PCS_info_buildConfigId = PCS_info_buildConfigId; + datalayer_extended.tesla.PCS_info_hardwareId = PCS_info_hardwareId; + datalayer_extended.tesla.PCS_info_componentId = PCS_info_componentId; //0x2A4 datalayer_extended.tesla.PCS_dcdcTemp = PCS_dcdcTemp; datalayer_extended.tesla.PCS_ambientTemp = PCS_ambientTemp; @@ -575,6 +901,10 @@ void TeslaBattery:: datalayer_extended.tesla.PCS_dcdcIntervalMinLvBusVolt = PCS_dcdcIntervalMinLvBusVolt; datalayer_extended.tesla.PCS_dcdcIntervalMinLvOutputCurr = PCS_dcdcIntervalMinLvOutputCurr; datalayer_extended.tesla.PCS_dcdc12vSupportLifetimekWh = PCS_dcdc12vSupportLifetimekWh; + //0x310 + datalayer_extended.tesla.HVP_info_buildConfigId = HVP_info_buildConfigId; + datalayer_extended.tesla.HVP_info_hardwareId = HVP_info_hardwareId; + datalayer_extended.tesla.HVP_info_componentId = HVP_info_componentId; //0x7AA datalayer_extended.tesla.HVP_gpioPassivePyroDepl = HVP_gpioPassivePyroDepl; datalayer_extended.tesla.HVP_gpioPyroIsoEn = HVP_gpioPyroIsoEn; @@ -633,21 +963,48 @@ void TeslaBattery:: datalayer_extended.tesla.HVP_shuntBarTempStatus = HVP_shuntBarTempStatus; datalayer_extended.tesla.HVP_shuntAsicTempStatus = HVP_shuntAsicTempStatus; + //Safety checks for CAN message sesnding + if ((datalayer.system.status.inverter_allows_contactor_closing == true) && + (datalayer.battery.status.bms_status != FAULT) && (!datalayer.system.settings.equipment_stop_active)) { + // Carry on: 0x221 DRIVE state & reset power down timer + vehicleState = 1; + powerDownTimer = 180; //0x221 50ms cyclic, 20 calls/second + } else { + // Faulted state, or inverter blocks contactor closing + // Shut down: 0x221 ACCESSORY state for 3 seconds, followed by GOING_DOWN, then OFF + if (powerDownTimer <= 180 && powerDownTimer > 120) { + vehicleState = 2; //ACCESSORY + powerDownTimer--; + } + if (powerDownTimer <= 120 && powerDownTimer > 60) { + vehicleState = 3; //GOING_DOWN + powerDownTimer--; + } + if (powerDownTimer <= 60 && powerDownTimer > 0) { + vehicleState = 0; //OFF + powerDownTimer--; + } + } + #ifdef DEBUG_LOG printFaultCodesIfActive(); - - logging.print(getContactorText(battery_contactor)); // Display what state the contactor is in + logging.print("BMS Contactors State: "); + logging.print(getBMSContactorState(battery_contactor)); // Display what state the BMS thinks the contactors are in logging.print(", HVIL: "); logging.print(getHvilStatusState(battery_hvil_status)); logging.print(", NegativeState: "); logging.print(getContactorState(battery_packContNegativeState)); logging.print(", PositiveState: "); - logging.print(getContactorState(battery_packContPositiveState)); - logging.print(", setState: "); - logging.print(getContactorState(battery_packContactorSetState)); - logging.print(", close allowed: "); - logging.print(getNoYes(battery_packCtrsClosingAllowed)); + logging.println(getContactorState(battery_packContPositiveState)); + logging.print("HVP Contactors setState: "); + logging.print( + getContactorText(battery_packContactorSetState)); // Display what state the HVP has set the contactors to be in + logging.print(", Closing blocked: "); + logging.print(getNoYes(battery_packCtrsClosingBlocked)); + if (battery_packContactorSetState == 5) { + logging.print(" (already CLOSED)"); + } logging.print(", Pyrotest: "); logging.println(getNoYes(battery_pyroTestInProgress)); @@ -698,7 +1055,8 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { static bool mux1_read = false; switch (rx_frame.ID) { - case 0x352: // 850 BMS_energyStatus newer BMS + case 0x352: // 850 BMS_energyStatus newer BMS + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; mux = ((rx_frame.data.u8[0]) & 0x03); //BMS_energyStatusIndex M : 0|2@1+ (1,0) [0|0] "" X if (mux == 0) { battery_nominal_full_pack_energy_m0 = @@ -713,7 +1071,7 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { mux0_read = true; //Set flag to true } if (mux == 1) { - battery_fully_charged = (rx_frame.data.u8[1] & 0x01); //15|1@1+ (1,0) [0|1]//noYes + battery_fully_charged = (rx_frame.data.u8[1] & 0x01); //BMS_fullChargeComplete : 15|1@1+ (1,0) [0|1]//noYes battery_energy_buffer_m1 = ((rx_frame.data.u8[3] << 8) | rx_frame.data.u8[2]); //16|16@1+ (0.01,0) [0|0] "kWh"//to datalayer_extended battery_expected_energy_remaining_m1 = @@ -728,33 +1086,39 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { mux0_read = false; mux1_read = false; BMS352_mux = true; //Set flag to true + break; } - // older BMS <2021 without mux - battery_nominal_full_pack_energy = //BMS_nominalFullPackEnergy : 0|11@1+ (0.1,0) [0|204.6] "KWh" //((_d[1] & (0x07U)) << 8) | (_d[0] & (0xFFU)); + if (mux0_read || mux1_read || BMS352_mux) { + //Skip older BMS frame parsing + break; + } + // Older BMS <2021 without mux + battery_nominal_full_pack_energy = //BMS_nominalFullPackEnergy : 0|11@1+ (0.1,0) [0|204.6] "kWh" //((_d[1] & (0x07U)) << 8) | (_d[0] & (0xFFU)); (((rx_frame.data.u8[1] & 0x07) << 8) | (rx_frame.data.u8[0])); //Example 752 (75.2kWh) - battery_nominal_energy_remaining = //BMS_nominalEnergyRemaining : 11|11@1+ (0.1,0) [0|204.6] "KWh" //((_d[2] & (0x3FU)) << 5) | ((_d[1] >> 3) & (0x1FU)); + battery_nominal_energy_remaining = //BMS_nominalEnergyRemaining : 11|11@1+ (0.1,0) [0|204.6] "kWh" //((_d[2] & (0x3FU)) << 5) | ((_d[1] >> 3) & (0x1FU)); (((rx_frame.data.u8[2] & 0x3F) << 5) | ((rx_frame.data.u8[1] & 0x1F) >> 3)); //Example 1247 * 0.1 = 124.7kWh - battery_expected_energy_remaining = //BMS_expectedEnergyRemaining : 22|11@1+ (0.1,0) [0|204.6] "KWh"// ((_d[4] & (0x01U)) << 10) | ((_d[3] & (0xFFU)) << 2) | ((_d[2] >> 6) & (0x03U)); + battery_expected_energy_remaining = //BMS_expectedEnergyRemaining : 22|11@1+ (0.1,0) [0|204.6] "kWh"// ((_d[4] & (0x01U)) << 10) | ((_d[3] & (0xFFU)) << 2) | ((_d[2] >> 6) & (0x03U)); (((rx_frame.data.u8[4] & 0x01) << 10) | (rx_frame.data.u8[3] << 2) | ((rx_frame.data.u8[2] & 0x03) >> 6)); //Example 622 (62.2kWh) - battery_ideal_energy_remaining = //BMS_idealEnergyRemaining : 33|11@1+ (0.1,0) [0|204.6] "KWh" //((_d[5] & (0x0FU)) << 7) | ((_d[4] >> 1) & (0x7FU)); + battery_ideal_energy_remaining = //BMS_idealEnergyRemaining : 33|11@1+ (0.1,0) [0|204.6] "kWh" //((_d[5] & (0x0FU)) << 7) | ((_d[4] >> 1) & (0x7FU)); (((rx_frame.data.u8[5] & 0x0F) << 7) | ((rx_frame.data.u8[4] & 0x7F) >> 1)); //Example 311 * 0.1 = 31.1kWh - battery_energy_to_charge_complete = // BMS_energyToChargeComplete : 44|11@1+ (0.1,0) [0|204.6] "KWh"// ((_d[6] & (0x7FU)) << 4) | ((_d[5] >> 4) & (0x0FU)); + battery_energy_to_charge_complete = // BMS_energyToChargeComplete : 44|11@1+ (0.1,0) [0|204.6] "kWh"// ((_d[6] & (0x7FU)) << 4) | ((_d[5] >> 4) & (0x0FU)); (((rx_frame.data.u8[6] & 0x7F) << 4) | ((rx_frame.data.u8[5] & 0x0F) << 4)); //Example 147 * 0.1 = 14.7kWh - battery_energy_buffer = //BMS_energyBuffer : 55|8@1+ (0.1,0) [0|25.4] "KWh"// ((_d[7] & (0x7FU)) << 1) | ((_d[6] >> 7) & (0x01U)); + battery_energy_buffer = //BMS_energyBuffer : 55|8@1+ (0.1,0) [0|25.4] "kWh"// ((_d[7] & (0x7FU)) << 1) | ((_d[6] >> 7) & (0x01U)); (((rx_frame.data.u8[7] & 0xFE) >> 1) | ((rx_frame.data.u8[6] & 0x80) >> 7)); //Example 1 * 0.1 = 0 - battery_full_charge_complete = //BMS_fullChargeComplete : 63|1@1+ (1,0) [0|1] ""//((_d[7] >> 7) & (0x01U)); + battery_fully_charged = //BMS_fullChargeComplete : 63|1@1+ (1,0) [0|1] ""//((_d[7] >> 7) & (0x01U)); ((rx_frame.data.u8[7] >> 7) & 0x01); //noYes break; case 0x20A: //522 HVP_contactorState: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; battery_packContNegativeState = (rx_frame.data.u8[0] & 0x07); //(_d[0] & (0x07U)); 0|3@1+ (1,0) [0|7] //contactorState battery_packContPositiveState = - (rx_frame.data.u8[0] & 0x38) >> 3; //((_d[0] >> 3) & (0x07U)); 3|3@1+ (1,0) [0|7] //contactorState - battery_contactor = (rx_frame.data.u8[1] & 0x0F); // 8|4@1+ (1,0) [0|9] //contactorText + (rx_frame.data.u8[0] & 0x38) >> 3; //((_d[0] >> 3) & (0x07U)); 3|3@1+ (1,0) [0|7] //contactorState + //battery_contactor = (rx_frame.data.u8[1] & 0x0F); // 8|4@1+ (1,0) [0|9] //contactorText battery_packContactorSetState = (rx_frame.data.u8[1] & 0x0F); //(_d[1] & (0x0FU)); 8|4@1+ (1,0) [0|9] //contactorState - battery_packCtrsClosingAllowed = + battery_packCtrsClosingBlocked = (rx_frame.data.u8[4] & 0x08) >> 3; //((_d[4] >> 3) & (0x01U)); 35|1@1+ (1,0) [0|1] //noYes battery_pyroTestInProgress = (rx_frame.data.u8[4] & 0x20) >> 5; //((_d[4] >> 5) & (0x01U));//37|1@1+ (1,0) [0|1] //noYes @@ -776,70 +1140,76 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { battery_fcCtrsRequestStatus = (rx_frame.data.u8[3] & (0x03U)); //24|2@1+ (1,0) [0|2] "" Receiver battery_fcCtrsResetRequestRequired = ((rx_frame.data.u8[3] >> 2) & (0x01U)); //26|1@1+ (1,0) [0|1] "" Receiver battery_fcLinkAllowedToEnergize = ((rx_frame.data.u8[5] >> 4) & (0x03U)); //44|2@1+ (1,0) [0|2] "" Receiver - break; - case 0x212: //530 BMS_status: 8 - battery_BMS_hvacPowerRequest = (rx_frame.data.u8[0] & (0x01U)); - battery_BMS_notEnoughPowerForDrive = ((rx_frame.data.u8[0] >> 1) & (0x01U)); - battery_BMS_notEnoughPowerForSupport = ((rx_frame.data.u8[0] >> 2) & (0x01U)); - battery_BMS_preconditionAllowed = ((rx_frame.data.u8[0] >> 3) & (0x01U)); - battery_BMS_updateAllowed = ((rx_frame.data.u8[0] >> 4) & (0x01U)); - battery_BMS_activeHeatingWorthwhile = ((rx_frame.data.u8[0] >> 5) & (0x01U)); - battery_BMS_cpMiaOnHvs = ((rx_frame.data.u8[0] >> 6) & (0x01U)); - battery_BMS_contactorState = - (rx_frame.data.u8[1] & - (0x07U)); //0 "SNA" 1 "OPEN" 2 "OPENING" 3 "CLOSING" 4 "CLOSED" 5 "WELDED" 6 "BLOCKED" ; - battery_BMS_state = - ((rx_frame.data.u8[1] >> 3) & - (0x0FU)); //0 "STANDBY" 1 "DRIVE" 2 "SUPPORT" 3 "CHARGE" 4 "FEIM" 5 "CLEAR_FAULT" 6 "FAULT" 7 "WELD" 8 "TEST" 9 "SNA" ; - battery_BMS_hvState = - (rx_frame.data.u8[2] & - (0x07U)); //0 "DOWN" 1 "COMING_UP" 2 "GOING_DOWN" 3 "UP_FOR_DRIVE" 4 "UP_FOR_CHARGE" 5 "UP_FOR_DC_CHARGE" 6 "UP" ; - battery_BMS_isolationResistance = + case 0x212: //530 BMS_status: 8 + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + BMS_hvacPowerRequest = (rx_frame.data.u8[0] & (0x01U)); + BMS_notEnoughPowerForDrive = ((rx_frame.data.u8[0] >> 1) & (0x01U)); + BMS_notEnoughPowerForSupport = ((rx_frame.data.u8[0] >> 2) & (0x01U)); + BMS_preconditionAllowed = ((rx_frame.data.u8[0] >> 3) & (0x01U)); + BMS_updateAllowed = ((rx_frame.data.u8[0] >> 4) & (0x01U)); + BMS_activeHeatingWorthwhile = ((rx_frame.data.u8[0] >> 5) & (0x01U)); + BMS_cpMiaOnHvs = ((rx_frame.data.u8[0] >> 6) & (0x01U)); + BMS_contactorState = (rx_frame.data.u8[1] & + (0x07U)); //0 "SNA" 1 "OPEN" 2 "OPENING" 3 "CLOSING" 4 "CLOSED" 5 "WELDED" 6 "BLOCKED" ; + battery_contactor = BMS_contactorState; + //BMS_state = // Original code from older DBCs + //((rx_frame.data.u8[1] >> 3) & + //(0x0FU)); //0 "STANDBY" 1 "DRIVE" 2 "SUPPORT" 3 "CHARGE" 4 "FEIM" 5 "CLEAR_FAULT" 6 "FAULT" 7 "WELD" 8 "TEST" 9 "SNA" ; + BMS_state = static_cast(extract_signal_value(rx_frame.data.u8, 31, 4)); + //0 "STANDBY" 1 "DRIVE" 2 "SUPPORT" 3 "CHARGE" 4 "FEIM" 5 "CLEAR_FAULT" 6 "FAULT" 7 "WELD" 8 "TEST" 9 "SNA" 10 "BMS_DIAG"; + BMS_hvState = (rx_frame.data.u8[2] & (0x07U)); + //0 "DOWN" 1 "COMING_UP" 2 "GOING_DOWN" 3 "UP_FOR_DRIVE" 4 "UP_FOR_CHARGE" 5 "UP_FOR_DC_CHARGE" 6 "UP" ; + BMS_isolationResistance = ((rx_frame.data.u8[3] & (0x1FU)) << 5) | ((rx_frame.data.u8[2] >> 3) & (0x1FU)); //19|10@1+ (10,0) [0|0] "kOhm"/to datalayer_extended - battery_BMS_chargeRequest = ((rx_frame.data.u8[3] >> 5) & (0x01U)); - battery_BMS_keepWarmRequest = ((rx_frame.data.u8[3] >> 6) & (0x01U)); - battery_BMS_uiChargeStatus = - (rx_frame.data.u8[4] & - (0x07U)); // 0 "DISCONNECTED" 1 "NO_POWER" 2 "ABOUT_TO_CHARGE" 3 "CHARGING" 4 "CHARGE_COMPLETE" 5 "CHARGE_STOPPED" ; - battery_BMS_diLimpRequest = ((rx_frame.data.u8[4] >> 3) & (0x01U)); - battery_BMS_okToShipByAir = ((rx_frame.data.u8[4] >> 4) & (0x01U)); - battery_BMS_okToShipByLand = ((rx_frame.data.u8[4] >> 5) & (0x01U)); - battery_BMS_chgPowerAvailable = ((rx_frame.data.u8[6] & (0x01U)) << 10) | ((rx_frame.data.u8[5] & (0xFFU)) << 2) | - ((rx_frame.data.u8[4] >> 6) & (0x03U)); //38|11@1+ (0.125,0) [0|0] "kW" - battery_BMS_chargeRetryCount = ((rx_frame.data.u8[6] >> 1) & (0x0FU)); - battery_BMS_pcsPwmEnabled = ((rx_frame.data.u8[6] >> 5) & (0x01U)); - battery_BMS_ecuLogUploadRequest = ((rx_frame.data.u8[6] >> 6) & (0x03U)); - battery_BMS_minPackTemperature = (rx_frame.data.u8[7] & (0xFFU)); //56|8@1+ (0.5,-40) [0|0] "DegC + //BMS_chargeRequest = ((rx_frame.data.u8[3] >> 5) & (0x01U)); + BMS_chargeRequest = static_cast(extract_signal_value(rx_frame.data.u8, 29, 1)); + BMS_keepWarmRequest = ((rx_frame.data.u8[3] >> 6) & (0x01U)); + BMS_uiChargeStatus = static_cast(extract_signal_value(rx_frame.data.u8, 32, 3)); + //BMS_uiChargeStatus = + //(rx_frame.data.u8[4] & + //(0x07U)); + // 0 "DISCONNECTED" 1 "NO_POWER" 2 "ABOUT_TO_CHARGE" 3 "CHARGING" 4 "CHARGE_COMPLETE" 5 "CHARGE_STOPPED" ; + BMS_diLimpRequest = ((rx_frame.data.u8[4] >> 3) & (0x01U)); + BMS_okToShipByAir = ((rx_frame.data.u8[4] >> 4) & (0x01U)); + BMS_okToShipByLand = ((rx_frame.data.u8[4] >> 5) & (0x01U)); + BMS_chgPowerAvailable = ((rx_frame.data.u8[6] & (0x01U)) << 10) | ((rx_frame.data.u8[5] & (0xFFU)) << 2) | + ((rx_frame.data.u8[4] >> 6) & (0x03U)); //38|11@1+ (0.125,0) [0|0] "kW" + BMS_chargeRetryCount = ((rx_frame.data.u8[6] >> 1) & (0x0FU)); + BMS_pcsPwmEnabled = ((rx_frame.data.u8[6] >> 5) & (0x01U)); + BMS_ecuLogUploadRequest = ((rx_frame.data.u8[6] >> 6) & (0x03U)); + BMS_minPackTemperature = (rx_frame.data.u8[7] & (0xFFU)); //56|8@1+ (0.5,-40) [0|0] "DegC break; - case 0x224: //548 PCS_dcdcStatus: - battery_PCS_dcdcPrechargeStatus = (rx_frame.data.u8[0] & (0x03U)); //0 "IDLE" 1 "ACTIVE" 2 "FAULTED" ; - battery_PCS_dcdc12VSupportStatus = ((rx_frame.data.u8[0] >> 2) & (0x03U)); //0 "IDLE" 1 "ACTIVE" 2 "FAULTED" - battery_PCS_dcdcHvBusDischargeStatus = ((rx_frame.data.u8[0] >> 4) & (0x03U)); //0 "IDLE" 1 "ACTIVE" 2 "FAULTED" - battery_PCS_dcdcMainState = + case 0x224: //548 PCS_dcdcStatus: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + PCS_dcdcPrechargeStatus = (rx_frame.data.u8[0] & (0x03U)); //0 "IDLE" 1 "ACTIVE" 2 "FAULTED" ; + PCS_dcdc12VSupportStatus = ((rx_frame.data.u8[0] >> 2) & (0x03U)); //0 "IDLE" 1 "ACTIVE" 2 "FAULTED" + PCS_dcdcHvBusDischargeStatus = ((rx_frame.data.u8[0] >> 4) & (0x03U)); //0 "IDLE" 1 "ACTIVE" 2 "FAULTED" + PCS_dcdcMainState = ((rx_frame.data.u8[1] & (0x03U)) << 2) | ((rx_frame.data.u8[0] >> 6) & (0x03U)); //0 "STANDBY" 1 "12V_SUPPORT_ACTIVE" 2 "PRECHARGE_STARTUP" 3 "PRECHARGE_ACTIVE" 4 "DIS_HVBUS_ACTIVE" 5 "SHUTDOWN" 6 "FAULTED" ; - battery_PCS_dcdcSubState = + PCS_dcdcSubState = ((rx_frame.data.u8[1] >> 2) & (0x1FU)); //0 "PWR_UP_INIT" 1 "STANDBY" 2 "12V_SUPPORT_ACTIVE" 3 "DIS_HVBUS" 4 "PCHG_FAST_DIS_HVBUS" 5 "PCHG_SLOW_DIS_HVBUS" 6 "PCHG_DWELL_CHARGE" 7 "PCHG_DWELL_WAIT" 8 "PCHG_DI_RECOVERY_WAIT" 9 "PCHG_ACTIVE" 10 "PCHG_FLT_FAST_DIS_HVBUS" 11 "SHUTDOWN" 12 "12V_SUPPORT_FAULTED" 13 "DIS_HVBUS_FAULTED" 14 "PCHG_FAULTED" 15 "CLEAR_FAULTS" 16 "FAULTED" 17 "NUM" ; - battery_PCS_dcdcFaulted = ((rx_frame.data.u8[1] >> 7) & (0x01U)); - battery_PCS_dcdcOutputIsLimited = ((rx_frame.data.u8[3] >> 4) & (0x01U)); - battery_PCS_dcdcMaxOutputCurrentAllowed = ((rx_frame.data.u8[5] & (0x01U)) << 11) | - ((rx_frame.data.u8[4] & (0xFFU)) << 3) | - ((rx_frame.data.u8[3] >> 5) & (0x07U)); //29|12@1+ (0.1,0) [0|0] "A" - battery_PCS_dcdcPrechargeRtyCnt = ((rx_frame.data.u8[5] >> 1) & (0x07U)); //Retry Count - battery_PCS_dcdc12VSupportRtyCnt = ((rx_frame.data.u8[5] >> 4) & (0x0FU)); //Retry Count - battery_PCS_dcdcDischargeRtyCnt = (rx_frame.data.u8[6] & (0x0FU)); //Retry Count - battery_PCS_dcdcPwmEnableLine = ((rx_frame.data.u8[6] >> 4) & (0x01U)); - battery_PCS_dcdcSupportingFixedLvTarget = ((rx_frame.data.u8[6] >> 5) & (0x01U)); - battery_PCS_ecuLogUploadRequest = ((rx_frame.data.u8[6] >> 6) & (0x03U)); - battery_PCS_dcdcPrechargeRestartCnt = (rx_frame.data.u8[7] & (0x07U)); - battery_PCS_dcdcInitialPrechargeSubState = + PCS_dcdcFaulted = ((rx_frame.data.u8[1] >> 7) & (0x01U)); + PCS_dcdcOutputIsLimited = ((rx_frame.data.u8[3] >> 4) & (0x01U)); + PCS_dcdcMaxOutputCurrentAllowed = ((rx_frame.data.u8[5] & (0x01U)) << 11) | + ((rx_frame.data.u8[4] & (0xFFU)) << 3) | + ((rx_frame.data.u8[3] >> 5) & (0x07U)); //29|12@1+ (0.1,0) [0|0] "A" + PCS_dcdcPrechargeRtyCnt = ((rx_frame.data.u8[5] >> 1) & (0x07U)); //Retry Count + PCS_dcdc12VSupportRtyCnt = ((rx_frame.data.u8[5] >> 4) & (0x0FU)); //Retry Count + PCS_dcdcDischargeRtyCnt = (rx_frame.data.u8[6] & (0x0FU)); //Retry Count + PCS_dcdcPwmEnableLine = ((rx_frame.data.u8[6] >> 4) & (0x01U)); + PCS_dcdcSupportingFixedLvTarget = ((rx_frame.data.u8[6] >> 5) & (0x01U)); + PCS_ecuLogUploadRequest = ((rx_frame.data.u8[6] >> 6) & (0x03U)); + PCS_dcdcPrechargeRestartCnt = (rx_frame.data.u8[7] & (0x07U)); + PCS_dcdcInitialPrechargeSubState = ((rx_frame.data.u8[7] >> 3) & (0x1FU)); //0 "PWR_UP_INIT" 1 "STANDBY" 2 "12V_SUPPORT_ACTIVE" 3 "DIS_HVBUS" 4 "PCHG_FAST_DIS_HVBUS" 5 "PCHG_SLOW_DIS_HVBUS" 6 "PCHG_DWELL_CHARGE" 7 "PCHG_DWELL_WAIT" 8 "PCHG_DI_RECOVERY_WAIT" 9 "PCHG_ACTIVE" 10 "PCHG_FLT_FAST_DIS_HVBUS" 11 "SHUTDOWN" 12 "12V_SUPPORT_FAULTED" 13 "DIS_HVBUS_FAULTED" 14 "PCHG_FAULTED" 15 "CLEAR_FAULTS" 16 "FAULTED" 17 "NUM" ; break; case 0x252: //Limit //594 BMS_powerAvailable: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; BMS_maxRegenPower = ((rx_frame.data.u8[1] << 8) | rx_frame.data.u8[0]); //0|16@1+ (0.01,0) [0|655.35] "kW" //Example 4715 * 0.01 = 47.15kW BMS_maxDischargePower = @@ -859,6 +1229,7 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { BMS_inverterTQF = ((rx_frame.data.u8[7] >> 4) & (0x03U)); break; case 0x132: //battery amps/volts //HVBattAmpVolt + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; battery_volts = ((rx_frame.data.u8[1] << 8) | rx_frame.data.u8[0]) * 0.1; //0|16@1+ (0.01,0) [0|655.35] "V" //Example 37030mv * 0.01 = 3703dV battery_amps = @@ -876,6 +1247,7 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { } break; case 0x3D2: //TotalChargeDischarge: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; battery_total_discharge = ((rx_frame.data.u8[3] << 24) | (rx_frame.data.u8[2] << 16) | (rx_frame.data.u8[1] << 8) | rx_frame.data.u8[0]); //0|32@1+ (0.001,0) [0|4294970] "kWh" @@ -883,7 +1255,8 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { rx_frame.data.u8[4]); //32|32@1+ (0.001,0) [0|4294970] "kWh" break; - case 0x332: //min/max hist values //BattBrickMinMax: + case 0x332: //min/max hist values //BattBrickMinMax: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; mux = (rx_frame.data.u8[0] & 0x03); //BattBrickMultiplexer M : 0|2@1+ (1,0) [0|0] "" if (mux == 1) //Cell voltages @@ -925,6 +1298,7 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { } break; case 0x312: // 786 BMS_thermalStatus + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; BMS_powerDissipation = ((rx_frame.data.u8[1] & (0x03U)) << 8) | (rx_frame.data.u8[0] & (0xFFU)); //0|10@1+ (0.02,0) [0|0] "kW" BMS_flowRequest = ((rx_frame.data.u8[2] & (0x01U)) << 6) | @@ -942,7 +1316,8 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { BMS_pcsNoFlowRequest = ((rx_frame.data.u8[7] >> 6) & (0x01U)); // 62|1@1+ (1,0) [0|0] "" BMS_noFlowRequest = ((rx_frame.data.u8[7] >> 7) & (0x01U)); //63|1@1+ (1,0) [0|0] "" break; - case 0x2A4: //676 PCS_thermalStatus + case 0x2A4: //676 PCS_thermalStatus + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; PCS_chgPhATemp = (rx_frame.data.u8[0] & 0xFF) | ((rx_frame.data.u8[1] & 0x07) << 8); //0|11@1- (0.1,40) [0|0] "C" PCS_chgPhBTemp = ((rx_frame.data.u8[1] & 0xF8) >> 3) | ((rx_frame.data.u8[2] & 0x3F) << 5); //11|11@1- (0.1,40) [0|0] "C" @@ -953,6 +1328,7 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { PCS_ambientTemp = ((rx_frame.data.u8[5] & 0xF0) >> 4) | (rx_frame.data.u8[6] << 4); //44|11@1- (0.1,40) [0|0] "C" break; case 0x2C4: // 708 PCS_logging: not all frames are listed, just ones relating to dcdc + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; mux = (rx_frame.data.u8[0] & (0x1FU)); //PCS_logMessageSelect = (rx_frame.data.u8[0] & (0x1FU)); //0|5@1+ (1,0) [0|0] "" if (mux == 6) { @@ -1009,7 +1385,8 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { (rx_frame.data.u8[1] & (0xFFU)); // m22 : 8|24@1+ (0.01,0) [0|0] "kWh" X } break; - case 0x401: // Cell stats //BrickVoltages + case 0x401: // Cell stats //BrickVoltages + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; mux = (rx_frame.data.u8[0]); //MultiplexSelector M : 0|8@1+ (1,0) [0|0] "" //StatusFlags : 8|8@1+ (1,0) [0|0] "" //Brick0 m0 : 16|16@1+ (0.0001,0) [0|0] "V" @@ -1044,18 +1421,18 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { } break; case 0x2d2: //BMSVAlimits: - battery_bms_min_voltage = - ((rx_frame.data.u8[1] << 8) | - rx_frame.data.u8[0]); //0|16@1+ (0.01,0) [0|430] "V" //Example 24148mv * 0.01 = 241.48 V - battery_bms_max_voltage = - ((rx_frame.data.u8[3] << 8) | - rx_frame.data.u8[2]); //16|16@1+ (0.01,0) [0|430] "V" //Example 40282mv * 0.01 = 402.82 V + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + BMS_min_voltage = ((rx_frame.data.u8[1] << 8) | + rx_frame.data.u8[0]); //0|16@1+ (0.01,0) [0|430] "V" //Example 24148mv * 0.01 = 241.48 V + BMS_max_voltage = ((rx_frame.data.u8[3] << 8) | + rx_frame.data.u8[2]); //16|16@1+ (0.01,0) [0|430] "V" //Example 40282mv * 0.01 = 402.82 V battery_max_charge_current = (((rx_frame.data.u8[5] & 0x3F) << 8) | rx_frame.data.u8[4]) * 0.1; //32|14@1+ (0.1,0) [0|1638.2] "A" //Example 1301? * 0.1 = 130.1? battery_max_discharge_current = (((rx_frame.data.u8[7] & 0x3F) << 8) | rx_frame.data.u8[6]) * 0.128; //48|14@1+ (0.128,0) [0|2096.9] "A" //Example 430? * 0.128 = 55.4? break; case 0x2b4: //PCS_dcdcRailStatus: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; battery_dcdcLvBusVolt = (((rx_frame.data.u8[1] & 0x03) << 8) | rx_frame.data.u8[0]); //0|10@1+ (0.0390625,0) [0|39.9609] "V" battery_dcdcHvBusVolt = (((rx_frame.data.u8[2] & 0x3F) << 6) | @@ -1063,8 +1440,8 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { battery_dcdcLvOutputCurrent = (((rx_frame.data.u8[4] & 0x0F) << 8) | rx_frame.data.u8[3]); //24|12@1+ (0.1,0) [0|400] "A" break; - case 0x292: //BMS_socStatus - datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; //We are getting CAN messages from the BMS + case 0x292: //BMS_socStatus + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; battery_beginning_of_life = (((rx_frame.data.u8[6] & 0x03) << 8) | rx_frame.data.u8[5]) * 0.1; //40|10@1+ (0.1,0) [0|102.3] "kWh" battery_soc_min = (((rx_frame.data.u8[1] & 0x03) << 8) | rx_frame.data.u8[0]); //0|10@1+ (0.1,0) [0|102.3] "%" @@ -1078,6 +1455,7 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { (((rx_frame.data.u8[7] & 0x03) << 6) | (rx_frame.data.u8[6] & 0x3F) >> 2); //50|8@1+ (0.4,0) [0|100] "%" break; case 0x392: //BMS_packConfig + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; mux = (rx_frame.data.u8[0] & (0xFF)); if (mux == 1) { battery_packConfigMultiplexer = (rx_frame.data.u8[0] & (0xff)); //0|8@1+ (1,0) [0|1] "" @@ -1095,6 +1473,7 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { } break; case 0x7AA: //1962 HVP_debugMessage: + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; mux = (rx_frame.data.u8[0] & (0x0FU)); //HVP_debugMessageMultiplexer = (rx_frame.data.u8[0] & (0x0FU)); //0|4@1+ (1,0) [0|6] "" if (mux == 0) { @@ -1191,6 +1570,7 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { HVP_shuntAsicTempStatus = ((rx_frame.data.u8[7] >> 4) & (0x03U)); //: 60|2@1+ (1,0) [0|3] "" Receiver } break; + /* We ignore 0x3AA for now, as on later software/firmware this is a muxed frame so values aren't correct case 0x3aa: //HVP_alertMatrix1 battery_WatchdogReset = (rx_frame.data.u8[0] & 0x01); battery_PowerLossReset = ((rx_frame.data.u8[0] & 0x02) >> 1); @@ -1243,138 +1623,340 @@ void TeslaBattery::handle_incoming_can_frame(CAN_frame rx_frame) { battery_packCtrCloseFailed = (rx_frame.data.u8[6] & 0x01); battery_fcCtrCloseFailed = ((rx_frame.data.u8[6] & 0x02) >> 1); battery_shuntThermistorMia = ((rx_frame.data.u8[6] & 0x04) >> 2); - break; + break;*/ case 0x320: //800 BMS_alertMatrix //BMS_alertMatrix 800 BMS_alertMatrix: 8 VEH + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; mux = (rx_frame.data.u8[0] & (0x0F)); - if (mux == 0) { //mux0 - battery_BMS_matrixIndex = (rx_frame.data.u8[0] & (0x0F)); // 0|4@1+ (1,0) [0|0] "" X - battery_BMS_a017_SW_Brick_OV = ((rx_frame.data.u8[2] >> 4) & (0x01)); //20|1@1+ (1,0) [0|0] "" X - battery_BMS_a018_SW_Brick_UV = ((rx_frame.data.u8[2] >> 5) & (0x01)); //21|1@1+ (1,0) [0|0] "" X - battery_BMS_a019_SW_Module_OT = ((rx_frame.data.u8[2] >> 6) & (0x01)); //22|1@1+ (1,0) [0|0] "" X - battery_BMS_a021_SW_Dr_Limits_Regulation = (rx_frame.data.u8[3] & (0x01U)); //24|1@1+ (1,0) [0|0] "" X - battery_BMS_a022_SW_Over_Current = ((rx_frame.data.u8[3] >> 1) & (0x01U)); //25|1@1+ (1,0) [0|0] "" X - battery_BMS_a023_SW_Stack_OV = ((rx_frame.data.u8[3] >> 2) & (0x01U)); //26|1@1+ (1,0) [0|0] "" X - battery_BMS_a024_SW_Islanded_Brick = ((rx_frame.data.u8[3] >> 3) & (0x01U)); //27|1@1+ (1,0) [0|0] "" X - battery_BMS_a025_SW_PwrBalance_Anomaly = ((rx_frame.data.u8[3] >> 4) & (0x01U)); //28|1@1+ (1,0) [0|0] "" X - battery_BMS_a026_SW_HFCurrent_Anomaly = ((rx_frame.data.u8[3] >> 5) & (0x01U)); //29|1@1+ (1,0) [0|0] "" X - battery_BMS_a034_SW_Passive_Isolation = ((rx_frame.data.u8[4] >> 5) & (0x01U)); //37|1@1+ (1,0) [0|0] "" X ? - battery_BMS_a035_SW_Isolation = ((rx_frame.data.u8[4] >> 6) & (0x01U)); //38|1@1+ (1,0) [0|0] "" X - battery_BMS_a036_SW_HvpHvilFault = ((rx_frame.data.u8[4] >> 6) & (0x01U)); //39|1@1+ (1,0) [0|0] "" X - battery_BMS_a037_SW_Flood_Port_Open = (rx_frame.data.u8[5] & (0x01U)); //40|1@1+ (1,0) [0|0] "" X - battery_BMS_a039_SW_DC_Link_Over_Voltage = ((rx_frame.data.u8[5] >> 2) & (0x01U)); //42|1@1+ (1,0) [0|0] "" X - battery_BMS_a041_SW_Power_On_Reset = ((rx_frame.data.u8[5] >> 4) & (0x01U)); //44|1@1+ (1,0) [0|0] "" X - battery_BMS_a042_SW_MPU_Error = ((rx_frame.data.u8[5] >> 5) & (0x01U)); //45|1@1+ (1,0) [0|0] "" X - battery_BMS_a043_SW_Watch_Dog_Reset = ((rx_frame.data.u8[5] >> 6) & (0x01U)); //46|1@1+ (1,0) [0|0] "" X - battery_BMS_a044_SW_Assertion = ((rx_frame.data.u8[5] >> 7) & (0x01U)); //47|1@1+ (1,0) [0|0] "" X - battery_BMS_a045_SW_Exception = (rx_frame.data.u8[6] & (0x01U)); //48|1@1+ (1,0) [0|0] "" X - battery_BMS_a046_SW_Task_Stack_Usage = ((rx_frame.data.u8[6] >> 1) & (0x01U)); //49|1@1+ (1,0) [0|0] "" X - battery_BMS_a047_SW_Task_Stack_Overflow = ((rx_frame.data.u8[6] >> 2) & (0x01U)); //50|1@1+ (1,0) [0|0] "" X - battery_BMS_a048_SW_Log_Upload_Request = ((rx_frame.data.u8[6] >> 3) & (0x01U)); //51|1@1+ (1,0) [0|0] "" X - battery_BMS_a050_SW_Brick_Voltage_MIA = ((rx_frame.data.u8[6] >> 5) & (0x01U)); //53|1@1+ (1,0) [0|0] "" X - battery_BMS_a051_SW_HVC_Vref_Bad = ((rx_frame.data.u8[6] >> 6) & (0x01U)); //54|1@1+ (1,0) [0|0] "" X - battery_BMS_a052_SW_PCS_MIA = ((rx_frame.data.u8[6] >> 7) & (0x01U)); //55|1@1+ (1,0) [0|0] "" X - battery_BMS_a053_SW_ThermalModel_Sanity = (rx_frame.data.u8[7] & (0x01U)); //56|1@1+ (1,0) [0|0] "" X - battery_BMS_a054_SW_Ver_Supply_Fault = ((rx_frame.data.u8[7] >> 1) & (0x01U)); //57|1@1+ (1,0) [0|0] "" X - battery_BMS_a059_SW_Pack_Voltage_Sensing = ((rx_frame.data.u8[7] >> 6) & (0x01U)); //62|1@1+ (1,0) [0|0] "" X - battery_BMS_a060_SW_Leakage_Test_Failure = ((rx_frame.data.u8[7] >> 7) & (0x01U)); //63|1@1+ (1,0) [0|0] "" X + if (mux == 0) { //mux0 + BMS_matrixIndex = (rx_frame.data.u8[0] & (0x0F)); // 0|4@1+ (1,0) [0|0] "" X + BMS_a017_SW_Brick_OV = ((rx_frame.data.u8[2] >> 4) & (0x01)); //20|1@1+ (1,0) [0|0] "" X + BMS_a018_SW_Brick_UV = ((rx_frame.data.u8[2] >> 5) & (0x01)); //21|1@1+ (1,0) [0|0] "" X + BMS_a019_SW_Module_OT = ((rx_frame.data.u8[2] >> 6) & (0x01)); //22|1@1+ (1,0) [0|0] "" X + BMS_a021_SW_Dr_Limits_Regulation = (rx_frame.data.u8[3] & (0x01U)); //24|1@1+ (1,0) [0|0] "" X + BMS_a022_SW_Over_Current = ((rx_frame.data.u8[3] >> 1) & (0x01U)); //25|1@1+ (1,0) [0|0] "" X + BMS_a023_SW_Stack_OV = ((rx_frame.data.u8[3] >> 2) & (0x01U)); //26|1@1+ (1,0) [0|0] "" X + BMS_a024_SW_Islanded_Brick = ((rx_frame.data.u8[3] >> 3) & (0x01U)); //27|1@1+ (1,0) [0|0] "" X + BMS_a025_SW_PwrBalance_Anomaly = ((rx_frame.data.u8[3] >> 4) & (0x01U)); //28|1@1+ (1,0) [0|0] "" X + BMS_a026_SW_HFCurrent_Anomaly = ((rx_frame.data.u8[3] >> 5) & (0x01U)); //29|1@1+ (1,0) [0|0] "" X + BMS_a034_SW_Passive_Isolation = ((rx_frame.data.u8[4] >> 5) & (0x01U)); //37|1@1+ (1,0) [0|0] "" X ? + BMS_a035_SW_Isolation = ((rx_frame.data.u8[4] >> 6) & (0x01U)); //38|1@1+ (1,0) [0|0] "" X + BMS_a036_SW_HvpHvilFault = ((rx_frame.data.u8[4] >> 6) & (0x01U)); //39|1@1+ (1,0) [0|0] "" X + BMS_a037_SW_Flood_Port_Open = (rx_frame.data.u8[5] & (0x01U)); //40|1@1+ (1,0) [0|0] "" X + BMS_a039_SW_DC_Link_Over_Voltage = ((rx_frame.data.u8[5] >> 2) & (0x01U)); //42|1@1+ (1,0) [0|0] "" X + BMS_a041_SW_Power_On_Reset = ((rx_frame.data.u8[5] >> 4) & (0x01U)); //44|1@1+ (1,0) [0|0] "" X + BMS_a042_SW_MPU_Error = ((rx_frame.data.u8[5] >> 5) & (0x01U)); //45|1@1+ (1,0) [0|0] "" X + BMS_a043_SW_Watch_Dog_Reset = ((rx_frame.data.u8[5] >> 6) & (0x01U)); //46|1@1+ (1,0) [0|0] "" X + BMS_a044_SW_Assertion = ((rx_frame.data.u8[5] >> 7) & (0x01U)); //47|1@1+ (1,0) [0|0] "" X + BMS_a045_SW_Exception = (rx_frame.data.u8[6] & (0x01U)); //48|1@1+ (1,0) [0|0] "" X + BMS_a046_SW_Task_Stack_Usage = ((rx_frame.data.u8[6] >> 1) & (0x01U)); //49|1@1+ (1,0) [0|0] "" X + BMS_a047_SW_Task_Stack_Overflow = ((rx_frame.data.u8[6] >> 2) & (0x01U)); //50|1@1+ (1,0) [0|0] "" X + BMS_a048_SW_Log_Upload_Request = ((rx_frame.data.u8[6] >> 3) & (0x01U)); //51|1@1+ (1,0) [0|0] "" X + BMS_a050_SW_Brick_Voltage_MIA = ((rx_frame.data.u8[6] >> 5) & (0x01U)); //53|1@1+ (1,0) [0|0] "" X + BMS_a051_SW_HVC_Vref_Bad = ((rx_frame.data.u8[6] >> 6) & (0x01U)); //54|1@1+ (1,0) [0|0] "" X + BMS_a052_SW_PCS_MIA = ((rx_frame.data.u8[6] >> 7) & (0x01U)); //55|1@1+ (1,0) [0|0] "" X + BMS_a053_SW_ThermalModel_Sanity = (rx_frame.data.u8[7] & (0x01U)); //56|1@1+ (1,0) [0|0] "" X + BMS_a054_SW_Ver_Supply_Fault = ((rx_frame.data.u8[7] >> 1) & (0x01U)); //57|1@1+ (1,0) [0|0] "" X + BMS_a059_SW_Pack_Voltage_Sensing = ((rx_frame.data.u8[7] >> 6) & (0x01U)); //62|1@1+ (1,0) [0|0] "" X + BMS_a060_SW_Leakage_Test_Failure = ((rx_frame.data.u8[7] >> 7) & (0x01U)); //63|1@1+ (1,0) [0|0] "" X } - if (mux == 1) { //mux1 - battery_BMS_a061_robinBrickOverVoltage = ((rx_frame.data.u8[0] >> 4) & (0x01U)); //4|1@1+ (1,0) [0|0] "" X - battery_BMS_a062_SW_BrickV_Imbalance = ((rx_frame.data.u8[0] >> 5) & (0x01U)); //5|1@1+ (1,0) [0|0] "" X - battery_BMS_a063_SW_ChargePort_Fault = ((rx_frame.data.u8[0] >> 6) & (0x01U)); //6|1@1+ (1,0) [0|0] "" X - battery_BMS_a064_SW_SOC_Imbalance = ((rx_frame.data.u8[0] >> 7) & (0x01U)); //7|1@1+ (1,0) [0|0] "" X - battery_BMS_a069_SW_Low_Power = ((rx_frame.data.u8[1] >> 4) & (0x01U)); //12|1@1+ (1,0) [0|0] "" X - battery_BMS_a071_SW_SM_TransCon_Not_Met = ((rx_frame.data.u8[1] >> 6) & (0x01U)); //14|1@1+ (1,0) [0|0] "" X - battery_BMS_a075_SW_Chg_Disable_Failure = ((rx_frame.data.u8[2] >> 2) & (0x01U)); //18|1@1+ (1,0) [0|0] "" X - battery_BMS_a076_SW_Dch_While_Charging = ((rx_frame.data.u8[2] >> 3) & (0x01U)); //19|1@1+ (1,0) [0|0] "" X - battery_BMS_a077_SW_Charger_Regulation = ((rx_frame.data.u8[2] >> 4) & (0x01U)); //20|1@1+ (1,0) [0|0] "" X - battery_BMS_a081_SW_Ctr_Close_Blocked = (rx_frame.data.u8[3] & (0x01U)); //24|1@1+ (1,0) [0|0] "" X - battery_BMS_a082_SW_Ctr_Force_Open = ((rx_frame.data.u8[3] >> 1) & (0x01U)); //25|1@1+ (1,0) [0|0] "" X - battery_BMS_a083_SW_Ctr_Close_Failure = ((rx_frame.data.u8[3] >> 2) & (0x01U)); //26|1@1+ (1,0) [0|0] "" X - battery_BMS_a084_SW_Sleep_Wake_Aborted = ((rx_frame.data.u8[3] >> 3) & (0x01U)); //27|1@1+ (1,0) [0|0] "" X - battery_BMS_a087_SW_Feim_Test_Blocked = ((rx_frame.data.u8[3] >> 6) & (0x01U)); //30|1@1+ (1,0) [0|0] "" X - battery_BMS_a088_SW_VcFront_MIA_InDrive = ((rx_frame.data.u8[3] >> 7) & (0x01U)); //31|1@1+ (1,0) [0|0] "" X - battery_BMS_a089_SW_VcFront_MIA = (rx_frame.data.u8[4] & (0x01U)); //32|1@1+ (1,0) [0|0] "" X - battery_BMS_a090_SW_Gateway_MIA = ((rx_frame.data.u8[4] >> 1) & (0x01U)); //33|1@1+ (1,0) [0|0] "" X - battery_BMS_a091_SW_ChargePort_MIA = ((rx_frame.data.u8[4] >> 2) & (0x01U)); //34|1@1+ (1,0) [0|0] "" X - battery_BMS_a092_SW_ChargePort_Mia_On_Hv = ((rx_frame.data.u8[4] >> 3) & (0x01U)); //35|1@1+ (1,0) [0|0] "" X - battery_BMS_a094_SW_Drive_Inverter_MIA = ((rx_frame.data.u8[4] >> 5) & (0x01U)); //37|1@1+ (1,0) [0|0] "" X - battery_BMS_a099_SW_BMB_Communication = ((rx_frame.data.u8[5] >> 2) & (0x01U)); //42|1@1+ (1,0) [0|0] "" X - battery_BMS_a105_SW_One_Module_Tsense = (rx_frame.data.u8[6] & (0x01U)); //48|1@1+ (1,0) [0|0] "" X - battery_BMS_a106_SW_All_Module_Tsense = ((rx_frame.data.u8[6] >> 1) & (0x01U)); //49|1@1+ (1,0) [0|0] "" X - battery_BMS_a107_SW_Stack_Voltage_MIA = ((rx_frame.data.u8[6] >> 2) & (0x01U)); //50|1@1+ (1,0) [0|0] "" X + if (mux == 1) { //mux1 + BMS_a061_robinBrickOverVoltage = ((rx_frame.data.u8[0] >> 4) & (0x01U)); //4|1@1+ (1,0) [0|0] "" X + BMS_a062_SW_BrickV_Imbalance = ((rx_frame.data.u8[0] >> 5) & (0x01U)); //5|1@1+ (1,0) [0|0] "" X + BMS_a063_SW_ChargePort_Fault = ((rx_frame.data.u8[0] >> 6) & (0x01U)); //6|1@1+ (1,0) [0|0] "" X + BMS_a064_SW_SOC_Imbalance = ((rx_frame.data.u8[0] >> 7) & (0x01U)); //7|1@1+ (1,0) [0|0] "" X + BMS_a069_SW_Low_Power = ((rx_frame.data.u8[1] >> 4) & (0x01U)); //12|1@1+ (1,0) [0|0] "" X + BMS_a071_SW_SM_TransCon_Not_Met = ((rx_frame.data.u8[1] >> 6) & (0x01U)); //14|1@1+ (1,0) [0|0] "" X + BMS_a075_SW_Chg_Disable_Failure = ((rx_frame.data.u8[2] >> 2) & (0x01U)); //18|1@1+ (1,0) [0|0] "" X + BMS_a076_SW_Dch_While_Charging = ((rx_frame.data.u8[2] >> 3) & (0x01U)); //19|1@1+ (1,0) [0|0] "" X + BMS_a077_SW_Charger_Regulation = ((rx_frame.data.u8[2] >> 4) & (0x01U)); //20|1@1+ (1,0) [0|0] "" X + BMS_a081_SW_Ctr_Close_Blocked = (rx_frame.data.u8[3] & (0x01U)); //24|1@1+ (1,0) [0|0] "" X + BMS_a082_SW_Ctr_Force_Open = ((rx_frame.data.u8[3] >> 1) & (0x01U)); //25|1@1+ (1,0) [0|0] "" X + BMS_a083_SW_Ctr_Close_Failure = ((rx_frame.data.u8[3] >> 2) & (0x01U)); //26|1@1+ (1,0) [0|0] "" X + BMS_a084_SW_Sleep_Wake_Aborted = ((rx_frame.data.u8[3] >> 3) & (0x01U)); //27|1@1+ (1,0) [0|0] "" X + BMS_a087_SW_Feim_Test_Blocked = ((rx_frame.data.u8[3] >> 6) & (0x01U)); //30|1@1+ (1,0) [0|0] "" X + BMS_a088_SW_VcFront_MIA_InDrive = ((rx_frame.data.u8[3] >> 7) & (0x01U)); //31|1@1+ (1,0) [0|0] "" X + BMS_a089_SW_VcFront_MIA = (rx_frame.data.u8[4] & (0x01U)); //32|1@1+ (1,0) [0|0] "" X + BMS_a090_SW_Gateway_MIA = ((rx_frame.data.u8[4] >> 1) & (0x01U)); //33|1@1+ (1,0) [0|0] "" X + BMS_a091_SW_ChargePort_MIA = ((rx_frame.data.u8[4] >> 2) & (0x01U)); //34|1@1+ (1,0) [0|0] "" X + BMS_a092_SW_ChargePort_Mia_On_Hv = ((rx_frame.data.u8[4] >> 3) & (0x01U)); //35|1@1+ (1,0) [0|0] "" X + BMS_a094_SW_Drive_Inverter_MIA = ((rx_frame.data.u8[4] >> 5) & (0x01U)); //37|1@1+ (1,0) [0|0] "" X + BMS_a099_SW_BMB_Communication = ((rx_frame.data.u8[5] >> 2) & (0x01U)); //42|1@1+ (1,0) [0|0] "" X + BMS_a105_SW_One_Module_Tsense = (rx_frame.data.u8[6] & (0x01U)); //48|1@1+ (1,0) [0|0] "" X + BMS_a106_SW_All_Module_Tsense = ((rx_frame.data.u8[6] >> 1) & (0x01U)); //49|1@1+ (1,0) [0|0] "" X + BMS_a107_SW_Stack_Voltage_MIA = ((rx_frame.data.u8[6] >> 2) & (0x01U)); //50|1@1+ (1,0) [0|0] "" X } - if (mux == 2) { //mux2 - battery_BMS_a121_SW_NVRAM_Config_Error = ((rx_frame.data.u8[0] >> 4) & (0x01U)); // 4|1@1+ (1,0) [0|0] "" X - battery_BMS_a122_SW_BMS_Therm_Irrational = ((rx_frame.data.u8[0] >> 5) & (0x01U)); //5|1@1+ (1,0) [0|0] "" X - battery_BMS_a123_SW_Internal_Isolation = ((rx_frame.data.u8[0] >> 6) & (0x01U)); //6|1@1+ (1,0) [0|0] "" X - battery_BMS_a127_SW_shunt_SNA = ((rx_frame.data.u8[1] >> 2) & (0x01U)); //10|1@1+ (1,0) [0|0] "" X - battery_BMS_a128_SW_shunt_MIA = ((rx_frame.data.u8[1] >> 3) & (0x01U)); //11|1@1+ (1,0) [0|0] "" X - battery_BMS_a129_SW_VSH_Failure = ((rx_frame.data.u8[1] >> 4) & (0x01U)); //12|1@1+ (1,0) [0|0] "" X - battery_BMS_a130_IO_CAN_Error = ((rx_frame.data.u8[1] >> 5) & (0x01U)); //13|1@1+ (1,0) [0|0] "" X - battery_BMS_a131_Bleed_FET_Failure = ((rx_frame.data.u8[1] >> 6) & (0x01U)); //14|1@1+ (1,0) [0|0] "" X - battery_BMS_a132_HW_BMB_OTP_Uncorrctbl = ((rx_frame.data.u8[1] >> 7) & (0x01U)); //15|1@1+ (1,0) [0|0] "" X - battery_BMS_a134_SW_Delayed_Ctr_Off = ((rx_frame.data.u8[2] >> 1) & (0x01U)); //17|1@1+ (1,0) [0|0] "" X - battery_BMS_a136_SW_Module_OT_Warning = ((rx_frame.data.u8[2] >> 3) & (0x01U)); //19|1@1+ (1,0) [0|0] "" X - battery_BMS_a137_SW_Brick_UV_Warning = ((rx_frame.data.u8[2] >> 4) & (0x01U)); //20|1@1+ (1,0) [0|0] "" X - battery_BMS_a138_SW_Brick_OV_Warning = ((rx_frame.data.u8[2] >> 5) & (0x01U)); //21|1@1+ (1,0) [0|0] "" X - battery_BMS_a139_SW_DC_Link_V_Irrational = ((rx_frame.data.u8[2] >> 6) & (0x01U)); //22|1@1+ (1,0) [0|0] "" X - battery_BMS_a141_SW_BMB_Status_Warning = (rx_frame.data.u8[3] & (0x01U)); //24|1@1+ (1,0) [0|0] "" X - battery_BMS_a144_Hvp_Config_Mismatch = ((rx_frame.data.u8[3] >> 3) & (0x01U)); //27|1@1+ (1,0) [0|0] "" X - battery_BMS_a145_SW_SOC_Change = ((rx_frame.data.u8[3] >> 4) & (0x01U)); //28|1@1+ (1,0) [0|0] "" X - battery_BMS_a146_SW_Brick_Overdischarged = ((rx_frame.data.u8[3] >> 5) & (0x01U)); //29|1@1+ (1,0) [0|0] "" X - battery_BMS_a149_SW_Missing_Config_Block = (rx_frame.data.u8[4] & (0x01U)); //32|1@1+ (1,0) [0|0] "" X - battery_BMS_a151_SW_external_isolation = ((rx_frame.data.u8[4] >> 2) & (0x01U)); //34|1@1+ (1,0) [0|0] "" X - battery_BMS_a156_SW_BMB_Vref_bad = ((rx_frame.data.u8[4] >> 7) & (0x01U)); //39|1@1+ (1,0) [0|0] "" X - battery_BMS_a157_SW_HVP_HVS_Comms = (rx_frame.data.u8[5] & (0x01U)); //40|1@1+ (1,0) [0|0] "" X - battery_BMS_a158_SW_HVP_HVI_Comms = ((rx_frame.data.u8[5] >> 1) & (0x01U)); //41|1@1+ (1,0) [0|0] "" X - battery_BMS_a159_SW_HVP_ECU_Error = ((rx_frame.data.u8[5] >> 2) & (0x01U)); //42|1@1+ (1,0) [0|0] "" X - battery_BMS_a161_SW_DI_Open_Request = ((rx_frame.data.u8[5] >> 4) & (0x01U)); //44|1@1+ (1,0) [0|0] "" X - battery_BMS_a162_SW_No_Power_For_Support = ((rx_frame.data.u8[5] >> 5) & (0x01U)); //45|1@1+ (1,0) [0|0] "" X - battery_BMS_a163_SW_Contactor_Mismatch = ((rx_frame.data.u8[5] >> 6) & (0x01U)); //46|1@1+ (1,0) [0|0] "" X - battery_BMS_a164_SW_Uncontrolled_Regen = ((rx_frame.data.u8[5] >> 7) & (0x01U)); //47|1@1+ (1,0) [0|0] "" X - battery_BMS_a165_SW_Pack_Partial_Weld = (rx_frame.data.u8[6] & (0x01U)); //48|1@1+ (1,0) [0|0] "" X - battery_BMS_a166_SW_Pack_Full_Weld = ((rx_frame.data.u8[6] >> 1) & (0x01U)); //49|1@1+ (1,0) [0|0] "" X - battery_BMS_a167_SW_FC_Partial_Weld = ((rx_frame.data.u8[6] >> 2) & (0x01U)); //50|1@1+ (1,0) [0|0] "" X - battery_BMS_a168_SW_FC_Full_Weld = ((rx_frame.data.u8[6] >> 3) & (0x01U)); //51|1@1+ (1,0) [0|0] "" X - battery_BMS_a169_SW_FC_Pack_Weld = ((rx_frame.data.u8[6] >> 4) & (0x01U)); //52|1@1+ (1,0) [0|0] "" X - battery_BMS_a170_SW_Limp_Mode = ((rx_frame.data.u8[6] >> 5) & (0x01U)); //53|1@1+ (1,0) [0|0] "" X - battery_BMS_a171_SW_Stack_Voltage_Sense = ((rx_frame.data.u8[6] >> 6) & (0x01U)); //54|1@1+ (1,0) [0|0] "" X - battery_BMS_a174_SW_Charge_Failure = ((rx_frame.data.u8[7] >> 1) & (0x01U)); //57|1@1+ (1,0) [0|0] "" X - battery_BMS_a176_SW_GracefulPowerOff = ((rx_frame.data.u8[7] >> 3) & (0x01U)); //59|1@1+ (1,0) [0|0] "" X - battery_BMS_a179_SW_Hvp_12V_Fault = ((rx_frame.data.u8[7] >> 6) & (0x01U)); //62|1@1+ (1,0) [0|0] "" X - battery_BMS_a180_SW_ECU_reset_blocked = ((rx_frame.data.u8[7] >> 7) & (0x01U)); //63|1@1+ (1,0) [0|0] "" X + if (mux == 2) { //mux2 + BMS_a121_SW_NVRAM_Config_Error = ((rx_frame.data.u8[0] >> 4) & (0x01U)); // 4|1@1+ (1,0) [0|0] "" X + BMS_a122_SW_BMS_Therm_Irrational = ((rx_frame.data.u8[0] >> 5) & (0x01U)); //5|1@1+ (1,0) [0|0] "" X + BMS_a123_SW_Internal_Isolation = ((rx_frame.data.u8[0] >> 6) & (0x01U)); //6|1@1+ (1,0) [0|0] "" X + BMS_a127_SW_shunt_SNA = ((rx_frame.data.u8[1] >> 2) & (0x01U)); //10|1@1+ (1,0) [0|0] "" X + BMS_a128_SW_shunt_MIA = ((rx_frame.data.u8[1] >> 3) & (0x01U)); //11|1@1+ (1,0) [0|0] "" X + BMS_a129_SW_VSH_Failure = ((rx_frame.data.u8[1] >> 4) & (0x01U)); //12|1@1+ (1,0) [0|0] "" X + BMS_a130_IO_CAN_Error = ((rx_frame.data.u8[1] >> 5) & (0x01U)); //13|1@1+ (1,0) [0|0] "" X + BMS_a131_Bleed_FET_Failure = ((rx_frame.data.u8[1] >> 6) & (0x01U)); //14|1@1+ (1,0) [0|0] "" X + BMS_a132_HW_BMB_OTP_Uncorrctbl = ((rx_frame.data.u8[1] >> 7) & (0x01U)); //15|1@1+ (1,0) [0|0] "" X + BMS_a134_SW_Delayed_Ctr_Off = ((rx_frame.data.u8[2] >> 1) & (0x01U)); //17|1@1+ (1,0) [0|0] "" X + BMS_a136_SW_Module_OT_Warning = ((rx_frame.data.u8[2] >> 3) & (0x01U)); //19|1@1+ (1,0) [0|0] "" X + BMS_a137_SW_Brick_UV_Warning = ((rx_frame.data.u8[2] >> 4) & (0x01U)); //20|1@1+ (1,0) [0|0] "" X + BMS_a138_SW_Brick_OV_Warning = ((rx_frame.data.u8[2] >> 5) & (0x01U)); //21|1@1+ (1,0) [0|0] "" X + BMS_a139_SW_DC_Link_V_Irrational = ((rx_frame.data.u8[2] >> 6) & (0x01U)); //22|1@1+ (1,0) [0|0] "" X + BMS_a141_SW_BMB_Status_Warning = (rx_frame.data.u8[3] & (0x01U)); //24|1@1+ (1,0) [0|0] "" X + BMS_a144_Hvp_Config_Mismatch = ((rx_frame.data.u8[3] >> 3) & (0x01U)); //27|1@1+ (1,0) [0|0] "" X + BMS_a145_SW_SOC_Change = ((rx_frame.data.u8[3] >> 4) & (0x01U)); //28|1@1+ (1,0) [0|0] "" X + BMS_a146_SW_Brick_Overdischarged = ((rx_frame.data.u8[3] >> 5) & (0x01U)); //29|1@1+ (1,0) [0|0] "" X + BMS_a149_SW_Missing_Config_Block = (rx_frame.data.u8[4] & (0x01U)); //32|1@1+ (1,0) [0|0] "" X + BMS_a151_SW_external_isolation = ((rx_frame.data.u8[4] >> 2) & (0x01U)); //34|1@1+ (1,0) [0|0] "" X + BMS_a156_SW_BMB_Vref_bad = ((rx_frame.data.u8[4] >> 7) & (0x01U)); //39|1@1+ (1,0) [0|0] "" X + BMS_a157_SW_HVP_HVS_Comms = (rx_frame.data.u8[5] & (0x01U)); //40|1@1+ (1,0) [0|0] "" X + BMS_a158_SW_HVP_HVI_Comms = ((rx_frame.data.u8[5] >> 1) & (0x01U)); //41|1@1+ (1,0) [0|0] "" X + BMS_a159_SW_HVP_ECU_Error = ((rx_frame.data.u8[5] >> 2) & (0x01U)); //42|1@1+ (1,0) [0|0] "" X + BMS_a161_SW_DI_Open_Request = ((rx_frame.data.u8[5] >> 4) & (0x01U)); //44|1@1+ (1,0) [0|0] "" X + BMS_a162_SW_No_Power_For_Support = ((rx_frame.data.u8[5] >> 5) & (0x01U)); //45|1@1+ (1,0) [0|0] "" X + BMS_a163_SW_Contactor_Mismatch = ((rx_frame.data.u8[5] >> 6) & (0x01U)); //46|1@1+ (1,0) [0|0] "" X + BMS_a164_SW_Uncontrolled_Regen = ((rx_frame.data.u8[5] >> 7) & (0x01U)); //47|1@1+ (1,0) [0|0] "" X + BMS_a165_SW_Pack_Partial_Weld = (rx_frame.data.u8[6] & (0x01U)); //48|1@1+ (1,0) [0|0] "" X + BMS_a166_SW_Pack_Full_Weld = ((rx_frame.data.u8[6] >> 1) & (0x01U)); //49|1@1+ (1,0) [0|0] "" X + BMS_a167_SW_FC_Partial_Weld = ((rx_frame.data.u8[6] >> 2) & (0x01U)); //50|1@1+ (1,0) [0|0] "" X + BMS_a168_SW_FC_Full_Weld = ((rx_frame.data.u8[6] >> 3) & (0x01U)); //51|1@1+ (1,0) [0|0] "" X + BMS_a169_SW_FC_Pack_Weld = ((rx_frame.data.u8[6] >> 4) & (0x01U)); //52|1@1+ (1,0) [0|0] "" X + BMS_a170_SW_Limp_Mode = ((rx_frame.data.u8[6] >> 5) & (0x01U)); //53|1@1+ (1,0) [0|0] "" X + BMS_a171_SW_Stack_Voltage_Sense = ((rx_frame.data.u8[6] >> 6) & (0x01U)); //54|1@1+ (1,0) [0|0] "" X + BMS_a174_SW_Charge_Failure = ((rx_frame.data.u8[7] >> 1) & (0x01U)); //57|1@1+ (1,0) [0|0] "" X + BMS_a176_SW_GracefulPowerOff = ((rx_frame.data.u8[7] >> 3) & (0x01U)); //59|1@1+ (1,0) [0|0] "" X + BMS_a179_SW_Hvp_12V_Fault = ((rx_frame.data.u8[7] >> 6) & (0x01U)); //62|1@1+ (1,0) [0|0] "" X + BMS_a180_SW_ECU_reset_blocked = ((rx_frame.data.u8[7] >> 7) & (0x01U)); //63|1@1+ (1,0) [0|0] "" X } break; - case 0x72A: //1834 ID72ABMS_serialNumber - //Work in progress to display BMS Serial Number in ASCII: 00 54 47 33 32 31 32 30 (mux 0) .TG32120 + 01 32 30 30 33 41 48 58 (mux 1) .2003AHX = TG321202003AHX - if (rx_frame.data.u8[0] == 0x00) { - BMS_SerialNumber[0] = rx_frame.data.u8[1]; - BMS_SerialNumber[1] = rx_frame.data.u8[2]; - BMS_SerialNumber[2] = rx_frame.data.u8[3]; - BMS_SerialNumber[3] = rx_frame.data.u8[4]; - BMS_SerialNumber[4] = rx_frame.data.u8[5]; - BMS_SerialNumber[5] = rx_frame.data.u8[6]; - BMS_SerialNumber[6] = rx_frame.data.u8[7]; + case 0x72A: //BMS_serialNumber + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + //Pack serial number in ASCII: 00 54 47 33 32 31 32 30 (mux 0) .TG32120 + 01 32 30 30 33 41 48 58 (mux 1) .2003AHX = TG321202003AHX + if (rx_frame.data.u8[0] == 0x00 && !parsed_battery_serialNumber) { // Serial number 1-7 + battery_serialNumber[0] = rx_frame.data.u8[1]; + battery_serialNumber[1] = rx_frame.data.u8[2]; + battery_serialNumber[2] = rx_frame.data.u8[3]; + battery_serialNumber[3] = rx_frame.data.u8[4]; + battery_serialNumber[4] = rx_frame.data.u8[5]; + battery_serialNumber[5] = rx_frame.data.u8[6]; + battery_serialNumber[6] = rx_frame.data.u8[7]; } - if (rx_frame.data.u8[0] == 0x01) { - BMS_SerialNumber[7] = rx_frame.data.u8[1]; - BMS_SerialNumber[8] = rx_frame.data.u8[2]; - BMS_SerialNumber[9] = rx_frame.data.u8[3]; - BMS_SerialNumber[10] = rx_frame.data.u8[4]; - BMS_SerialNumber[11] = rx_frame.data.u8[5]; - BMS_SerialNumber[12] = rx_frame.data.u8[6]; - BMS_SerialNumber[13] = rx_frame.data.u8[7]; + if (rx_frame.data.u8[0] == 0x01 && !parsed_battery_serialNumber) { // Serial number 8-14 + battery_serialNumber[7] = rx_frame.data.u8[1]; + battery_serialNumber[8] = rx_frame.data.u8[2]; + battery_serialNumber[9] = rx_frame.data.u8[3]; + battery_serialNumber[10] = rx_frame.data.u8[4]; + battery_serialNumber[11] = rx_frame.data.u8[5]; + battery_serialNumber[12] = rx_frame.data.u8[6]; + battery_serialNumber[13] = rx_frame.data.u8[7]; + } + if (battery_serialNumber[6] != 0 && battery_serialNumber[12] != 0 && + !parsed_battery_serialNumber) { // Serial number complete + //Manufacture year + char yearStr[5]; // Full year string (including the "20" prefix) + snprintf(yearStr, sizeof(yearStr), "20%c%c", battery_serialNumber[3], battery_serialNumber[4]); + int year = atoi(yearStr); + //Manufacture day (Julian calendar) + char dayStr[4]; + snprintf(dayStr, sizeof(dayStr), "%c%c%c", battery_serialNumber[5], battery_serialNumber[6], + battery_serialNumber[7]); + int day = atoi(dayStr); + battery_manufactureDate = dayOfYearToDate(year, day); + parsed_battery_serialNumber = true; } break; - case 0x612: // CAN UDS responses for BMS ECU reset - if (memcmp(rx_frame.data.u8, "\x02\x67\x06\xAA\xAA\xAA\xAA\xAA", 8) == 0) { - logging.println("CAN UDS response: ECU unlocked"); - } else if (memcmp(rx_frame.data.u8, "\x03\x7F\x11\x78\xAA\xAA\xAA\xAA", 8) == 0) { - logging.println("CAN UDS response: ECU reset request successful but ECU busy, response pending"); - } else if (memcmp(rx_frame.data.u8, "\x02\x51\x01\xAA\xAA\xAA\xAA\xAA", 8) == 0) { - logging.println("CAN UDS response: ECU reset positive response, 1 second downtime"); + case 0x300: //BMS_info + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + //Display internal BMS info and other build/version data + if (rx_frame.data.u8[0] == 0x0A) { // Mux 10: BUILD_HWID_COMPONENTID + if (BMS_info_buildConfigId == 0) { + BMS_info_buildConfigId = static_cast(extract_signal_value(rx_frame.data.u8, 16, 16)); + } + if (BMS_info_hardwareId == 0) { + BMS_info_hardwareId = static_cast(extract_signal_value(rx_frame.data.u8, 32, 16)); + } + if (BMS_info_componentId == 0) { + BMS_info_componentId = static_cast(extract_signal_value(rx_frame.data.u8, 48, 16)); + } } + /* + if (rx_frame.data.u8[0] == 0x0B) { // Mux 11: PCBAID_ASSYID_USAGEID + if (BMS_info_pcbaId == 0) {BMS_info_pcbaId = static_cast(extract_signal_value(rx_frame.data.u8, 16, 8));} + if (BMS_info_assemblyId == 0) {BMS_info_assemblyId = static_cast(extract_signal_value(rx_frame.data.u8, 24, 8));} + if (BMS_info_usageId == 0) {BMS_info_usageId = static_cast(extract_signal_value(rx_frame.data.u8, 32, 16));} + if (BMS_info_subUsageId == 0) {BMS_info_subUsageId = static_cast(extract_signal_value(rx_frame.data.u8, 48, 16));} + } + if (rx_frame.data.u8[0] == 0x0D) { // Mux 13: APP_CRC + if (BMS_info_platformType == 0) {BMS_info_platformType = static_cast(extract_signal_value(rx_frame.data.u8, 8, 8));} + if (BMS_info_appCrc == 0) {BMS_info_appCrc = static_cast(extract_signal_value(rx_frame.data.u8, 32, 32));} + } + if (rx_frame.data.u8[0] == 0x12) { // Mux 18: BOOTLOADER_GITHASH + if (BMS_info_bootGitHash == 0) {BMS_info_bootGitHash = static_cast(extract_signal_value(rx_frame.data.u8, 10, 54));} + } + if (rx_frame.data.u8[0] == 0x14) { // Mux 20: UDS_PROTOCOL_BOOTCRC + if (BMS_info_bootUdsProtoVersion == 0) {BMS_info_bootUdsProtoVersion = static_cast(extract_signal_value(rx_frame.data.u8, 8, 8));} + if (BMS_info_bootCrc == 0) {BMS_info_bootCrc = static_cast(extract_signal_value(rx_frame.data.u8, 32, 32));} + } + */ + break; + case 0x3C4: //PCS_info + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + //Display internal PCS info and other build/version data + if (rx_frame.data.u8[0] == 0x0A) { // Mux 10: BUILD_HWID_COMPONENTID + if (PCS_info_buildConfigId == 0) { + PCS_info_buildConfigId = static_cast(extract_signal_value(rx_frame.data.u8, 16, 16)); + } + if (PCS_info_hardwareId == 0) { + PCS_info_hardwareId = static_cast(extract_signal_value(rx_frame.data.u8, 32, 16)); + } + if (PCS_info_componentId == 0) { + PCS_info_componentId = static_cast(extract_signal_value(rx_frame.data.u8, 48, 16)); + } + } + /* + if (rx_frame.data.u8[0] == 0x0B) { // Mux 11: PCBAID_ASSYID_USAGEID + if (PCS_info_pcbaId == 0) {PCS_info_pcbaId = static_cast(extract_signal_value(rx_frame.data.u8, 16, 8));} + if (PCS_info_assemblyId == 0) {PCS_info_assemblyId = static_cast(extract_signal_value(rx_frame.data.u8, 24, 8));} + if (PCS_info_usageId == 0) {PCS_info_usageId = static_cast(extract_signal_value(rx_frame.data.u8, 32, 16));} + if (PCS_info_subUsageId == 0) {PCS_info_subUsageId = static_cast(extract_signal_value(rx_frame.data.u8, 48, 16));} + } + if (rx_frame.data.u8[0] == 0x0D) { // Mux 13: APP_CRC + PCS_info_platformType = static_cast(extract_signal_value(rx_frame.data.u8, 8, 8)); + PCS_info_appCrc = static_cast(extract_signal_value(rx_frame.data.u8, 32, 32)); + } + if (rx_frame.data.u8[0] == 0x10) { // Mux 16: SUBCOMPONENT + PCS_info_cpu2AppCrc = static_cast(extract_signal_value(rx_frame.data.u8, 32, 32)); + } + if (rx_frame.data.u8[0] == 0x12) { // Mux 18: BOOTLOADER_GITHASH + PCS_info_bootGitHash = static_cast(extract_signal_value(rx_frame.data.u8, 10, 54)); + } + if (rx_frame.data.u8[0] == 0x14) { // Mux 20: UDS_PROTOCOL_BOOTCRC + PCS_info_bootUdsProtoVersion = static_cast(extract_signal_value(rx_frame.data.u8, 8, 8)); + PCS_info_bootCrc = static_cast(extract_signal_value(rx_frame.data.u8, 32, 32)); + } + */ + //PCS Part Number in ASCII + if (rx_frame.data.u8[0] == 0x19 && !parsed_PCS_partNumber) { // Part number 1-7 + PCS_partNumber[0] = rx_frame.data.u8[1]; + PCS_partNumber[1] = rx_frame.data.u8[2]; + PCS_partNumber[2] = rx_frame.data.u8[3]; + PCS_partNumber[3] = rx_frame.data.u8[4]; + PCS_partNumber[4] = rx_frame.data.u8[5]; + PCS_partNumber[5] = rx_frame.data.u8[6]; + PCS_partNumber[6] = rx_frame.data.u8[7]; + } + if (rx_frame.data.u8[0] == 0x1A && !parsed_PCS_partNumber) { // Part number 8-14 + PCS_partNumber[7] = rx_frame.data.u8[1]; + PCS_partNumber[8] = rx_frame.data.u8[2]; + PCS_partNumber[9] = rx_frame.data.u8[3]; + PCS_partNumber[10] = rx_frame.data.u8[4]; + PCS_partNumber[11] = rx_frame.data.u8[5]; + PCS_partNumber[12] = rx_frame.data.u8[6]; + } + if (PCS_partNumber[6] != 0 && PCS_partNumber[11] != 0) { + parsed_PCS_partNumber = true; + } + break; + case 0x310: //HVP_info + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + //Display internal HVP info and other build/version data + if (rx_frame.data.u8[0] == 0x0A) { // Mux 10: BUILD_HWID_COMPONENTID + if (HVP_info_buildConfigId == 0) { + HVP_info_buildConfigId = static_cast(extract_signal_value(rx_frame.data.u8, 16, 16)); + } + if (HVP_info_hardwareId == 0) { + HVP_info_hardwareId = static_cast(extract_signal_value(rx_frame.data.u8, 32, 16)); + } + if (HVP_info_componentId == 0) { + HVP_info_componentId = static_cast(extract_signal_value(rx_frame.data.u8, 48, 16)); + } + } + /* + if (rx_frame.data.u8[0] == 0x0B) { // Mux 11: PCBAID_ASSYID_USAGEID + if (HVP_info_pcbaId == 0) {HVP_info_pcbaId = static_cast(extract_signal_value(rx_frame.data.u8, 16, 8));} + if (HVP_info_assemblyId == 0) {HVP_info_assemblyId = static_cast(extract_signal_value(rx_frame.data.u8, 24, 8));} + if (HVP_info_usageId == 0) {HVP_info_usageId = static_cast(extract_signal_value(rx_frame.data.u8, 32, 16));} + if (HVP_info_subUsageId == 0) {HVP_info_subUsageId = static_cast(extract_signal_value(rx_frame.data.u8, 48, 16));} + } + if (rx_frame.data.u8[0] == 0x0D) { // Mux 13: APP_CRC + HVP_info_platformType = static_cast(extract_signal_value(rx_frame.data.u8, 8, 8)); + HVP_info_appCrc = static_cast(extract_signal_value(rx_frame.data.u8, 32, 32)); + } + if (rx_frame.data.u8[0] == 0x12) { // Mux 18: BOOTLOADER_GITHASH + HVP_info_bootGitHash = static_cast(extract_signal_value(rx_frame.data.u8, 10, 54)); + } + if (rx_frame.data.u8[0] == 0x14) { // Mux 20: UDS_PROTOCOL_BOOTCRC + HVP_info_bootUdsProtoVersion = static_cast(extract_signal_value(rx_frame.data.u8, 8, 8)); + HVP_info_bootCrc = static_cast(extract_signal_value(rx_frame.data.u8, 32, 32)); + } + */ + break; + case 0x612: // CAN UDSs for BMS + datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; + //BMS Query + if (stateMachineBMSQuery != 0xFF && stateMachineBMSReset == 0xFF) { + if (memcmp(rx_frame.data.u8, "\x02\x50\x03\xAA\xAA\xAA\xAA\xAA", 8) == 0) { + //Received initial response, proceed to actual query +#ifdef DEBUG_LOG + logging.println("CAN UDS: Received BMS query initial handshake reply"); +#endif //DEBUG_LOG + stateMachineBMSQuery = 1; + break; + } + if (memcmp(&rx_frame.data.u8[0], "\x10", 1) == 0) { + //Received first data frame + battery_partNumber[0] = rx_frame.data.u8[5]; + battery_partNumber[1] = rx_frame.data.u8[6]; + battery_partNumber[2] = rx_frame.data.u8[7]; +#ifdef DEBUG_LOG + logging.println("CAN UDS: Received BMS query data frame"); +#endif //DEBUG_LOG + stateMachineBMSQuery = 2; + break; + } + if (memcmp(&rx_frame.data.u8[0], "\x21", 1) == 0) { + //Second part of part number after flow control + battery_partNumber[3] = rx_frame.data.u8[1]; + battery_partNumber[4] = rx_frame.data.u8[2]; + battery_partNumber[5] = rx_frame.data.u8[3]; + battery_partNumber[6] = rx_frame.data.u8[4]; + battery_partNumber[7] = rx_frame.data.u8[5]; + battery_partNumber[8] = rx_frame.data.u8[6]; + battery_partNumber[9] = rx_frame.data.u8[7]; +#ifdef DEBUG_LOG + logging.println("CAN UDS: Received BMS query second data frame"); +#endif //DEBUG_LOG + break; + } + if (memcmp(&rx_frame.data.u8[0], "\x22", 1) == 0) { + //Final part of part number + battery_partNumber[10] = rx_frame.data.u8[1]; + battery_partNumber[11] = rx_frame.data.u8[2]; +#ifdef DEBUG_LOG + logging.println("CAN UDS: Received BMS query final data frame"); +#endif //DEBUG_LOG + break; + } + if (memcmp(rx_frame.data.u8, "\x23\x00\x00\x00\xAA\xAA\xAA\xAA", 8) == 0) { + //Received final frame +#ifdef DEBUG_LOG + logging.println("CAN UDS: Received BMS query termination frame"); +#endif //DEBUG_LOG + parsed_battery_partNumber = true; + stateMachineBMSQuery = 0xFF; + break; + } + } + //BMS Reset +#ifdef DEBUG_LOG + if (stateMachineBMSQuery == 0xFF) { // Make sure this is reset request not query + if (memcmp(rx_frame.data.u8, "\x02\x67\x06\xAA\xAA\xAA\xAA\xAA", 8) == 0) { + logging.println("CAN UDS: ECU unlocked"); + } else if (memcmp(rx_frame.data.u8, "\x03\x7F\x11\x78\xAA\xAA\xAA\xAA", 8) == 0) { + logging.println("CAN UDS: ECU reset request successful but ECU busy, response pending"); + } else if (memcmp(rx_frame.data.u8, "\x02\x51\x01\xAA\xAA\xAA\xAA\xAA", 8) == 0) { + logging.println("CAN UDS: ECU reset positive response, 1 second downtime"); + } + } +#endif //DEBUG_LOG break; default: break; @@ -1416,16 +1998,8 @@ int index_1CF = 0; int index_118 = 0; void TeslaBattery::transmit_can(unsigned long currentMillis) { - /*From bielec: My fist 221 message, to close the contactors is 0x41, 0x11, 0x01, 0x00, 0x00, 0x00, 0x20, 0x96 and then, -to cause "hv_up_for_drive" I send an additional 221 message 0x61, 0x15, 0x01, 0x00, 0x00, 0x00, 0x20, 0xBA so -two 221 messages are being continuously transmitted. When I want to shut down, I stop the second message and only send -the first, for a few cycles, then stop all messages which causes the contactor to open. */ - if (!cellvoltagesRead) { - return; //All cellvoltages not read yet, do not proceed with contactor closing - } - - if (operate_contactors) { + if (operate_contactors) { //Special S/X mode if ((datalayer.system.status.inverter_allows_contactor_closing) && (datalayer.battery.status.bms_status != FAULT)) { if (currentMillis - lastSend1CF >= 10) { transmit_can_frame(&can_msg_1CF[index_1CF], can_config.battery); @@ -1446,47 +2020,205 @@ the first, for a few cycles, then stop all messages which causes the contactor } } - //Send 10ms message + //Send 10ms messages if (currentMillis - previousMillis10 >= INTERVAL_10_MS) { previousMillis10 = currentMillis; - transmit_can_frame(&TESLA_129, can_config.battery); + //0x118 DI_systemStatus + transmit_can_frame(&TESLA_118, can_config.battery); + + //0x2E1 VCFRONT_status + switch (muxNumber_TESLA_2E1) { + case 0: + transmit_can_frame(&TESLA_2E1_VEHICLE_AND_RAILS, can_config.battery); + muxNumber_TESLA_2E1++; + break; + case 1: + transmit_can_frame(&TESLA_2E1_HOMELINK, can_config.battery); + muxNumber_TESLA_2E1++; + break; + case 2: + transmit_can_frame(&TESLA_2E1_REFRIGERANT_SYSTEM, can_config.battery); + muxNumber_TESLA_2E1++; + break; + case 3: + transmit_can_frame(&TESLA_2E1_LV_BATTERY_DEBUG, can_config.battery); + muxNumber_TESLA_2E1++; + break; + case 4: + transmit_can_frame(&TESLA_2E1_MUX_5, can_config.battery); + muxNumber_TESLA_2E1++; + break; + case 5: + transmit_can_frame(&TESLA_2E1_BODY_CONTROLS, can_config.battery); + muxNumber_TESLA_2E1 = 0; + break; + default: + break; + } + //Generate next frames + generateFrameCounterChecksum(TESLA_118, 8, 4, 0, 8); } - //Send 50ms message + //Send 50ms messages if (currentMillis - previousMillis50 >= INTERVAL_50_MS) { previousMillis50 = currentMillis; - if ((datalayer.system.status.inverter_allows_contactor_closing == true) && - (datalayer.battery.status.bms_status != FAULT)) { - sendContactorClosingMessagesStill = 300; - transmit_can_frame(&TESLA_221_1, can_config.battery); - transmit_can_frame(&TESLA_221_2, can_config.battery); - } else { // Faulted state, or inverter blocks contactor closing - if (sendContactorClosingMessagesStill > 0) { - transmit_can_frame(&TESLA_221_1, can_config.battery); - sendContactorClosingMessagesStill--; + //0x221 VCFRONT_LVPowerState + if (vehicleState == 1) { // Drive + switch (muxNumber_TESLA_221) { + case 0: + generateMuxFrameCounterChecksum(TESLA_221_DRIVE_Mux0, frameCounter_TESLA_221, 52, 4, 56, 8); + transmit_can_frame(&TESLA_221_DRIVE_Mux0, can_config.battery); + muxNumber_TESLA_221++; + break; + case 1: + generateMuxFrameCounterChecksum(TESLA_221_DRIVE_Mux1, frameCounter_TESLA_221, 52, 4, 56, 8); + transmit_can_frame(&TESLA_221_DRIVE_Mux1, can_config.battery); + muxNumber_TESLA_221 = 0; + break; + default: + break; } + //Generate next new frame + frameCounter_TESLA_221 = (frameCounter_TESLA_221 + 1) % 16; } + if (vehicleState == 2) { // Accessory + switch (muxNumber_TESLA_221) { + case 0: + generateMuxFrameCounterChecksum(TESLA_221_ACCESSORY_Mux0, frameCounter_TESLA_221, 52, 4, 56, 8); + transmit_can_frame(&TESLA_221_ACCESSORY_Mux0, can_config.battery); + muxNumber_TESLA_221++; + break; + case 1: + generateMuxFrameCounterChecksum(TESLA_221_ACCESSORY_Mux1, frameCounter_TESLA_221, 52, 4, 56, 8); + transmit_can_frame(&TESLA_221_ACCESSORY_Mux1, can_config.battery); + muxNumber_TESLA_221 = 0; + break; + default: + break; + } + //Generate next new frame + frameCounter_TESLA_221 = (frameCounter_TESLA_221 + 1) % 16; + } + if (vehicleState == 3) { // Going down + switch (muxNumber_TESLA_221) { + case 0: + generateMuxFrameCounterChecksum(TESLA_221_GOING_DOWN_Mux0, frameCounter_TESLA_221, 52, 4, 56, 8); + transmit_can_frame(&TESLA_221_GOING_DOWN_Mux0, can_config.battery); + muxNumber_TESLA_221++; + break; + case 1: + generateMuxFrameCounterChecksum(TESLA_221_GOING_DOWN_Mux1, frameCounter_TESLA_221, 52, 4, 56, 8); + transmit_can_frame(&TESLA_221_GOING_DOWN_Mux1, can_config.battery); + muxNumber_TESLA_221 = 0; + break; + default: + break; + } + //Generate next new frame + frameCounter_TESLA_221 = (frameCounter_TESLA_221 + 1) % 16; + } + if (vehicleState == 0) { // Off + switch (muxNumber_TESLA_221) { + case 0: + generateMuxFrameCounterChecksum(TESLA_221_OFF_Mux0, frameCounter_TESLA_221, 52, 4, 56, 8); + transmit_can_frame(&TESLA_221_OFF_Mux0, can_config.battery); + muxNumber_TESLA_221++; + break; + case 1: + generateMuxFrameCounterChecksum(TESLA_221_OFF_Mux1, frameCounter_TESLA_221, 52, 4, 56, 8); + transmit_can_frame(&TESLA_221_OFF_Mux1, can_config.battery); + muxNumber_TESLA_221 = 0; + break; + default: + break; + } + //Generate next new frame + frameCounter_TESLA_221 = (frameCounter_TESLA_221 + 1) % 16; + } + + //0x3C2 VCLEFT_switchStatus + switch (muxNumber_TESLA_3C2) { + case 0: + transmit_can_frame(&TESLA_3C2_Mux0, can_config.battery); + muxNumber_TESLA_3C2++; + break; + case 1: + transmit_can_frame(&TESLA_3C2_Mux1, can_config.battery); + muxNumber_TESLA_3C2 = 0; + break; + default: + break; + } + + //0x39D IBST_status + transmit_can_frame(&TESLA_39D, can_config.battery); + + if (battery_contactor == 4) { // Contactors closed + + // Frames to be sent only when contactors closed + + //0x3A1 VCFRONT_vehicleStatus, critical otherwise VCFRONT_MIA triggered + transmit_can_frame(&TESLA_3A1[frameCounter_TESLA_3A1], can_config.battery); + frameCounter_TESLA_3A1 = (frameCounter_TESLA_3A1 + 1) % 16; + } + + //Generate next frame + generateFrameCounterChecksum(TESLA_39D, 8, 4, 0, 8); } - //Send 100ms message + //Send 100ms messages if (currentMillis - previousMillis100 >= INTERVAL_100_MS) { previousMillis100 = currentMillis; - transmit_can_frame(&TESLA_129, can_config.battery); + //0x102 VCLEFT_doorStatus, static + transmit_can_frame(&TESLA_102, can_config.battery); + //0x103 VCRIGHT_doorStatus, static + transmit_can_frame(&TESLA_103, can_config.battery); + //0x229 SCCM_rightStalk + transmit_can_frame(&TESLA_229, can_config.battery); + //0x241 VCFRONT_coolant, static transmit_can_frame(&TESLA_241, can_config.battery); - transmit_can_frame(&TESLA_242, can_config.battery); - if (alternate243) { - transmit_can_frame(&TESLA_243_1, can_config.battery); - alternate243 = false; - } else { - transmit_can_frame(&TESLA_243_2, can_config.battery); - alternate243 = true; + //0x2D1 VCFRONT_okToUseHighPower, static + transmit_can_frame(&TESLA_2D1, can_config.battery); + //0x2A8 CMPD_state + transmit_can_frame(&TESLA_2A8, can_config.battery); + //0x2E8 EPBR_status + transmit_can_frame(&TESLA_2E8, can_config.battery); + //0x7FF GTW_carConfig + switch (muxNumber_TESLA_7FF) { + case 0: + transmit_can_frame(&TESLA_7FF_Mux1, can_config.battery); + muxNumber_TESLA_7FF++; + break; + case 1: + transmit_can_frame(&TESLA_7FF_Mux2, can_config.battery); + muxNumber_TESLA_7FF++; + break; + case 2: + transmit_can_frame(&TESLA_7FF_Mux3, can_config.battery); + muxNumber_TESLA_7FF++; + break; + case 3: + transmit_can_frame(&TESLA_7FF_Mux4, can_config.battery); + muxNumber_TESLA_7FF++; + break; + case 4: + transmit_can_frame(&TESLA_7FF_Mux5, can_config.battery); + muxNumber_TESLA_7FF = 0; + break; + default: + break; } + //Generate next frames + generateTESLA_229(TESLA_229); + generateFrameCounterChecksum(TESLA_2A8, 52, 4, 56, 8); + generateFrameCounterChecksum(TESLA_2E8, 52, 4, 56, 8); + if (stateMachineClearIsolationFault != 0xFF) { - //This implementation should be rewritten to actually replying to the UDS replied sent by the BMS + //This implementation should be rewritten to actually reply to the UDS responses sent by the BMS //While this may work, it is not the correct way to implement this clearing logic switch (stateMachineClearIsolationFault) { case 0: @@ -1527,59 +2259,133 @@ the first, for a few cycles, then stop all messages which causes the contactor stateMachineClearIsolationFault = 0xFF; break; } - if (stateMachineBMSReset != 0xFF) { - //This implementation should be rewritten to actually replying to the UDS replied sent by the BMS - //While this may work, it is not the correct way to implement this clearing logic - switch (stateMachineBMSReset) { - case 0: - TESLA_602.data = {0x02, 0x27, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00}; - transmit_can_frame(&TESLA_602, can_config.battery); - stateMachineBMSReset = 1; - break; - case 1: - TESLA_602.data = {0x30, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00}; - transmit_can_frame(&TESLA_602, can_config.battery); - stateMachineBMSReset = 2; - break; - case 2: - TESLA_602.data = {0x10, 0x12, 0x27, 0x06, 0x35, 0x34, 0x37, 0x36}; - transmit_can_frame(&TESLA_602, can_config.battery); - stateMachineBMSReset = 3; - break; - case 3: - TESLA_602.data = {0x21, 0x31, 0x30, 0x33, 0x32, 0x3D, 0x3C, 0x3F}; - transmit_can_frame(&TESLA_602, can_config.battery); - stateMachineBMSReset = 4; - break; - case 4: - TESLA_602.data = {0x22, 0x3E, 0x39, 0x38, 0x3B, 0x3A, 0x00, 0x00}; - transmit_can_frame(&TESLA_602, can_config.battery); - //Should generate a CAN UDS log message indicating ECU unlocked - stateMachineBMSReset = 5; - break; - case 5: - TESLA_602.data = {0x02, 0x10, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}; - transmit_can_frame(&TESLA_602, can_config.battery); - stateMachineBMSReset = 6; - break; - case 6: - TESLA_602.data = {0x02, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; - transmit_can_frame(&TESLA_602, can_config.battery); - stateMachineBMSReset = 7; - break; - case 7: - TESLA_602.data = {0x02, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; - transmit_can_frame(&TESLA_602, can_config.battery); - //Should generate a CAN UDS log message(s) indicating ECU has reset - stateMachineBMSReset = 0xFF; - break; - default: - //Something went wrong. Reset all and cancel - stateMachineBMSReset = 0xFF; - break; - } + } + if (stateMachineBMSReset != 0xFF) { + //This implementation should be rewritten to actually reply to the UDS responses sent by the BMS + //While this may work, it is not the correct way to implement this reset logic + switch (stateMachineBMSReset) { + case 0: + TESLA_602.data = {0x02, 0x27, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00}; + transmit_can_frame(&TESLA_602, can_config.battery); + stateMachineBMSReset = 1; + break; + case 1: + TESLA_602.data = {0x30, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00}; + transmit_can_frame(&TESLA_602, can_config.battery); + stateMachineBMSReset = 2; + break; + case 2: + TESLA_602.data = {0x10, 0x12, 0x27, 0x06, 0x35, 0x34, 0x37, 0x36}; + transmit_can_frame(&TESLA_602, can_config.battery); + stateMachineBMSReset = 3; + break; + case 3: + TESLA_602.data = {0x21, 0x31, 0x30, 0x33, 0x32, 0x3D, 0x3C, 0x3F}; + transmit_can_frame(&TESLA_602, can_config.battery); + stateMachineBMSReset = 4; + break; + case 4: + TESLA_602.data = {0x22, 0x3E, 0x39, 0x38, 0x3B, 0x3A, 0x00, 0x00}; + transmit_can_frame(&TESLA_602, can_config.battery); + //Should generate a CAN UDS log message indicating ECU unlocked + stateMachineBMSReset = 5; + break; + case 5: + TESLA_602.data = {0x02, 0x10, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}; + transmit_can_frame(&TESLA_602, can_config.battery); + stateMachineBMSReset = 6; + break; + case 6: + TESLA_602.data = {0x02, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; + transmit_can_frame(&TESLA_602, can_config.battery); + stateMachineBMSReset = 7; + break; + case 7: + TESLA_602.data = {0x02, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; + transmit_can_frame(&TESLA_602, can_config.battery); + //Should generate a CAN UDS log message(s) indicating ECU has reset + stateMachineBMSReset = 0xFF; + break; + default: + //Something went wrong. Reset all and cancel + stateMachineBMSReset = 0xFF; + break; } } + if (stateMachineBMSQuery != 0xFF) { + //This implementation should be rewritten to actually reply to the UDS responses sent by the BMS + //While this may work, it is not the correct way to implement this query logic + switch (stateMachineBMSQuery) { + case 0: + //Initial request +#ifdef DEBUG_LOG + logging.println("CAN UDS: Sending BMS query initial handshake"); +#endif //DEBUG_LOG + TESLA_602.data = {0x02, 0x10, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}; + transmit_can_frame(&TESLA_602, can_config.battery); + break; + case 1: + //Send query +#ifdef DEBUG_LOG + logging.println("CAN UDS: Sending BMS query for pack part number"); +#endif //DEBUG_LOG + TESLA_602.data = {0x03, 0x22, 0xF0, 0x14, 0x00, 0x00, 0x00, 0x00}; + transmit_can_frame(&TESLA_602, can_config.battery); + break; + case 2: + //Flow control +#ifdef DEBUG_LOG + logging.println("CAN UDS: Sending BMS query flow control"); +#endif //DEBUG_LOG + TESLA_602.data = {0x30, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00}; + transmit_can_frame(&TESLA_602, can_config.battery); + break; + case 3: + break; + case 4: + break; + default: + //Something went wrong. Reset all and cancel + stateMachineBMSQuery = 0xFF; + break; + } + } + } + + //Send 500ms messages + if (currentMillis - previousMillis500 >= INTERVAL_500_MS) { + previousMillis500 = currentMillis; + + transmit_can_frame(&TESLA_213, can_config.battery); + transmit_can_frame(&TESLA_284, can_config.battery); + transmit_can_frame(&TESLA_293, can_config.battery); + transmit_can_frame(&TESLA_313, can_config.battery); + transmit_can_frame(&TESLA_333, can_config.battery); + if (TESLA_334_INITIAL_SENT == false) { + transmit_can_frame(&TESLA_334_INITIAL, can_config.battery); + TESLA_334_INITIAL_SENT = true; + } else { + transmit_can_frame(&TESLA_334, can_config.battery); + } + transmit_can_frame(&TESLA_3B3, can_config.battery); + transmit_can_frame(&TESLA_55A, can_config.battery); + + //Generate next frames + generateTESLA_213(TESLA_213); + generateFrameCounterChecksum(TESLA_293, 52, 4, 56, 8); + generateFrameCounterChecksum(TESLA_313, 52, 4, 56, 8); + generateFrameCounterChecksum(TESLA_334, 52, 4, 56, 8); + } + + //Send 1000ms messages + if (currentMillis - previousMillis1000 >= INTERVAL_1_S) { + previousMillis1000 = currentMillis; + + transmit_can_frame(&TESLA_082, can_config.battery); + transmit_can_frame(&TESLA_321, can_config.battery); + + //Generate next frames + generateFrameCounterChecksum(TESLA_321, 52, 4, 56, 8); } } @@ -1590,18 +2396,18 @@ void printDebugIfActive(uint8_t symbol, const char* message) { } void TeslaBattery::printFaultCodesIfActive() { - if (battery_packCtrsClosingAllowed == 0) { - logging.println( - "ERROR: Check high voltage connectors and interlock circuit! Closing contactor not allowed! Values: "); + if (battery_packCtrsClosingBlocked && + battery_packContactorSetState != 5) { // Contactors blocked closing and not already closed + logging.println("ERROR: Check high voltage connectors and interlock circuit, closing contactors not allowed!"); } - if (battery_pyroTestInProgress == 1) { - logging.println("ERROR: Please wait for Pyro Connection check to finish, HV cables successfully seated!"); + if (battery_pyroTestInProgress) { + logging.println("ERROR: Please wait for pyro test to finish, HV cables successfully seated!"); } if (datalayer.system.status.inverter_allows_contactor_closing == false) { logging.println( "ERROR: Solar inverter does not allow for contactor closing. Check communication connection to the inverter " - "OR " - "disable the inverter protocol to proceed with contactor closing"); + "or " + "disable the inverter protocol to proceed in Tesla battery testing mode."); } // Check each symbol and print debug information if its value is 1 // 0X3AA: 938 HVP_alertMatrix1 @@ -1619,20 +2425,20 @@ void TeslaBattery::printFaultCodesIfActive() { printDebugIfActive(battery_OverVoltageFault, "ERROR: A brick voltage is above maximum voltage limit"); printDebugIfActive(battery_UnderVoltageFault, "ERROR: A brick voltage is below minimum voltage limit"); printDebugIfActive(battery_PrimaryBmbMiaFault, - "ERROR: voltage and temperature readings from primary BMB chain are mia"); + "ERROR: Voltage and temperature readings from primary BMB chain are mia"); printDebugIfActive(battery_SecondaryBmbMiaFault, - "ERROR: voltage and temperature readings from secondary BMB chain are mia"); + "ERROR: Voltage and temperature readings from secondary BMB chain are mia"); printDebugIfActive(battery_BmbMismatchFault, - "ERROR: primary and secondary BMB chain readings don't match with each other"); + "ERROR: Primary and secondary BMB chain readings don't match with each other"); printDebugIfActive(battery_BmsHviMiaFault, "ERROR: BMS node is mia on HVS or HVI CAN"); //printDebugIfActive(battery_CpMiaFault, "ERROR: CP node is mia on HVS CAN"); //Uncommented due to not affecting usage printDebugIfActive(battery_PcsMiaFault, "ERROR: PCS node is mia on HVS CAN"); //printDebugIfActive(battery_BmsFault, "ERROR: BmsFault is active"); //Uncommented due to not affecting usage printDebugIfActive(battery_PcsFault, "ERROR: PcsFault is active"); //printDebugIfActive(battery_CpFault, "ERROR: CpFault is active"); //Uncommented due to not affecting usage - printDebugIfActive(battery_ShuntHwMiaFault, "ERROR: shunt current reading is not available"); - printDebugIfActive(battery_PyroMiaFault, "ERROR: pyro squib is not connected"); - printDebugIfActive(battery_hvsMiaFault, "ERROR: pack contactor hw fault"); + printDebugIfActive(battery_ShuntHwMiaFault, "ERROR: Shunt current reading is not available"); + printDebugIfActive(battery_PyroMiaFault, "ERROR: Pyro squib is not connected"); + printDebugIfActive(battery_hvsMiaFault, "ERROR: Pack contactor hw fault"); printDebugIfActive(battery_hviMiaFault, "ERROR: FC contactor hw fault"); printDebugIfActive(battery_Supply12vFault, "ERROR: Low voltage (12V) battery is below minimum voltage threshold"); printDebugIfActive(battery_VerSupplyFault, "ERROR: Energy reserve voltage supply is below minimum voltage threshold"); @@ -1664,97 +2470,97 @@ void TeslaBattery::printFaultCodesIfActive() { printDebugIfActive(battery_fcCtrCloseFailed, "ERROR: fcCtrCloseFailed is active"); printDebugIfActive(battery_shuntThermistorMia, "ERROR: shuntThermistorMia is active"); // 0x320 800 BMS_alertMatrix - printDebugIfActive(battery_BMS_a017_SW_Brick_OV, "ERROR: BMS_a017_SW_Brick_OV"); - printDebugIfActive(battery_BMS_a018_SW_Brick_UV, "ERROR: BMS_a018_SW_Brick_UV"); - printDebugIfActive(battery_BMS_a019_SW_Module_OT, "ERROR: BMS_a019_SW_Module_OT"); - printDebugIfActive(battery_BMS_a021_SW_Dr_Limits_Regulation, "ERROR: BMS_a021_SW_Dr_Limits_Regulation"); - //printDebugIfActive(battery_BMS_a022_SW_Over_Current, "ERROR: BMS_a022_SW_Over_Current"); - printDebugIfActive(battery_BMS_a023_SW_Stack_OV, "ERROR: BMS_a023_SW_Stack_OV"); - printDebugIfActive(battery_BMS_a024_SW_Islanded_Brick, "ERROR: BMS_a024_SW_Islanded_Brick"); - printDebugIfActive(battery_BMS_a025_SW_PwrBalance_Anomaly, "ERROR: BMS_a025_SW_PwrBalance_Anomaly"); - printDebugIfActive(battery_BMS_a026_SW_HFCurrent_Anomaly, "ERROR: BMS_a026_SW_HFCurrent_Anomaly"); - printDebugIfActive(battery_BMS_a034_SW_Passive_Isolation, "ERROR: BMS_a034_SW_Passive_Isolation"); - printDebugIfActive(battery_BMS_a035_SW_Isolation, "ERROR: BMS_a035_SW_Isolation"); - printDebugIfActive(battery_BMS_a036_SW_HvpHvilFault, "ERROR: BMS_a036_SW_HvpHvilFault"); - printDebugIfActive(battery_BMS_a037_SW_Flood_Port_Open, "ERROR: BMS_a037_SW_Flood_Port_Open"); - printDebugIfActive(battery_BMS_a039_SW_DC_Link_Over_Voltage, "ERROR: BMS_a039_SW_DC_Link_Over_Voltage"); - printDebugIfActive(battery_BMS_a041_SW_Power_On_Reset, "ERROR: BMS_a041_SW_Power_On_Reset"); - printDebugIfActive(battery_BMS_a042_SW_MPU_Error, "ERROR: BMS_a042_SW_MPU_Error"); - printDebugIfActive(battery_BMS_a043_SW_Watch_Dog_Reset, "ERROR: BMS_a043_SW_Watch_Dog_Reset"); - printDebugIfActive(battery_BMS_a044_SW_Assertion, "ERROR: BMS_a044_SW_Assertion"); - printDebugIfActive(battery_BMS_a045_SW_Exception, "ERROR: BMS_a045_SW_Exception"); - printDebugIfActive(battery_BMS_a046_SW_Task_Stack_Usage, "ERROR: BMS_a046_SW_Task_Stack_Usage"); - printDebugIfActive(battery_BMS_a047_SW_Task_Stack_Overflow, "ERROR: BMS_a047_SW_Task_Stack_Overflow"); - printDebugIfActive(battery_BMS_a048_SW_Log_Upload_Request, "ERROR: BMS_a048_SW_Log_Upload_Request"); - //printDebugIfActive(battery_BMS_a050_SW_Brick_Voltage_MIA, "ERROR: BMS_a050_SW_Brick_Voltage_MIA"); - printDebugIfActive(battery_BMS_a051_SW_HVC_Vref_Bad, "ERROR: BMS_a051_SW_HVC_Vref_Bad"); - printDebugIfActive(battery_BMS_a052_SW_PCS_MIA, "ERROR: BMS_a052_SW_PCS_MIA"); - printDebugIfActive(battery_BMS_a053_SW_ThermalModel_Sanity, "ERROR: BMS_a053_SW_ThermalModel_Sanity"); - printDebugIfActive(battery_BMS_a054_SW_Ver_Supply_Fault, "ERROR: BMS_a054_SW_Ver_Supply_Fault"); - printDebugIfActive(battery_BMS_a059_SW_Pack_Voltage_Sensing, "ERROR: BMS_a059_SW_Pack_Voltage_Sensing"); - printDebugIfActive(battery_BMS_a060_SW_Leakage_Test_Failure, "ERROR: BMS_a060_SW_Leakage_Test_Failure"); - printDebugIfActive(battery_BMS_a061_robinBrickOverVoltage, "ERROR: BMS_a061_robinBrickOverVoltage"); - printDebugIfActive(battery_BMS_a062_SW_BrickV_Imbalance, "ERROR: BMS_a062_SW_BrickV_Imbalance"); - printDebugIfActive(battery_BMS_a063_SW_ChargePort_Fault, "ERROR: BMS_a063_SW_ChargePort_Fault"); - printDebugIfActive(battery_BMS_a064_SW_SOC_Imbalance, "ERROR: BMS_a064_SW_SOC_Imbalance"); - printDebugIfActive(battery_BMS_a069_SW_Low_Power, "ERROR: BMS_a069_SW_Low_Power"); - printDebugIfActive(battery_BMS_a071_SW_SM_TransCon_Not_Met, "ERROR: BMS_a071_SW_SM_TransCon_Not_Met"); - printDebugIfActive(battery_BMS_a075_SW_Chg_Disable_Failure, "ERROR: BMS_a075_SW_Chg_Disable_Failure"); - printDebugIfActive(battery_BMS_a076_SW_Dch_While_Charging, "ERROR: BMS_a076_SW_Dch_While_Charging"); - printDebugIfActive(battery_BMS_a077_SW_Charger_Regulation, "ERROR: BMS_a077_SW_Charger_Regulation"); - printDebugIfActive(battery_BMS_a081_SW_Ctr_Close_Blocked, "ERROR: BMS_a081_SW_Ctr_Close_Blocked"); - printDebugIfActive(battery_BMS_a082_SW_Ctr_Force_Open, "ERROR: BMS_a082_SW_Ctr_Force_Open"); - printDebugIfActive(battery_BMS_a083_SW_Ctr_Close_Failure, "ERROR: BMS_a083_SW_Ctr_Close_Failure"); - printDebugIfActive(battery_BMS_a084_SW_Sleep_Wake_Aborted, "ERROR: BMS_a084_SW_Sleep_Wake_Aborted"); - printDebugIfActive(battery_BMS_a087_SW_Feim_Test_Blocked, "ERROR: BMS_a087_SW_Feim_Test_Blocked"); - printDebugIfActive(battery_BMS_a088_SW_VcFront_MIA_InDrive, "ERROR: BMS_a088_SW_VcFront_MIA_InDrive"); - printDebugIfActive(battery_BMS_a089_SW_VcFront_MIA, "ERROR: BMS_a089_SW_VcFront_MIA"); - //printDebugIfActive(battery_BMS_a090_SW_Gateway_MIA, "ERROR: BMS_a090_SW_Gateway_MIA"); - //printDebugIfActive(battery_BMS_a091_SW_ChargePort_MIA, "ERROR: BMS_a091_SW_ChargePort_MIA"); - //printDebugIfActive(battery_BMS_a092_SW_ChargePort_Mia_On_Hv, "ERROR: BMS_a092_SW_ChargePort_Mia_On_Hv"); - //printDebugIfActive(battery_BMS_a094_SW_Drive_Inverter_MIA, "ERROR: BMS_a094_SW_Drive_Inverter_MIA"); - printDebugIfActive(battery_BMS_a099_SW_BMB_Communication, "ERROR: BMS_a099_SW_BMB_Communication"); - printDebugIfActive(battery_BMS_a105_SW_One_Module_Tsense, "ERROR: BMS_a105_SW_One_Module_Tsense"); - printDebugIfActive(battery_BMS_a106_SW_All_Module_Tsense, "ERROR: BMS_a106_SW_All_Module_Tsense"); - printDebugIfActive(battery_BMS_a107_SW_Stack_Voltage_MIA, "ERROR: BMS_a107_SW_Stack_Voltage_MIA"); - printDebugIfActive(battery_BMS_a121_SW_NVRAM_Config_Error, "ERROR: BMS_a121_SW_NVRAM_Config_Error"); - printDebugIfActive(battery_BMS_a122_SW_BMS_Therm_Irrational, "ERROR: BMS_a122_SW_BMS_Therm_Irrational"); - printDebugIfActive(battery_BMS_a123_SW_Internal_Isolation, "ERROR: BMS_a123_SW_Internal_Isolation"); - printDebugIfActive(battery_BMS_a127_SW_shunt_SNA, "ERROR: BMS_a127_SW_shunt_SNA"); - printDebugIfActive(battery_BMS_a128_SW_shunt_MIA, "ERROR: BMS_a128_SW_shunt_MIA"); - printDebugIfActive(battery_BMS_a129_SW_VSH_Failure, "ERROR: BMS_a129_SW_VSH_Failure"); - printDebugIfActive(battery_BMS_a130_IO_CAN_Error, "ERROR: BMS_a130_IO_CAN_Error"); - printDebugIfActive(battery_BMS_a131_Bleed_FET_Failure, "ERROR: BMS_a131_Bleed_FET_Failure"); - printDebugIfActive(battery_BMS_a132_HW_BMB_OTP_Uncorrctbl, "ERROR: BMS_a132_HW_BMB_OTP_Uncorrctbl"); - printDebugIfActive(battery_BMS_a134_SW_Delayed_Ctr_Off, "ERROR: BMS_a134_SW_Delayed_Ctr_Off"); - printDebugIfActive(battery_BMS_a136_SW_Module_OT_Warning, "ERROR: BMS_a136_SW_Module_OT_Warning"); - printDebugIfActive(battery_BMS_a137_SW_Brick_UV_Warning, "ERROR: BMS_a137_SW_Brick_UV_Warning"); - printDebugIfActive(battery_BMS_a139_SW_DC_Link_V_Irrational, "ERROR: BMS_a139_SW_DC_Link_V_Irrational"); - printDebugIfActive(battery_BMS_a141_SW_BMB_Status_Warning, "ERROR: BMS_a141_SW_BMB_Status_Warning"); - printDebugIfActive(battery_BMS_a144_Hvp_Config_Mismatch, "ERROR: BMS_a144_Hvp_Config_Mismatch"); - printDebugIfActive(battery_BMS_a145_SW_SOC_Change, "ERROR: BMS_a145_SW_SOC_Change"); - printDebugIfActive(battery_BMS_a146_SW_Brick_Overdischarged, "ERROR: BMS_a146_SW_Brick_Overdischarged"); - printDebugIfActive(battery_BMS_a149_SW_Missing_Config_Block, "ERROR: BMS_a149_SW_Missing_Config_Block"); - printDebugIfActive(battery_BMS_a151_SW_external_isolation, "ERROR: BMS_a151_SW_external_isolation"); - printDebugIfActive(battery_BMS_a156_SW_BMB_Vref_bad, "ERROR: BMS_a156_SW_BMB_Vref_bad"); - printDebugIfActive(battery_BMS_a157_SW_HVP_HVS_Comms, "ERROR: BMS_a157_SW_HVP_HVS_Comms"); - printDebugIfActive(battery_BMS_a158_SW_HVP_HVI_Comms, "ERROR: BMS_a158_SW_HVP_HVI_Comms"); - printDebugIfActive(battery_BMS_a159_SW_HVP_ECU_Error, "ERROR: BMS_a159_SW_HVP_ECU_Error"); - printDebugIfActive(battery_BMS_a161_SW_DI_Open_Request, "ERROR: BMS_a161_SW_DI_Open_Request"); - printDebugIfActive(battery_BMS_a162_SW_No_Power_For_Support, "ERROR: BMS_a162_SW_No_Power_For_Support"); - printDebugIfActive(battery_BMS_a163_SW_Contactor_Mismatch, "ERROR: BMS_a163_SW_Contactor_Mismatch"); - printDebugIfActive(battery_BMS_a164_SW_Uncontrolled_Regen, "ERROR: BMS_a164_SW_Uncontrolled_Regen"); - printDebugIfActive(battery_BMS_a165_SW_Pack_Partial_Weld, "ERROR: BMS_a165_SW_Pack_Partial_Weld"); - printDebugIfActive(battery_BMS_a166_SW_Pack_Full_Weld, "ERROR: BMS_a166_SW_Pack_Full_Weld"); - printDebugIfActive(battery_BMS_a167_SW_FC_Partial_Weld, "ERROR: BMS_a167_SW_FC_Partial_Weld"); - printDebugIfActive(battery_BMS_a168_SW_FC_Full_Weld, "ERROR: BMS_a168_SW_FC_Full_Weld"); - printDebugIfActive(battery_BMS_a169_SW_FC_Pack_Weld, "ERROR: BMS_a169_SW_FC_Pack_Weld"); - //printDebugIfActive(battery_BMS_a170_SW_Limp_Mode, "ERROR: BMS_a170_SW_Limp_Mode"); - printDebugIfActive(battery_BMS_a171_SW_Stack_Voltage_Sense, "ERROR: BMS_a171_SW_Stack_Voltage_Sense"); - printDebugIfActive(battery_BMS_a174_SW_Charge_Failure, "ERROR: BMS_a174_SW_Charge_Failure"); - printDebugIfActive(battery_BMS_a176_SW_GracefulPowerOff, "ERROR: BMS_a176_SW_GracefulPowerOff"); - printDebugIfActive(battery_BMS_a179_SW_Hvp_12V_Fault, "ERROR: BMS_a179_SW_Hvp_12V_Fault"); - printDebugIfActive(battery_BMS_a180_SW_ECU_reset_blocked, "ERROR: BMS_a180_SW_ECU_reset_blocked"); + printDebugIfActive(BMS_a017_SW_Brick_OV, "ERROR: BMS_a017_SW_Brick_OV"); + printDebugIfActive(BMS_a018_SW_Brick_UV, "ERROR: BMS_a018_SW_Brick_UV"); + printDebugIfActive(BMS_a019_SW_Module_OT, "ERROR: BMS_a019_SW_Module_OT"); + printDebugIfActive(BMS_a021_SW_Dr_Limits_Regulation, "ERROR: BMS_a021_SW_Dr_Limits_Regulation"); + //printDebugIfActive(BMS_a022_SW_Over_Current, "ERROR: BMS_a022_SW_Over_Current"); + printDebugIfActive(BMS_a023_SW_Stack_OV, "ERROR: BMS_a023_SW_Stack_OV"); + printDebugIfActive(BMS_a024_SW_Islanded_Brick, "ERROR: BMS_a024_SW_Islanded_Brick"); + printDebugIfActive(BMS_a025_SW_PwrBalance_Anomaly, "ERROR: BMS_a025_SW_PwrBalance_Anomaly"); + printDebugIfActive(BMS_a026_SW_HFCurrent_Anomaly, "ERROR: BMS_a026_SW_HFCurrent_Anomaly"); + printDebugIfActive(BMS_a034_SW_Passive_Isolation, "ERROR: BMS_a034_SW_Passive_Isolation"); + printDebugIfActive(BMS_a035_SW_Isolation, "ERROR: BMS_a035_SW_Isolation"); + printDebugIfActive(BMS_a036_SW_HvpHvilFault, "ERROR: BMS_a036_SW_HvpHvilFault"); + printDebugIfActive(BMS_a037_SW_Flood_Port_Open, "ERROR: BMS_a037_SW_Flood_Port_Open"); + printDebugIfActive(BMS_a039_SW_DC_Link_Over_Voltage, "ERROR: BMS_a039_SW_DC_Link_Over_Voltage"); + printDebugIfActive(BMS_a041_SW_Power_On_Reset, "ERROR: BMS_a041_SW_Power_On_Reset"); + printDebugIfActive(BMS_a042_SW_MPU_Error, "ERROR: BMS_a042_SW_MPU_Error"); + printDebugIfActive(BMS_a043_SW_Watch_Dog_Reset, "ERROR: BMS_a043_SW_Watch_Dog_Reset"); + printDebugIfActive(BMS_a044_SW_Assertion, "ERROR: BMS_a044_SW_Assertion"); + printDebugIfActive(BMS_a045_SW_Exception, "ERROR: BMS_a045_SW_Exception"); + printDebugIfActive(BMS_a046_SW_Task_Stack_Usage, "ERROR: BMS_a046_SW_Task_Stack_Usage"); + printDebugIfActive(BMS_a047_SW_Task_Stack_Overflow, "ERROR: BMS_a047_SW_Task_Stack_Overflow"); + printDebugIfActive(BMS_a048_SW_Log_Upload_Request, "ERROR: BMS_a048_SW_Log_Upload_Request"); + //printDebugIfActive(BMS_a050_SW_Brick_Voltage_MIA, "ERROR: BMS_a050_SW_Brick_Voltage_MIA"); + printDebugIfActive(BMS_a051_SW_HVC_Vref_Bad, "ERROR: BMS_a051_SW_HVC_Vref_Bad"); + printDebugIfActive(BMS_a052_SW_PCS_MIA, "ERROR: BMS_a052_SW_PCS_MIA"); + printDebugIfActive(BMS_a053_SW_ThermalModel_Sanity, "ERROR: BMS_a053_SW_ThermalModel_Sanity"); + printDebugIfActive(BMS_a054_SW_Ver_Supply_Fault, "ERROR: BMS_a054_SW_Ver_Supply_Fault"); + printDebugIfActive(BMS_a059_SW_Pack_Voltage_Sensing, "ERROR: BMS_a059_SW_Pack_Voltage_Sensing"); + printDebugIfActive(BMS_a060_SW_Leakage_Test_Failure, "ERROR: BMS_a060_SW_Leakage_Test_Failure"); + printDebugIfActive(BMS_a061_robinBrickOverVoltage, "ERROR: BMS_a061_robinBrickOverVoltage"); + printDebugIfActive(BMS_a062_SW_BrickV_Imbalance, "ERROR: BMS_a062_SW_BrickV_Imbalance"); + //printDebugIfActive(BMS_a063_SW_ChargePort_Fault, "ERROR: BMS_a063_SW_ChargePort_Fault"); + printDebugIfActive(BMS_a064_SW_SOC_Imbalance, "ERROR: BMS_a064_SW_SOC_Imbalance"); + printDebugIfActive(BMS_a069_SW_Low_Power, "ERROR: BMS_a069_SW_Low_Power"); + printDebugIfActive(BMS_a071_SW_SM_TransCon_Not_Met, "ERROR: BMS_a071_SW_SM_TransCon_Not_Met"); + printDebugIfActive(BMS_a075_SW_Chg_Disable_Failure, "ERROR: BMS_a075_SW_Chg_Disable_Failure"); + printDebugIfActive(BMS_a076_SW_Dch_While_Charging, "ERROR: BMS_a076_SW_Dch_While_Charging"); + printDebugIfActive(BMS_a077_SW_Charger_Regulation, "ERROR: BMS_a077_SW_Charger_Regulation"); + printDebugIfActive(BMS_a081_SW_Ctr_Close_Blocked, "ERROR: BMS_a081_SW_Ctr_Close_Blocked"); + printDebugIfActive(BMS_a082_SW_Ctr_Force_Open, "ERROR: BMS_a082_SW_Ctr_Force_Open"); + printDebugIfActive(BMS_a083_SW_Ctr_Close_Failure, "ERROR: BMS_a083_SW_Ctr_Close_Failure"); + printDebugIfActive(BMS_a084_SW_Sleep_Wake_Aborted, "ERROR: BMS_a084_SW_Sleep_Wake_Aborted"); + printDebugIfActive(BMS_a087_SW_Feim_Test_Blocked, "ERROR: BMS_a087_SW_Feim_Test_Blocked"); + printDebugIfActive(BMS_a088_SW_VcFront_MIA_InDrive, "ERROR: BMS_a088_SW_VcFront_MIA_InDrive"); + printDebugIfActive(BMS_a089_SW_VcFront_MIA, "ERROR: BMS_a089_SW_VcFront_MIA"); + printDebugIfActive(BMS_a090_SW_Gateway_MIA, "ERROR: BMS_a090_SW_Gateway_MIA"); + //printDebugIfActive(BMS_a091_SW_ChargePort_MIA, "ERROR: BMS_a091_SW_ChargePort_MIA"); + //printDebugIfActive(BMS_a092_SW_ChargePort_Mia_On_Hv, "ERROR: BMS_a092_SW_ChargePort_Mia_On_Hv"); + //printDebugIfActive(BMS_a094_SW_Drive_Inverter_MIA, "ERROR: BMS_a094_SW_Drive_Inverter_MIA"); + printDebugIfActive(BMS_a099_SW_BMB_Communication, "ERROR: BMS_a099_SW_BMB_Communication"); + printDebugIfActive(BMS_a105_SW_One_Module_Tsense, "ERROR: BMS_a105_SW_One_Module_Tsense"); + printDebugIfActive(BMS_a106_SW_All_Module_Tsense, "ERROR: BMS_a106_SW_All_Module_Tsense"); + printDebugIfActive(BMS_a107_SW_Stack_Voltage_MIA, "ERROR: BMS_a107_SW_Stack_Voltage_MIA"); + printDebugIfActive(BMS_a121_SW_NVRAM_Config_Error, "ERROR: BMS_a121_SW_NVRAM_Config_Error"); + printDebugIfActive(BMS_a122_SW_BMS_Therm_Irrational, "ERROR: BMS_a122_SW_BMS_Therm_Irrational"); + printDebugIfActive(BMS_a123_SW_Internal_Isolation, "ERROR: BMS_a123_SW_Internal_Isolation"); + printDebugIfActive(BMS_a127_SW_shunt_SNA, "ERROR: BMS_a127_SW_shunt_SNA"); + printDebugIfActive(BMS_a128_SW_shunt_MIA, "ERROR: BMS_a128_SW_shunt_MIA"); + printDebugIfActive(BMS_a129_SW_VSH_Failure, "ERROR: BMS_a129_SW_VSH_Failure"); + printDebugIfActive(BMS_a130_IO_CAN_Error, "ERROR: BMS_a130_IO_CAN_Error"); + printDebugIfActive(BMS_a131_Bleed_FET_Failure, "ERROR: BMS_a131_Bleed_FET_Failure"); + printDebugIfActive(BMS_a132_HW_BMB_OTP_Uncorrctbl, "ERROR: BMS_a132_HW_BMB_OTP_Uncorrctbl"); + printDebugIfActive(BMS_a134_SW_Delayed_Ctr_Off, "ERROR: BMS_a134_SW_Delayed_Ctr_Off"); + printDebugIfActive(BMS_a136_SW_Module_OT_Warning, "ERROR: BMS_a136_SW_Module_OT_Warning"); + printDebugIfActive(BMS_a137_SW_Brick_UV_Warning, "ERROR: BMS_a137_SW_Brick_UV_Warning"); + printDebugIfActive(BMS_a139_SW_DC_Link_V_Irrational, "ERROR: BMS_a139_SW_DC_Link_V_Irrational"); + printDebugIfActive(BMS_a141_SW_BMB_Status_Warning, "ERROR: BMS_a141_SW_BMB_Status_Warning"); + printDebugIfActive(BMS_a144_Hvp_Config_Mismatch, "ERROR: BMS_a144_Hvp_Config_Mismatch"); + printDebugIfActive(BMS_a145_SW_SOC_Change, "ERROR: BMS_a145_SW_SOC_Change"); + printDebugIfActive(BMS_a146_SW_Brick_Overdischarged, "ERROR: BMS_a146_SW_Brick_Overdischarged"); + printDebugIfActive(BMS_a149_SW_Missing_Config_Block, "ERROR: BMS_a149_SW_Missing_Config_Block"); + printDebugIfActive(BMS_a151_SW_external_isolation, "ERROR: BMS_a151_SW_external_isolation"); + printDebugIfActive(BMS_a156_SW_BMB_Vref_bad, "ERROR: BMS_a156_SW_BMB_Vref_bad"); + printDebugIfActive(BMS_a157_SW_HVP_HVS_Comms, "ERROR: BMS_a157_SW_HVP_HVS_Comms"); + printDebugIfActive(BMS_a158_SW_HVP_HVI_Comms, "ERROR: BMS_a158_SW_HVP_HVI_Comms"); + printDebugIfActive(BMS_a159_SW_HVP_ECU_Error, "ERROR: BMS_a159_SW_HVP_ECU_Error"); + printDebugIfActive(BMS_a161_SW_DI_Open_Request, "ERROR: BMS_a161_SW_DI_Open_Request"); + printDebugIfActive(BMS_a162_SW_No_Power_For_Support, "ERROR: BMS_a162_SW_No_Power_For_Support"); + printDebugIfActive(BMS_a163_SW_Contactor_Mismatch, "ERROR: BMS_a163_SW_Contactor_Mismatch"); + printDebugIfActive(BMS_a164_SW_Uncontrolled_Regen, "ERROR: BMS_a164_SW_Uncontrolled_Regen"); + printDebugIfActive(BMS_a165_SW_Pack_Partial_Weld, "ERROR: BMS_a165_SW_Pack_Partial_Weld"); + printDebugIfActive(BMS_a166_SW_Pack_Full_Weld, "ERROR: BMS_a166_SW_Pack_Full_Weld"); + printDebugIfActive(BMS_a167_SW_FC_Partial_Weld, "ERROR: BMS_a167_SW_FC_Partial_Weld"); + printDebugIfActive(BMS_a168_SW_FC_Full_Weld, "ERROR: BMS_a168_SW_FC_Full_Weld"); + printDebugIfActive(BMS_a169_SW_FC_Pack_Weld, "ERROR: BMS_a169_SW_FC_Pack_Weld"); + //printDebugIfActive(BMS_a170_SW_Limp_Mode, "ERROR: BMS_a170_SW_Limp_Mode"); + printDebugIfActive(BMS_a171_SW_Stack_Voltage_Sense, "ERROR: BMS_a171_SW_Stack_Voltage_Sense"); + printDebugIfActive(BMS_a174_SW_Charge_Failure, "ERROR: BMS_a174_SW_Charge_Failure"); + printDebugIfActive(BMS_a176_SW_GracefulPowerOff, "ERROR: BMS_a176_SW_GracefulPowerOff"); + printDebugIfActive(BMS_a179_SW_Hvp_12V_Fault, "ERROR: BMS_a179_SW_Hvp_12V_Fault"); + printDebugIfActive(BMS_a180_SW_ECU_reset_blocked, "ERROR: BMS_a180_SW_ECU_reset_blocked"); } void TeslaModel3YBattery::setup(void) { // Performs one time setup at startup @@ -1763,6 +2569,15 @@ void TeslaModel3YBattery::setup(void) { // Performs one time setup at startup *allows_contactor_closing = true; } + //0x7FF GTW CAN frame values + //Mux1 + write_signal_value(&TESLA_7FF_Mux1, 16, 16, GTW_country, false); + write_signal_value(&TESLA_7FF_Mux1, 11, 1, GTW_rightHandDrive, false); + //Mux3 + write_signal_value(&TESLA_7FF_Mux3, 8, 4, GTW_mapRegion, false); + write_signal_value(&TESLA_7FF_Mux3, 18, 3, GTW_chassisType, false); + write_signal_value(&TESLA_7FF_Mux3, 32, 5, GTW_packEnergy, false); + strncpy(datalayer.system.info.battery_protocol, Name, 63); datalayer.system.info.battery_protocol[63] = '\0'; diff --git a/Software/src/battery/TESLA-BATTERY.h b/Software/src/battery/TESLA-BATTERY.h index ca5dacfa..16282357 100644 --- a/Software/src/battery/TESLA-BATTERY.h +++ b/Software/src/battery/TESLA-BATTERY.h @@ -12,6 +12,11 @@ #define SELECTED_BATTERY_CLASS TeslaModelSXBattery #endif +/*NOTE! IMPORTANT INFORMATION! +Be sure to scroll down in this file and configure all "GTW_" parameters to suit your battery. +Failure to configure these will result in VCFRONT and GTW MIA errors +*/ + //#define EXP_TESLA_BMS_DIGITAL_HVIL // Experimental parameter. Forces the transmission of additional CAN frames for experimental purposes, to test potential HVIL issues in 3/Y packs with newer firmware. class TeslaBattery : public CanBattery { @@ -43,7 +48,25 @@ class TeslaBattery : public CanBattery { static const int MAXDISCHARGEPOWERALLOWED = 60000; // 60000W we use a define since the value supplied by Tesla is always 0 - /* Do not change the defines below */ + // Set this to true to try to close contactors/full startup even with no inverter defined/connected + bool batteryTestOverride = false; + + // 0x7FF gateway config, "Gen3" vehicles only, not applicable to Gen2 "classic" Model S and Model X + // + // ** MANUALLY SET FOR NOW **, TODO: change based on USER_SETTINGS.h or preset + // + static const uint16_t GTW_country = + 18242; // "US" (USA): 21843, "CA" (Canada): 17217, "GB" (UK & N Ireland): 18242, "DK" (Denmark): 17483, "DE" (Germany): 17477, "AU" (Australia): 16725 [HVP shows errors if EU/US region mismatch for example] + // GTW_country is ISO 3166-1 Alpha-2 code, each letter converted to binary (8-bit chunks), those 8-bit chunks concatenated and then converted to decimal + static const uint8_t GTW_rightHandDrive = + 1; // Left: 0, Right: 1 (not sure this matters but there for consistency in emulating the car - make sure correct for GTW_country, e.g. 0 for USA) + static const uint8_t GTW_mapRegion = + 1; // "ME": 8, "NONE": 2, "CN": 3, "TW": 6, "JP": 5, "US": 0, "KR": 7, "AU": 4, "EU": 1 (not sure this matters but there for consistency) + static const uint8_t GTW_chassisType = + 2; // "MODEL_3_CHASSIS": 2, "MODEL_Y_CHASSIS": 3 ("MODEL_S_CHASSIS": 0, "MODEL_X_CHASSIS": 1) + static const uint8_t GTW_packEnergy = 1; // "PACK_50_KWH": 0, "PACK_74_KWH": 1, "PACK_62_KWH": 2, "PACK_100_KWH": 3 + + /* Do not change anything below this line! */ static const int RAMPDOWN_SOC = 900; // 90.0 SOC% to start ramping down from max charge power towards 0 at 100.00% static const int RAMPDOWNPOWERALLOWED = 10000; // What power we ramp down from towards top balancing static const int FLOAT_MAX_POWER_W = 200; // W, what power to allow for top balancing battery @@ -75,53 +98,391 @@ class TeslaBattery : public CanBattery { unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was sent unsigned long previousMillis500 = 0; // will store last time a 500ms CAN Message was sent unsigned long previousMillis1000 = 0; // will store last time a 1000ms CAN Message was sent - bool alternate243 = false; - //0x221 545 VCFRONT_LVPowerState: "GenMsgCycleTime" 50ms - CAN_frame TESLA_221_1 = { - .FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x221, - .data = {0x41, 0x11, 0x01, 0x00, 0x00, 0x00, 0x20, 0x96}}; //Contactor frame 221 - close contactors - CAN_frame TESLA_221_2 = { - .FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x221, - .data = {0x61, 0x15, 0x01, 0x00, 0x00, 0x00, 0x20, 0xBA}}; //Contactor Frame 221 - hv_up_for_drive - //0x241 VCFRONT_coolant 100ms + + //UDS session tracker + //static bool uds_SessionInProgress = false; // Future use + //0x221 VCFRONT_LVPowerState + uint8_t muxNumber_TESLA_221 = 0; + uint8_t frameCounter_TESLA_221 = 15; // Start at 15 for Mux 0 + uint8_t vehicleState = 1; // "OFF": 0, "DRIVE": 1, "ACCESSORY": 2, "GOING_DOWN": 3 + uint16_t powerDownTimer = 180; // Car power down (i.e. contactor open) tracking timer, 3 seconds per sendingState + //0x2E1 VCFRONT_status, 6 mux tracker + uint8_t muxNumber_TESLA_2E1 = 0; + //0x334 UI + bool TESLA_334_INITIAL_SENT = false; + //0x3A1 VCFRONT_vehicleStatus, 15 frame counter (temporary) + uint8_t frameCounter_TESLA_3A1 = 0; + //0x3C2 VCLEFT_switchStatus + uint8_t muxNumber_TESLA_3C2 = 0; + //0x504 TWC_status + bool TESLA_504_INITIAL_SENT = false; + //0x7FF GTW_carConfig, 5 mux tracker + uint8_t muxNumber_TESLA_7FF = 0; + //Max percentage charge tracker + uint16_t previous_max_percentage = datalayer.battery.settings.max_percentage; + + //0x082 UI_tripPlanning: "cycle_time" 1000ms + CAN_frame TESLA_082 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x082, + .data = {0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80}}; + + //0x102 VCLEFT_doorStatus: "cycle_time" 100ms + CAN_frame TESLA_102 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x102, + .data = {0x22, 0x33, 0x00, 0x00, 0xC0, 0x38, 0x21, 0x08}}; + + //0x103 VCRIGHT_doorStatus: "cycle_time" 100ms + CAN_frame TESLA_103 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x103, + .data = {0x22, 0x33, 0x00, 0x00, 0x30, 0xF2, 0x20, 0x02}}; + + //0x118 DI_systemStatus: "cycle_time" 50ms, DI_systemStatusChecksum/DI_systemStatusCounter generated via generateFrameCounterChecksum + CAN_frame TESLA_118 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x118, + .data = {0xAB, 0x60, 0x2A, 0x00, 0x00, 0x08, 0x00, 0x00}}; + + //0x2A8 CMPD_state: "cycle_time" 100ms, different depending on firmware, semi-manual increment for now + CAN_frame TESLA_2A8 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x2A8, + .data = {0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x2C}}; + + //0x213 UI_cruiseControl: "cycle_time" 500ms, UI_speedLimitTick/UI_cruiseControlCounter - different depending on firmware, semi-manual increment for now + CAN_frame TESLA_213 = {.FD = false, .ext_ID = false, .DLC = 2, .ID = 0x213, .data = {0x00, 0x15}}; + + //0x221 These frames will/should eventually be migrated to 2 base frames (1 per mux), and then just the relevant bits changed + + //0x221 VCFRONT_LVPowerState "Drive" + //VCFRONT_vehiclePowerState VEHICLE_POWER_STATE_DRIVE (Mux0, Counter 15): "cycle_time" 50ms each mux/LVPowerStateIndex, VCFRONT_LVPowerStateChecksum/VCFRONT_LVPowerStateCounter generated via generateMuxFrameCounterChecksum + CAN_frame TESLA_221_DRIVE_Mux0 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x221, + .data = {0x60, 0x55, 0x55, 0x15, 0x54, 0x51, 0xF1, 0xD8}}; + + //0x221 VCFRONT_LVPowerState "Drive" + //VCFRONT_vehiclePowerState VEHICLE_POWER_STATE_DRIVE (Mux1, Counter 0): "cycle_time" 50ms each mux/LVPowerStateIndex, VCFRONT_LVPowerStateChecksum/VCFRONT_LVPowerStateCounter generated via generateMuxFrameCounterChecksum + CAN_frame TESLA_221_DRIVE_Mux1 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x221, + .data = {0x61, 0x05, 0x55, 0x05, 0x00, 0x00, 0x00, 0xE3}}; + + //0x221 VCFRONT_LVPowerState "Accessory" + //VCFRONT_vehiclePowerState VEHICLE_POWER_STATE_ACCESSORY (Mux0, Counter 15): "cycle_time" 50ms each mux/LVPowerStateIndex, VCFRONT_LVPowerStateChecksum/VCFRONT_LVPowerStateCounter generated via generateMuxFrameCounterChecksum + CAN_frame TESLA_221_ACCESSORY_Mux0 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x221, + .data = {0x40, 0x55, 0x55, 0x05, 0x54, 0x51, 0xF5, 0xAC}}; + + //0x221 VCFRONT_LVPowerState "Accessory" + //VCFRONT_vehiclePowerState VEHICLE_POWER_STATE_ACCESSORY (Mux1, Counter 0): "cycle_time" 50ms each mux/LVPowerStateIndex, VCFRONT_LVPowerStateChecksum/VCFRONT_LVPowerStateCounter generated via generateMuxFrameCounterChecksum + CAN_frame TESLA_221_ACCESSORY_Mux1 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x221, + .data = {0x41, 0x05, 0x55, 0x55, 0x01, 0x00, 0x04, 0x18}}; + + //0x221 VCFRONT_LVPowerState "Going Down" + //VCFRONT_vehiclePowerState VEHICLE_POWER_STATE_OFF, key parts GOING_DOWN (Mux0, Counter 15): "cycle_time" 50ms each mux/LVPowerStateIndex, VCFRONT_LVPowerStateChecksum/VCFRONT_LVPowerStateCounter generated via generateMuxFrameCounterChecksum + CAN_frame TESLA_221_GOING_DOWN_Mux0 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x221, + .data = {0x00, 0x89, 0x55, 0x06, 0xA4, 0x51, 0xF1, 0xED}}; + + //0x221 VCFRONT_LVPowerState "Going Down" + //VCFRONT_vehiclePowerState VEHICLE_POWER_STATE_OFF, key parts GOING_DOWN (Mux1, Counter 0): "cycle_time" 50ms each mux/LVPowerStateIndex, VCFRONT_LVPowerStateChecksum/VCFRONT_LVPowerStateCounter generated via generateMuxFrameCounterChecksum + CAN_frame TESLA_221_GOING_DOWN_Mux1 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x221, + .data = {0x01, 0x09, 0x55, 0x59, 0x00, 0x00, 0x00, 0xDB}}; + + //0x221 VCFRONT_LVPowerState "Off" + //VCFRONT_vehiclePowerState VEHICLE_POWER_STATE_OFF, key parts OFF (Mux0, Counter 15): "cycle_time" 50ms each mux/LVPowerStateIndex, VCFRONT_LVPowerStateChecksum/VCFRONT_LVPowerStateCounter generated via generateMuxFrameCounterChecksum + CAN_frame TESLA_221_OFF_Mux0 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x221, + .data = {0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0xF1, 0x65}}; + + //0x221 VCFRONT_LVPowerState "Off" + //VCFRONT_vehiclePowerState VEHICLE_POWER_STATE_OFF, key parts OFF (Mux1, Counter 0): "cycle_time" 50ms each mux/LVPowerStateIndex, VCFRONT_LVPowerStateChecksum/VCFRONT_LVPowerStateCounter generated via generateMuxFrameCounterChecksum + CAN_frame TESLA_221_OFF_Mux1 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x221, + .data = {0x01, 0x01, 0x01, 0x50, 0x00, 0x00, 0x00, 0x76}}; + + //0x229 SCCM_rightStalk: "cycle_time" 100ms, SCCM_rightStalkChecksum/SCCM_rightStalkCounter generated via dedicated generateTESLA_229 function for now + //CRC seemingly related to AUTOSAR ID array... "autosarDataIds": [124,182,240,47,105,163,221,28,86,144,202,9,67,125,183,241] found in Model 3 firmware + CAN_frame TESLA_229 = {.FD = false, .ext_ID = false, .DLC = 3, .ID = 0x229, .data = {0x46, 0x00, 0x00}}; + + //0x241 VCFRONT_coolant: "cycle_time" 100ms CAN_frame TESLA_241 = {.FD = false, .ext_ID = false, .DLC = 7, .ID = 0x241, - .data = {0x3C, 0x78, 0x2C, 0x0F, 0x1E, 0x5B, 0x00}}; - //0x242 VCLEFT_LVPowerState 100ms - CAN_frame TESLA_242 = {.FD = false, .ext_ID = false, .DLC = 2, .ID = 0x242, .data = {0x10, 0x95}}; - //0x243 VCRIGHT_hvacStatus 50ms - CAN_frame TESLA_243_1 = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x243, - .data = {0xC9, 0x00, 0xEB, 0xD4, 0x31, 0x32, 0x02, 0x00}}; - CAN_frame TESLA_243_2 = {.FD = false, - .ext_ID = false, - .DLC = 8, - .ID = 0x243, - .data = {0x08, 0x81, 0x42, 0x60, 0x92, 0x2C, 0x0E, 0x09}}; - //0x129 SteeringAngle 10ms - CAN_frame TESLA_129 = {.FD = false, + .data = {0x35, 0x34, 0x0C, 0x0F, 0x8F, 0x55, 0x00}}; + + //0x2D1 VCFRONT_okToUseHighPower: "cycle_time" 100ms + CAN_frame TESLA_2D1 = {.FD = false, .ext_ID = false, .DLC = 2, .ID = 0x2D1, .data = {0xFF, 0x01}}; + + //0x2E1, 6 muxes + //0x2E1 VCFRONT_status: "cycle_time" 10ms each mux/statusIndex + CAN_frame TESLA_2E1_VEHICLE_AND_RAILS = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x2E1, + .data = {0x29, 0x0A, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x00}}; + + //{0x29, 0x0A, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x00} INIT + //{0x29, 0x0A, 0x0D, 0xFF, 0x0F, 0x00, 0x00, 0x00} DRIVE + //{0x29, 0x0A, 0x09, 0xFF, 0x0F, 0x00, 0x00, 0x00} HV_UP_STANDBY + //{0x29, 0x0A, 0x0A, 0xFF, 0x0F, 0x00, 0x00, 0x00} ACCESSORY + //{0x29, 0x0A, 0x06, 0xFF, 0x0F, 0x00, 0x00, 0x00} SLEEP_STANDBY + + //0x2E1 VCFRONT_status: "cycle_time" 10ms each mux/statusIndex + CAN_frame TESLA_2E1_HOMELINK = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x2E1, + .data = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00}}; + + //0x2E1 VCFRONT_status: "cycle_time" 10ms each mux/statusIndex + CAN_frame TESLA_2E1_REFRIGERANT_SYSTEM = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x2E1, + .data = {0x03, 0x6D, 0x99, 0x02, 0x1B, 0x57, 0x00, 0x00}}; + + //0x2E1 VCFRONT_status: "cycle_time" 10ms each mux/statusIndex + CAN_frame TESLA_2E1_LV_BATTERY_DEBUG = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x2E1, + .data = {0xFC, 0x1B, 0xD1, 0x99, 0x9A, 0xD8, 0x09, 0x00}}; + + //0x2E1 VCFRONT_status: "cycle_time" 10ms each mux/statusIndex + CAN_frame TESLA_2E1_MUX_5 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x2E1, + .data = {0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + + //0x2E1 VCFRONT_status: "cycle_time" 10ms each mux/statusIndex + CAN_frame TESLA_2E1_BODY_CONTROLS = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x2E1, + .data = {0x08, 0x21, 0x04, 0x6E, 0xA0, 0x88, 0x06, 0x04}}; + + //0x2E8 EPBR_status: "cycle_time" 100ms + CAN_frame TESLA_2E8 = {.FD = false, .ext_ID = false, .DLC = 8, - .ID = 0x129, - .data = {0x21, 0x24, 0x36, 0x5F, 0x00, 0x20, 0xFF, 0x3F}}; - //0x612 UDS diagnostic requests - on demand + .ID = 0x2E8, + .data = {0x02, 0x00, 0x10, 0x00, 0x00, 0x80, 0x00, 0x6C}}; + + //0x284 UI_vehicleModes: "cycle_time" 500ms + CAN_frame TESLA_284 = {.FD = false, .ext_ID = false, .DLC = 5, .ID = 0x284, .data = {0x10, 0x00, 0x00, 0x00, 0x00}}; + + //0x293 UI_chassisControl: "cycle_time" 500ms, UI_chassisControlChecksum/UI_chassisControlCounter generated via generateFrameCounterChecksum + CAN_frame TESLA_293 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x293, + .data = {0x01, 0x0C, 0x55, 0x91, 0x55, 0x15, 0x01, 0xF3}}; + + //0x3A1 VCFRONT_vehicleStatus: "cycle_time" 50ms, VCFRONT_vehicleStatusChecksum/VCFRONT_vehicleStatusCounter eventually need to be generated via generateMuxFrameCounterChecksum + //Looks like 2 muxes, counter at bit 52 width 4 and checksum at bit 56 width 8? Need later software Model3_ETH.compact.json signal file or DBC. + //Migrated to an array until figured out + CAN_frame TESLA_3A1[16] = { + {.FD = false, .ext_ID = false, .DLC = 8, .ID = 0x3A1, .data = {0xC3, 0xFF, 0xFF, 0xFF, 0x3D, 0x00, 0xD0, 0x01}}, + {.FD = false, .ext_ID = false, .DLC = 8, .ID = 0x3A1, .data = {0x08, 0x62, 0x0B, 0x18, 0x00, 0x28, 0xE2, 0xCB}}, + {.FD = false, .ext_ID = false, .DLC = 8, .ID = 0x3A1, .data = {0xC3, 0xFF, 0xFF, 0xFF, 0x3D, 0x00, 0xF0, 0x21}}, + {.FD = false, .ext_ID = false, .DLC = 8, .ID = 0x3A1, .data = {0x08, 0x62, 0x0B, 0x18, 0x00, 0x28, 0x02, 0xEB}}, + {.FD = false, .ext_ID = false, .DLC = 8, .ID = 0x3A1, .data = {0xC3, 0xFF, 0xFF, 0xFF, 0x3D, 0x00, 0x10, 0x41}}, + {.FD = false, .ext_ID = false, .DLC = 8, .ID = 0x3A1, .data = {0x08, 0x62, 0x0B, 0x18, 0x00, 0x28, 0x22, 0x0B}}, + {.FD = false, .ext_ID = false, .DLC = 8, .ID = 0x3A1, .data = {0xC3, 0xFF, 0xFF, 0xFF, 0x3D, 0x00, 0x30, 0x61}}, + {.FD = false, .ext_ID = false, .DLC = 8, .ID = 0x3A1, .data = {0x08, 0x62, 0x0B, 0x18, 0x00, 0x28, 0x42, 0x2B}}, + {.FD = false, .ext_ID = false, .DLC = 8, .ID = 0x3A1, .data = {0xC3, 0xFF, 0xFF, 0xFF, 0x3D, 0x00, 0x50, 0x81}}, + {.FD = false, .ext_ID = false, .DLC = 8, .ID = 0x3A1, .data = {0x08, 0x62, 0x0B, 0x18, 0x00, 0x28, 0x62, 0x4B}}, + {.FD = false, .ext_ID = false, .DLC = 8, .ID = 0x3A1, .data = {0xC3, 0xFF, 0xFF, 0xFF, 0x3D, 0x00, 0x70, 0xA1}}, + {.FD = false, .ext_ID = false, .DLC = 8, .ID = 0x3A1, .data = {0x08, 0x62, 0x0B, 0x18, 0x00, 0x28, 0x82, 0x6B}}, + {.FD = false, .ext_ID = false, .DLC = 8, .ID = 0x3A1, .data = {0xC3, 0xFF, 0xFF, 0xFF, 0x3D, 0x00, 0x90, 0xC1}}, + {.FD = false, .ext_ID = false, .DLC = 8, .ID = 0x3A1, .data = {0x08, 0x62, 0x0B, 0x18, 0x00, 0x28, 0xA2, 0x8B}}, + {.FD = false, .ext_ID = false, .DLC = 8, .ID = 0x3A1, .data = {0xC3, 0xFF, 0xFF, 0xFF, 0x3D, 0x00, 0xB0, 0xE1}}, + {.FD = false, .ext_ID = false, .DLC = 8, .ID = 0x3A1, .data = {0x08, 0x62, 0x0B, 0x18, 0x00, 0x28, 0xC2, 0xAB}}}; + + //0x313 UI_powertrainControl: "cycle_time" 500ms, UI_powertrainControlChecksum/UI_powertrainControlCounter generated via generateFrameCounterChecksum + CAN_frame TESLA_313 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x313, + .data = {0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x1B}}; + + //0x321 VCFRONT_sensors: "cycle_time" 1000ms + CAN_frame TESLA_321 = { + .FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x321, + .data = {0xEC, 0x71, 0xA7, 0x6E, 0x02, 0x6C, 0x00, 0x04}}; // Last 2 bytes are counter and checksum + + //0x333 UI_chargeRequest: "cycle_time" 500ms, UI_chargeTerminationPct value = 900 [bit 16, width 10, scale 0.1, min 25, max 100] + CAN_frame TESLA_333 = {.FD = false, .ext_ID = false, .DLC = 5, .ID = 0x333, .data = {0x84, 0x30, 0x84, 0x07, 0x02}}; + + //0x334 UI request: "cycle_time" 500ms, initial frame car sends + CAN_frame TESLA_334_INITIAL = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x334, + .data = {0x3F, 0x3F, 0xC8, 0x00, 0xE2, 0x3F, 0x80, 0x1E}}; + + //0x334 UI request: "cycle_time" 500ms, generated via generateFrameCounterChecksum + CAN_frame TESLA_334 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x334, + .data = {0x3F, 0x3F, 0x00, 0x0F, 0xE2, 0x3F, 0x90, 0x75}}; + + //0x3B3 UI_vehicleControl2: "cycle_time" 500ms + CAN_frame TESLA_3B3 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x3B3, + .data = {0x90, 0x80, 0x05, 0x08, 0x00, 0x00, 0x00, 0x01}}; + + //0x39D IBST_status: "cycle_time" 50ms, IBST_statusChecksum/IBST_statusCounter generated via generateFrameCounterChecksum + CAN_frame TESLA_39D = {.FD = false, .ext_ID = false, .DLC = 5, .ID = 0x39D, .data = {0xE1, 0x59, 0xC1, 0x27, 0x00}}; + + //0x3C2 VCLEFT_switchStatus (Mux0, initial frame car sends): "cycle_time" 50ms, sent once + CAN_frame TESLA_3C2_INITIAL = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x3C2, + .data = {0x00, 0x55, 0x55, 0x55, 0x00, 0x00, 0x5A, 0x05}}; + + //0x3C2 VCLEFT_switchStatus (Mux0): "cycle_time" 50ms each mux/SwitchStatusIndex + CAN_frame TESLA_3C2_Mux0 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x3C2, + .data = {0x00, 0x55, 0x55, 0x55, 0x00, 0x00, 0x5A, 0x45}}; + + //0x3C2 VCLEFT_switchStatus (Mux1): "cycle_time" 50ms each mux/SwitchStatusIndex + CAN_frame TESLA_3C2_Mux1 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x3C2, + .data = {0x29, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + + //0x504 Initially sent + CAN_frame TESLA_504_INITIAL = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x504, + .data = {0x00, 0x1B, 0x06, 0x03, 0x00, 0x01, 0x00, 0x01}}; + + //0x55A Unknown but always sent: "cycle_time" 500ms + CAN_frame TESLA_55A = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x55A, + .data = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + + //0x7FF GTW_carConfig: "cycle_time" 100ms each mux/carConfigMultiplexer (UK/RHD) + CAN_frame TESLA_7FF_Mux1 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x7FF, + .data = {0x01, 0x49, 0x42, 0x47, 0x00, 0x03, 0x15, 0x01}}; + + //0x7FF GTW_carConfig: "cycle_time" 100ms each mux/carConfigMultiplexer + CAN_frame TESLA_7FF_Mux2 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x7FF, + .data = {0x02, 0x66, 0x32, 0x24, 0x04, 0x49, 0x95, 0x82}}; + + //0x7FF GTW_carConfig: "cycle_time" 100ms each mux/carConfigMultiplexer (EU/Long Range) + CAN_frame TESLA_7FF_Mux3 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x7FF, + .data = {0x03, 0x01, 0x08, 0x48, 0x01, 0x00, 0x00, 0x12}}; + + //0x7FF GTW_carConfig: "cycle_time" 100ms each mux/carConfigMultiplexer + CAN_frame TESLA_7FF_Mux4 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x7FF, + .data = {0x04, 0x73, 0x03, 0x67, 0x5C, 0x00, 0x00, 0x00}}; + + //0x7FF GTW_carConfig: "cycle_time" 100ms each mux/carConfigMultiplexer + CAN_frame TESLA_7FF_Mux5 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x7FF, + .data = {0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}}; + + //0x7FF GTW_carConfig: "cycle_time" 100ms each mux/carConfigMultiplexer - later firmware has muxes 6 & 7, needed? + CAN_frame TESLA_7FF_Mux6 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x7FF, + .data = {0x06, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0xD0}}; + + //0x7FF GTW_carConfig: "cycle_time" 100ms each mux/carConfigMultiplexer - later firmware has muxes 6 & 7, needed? + CAN_frame TESLA_7FF_Mux7 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x7FF, + .data = {0x07, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00}}; + + //0x722 BMS_bmbKeepAlive: "cycle_time" 100ms, should only be sent when testing packs or diagnosing problems + CAN_frame TESLA_722 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x722, + .data = {0x02, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}}; + + //0x25D CP_status: "cycle_time" 100ms, stops some cpMia errors, but not necessary for standalone pack operation so not used/necessary. Note CP_type for different regions, the below has "IEC_CCS" + CAN_frame TESLA_25D = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x25D, + .data = {0x37, 0x41, 0x01, 0x16, 0x08, 0x00, 0x00, 0x00}}; + + //0x602 BMS UDS diagnostic request: on demand CAN_frame TESLA_602 = {.FD = false, .ext_ID = false, .DLC = 8, .ID = 0x602, - .data = {0x02, 0x27, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00}}; + .data = {0x02, 0x27, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00}}; // Define initial UDS request + + //0x610 BMS Query UDS request: on demand + CAN_frame TESLA_610 = {.FD = false, + .ext_ID = false, + .DLC = 8, + .ID = 0x610, + .data = {0x02, 0x10, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}}; // Define initial UDS request + uint8_t stateMachineClearIsolationFault = 0xFF; uint8_t stateMachineBMSReset = 0xFF; + uint8_t stateMachineBMSQuery = 0xFF; uint16_t sendContactorClosingMessagesStill = 300; uint16_t battery_cell_max_v = 3300; uint16_t battery_cell_min_v = 3300; @@ -162,8 +523,8 @@ class TeslaBattery : public CanBattery { //0x2d2: 722 BMSVAlimits uint16_t battery_max_discharge_current = 0; uint16_t battery_max_charge_current = 0; - uint16_t battery_bms_max_voltage = 0; - uint16_t battery_bms_min_voltage = 0; + uint16_t BMS_max_voltage = 0; + uint16_t BMS_min_voltage = 0; //0x2b4: 692 PCS_dcdcRailStatus uint16_t battery_dcdcHvBusVolt = 0; // Change name from battery_high_voltage to battery_dcdcHvBusVolt uint16_t battery_dcdcLvBusVolt = 0; // Change name from battery_low_voltage to battery_dcdcLvBusVolt @@ -198,7 +559,7 @@ class TeslaBattery : public CanBattery { uint8_t battery_packContNegativeState = 0; uint8_t battery_packContPositiveState = 0; uint8_t battery_packContactorSetState = 0; - bool battery_packCtrsClosingAllowed = false; // Change to bool + bool battery_packCtrsClosingBlocked = false; // Change to bool bool battery_pyroTestInProgress = false; // Change to bool bool battery_packCtrsOpenNowRequested = false; // Change to bool bool battery_packCtrsOpenRequested = false; // Change to bool @@ -216,48 +577,69 @@ class TeslaBattery : public CanBattery { uint8_t battery_fcCtrsRequestStatus = 0; bool battery_fcCtrsResetRequestRequired = false; // Change to bool bool battery_fcLinkAllowedToEnergize = false; // Change to bool - //0x72A: BMS_serialNumber - uint8_t BMS_SerialNumber[14] = {0}; // Stores raw HEX values for ASCII chars + //0x72A: BMS_serialNumber + uint8_t battery_serialNumber[14] = {0}; // Stores raw HEX values for ASCII chars + bool parsed_battery_serialNumber = false; + char* battery_manufactureDate; // YYYY-MM-DD\0 + //Via UDS + uint8_t battery_partNumber[12] = {0}; //stores raw HEX values for ASCII chars + bool parsed_battery_partNumber = false; + //Via UDS + //static uint8_t BMS_partNumber[12] = {0}; //stores raw HEX values for ASCII chars + //static bool parsed_BMS_partNumber = false; + //0x300: BMS_info + uint16_t BMS_info_buildConfigId = 0; + uint16_t BMS_info_hardwareId = 0; + uint16_t BMS_info_componentId = 0; + uint8_t BMS_info_pcbaId = 0; + uint8_t BMS_info_assemblyId = 0; + uint16_t BMS_info_usageId = 0; + uint16_t BMS_info_subUsageId = 0; + uint8_t BMS_info_platformType = 0; + uint32_t BMS_info_appCrc = 0; + uint64_t BMS_info_bootGitHash = 0; + uint8_t BMS_info_bootUdsProtoVersion = 0; + uint32_t BMS_info_bootCrc = 0; //0x212: 530 BMS_status - bool battery_BMS_hvacPowerRequest = false; //Change to bool - bool battery_BMS_notEnoughPowerForDrive = false; //Change to bool - bool battery_BMS_notEnoughPowerForSupport = false; //Change to bool - bool battery_BMS_preconditionAllowed = false; //Change to bool - bool battery_BMS_updateAllowed = false; //Change to bool - bool battery_BMS_activeHeatingWorthwhile = false; //Change to bool - bool battery_BMS_cpMiaOnHvs = false; //Change to bool - uint8_t battery_BMS_contactorState = 0; - uint8_t battery_BMS_state = 0; - uint8_t battery_BMS_hvState = 0; - uint16_t battery_BMS_isolationResistance = 0; - bool battery_BMS_chargeRequest = false; //Change to bool - bool battery_BMS_keepWarmRequest = false; //Change to bool - uint8_t battery_BMS_uiChargeStatus = 0; - bool battery_BMS_diLimpRequest = false; //Change to bool - bool battery_BMS_okToShipByAir = false; //Change to bool - bool battery_BMS_okToShipByLand = false; //Change to bool - uint32_t battery_BMS_chgPowerAvailable = 0; - uint8_t battery_BMS_chargeRetryCount = 0; - bool battery_BMS_pcsPwmEnabled = false; //Change to bool - bool battery_BMS_ecuLogUploadRequest = false; //Change to bool - uint8_t battery_BMS_minPackTemperature = 0; + bool BMS_hvacPowerRequest = false; //Change to bool + bool BMS_notEnoughPowerForDrive = false; //Change to bool + bool BMS_notEnoughPowerForSupport = false; //Change to bool + bool BMS_preconditionAllowed = false; //Change to bool + bool BMS_updateAllowed = false; //Change to bool + bool BMS_activeHeatingWorthwhile = false; //Change to bool + bool BMS_cpMiaOnHvs = false; //Change to bool + uint8_t BMS_contactorState = 0; + uint8_t BMS_state = 0; + uint8_t BMS_hvState = 0; + uint16_t BMS_isolationResistance = 0; + bool BMS_chargeRequest = false; //Change to bool + bool BMS_keepWarmRequest = false; //Change to bool + uint8_t BMS_uiChargeStatus = 0; + bool BMS_diLimpRequest = false; //Change to bool + bool BMS_okToShipByAir = false; //Change to bool + bool BMS_okToShipByLand = false; //Change to bool + uint32_t BMS_chgPowerAvailable = 0; + uint8_t BMS_chargeRetryCount = 0; + bool BMS_pcsPwmEnabled = false; //Change to bool + bool BMS_ecuLogUploadRequest = false; //Change to bool + uint8_t BMS_minPackTemperature = 0; // 0x224:548 PCS_dcdcStatus - uint8_t battery_PCS_dcdcPrechargeStatus = 0; - uint8_t battery_PCS_dcdc12VSupportStatus = 0; - uint8_t battery_PCS_dcdcHvBusDischargeStatus = 0; - uint16_t battery_PCS_dcdcMainState = 0; - uint8_t battery_PCS_dcdcSubState = 0; - bool battery_PCS_dcdcFaulted = false; //Change to bool - bool battery_PCS_dcdcOutputIsLimited = false; //Change to bool - uint32_t battery_PCS_dcdcMaxOutputCurrentAllowed = 0; - uint8_t battery_PCS_dcdcPrechargeRtyCnt = 0; - uint8_t battery_PCS_dcdc12VSupportRtyCnt = 0; - uint8_t battery_PCS_dcdcDischargeRtyCnt = 0; - uint8_t battery_PCS_dcdcPwmEnableLine = 0; - uint8_t battery_PCS_dcdcSupportingFixedLvTarget = 0; - uint8_t battery_PCS_ecuLogUploadRequest = 0; - uint8_t battery_PCS_dcdcPrechargeRestartCnt = 0; - uint8_t battery_PCS_dcdcInitialPrechargeSubState = 0; + uint8_t PCS_dcdcPrechargeStatus = 0; + uint8_t PCS_dcdc12VSupportStatus = 0; + uint8_t PCS_dcdcHvBusDischargeStatus = 0; + uint16_t PCS_dcdcMainState = 0; + uint8_t PCS_dcdcSubState = 0; + bool PCS_dcdcFaulted = false; //Change to bool + bool PCS_dcdcOutputIsLimited = false; //Change to bool + uint32_t PCS_dcdcMaxOutputCurrentAllowed = 0; + uint8_t PCS_dcdcPrechargeRtyCnt = 0; + uint8_t PCS_dcdc12VSupportRtyCnt = 0; + uint8_t PCS_dcdcDischargeRtyCnt = 0; + uint8_t PCS_dcdcPwmEnableLine = 0; + uint8_t PCS_dcdcSupportingFixedLvTarget = 0; + uint8_t PCS_ecuLogUploadRequest = 0; + uint8_t PCS_dcdcPrechargeRestartCnt = 0; + uint8_t PCS_dcdcInitialPrechargeSubState = 0; //0x312: 786 BMS_thermalStatus uint16_t BMS_powerDissipation = 0; uint16_t BMS_flowRequest = 0; @@ -268,6 +650,22 @@ class TeslaBattery : public CanBattery { uint16_t BMS_packTMax = 0; bool BMS_pcsNoFlowRequest = false; bool BMS_noFlowRequest = false; + //0x3C4: PCS_info + uint8_t PCS_partNumber[12] = {0}; //stores raw HEX values for ASCII chars + bool parsed_PCS_partNumber = false; + uint16_t PCS_info_buildConfigId = 0; + uint16_t PCS_info_hardwareId = 0; + uint16_t PCS_info_componentId = 0; + uint8_t PCS_info_pcbaId = 0; + uint8_t PCS_info_assemblyId = 0; + uint16_t PCS_info_usageId = 0; + uint16_t PCS_info_subUsageId = 0; + uint8_t PCS_info_platformType = 0; + uint32_t PCS_info_appCrc = 0; + uint32_t PCS_info_cpu2AppCrc = 0; + uint64_t PCS_info_bootGitHash = 0; + uint8_t PCS_info_bootUdsProtoVersion = 0; + uint32_t PCS_info_bootCrc = 0; //0x2A4; 676 PCS_thermalStatus int16_t PCS_chgPhATemp = 0; int16_t PCS_chgPhBTemp = 0; @@ -330,6 +728,18 @@ class TeslaBattery : public CanBattery { bool HVP_shuntRefVoltageMismatch = false; //Change to bool bool HVP_shuntThermistorMia = false; //Change to bool bool HVP_shuntHwMia = false; //Change to bool + uint16_t HVP_info_buildConfigId = 0; + uint16_t HVP_info_hardwareId = 0; + uint16_t HVP_info_componentId = 0; + uint8_t HVP_info_pcbaId = 0; + uint8_t HVP_info_assemblyId = 0; + uint16_t HVP_info_usageId = 0; + uint16_t HVP_info_subUsageId = 0; + uint8_t HVP_info_platformType = 0; + uint32_t HVP_info_appCrc = 0; + uint64_t HVP_info_bootGitHash = 0; + uint8_t HVP_info_bootUdsProtoVersion = 0; + uint32_t HVP_info_bootCrc = 0; int16_t HVP_dcLinkVoltage = 0; int16_t HVP_packVoltage = 0; int16_t HVP_fcLinkVoltage = 0; @@ -411,99 +821,99 @@ class TeslaBattery : public CanBattery { bool battery_fcCtrCloseFailed = false; bool battery_shuntThermistorMia = false; //0x320: 800 BMS_alertMatrix - uint8_t battery_BMS_matrixIndex = 0; // Changed to bool - bool battery_BMS_a061_robinBrickOverVoltage = false; - bool battery_BMS_a062_SW_BrickV_Imbalance = false; - bool battery_BMS_a063_SW_ChargePort_Fault = false; - bool battery_BMS_a064_SW_SOC_Imbalance = false; - bool battery_BMS_a127_SW_shunt_SNA = false; - bool battery_BMS_a128_SW_shunt_MIA = false; - bool battery_BMS_a069_SW_Low_Power = false; - bool battery_BMS_a130_IO_CAN_Error = false; - bool battery_BMS_a071_SW_SM_TransCon_Not_Met = false; - bool battery_BMS_a132_HW_BMB_OTP_Uncorrctbl = false; - bool battery_BMS_a134_SW_Delayed_Ctr_Off = false; - bool battery_BMS_a075_SW_Chg_Disable_Failure = false; - bool battery_BMS_a076_SW_Dch_While_Charging = false; - bool battery_BMS_a017_SW_Brick_OV = false; - bool battery_BMS_a018_SW_Brick_UV = false; - bool battery_BMS_a019_SW_Module_OT = false; - bool battery_BMS_a021_SW_Dr_Limits_Regulation = false; - bool battery_BMS_a022_SW_Over_Current = false; - bool battery_BMS_a023_SW_Stack_OV = false; - bool battery_BMS_a024_SW_Islanded_Brick = false; - bool battery_BMS_a025_SW_PwrBalance_Anomaly = false; - bool battery_BMS_a026_SW_HFCurrent_Anomaly = false; - bool battery_BMS_a087_SW_Feim_Test_Blocked = false; - bool battery_BMS_a088_SW_VcFront_MIA_InDrive = false; - bool battery_BMS_a089_SW_VcFront_MIA = false; - bool battery_BMS_a090_SW_Gateway_MIA = false; - bool battery_BMS_a091_SW_ChargePort_MIA = false; - bool battery_BMS_a092_SW_ChargePort_Mia_On_Hv = false; - bool battery_BMS_a034_SW_Passive_Isolation = false; - bool battery_BMS_a035_SW_Isolation = false; - bool battery_BMS_a036_SW_HvpHvilFault = false; - bool battery_BMS_a037_SW_Flood_Port_Open = false; - bool battery_BMS_a158_SW_HVP_HVI_Comms = false; - bool battery_BMS_a039_SW_DC_Link_Over_Voltage = false; - bool battery_BMS_a041_SW_Power_On_Reset = false; - bool battery_BMS_a042_SW_MPU_Error = false; - bool battery_BMS_a043_SW_Watch_Dog_Reset = false; - bool battery_BMS_a044_SW_Assertion = false; - bool battery_BMS_a045_SW_Exception = false; - bool battery_BMS_a046_SW_Task_Stack_Usage = false; - bool battery_BMS_a047_SW_Task_Stack_Overflow = false; - bool battery_BMS_a048_SW_Log_Upload_Request = false; - bool battery_BMS_a169_SW_FC_Pack_Weld = false; - bool battery_BMS_a050_SW_Brick_Voltage_MIA = false; - bool battery_BMS_a051_SW_HVC_Vref_Bad = false; - bool battery_BMS_a052_SW_PCS_MIA = false; - bool battery_BMS_a053_SW_ThermalModel_Sanity = false; - bool battery_BMS_a054_SW_Ver_Supply_Fault = false; - bool battery_BMS_a176_SW_GracefulPowerOff = false; - bool battery_BMS_a059_SW_Pack_Voltage_Sensing = false; - bool battery_BMS_a060_SW_Leakage_Test_Failure = false; - bool battery_BMS_a077_SW_Charger_Regulation = false; - bool battery_BMS_a081_SW_Ctr_Close_Blocked = false; - bool battery_BMS_a082_SW_Ctr_Force_Open = false; - bool battery_BMS_a083_SW_Ctr_Close_Failure = false; - bool battery_BMS_a084_SW_Sleep_Wake_Aborted = false; - bool battery_BMS_a094_SW_Drive_Inverter_MIA = false; - bool battery_BMS_a099_SW_BMB_Communication = false; - bool battery_BMS_a105_SW_One_Module_Tsense = false; - bool battery_BMS_a106_SW_All_Module_Tsense = false; - bool battery_BMS_a107_SW_Stack_Voltage_MIA = false; - bool battery_BMS_a121_SW_NVRAM_Config_Error = false; - bool battery_BMS_a122_SW_BMS_Therm_Irrational = false; - bool battery_BMS_a123_SW_Internal_Isolation = false; - bool battery_BMS_a129_SW_VSH_Failure = false; - bool battery_BMS_a131_Bleed_FET_Failure = false; - bool battery_BMS_a136_SW_Module_OT_Warning = false; - bool battery_BMS_a137_SW_Brick_UV_Warning = false; - bool battery_BMS_a138_SW_Brick_OV_Warning = false; - bool battery_BMS_a139_SW_DC_Link_V_Irrational = false; - bool battery_BMS_a141_SW_BMB_Status_Warning = false; - bool battery_BMS_a144_Hvp_Config_Mismatch = false; - bool battery_BMS_a145_SW_SOC_Change = false; - bool battery_BMS_a146_SW_Brick_Overdischarged = false; - bool battery_BMS_a149_SW_Missing_Config_Block = false; - bool battery_BMS_a151_SW_external_isolation = false; - bool battery_BMS_a156_SW_BMB_Vref_bad = false; - bool battery_BMS_a157_SW_HVP_HVS_Comms = false; - bool battery_BMS_a159_SW_HVP_ECU_Error = false; - bool battery_BMS_a161_SW_DI_Open_Request = false; - bool battery_BMS_a162_SW_No_Power_For_Support = false; - bool battery_BMS_a163_SW_Contactor_Mismatch = false; - bool battery_BMS_a164_SW_Uncontrolled_Regen = false; - bool battery_BMS_a165_SW_Pack_Partial_Weld = false; - bool battery_BMS_a166_SW_Pack_Full_Weld = false; - bool battery_BMS_a167_SW_FC_Partial_Weld = false; - bool battery_BMS_a168_SW_FC_Full_Weld = false; - bool battery_BMS_a170_SW_Limp_Mode = false; - bool battery_BMS_a171_SW_Stack_Voltage_Sense = false; - bool battery_BMS_a174_SW_Charge_Failure = false; - bool battery_BMS_a179_SW_Hvp_12V_Fault = false; - bool battery_BMS_a180_SW_ECU_reset_blocked = false; + uint8_t BMS_matrixIndex = 0; // Changed to bool + bool BMS_a061_robinBrickOverVoltage = false; + bool BMS_a062_SW_BrickV_Imbalance = false; + bool BMS_a063_SW_ChargePort_Fault = false; + bool BMS_a064_SW_SOC_Imbalance = false; + bool BMS_a127_SW_shunt_SNA = false; + bool BMS_a128_SW_shunt_MIA = false; + bool BMS_a069_SW_Low_Power = false; + bool BMS_a130_IO_CAN_Error = false; + bool BMS_a071_SW_SM_TransCon_Not_Met = false; + bool BMS_a132_HW_BMB_OTP_Uncorrctbl = false; + bool BMS_a134_SW_Delayed_Ctr_Off = false; + bool BMS_a075_SW_Chg_Disable_Failure = false; + bool BMS_a076_SW_Dch_While_Charging = false; + bool BMS_a017_SW_Brick_OV = false; + bool BMS_a018_SW_Brick_UV = false; + bool BMS_a019_SW_Module_OT = false; + bool BMS_a021_SW_Dr_Limits_Regulation = false; + bool BMS_a022_SW_Over_Current = false; + bool BMS_a023_SW_Stack_OV = false; + bool BMS_a024_SW_Islanded_Brick = false; + bool BMS_a025_SW_PwrBalance_Anomaly = false; + bool BMS_a026_SW_HFCurrent_Anomaly = false; + bool BMS_a087_SW_Feim_Test_Blocked = false; + bool BMS_a088_SW_VcFront_MIA_InDrive = false; + bool BMS_a089_SW_VcFront_MIA = false; + bool BMS_a090_SW_Gateway_MIA = false; + bool BMS_a091_SW_ChargePort_MIA = false; + bool BMS_a092_SW_ChargePort_Mia_On_Hv = false; + bool BMS_a034_SW_Passive_Isolation = false; + bool BMS_a035_SW_Isolation = false; + bool BMS_a036_SW_HvpHvilFault = false; + bool BMS_a037_SW_Flood_Port_Open = false; + bool BMS_a158_SW_HVP_HVI_Comms = false; + bool BMS_a039_SW_DC_Link_Over_Voltage = false; + bool BMS_a041_SW_Power_On_Reset = false; + bool BMS_a042_SW_MPU_Error = false; + bool BMS_a043_SW_Watch_Dog_Reset = false; + bool BMS_a044_SW_Assertion = false; + bool BMS_a045_SW_Exception = false; + bool BMS_a046_SW_Task_Stack_Usage = false; + bool BMS_a047_SW_Task_Stack_Overflow = false; + bool BMS_a048_SW_Log_Upload_Request = false; + bool BMS_a169_SW_FC_Pack_Weld = false; + bool BMS_a050_SW_Brick_Voltage_MIA = false; + bool BMS_a051_SW_HVC_Vref_Bad = false; + bool BMS_a052_SW_PCS_MIA = false; + bool BMS_a053_SW_ThermalModel_Sanity = false; + bool BMS_a054_SW_Ver_Supply_Fault = false; + bool BMS_a176_SW_GracefulPowerOff = false; + bool BMS_a059_SW_Pack_Voltage_Sensing = false; + bool BMS_a060_SW_Leakage_Test_Failure = false; + bool BMS_a077_SW_Charger_Regulation = false; + bool BMS_a081_SW_Ctr_Close_Blocked = false; + bool BMS_a082_SW_Ctr_Force_Open = false; + bool BMS_a083_SW_Ctr_Close_Failure = false; + bool BMS_a084_SW_Sleep_Wake_Aborted = false; + bool BMS_a094_SW_Drive_Inverter_MIA = false; + bool BMS_a099_SW_BMB_Communication = false; + bool BMS_a105_SW_One_Module_Tsense = false; + bool BMS_a106_SW_All_Module_Tsense = false; + bool BMS_a107_SW_Stack_Voltage_MIA = false; + bool BMS_a121_SW_NVRAM_Config_Error = false; + bool BMS_a122_SW_BMS_Therm_Irrational = false; + bool BMS_a123_SW_Internal_Isolation = false; + bool BMS_a129_SW_VSH_Failure = false; + bool BMS_a131_Bleed_FET_Failure = false; + bool BMS_a136_SW_Module_OT_Warning = false; + bool BMS_a137_SW_Brick_UV_Warning = false; + bool BMS_a138_SW_Brick_OV_Warning = false; + bool BMS_a139_SW_DC_Link_V_Irrational = false; + bool BMS_a141_SW_BMB_Status_Warning = false; + bool BMS_a144_Hvp_Config_Mismatch = false; + bool BMS_a145_SW_SOC_Change = false; + bool BMS_a146_SW_Brick_Overdischarged = false; + bool BMS_a149_SW_Missing_Config_Block = false; + bool BMS_a151_SW_external_isolation = false; + bool BMS_a156_SW_BMB_Vref_bad = false; + bool BMS_a157_SW_HVP_HVS_Comms = false; + bool BMS_a159_SW_HVP_ECU_Error = false; + bool BMS_a161_SW_DI_Open_Request = false; + bool BMS_a162_SW_No_Power_For_Support = false; + bool BMS_a163_SW_Contactor_Mismatch = false; + bool BMS_a164_SW_Uncontrolled_Regen = false; + bool BMS_a165_SW_Pack_Partial_Weld = false; + bool BMS_a166_SW_Pack_Full_Weld = false; + bool BMS_a167_SW_FC_Partial_Weld = false; + bool BMS_a168_SW_FC_Full_Weld = false; + bool BMS_a170_SW_Limp_Mode = false; + bool BMS_a171_SW_Stack_Voltage_Sense = false; + bool BMS_a174_SW_Charge_Failure = false; + bool BMS_a179_SW_Hvp_12V_Fault = false; + bool BMS_a180_SW_ECU_reset_blocked = false; }; class TeslaModel3YBattery : public TeslaBattery { diff --git a/Software/src/battery/TESLA-HTML.h b/Software/src/battery/TESLA-HTML.h index 111c7eba..c0ff34d8 100644 --- a/Software/src/battery/TESLA-HTML.h +++ b/Software/src/battery/TESLA-HTML.h @@ -39,8 +39,8 @@ class TeslaHtmlRenderer : public BatteryHtmlRenderer { float packMass = static_cast(datalayer_extended.tesla.battery_packMass); float platformMaxBusVoltage = static_cast(datalayer_extended.tesla.battery_platformMaxBusVoltage) * 0.1 + 375; - float bms_min_voltage = static_cast(datalayer_extended.tesla.battery_bms_min_voltage) * 0.01 * 2; - float bms_max_voltage = static_cast(datalayer_extended.tesla.battery_bms_max_voltage) * 0.01 * 2; + float bms_min_voltage = static_cast(datalayer_extended.tesla.BMS_min_voltage) * 0.01 * 2; + float bms_max_voltage = static_cast(datalayer_extended.tesla.BMS_max_voltage) * 0.01 * 2; float max_charge_current = static_cast(datalayer_extended.tesla.battery_max_charge_current); float max_discharge_current = static_cast(datalayer_extended.tesla.battery_max_discharge_current); float soc_ave = static_cast(datalayer_extended.tesla.battery_soc_ave) * 0.1; @@ -51,9 +51,9 @@ class TeslaHtmlRenderer : public BatteryHtmlRenderer { float BrickVoltageMin = static_cast(datalayer_extended.tesla.battery_BrickVoltageMin) * 0.002; float BrickModelTMax = static_cast(datalayer_extended.tesla.battery_BrickModelTMax) * 0.5 - 40; float BrickModelTMin = static_cast(datalayer_extended.tesla.battery_BrickModelTMin) * 0.5 - 40; - float isolationResistance = static_cast(datalayer_extended.tesla.battery_BMS_isolationResistance) * 10; + float isolationResistance = static_cast(datalayer_extended.tesla.BMS_isolationResistance) * 10; float PCS_dcdcMaxOutputCurrentAllowed = - static_cast(datalayer_extended.tesla.battery_PCS_dcdcMaxOutputCurrentAllowed) * 0.1; + static_cast(datalayer_extended.tesla.PCS_dcdcMaxOutputCurrentAllowed) * 0.1; float PCS_dcdcTemp = static_cast(datalayer_extended.tesla.PCS_dcdcTemp) * 0.1 + 40; float PCS_ambientTemp = static_cast(datalayer_extended.tesla.PCS_ambientTemp) * 0.1 + 40; float PCS_chgPhATemp = static_cast(datalayer_extended.tesla.PCS_chgPhATemp) * 0.1 + 40; @@ -128,7 +128,7 @@ class TeslaHtmlRenderer : public BatteryHtmlRenderer { static const char* contactorText[] = {"UNKNOWN(0)", "OPEN", "CLOSING", "BLOCKED", "OPENING", "CLOSED", "UNKNOWN(6)", "WELDED", "POS_CL", "NEG_CL", "UNKNOWN(10)", "UNKNOWN(11)", "UNKNOWN(12)"}; - static const char* hvilStatusState[] = {"NOT Ok", + static const char* hvilStatusState[] = {"UNKNOWN or CONTACTORS OPEN", "STATUS_OK", "CURRENT_SOURCE_FAULT", "INTERNAL_OPEN_FAULT", @@ -183,15 +183,46 @@ class TeslaHtmlRenderer : public BatteryHtmlRenderer { static const char* noYes[] = {"No", "Yes"}; static const char* Fault[] = {"NOT_ACTIVE", "ACTIVE"}; - //0x20A 522 HVP_contatorState - content += "

Contactor Status: " + String(contactorText[datalayer_extended.tesla.status_contactor]) + "

"; - content += "

HVIL: " + String(hvilStatusState[datalayer_extended.tesla.hvil_status]) + "

"; + //Main battery info + char readableBatterySerialNumber[15]; // One extra space for null terminator + memcpy(readableBatterySerialNumber, datalayer_extended.tesla.battery_serialNumber, + sizeof(datalayer_extended.tesla.battery_serialNumber)); + readableBatterySerialNumber[14] = '\0'; // Null terminate the string + content += "

Battery Serial Number: " + String(readableBatterySerialNumber) + "

"; + char readableBatteryPartNumber[13]; // One extra space for null terminator + memcpy(readableBatteryPartNumber, datalayer_extended.tesla.battery_partNumber, + sizeof(datalayer_extended.tesla.battery_partNumber)); + readableBatteryPartNumber[12] = '\0'; // Null terminate the string + content += "

Battery Part Number: " + String(readableBatteryPartNumber) + "

"; + //0x3C4 PCS_info + char readablePCSPartNumber[13]; // One extra space for null terminator + memcpy(readablePCSPartNumber, datalayer_extended.tesla.PCS_partNumber, + sizeof(datalayer_extended.tesla.PCS_partNumber)); + readablePCSPartNumber[13] = '\0'; // Null terminate the string + content += "

PCS Part Number: " + String(readablePCSPartNumber) + "

"; + content += "

Battery Manufacture Date: " + String(datalayer_extended.tesla.battery_manufactureDate) + "

"; + content += "

Battery Pack Mass: " + String(packMass) + " KG

"; + //0x3D2 978 BMS_kwhCounter + content += "

Battery Total Discharge: " + String(total_discharge) + " kWh

"; + content += "

Battery Total Charge: " + String(total_charge) + " kWh

"; + //0x20A 522 HVP_contactorState + HVIL + //content += "

HVIL Fault: " + String(noYes[datalayer_extended.tesla.BMS_hvilFault]) + "

"; + content += "

HVIL Status: " + String(hvilStatusState[datalayer_extended.tesla.hvil_status]) + "

"; content += - "

Negative contactor: " + String(contactorState[datalayer_extended.tesla.packContNegativeState]) + "

"; + "

HVP Contactor State: " + String(contactorText[datalayer_extended.tesla.packContactorSetState]) + "

"; content += - "

Positive contactor: " + String(contactorState[datalayer_extended.tesla.packContPositiveState]) + "

"; - content += "

Closing allowed?: " + String(noYes[datalayer_extended.tesla.packCtrsClosingAllowed]) + "

"; - content += "

Pyrotest in Progress: " + String(noYes[datalayer_extended.tesla.pyroTestInProgress]) + "

"; + "

BMS Contactor State: " + String(BMS_contactorState[datalayer_extended.tesla.BMS_contactorState]) + "

"; + content += + "

Negative Contactor: " + String(contactorState[datalayer_extended.tesla.packContNegativeState]) + "

"; + content += + "

Positive Contactor: " + String(contactorState[datalayer_extended.tesla.packContPositiveState]) + "

"; + if (datalayer_extended.tesla.packContactorSetState == 5) { //Closed + content += "

Closing blocked: " + String(noYes[datalayer_extended.tesla.packCtrsClosingBlocked]) + + " (already CLOSED)

"; + } else { + content += "

Closing blocked: " + String(noYes[datalayer_extended.tesla.packCtrsClosingBlocked]) + "

"; + } + content += "

Pyrotest in progress: " + String(noYes[datalayer_extended.tesla.pyroTestInProgress]) + "

"; content += "

Contactors Open Now Requested: " + String(noYes[datalayer_extended.tesla.battery_packCtrsOpenNowRequested]) + "

"; content += @@ -204,21 +235,16 @@ class TeslaHtmlRenderer : public BatteryHtmlRenderer { content += "

DC Link Allowed to Energize: " + String(noYes[datalayer_extended.tesla.battery_dcLinkAllowedToEnergize]) + "

"; - char readableSerialNumber[15]; // One extra space for null terminator - memcpy(readableSerialNumber, datalayer_extended.tesla.BMS_SerialNumber, - sizeof(datalayer_extended.tesla.BMS_SerialNumber)); - readableSerialNumber[14] = '\0'; // Null terminate the string - content += "

BMS Serial number: " + String(readableSerialNumber) + "

"; // Comment what data you would like to display, order can be changed. //0x352 850 BMS_energyStatus if (datalayer_extended.tesla.BMS352_mux == false) { content += "

BMS 0x352 w/o mux

"; //if using older BMS <2021 and comment 0x352 without MUX content += "

Calculated SOH: " + String(nominal_full_pack_energy * 100 / beginning_of_life) + "

"; - content += "

Nominal Full Pack Energy: " + String(nominal_full_pack_energy) + " KWh

"; - content += "

Nominal Energy Remaining: " + String(nominal_energy_remaining) + " KWh

"; - content += "

Ideal Energy Remaining: " + String(ideal_energy_remaining) + " KWh

"; - content += "

Energy to Charge Complete: " + String(energy_to_charge_complete) + " KWh

"; - content += "

Energy Buffer: " + String(energy_buffer) + " KWh

"; + content += "

Nominal Full Pack Energy: " + String(nominal_full_pack_energy) + " kWh

"; + content += "

Nominal Energy Remaining: " + String(nominal_energy_remaining) + " kWh

"; + content += "

Ideal Energy Remaining: " + String(ideal_energy_remaining) + " kWh

"; + content += "

Energy to Charge Complete: " + String(energy_to_charge_complete) + " kWh

"; + content += "

Energy Buffer: " + String(energy_buffer) + " kWh

"; content += "

Full Charge Complete: " + String(noYes[datalayer_extended.tesla.battery_full_charge_complete]) + "

"; //bool } @@ -226,19 +252,26 @@ class TeslaHtmlRenderer : public BatteryHtmlRenderer { if (datalayer_extended.tesla.BMS352_mux == true) { content += "

BMS 0x352 w/ mux

"; //if using newer BMS >2021 and comment 0x352 with MUX content += "

Calculated SOH: " + String(nominal_full_pack_energy_m0 * 100 / beginning_of_life) + "

"; - content += "

Nominal Full Pack Energy: " + String(nominal_full_pack_energy_m0) + " KWh

"; - content += "

Nominal Energy Remaining: " + String(nominal_energy_remaining_m0) + " KWh

"; - content += "

Ideal Energy Remaining: " + String(ideal_energy_remaining_m0) + " KWh

"; - content += "

Energy to Charge Complete: " + String(energy_to_charge_complete_m1) + " KWh

"; - content += "

Energy Buffer: " + String(energy_buffer_m1) + " KWh

"; - content += "

Expected Energy Remaining: " + String(expected_energy_remaining_m1) + " KWh

"; + content += "

Nominal Full Pack Energy: " + String(nominal_full_pack_energy_m0) + " kWh

"; + content += "

Nominal Energy Remaining: " + String(nominal_energy_remaining_m0) + " kWh

"; + content += "

Ideal Energy Remaining: " + String(ideal_energy_remaining_m0) + " kWh

"; + content += "

Energy to Charge Complete: " + String(energy_to_charge_complete_m1) + " kWh

"; + content += "

Energy Buffer: " + String(energy_buffer_m1) + " kWh

"; + content += "

Expected Energy Remaining: " + String(expected_energy_remaining_m1) + " kWh

"; content += "

Fully Charged: " + String(noYes[datalayer_extended.tesla.battery_fully_charged]) + "

"; } - //0x3D2 978 BMS_kwhCounter - content += "

Total Discharge: " + String(total_discharge) + " KWh

"; - content += "

Total Charge: " + String(total_charge) + " KWh

"; + //0x212 530 BMS_status + content += "

Isolation Resistance: " + String(isolationResistance) + " kOhms

"; + content += "

BMS State: " + String(BMS_state[datalayer_extended.tesla.BMS_state]) + "

"; + content += "

BMS HV State: " + String(BMS_hvState[datalayer_extended.tesla.BMS_hvState]) + "

"; + content += "

BMS UI Charge Status: " + String(BMS_uiChargeStatus[datalayer_extended.tesla.BMS_uiChargeStatus]) + + "

"; + content += "

BMS_buildConfigId: " + String(datalayer_extended.tesla.BMS_info_buildConfigId) + "

"; + content += "

BMS_hardwareId: " + String(datalayer_extended.tesla.BMS_info_hardwareId) + "

"; + content += "

BMS_componentId: " + String(datalayer_extended.tesla.BMS_info_componentId) + "

"; + content += "

BMS PCS PWM Enabled: " + String(Fault[datalayer_extended.tesla.BMS_pcsPwmEnabled]) + "

"; //0x292 658 BMS_socStates - content += "

Battery Beginning of Life: " + String(beginning_of_life) + " KWh

"; + content += "

Battery Beginning of Life: " + String(beginning_of_life) + " kWh

"; content += "

Battery SOC UI: " + String(soc_ui) + "

"; content += "

Battery SOC Ave: " + String(soc_ave) + "

"; content += "

Battery SOC Max: " + String(soc_max) + "

"; @@ -252,7 +285,7 @@ class TeslaHtmlRenderer : public BatteryHtmlRenderer { //content += "

packConfigMultiplexer: " + String(datalayer_extended.tesla.battery_packConfigMultiplexer) + "

"; // Not giving useable data //content += "

moduleType: " + String(datalayer_extended.tesla.battery_moduleType) + "

"; // Not giving useable data //content += "

reserveConfig: " + String(datalayer_extended.tesla.battery_reservedConfig) + "

"; // Not giving useable data - content += "

Battery Pack Mass: " + String(packMass) + " KG

"; + //content += "

Battery Pack Mass: " + String(packMass) + " KG

"; content += "

Platform Max Bus Voltage: " + String(platformMaxBusVoltage) + " V

"; //0x2D2 722 BMSVAlimits content += "

BMS Min Voltage: " + String(bms_min_voltage) + " V

"; @@ -273,25 +306,14 @@ class TeslaHtmlRenderer : public BatteryHtmlRenderer { content += "

PCS Chg PhB Temp: " + String(PCS_chgPhBTemp) + " DegC

"; content += "

PCS Chg PhC Temp: " + String(PCS_chgPhCTemp) + " DegC

"; //0x252 594 BMS_powerAvailable - content += "

Max Regen Power: " + String(BMS_maxRegenPower) + " KW

"; - content += "

Max Discharge Power: " + String(BMS_maxDischargePower) + " KW

"; - //content += "

Max Stationary Heat Power: " + String(BMS_maxStationaryHeatPower) + " KWh

"; // Not giving useable data - //content += "

HVAC Power Budget: " + String(BMS_hvacPowerBudget) + " KW

"; // Not giving useable data + content += "

Max Regen Power: " + String(BMS_maxRegenPower) + " kW

"; + content += "

Max Discharge Power: " + String(BMS_maxDischargePower) + " kW

"; + //content += "

Max Stationary Heat Power: " + String(BMS_maxStationaryHeatPower) + " kWh

"; // Not giving useable data + //content += "

HVAC Power Budget: " + String(BMS_hvacPowerBudget) + " kW

"; // Not giving useable data //content += "

Not Enough Power For Heat Pump: " + String(noYes[datalayer_extended.tesla.BMS_notEnoughPowerForHeatPump]) + "

"; // Not giving useable data content += "

Power Limit State: " + String(BMS_powerLimitState[datalayer_extended.tesla.BMS_powerLimitState]) + "

"; //content += "

Inverter TQF: " + String(datalayer_extended.tesla.BMS_inverterTQF) + "

"; // Not giving useable data - //0x212 530 BMS_status - content += "

Isolation Resistance: " + String(isolationResistance) + " kOhms

"; - content += - "

BMS Contactor State: " + String(BMS_contactorState[datalayer_extended.tesla.battery_BMS_contactorState]) + - "

"; - content += "

BMS State: " + String(BMS_state[datalayer_extended.tesla.battery_BMS_state]) + "

"; - content += "

BMS HV State: " + String(BMS_hvState[datalayer_extended.tesla.battery_BMS_hvState]) + "

"; - content += "

BMS UI Charge Status: " + String(BMS_uiChargeStatus[datalayer_extended.tesla.battery_BMS_hvState]) + - "

"; - content += - "

BMS PCS PWM Enabled: " + String(Fault[datalayer_extended.tesla.battery_BMS_pcsPwmEnabled]) + "

"; //0x312 786 BMS_thermalStatus content += "

Power Dissipation: " + String(BMS_powerDissipation) + " kW

"; content += "

Flow Request: " + String(BMS_flowRequest) + " LPM

"; @@ -304,36 +326,34 @@ class TeslaHtmlRenderer : public BatteryHtmlRenderer { content += "

BMS No Flow Request: " + String(Fault[datalayer_extended.tesla.BMS_noFlowRequest]) + "

"; //0x224 548 PCS_dcdcStatus content += - "

Precharge Status: " + String(PCS_dcdcStatus[datalayer_extended.tesla.battery_PCS_dcdcPrechargeStatus]) + - "

"; - content += - "

12V Support Status: " + String(PCS_dcdcStatus[datalayer_extended.tesla.battery_PCS_dcdc12VSupportStatus]) + - "

"; + "

Precharge Status: " + String(PCS_dcdcStatus[datalayer_extended.tesla.PCS_dcdcPrechargeStatus]) + "

"; + content += "

12V Support Status: " + String(PCS_dcdcStatus[datalayer_extended.tesla.PCS_dcdc12VSupportStatus]) + + "

"; content += "

HV Bus Discharge Status: " + - String(PCS_dcdcStatus[datalayer_extended.tesla.battery_PCS_dcdcHvBusDischargeStatus]) + "

"; - content += - "

Main State: " + String(PCS_dcdcMainState[datalayer_extended.tesla.battery_PCS_dcdcMainState]) + "

"; - content += - "

Sub State: " + String(PCS_dcdcSubState[datalayer_extended.tesla.battery_PCS_dcdcSubState]) + "

"; - content += "

PCS Faulted: " + String(Fault[datalayer_extended.tesla.battery_PCS_dcdcFaulted]) + "

"; - content += - "

Output Is Limited: " + String(Fault[datalayer_extended.tesla.battery_PCS_dcdcOutputIsLimited]) + "

"; + String(PCS_dcdcStatus[datalayer_extended.tesla.PCS_dcdcHvBusDischargeStatus]) + ""; + content += "

Main State: " + String(PCS_dcdcMainState[datalayer_extended.tesla.PCS_dcdcMainState]) + "

"; + content += "

Sub State: " + String(PCS_dcdcSubState[datalayer_extended.tesla.PCS_dcdcSubState]) + "

"; + content += "

PCS Faulted: " + String(Fault[datalayer_extended.tesla.PCS_dcdcFaulted]) + "

"; + content += "

Output Is Limited: " + String(Fault[datalayer_extended.tesla.PCS_dcdcOutputIsLimited]) + "

"; content += "

Max Output Current Allowed: " + String(PCS_dcdcMaxOutputCurrentAllowed) + " A

"; - content += "

Precharge Rty Cnt: " + String(falseTrue[datalayer_extended.tesla.battery_PCS_dcdcPrechargeRtyCnt]) + - "

"; content += - "

12V Support Rty Cnt: " + String(falseTrue[datalayer_extended.tesla.battery_PCS_dcdc12VSupportRtyCnt]) + + "

Precharge Rty Cnt: " + String(falseTrue[datalayer_extended.tesla.PCS_dcdcPrechargeRtyCnt]) + "

"; + content += + "

12V Support Rty Cnt: " + String(falseTrue[datalayer_extended.tesla.PCS_dcdc12VSupportRtyCnt]) + "

"; + content += + "

Discharge Rty Cnt: " + String(falseTrue[datalayer_extended.tesla.PCS_dcdcDischargeRtyCnt]) + "

"; + content += "

PWM Enable Line: " + String(Fault[datalayer_extended.tesla.PCS_dcdcPwmEnableLine]) + "

"; + content += + "

Supporting Fixed LV Target: " + String(Fault[datalayer_extended.tesla.PCS_dcdcSupportingFixedLvTarget]) + "

"; - content += "

Discharge Rty Cnt: " + String(falseTrue[datalayer_extended.tesla.battery_PCS_dcdcDischargeRtyCnt]) + + content += "

Precharge Restart Cnt: " + String(falseTrue[datalayer_extended.tesla.PCS_dcdcPrechargeRestartCnt]) + "

"; - content += - "

PWM Enable Line: " + String(Fault[datalayer_extended.tesla.battery_PCS_dcdcPwmEnableLine]) + "

"; - content += "

Supporting Fixed LV Target: " + - String(Fault[datalayer_extended.tesla.battery_PCS_dcdcSupportingFixedLvTarget]) + "

"; - content += "

Precharge Restart Cnt: " + - String(falseTrue[datalayer_extended.tesla.battery_PCS_dcdcPrechargeRestartCnt]) + "

"; content += "

Initial Precharge Substate: " + - String(PCS_dcdcSubState[datalayer_extended.tesla.battery_PCS_dcdcInitialPrechargeSubState]) + "

"; + String(PCS_dcdcSubState[datalayer_extended.tesla.PCS_dcdcInitialPrechargeSubState]) + ""; + //0x3C4 PCS_info + content += "

PCS_buildConfigId: " + String(datalayer_extended.tesla.PCS_info_buildConfigId) + "

"; + content += "

PCS_hardwareId: " + String(datalayer_extended.tesla.PCS_info_hardwareId) + "

"; + content += "

PCS_componentId: " + String(datalayer_extended.tesla.PCS_info_componentId) + "

"; //0x2C4 708 PCS_logging content += "

PCS_dcdcMaxLvOutputCurrent: " + String(PCS_dcdcMaxLvOutputCurrent) + " A

"; content += "

PCS_dcdcCurrentLimit: " + String(PCS_dcdcCurrentLimit) + " A

"; @@ -355,6 +375,10 @@ class TeslaHtmlRenderer : public BatteryHtmlRenderer { content += "

PCS_dcdcIntervalMinLvBusVolt: " + String(PCS_dcdcIntervalMinLvBusVolt) + " V

"; content += "

PCS_dcdcIntervalMinLvOutputCurr: " + String(PCS_dcdcIntervalMinLvOutputCurr) + " A

"; content += "

PCS_dcdc12vSupportLifetimekWh: " + String(PCS_dcdc12vSupportLifetimekWh) + " kWh

"; + //0x310 HVP_info + content += "

HVP_buildConfigId: " + String(datalayer_extended.tesla.HVP_info_buildConfigId) + "

"; + content += "

HVP_hardwareId: " + String(datalayer_extended.tesla.HVP_info_hardwareId) + "

"; + content += "

HVP_componentId: " + String(datalayer_extended.tesla.HVP_info_componentId) + "

"; //0x7AA 1962 HVP_debugMessage content += "

HVP_battery12V: " + String(HVP_battery12V) + " V

"; content += "

HVP_dcLinkVoltage: " + String(HVP_dcLinkVoltage) + " V

"; diff --git a/Software/src/datalayer/datalayer_extended.h b/Software/src/datalayer/datalayer_extended.h index 06e0d459..d4ad098e 100644 --- a/Software/src/datalayer/datalayer_extended.h +++ b/Software/src/datalayer/datalayer_extended.h @@ -355,9 +355,9 @@ typedef struct { typedef struct { /** uint8_t */ /** Contactor status */ - uint8_t status_contactor = 0; + //uint8_t status_contactor = 0; /** uint8_t */ - /** Contactor status */ + /** HVIL status */ uint8_t hvil_status = 0; /** uint8_t */ /** Negative contactor state */ @@ -366,12 +366,12 @@ typedef struct { /** Positive contactor state */ uint8_t packContPositiveState = 0; /** uint8_t */ - /** Set state of contactors */ + /** HVP set state of contactors */ uint8_t packContactorSetState = 0; - /** uint8_t */ - /** Battery pack allows closing of contacors */ - uint8_t packCtrsClosingAllowed = 0; - /** uint8_t */ + /** bool */ + /** Battery pack allows closing of contactors */ + bool packCtrsClosingBlocked = false; + /** bool */ /** Pyro test in progress */ bool pyroTestInProgress = false; bool battery_packCtrsOpenNowRequested = false; @@ -379,7 +379,22 @@ typedef struct { uint8_t battery_packCtrsRequestStatus = 0; bool battery_packCtrsResetRequestRequired = false; bool battery_dcLinkAllowedToEnergize = false; - uint8_t BMS_SerialNumber[15] = {0}; //stores raw HEX values for ASCII chars + uint8_t BMS_partNumber[12] = {0}; //stores raw HEX values for ASCII chars + uint16_t BMS_info_buildConfigId = 0; + uint16_t BMS_info_hardwareId = 0; + uint16_t BMS_info_componentId = 0; + uint8_t BMS_info_pcbaId = 0; + uint8_t BMS_info_assemblyId = 0; + uint16_t BMS_info_usageId = 0; + uint16_t BMS_info_subUsageId = 0; + uint8_t BMS_info_platformType = 0; + uint32_t BMS_info_appCrc = 0; + uint64_t BMS_info_bootGitHash = 0; + uint8_t BMS_info_bootUdsProtoVersion = 0; + uint32_t BMS_info_bootCrc = 0; + uint8_t battery_serialNumber[15] = {0}; //stores raw HEX values for ASCII chars + uint8_t battery_partNumber[12] = {0}; //stores raw HEX values for ASCII chars + char* battery_manufactureDate; uint8_t battery_beginning_of_life = 0; uint8_t battery_battTempPct = 0; uint16_t battery_dcdcLvBusVolt = 0; @@ -413,37 +428,23 @@ typedef struct { uint16_t battery_reservedConfig = 0; uint32_t battery_packMass = 0; uint32_t battery_platformMaxBusVoltage = 0; - uint32_t battery_bms_min_voltage = 0; - uint32_t battery_bms_max_voltage = 0; + uint32_t BMS_min_voltage = 0; + uint32_t BMS_max_voltage = 0; uint32_t battery_max_charge_current = 0; uint32_t battery_max_discharge_current = 0; uint32_t battery_soc_min = 0; uint32_t battery_soc_max = 0; uint32_t battery_soc_ave = 0; uint32_t battery_soc_ui = 0; - uint8_t battery_BMS_contactorState = 0; - uint8_t battery_BMS_state = 0; - uint8_t battery_BMS_hvState = 0; - uint16_t battery_BMS_isolationResistance = 0; - uint8_t battery_BMS_uiChargeStatus = 0; - bool battery_BMS_diLimpRequest = false; - uint16_t battery_BMS_chgPowerAvailable = 0; - bool battery_BMS_pcsPwmEnabled = false; - uint8_t battery_PCS_dcdcPrechargeStatus = 0; - uint8_t battery_PCS_dcdc12VSupportStatus = 0; - uint8_t battery_PCS_dcdcHvBusDischargeStatus = 0; - uint8_t battery_PCS_dcdcMainState = 0; - uint8_t battery_PCS_dcdcSubState = 0; - bool battery_PCS_dcdcFaulted = false; - bool battery_PCS_dcdcOutputIsLimited = false; - uint16_t battery_PCS_dcdcMaxOutputCurrentAllowed = 0; - uint8_t battery_PCS_dcdcPrechargeRtyCnt = 0; - uint8_t battery_PCS_dcdc12VSupportRtyCnt = 0; - uint8_t battery_PCS_dcdcDischargeRtyCnt = 0; - uint8_t battery_PCS_dcdcPwmEnableLine = 0; - uint8_t battery_PCS_dcdcSupportingFixedLvTarget = 0; - uint8_t battery_PCS_dcdcPrechargeRestartCnt = 0; - uint8_t battery_PCS_dcdcInitialPrechargeSubState = 0; + bool BMS_hvilFault = false; + uint8_t BMS_contactorState = 0; + uint8_t BMS_state = 0; + uint8_t BMS_hvState = 0; + uint16_t BMS_isolationResistance = 0; + uint8_t BMS_uiChargeStatus = 0; + bool BMS_diLimpRequest = false; + uint16_t BMS_chgPowerAvailable = 0; + bool BMS_pcsPwmEnabled = false; uint16_t BMS_maxRegenPower = 0; uint16_t BMS_maxDischargePower = 0; uint16_t BMS_maxStationaryHeatPower = 0; @@ -460,6 +461,35 @@ typedef struct { uint16_t BMS_packTMax = 0; bool BMS_pcsNoFlowRequest = false; bool BMS_noFlowRequest = false; + uint8_t PCS_dcdcPrechargeStatus = 0; + uint8_t PCS_dcdc12VSupportStatus = 0; + uint8_t PCS_dcdcHvBusDischargeStatus = 0; + uint8_t PCS_dcdcMainState = 0; + uint8_t PCS_dcdcSubState = 0; + bool PCS_dcdcFaulted = false; + bool PCS_dcdcOutputIsLimited = false; + uint16_t PCS_dcdcMaxOutputCurrentAllowed = 0; + uint8_t PCS_dcdcPrechargeRtyCnt = 0; + uint8_t PCS_dcdc12VSupportRtyCnt = 0; + uint8_t PCS_dcdcDischargeRtyCnt = 0; + uint8_t PCS_dcdcPwmEnableLine = 0; + uint8_t PCS_dcdcSupportingFixedLvTarget = 0; + uint8_t PCS_dcdcPrechargeRestartCnt = 0; + uint8_t PCS_dcdcInitialPrechargeSubState = 0; + uint8_t PCS_partNumber[13] = {0}; //stores raw HEX values for ASCII chars + uint16_t PCS_info_buildConfigId = 0; + uint16_t PCS_info_hardwareId = 0; + uint16_t PCS_info_componentId = 0; + uint8_t PCS_info_pcbaId = 0; + uint8_t PCS_info_assemblyId = 0; + uint16_t PCS_info_usageId = 0; + uint16_t PCS_info_subUsageId = 0; + uint8_t PCS_info_platformType = 0; + uint32_t PCS_info_appCrc = 0; + uint32_t PCS_info_cpu2AppCrc = 0; + uint64_t PCS_info_bootGitHash = 0; + uint8_t PCS_info_bootUdsProtoVersion = 0; + uint32_t PCS_info_bootCrc = 0; uint16_t PCS_dcdcTemp = 0; uint16_t PCS_ambientTemp = 0; uint16_t PCS_chgPhATemp = 0; @@ -516,6 +546,19 @@ typedef struct { bool HVP_currentSenseMia = false; bool HVP_shuntRefVoltageMismatch = false; bool HVP_shuntThermistorMia = false; + uint8_t HVP_partNumber[13] = {0}; //stores raw HEX values for ASCII chars + uint16_t HVP_info_buildConfigId = 0; + uint16_t HVP_info_hardwareId = 0; + uint16_t HVP_info_componentId = 0; + uint8_t HVP_info_pcbaId = 0; + uint8_t HVP_info_assemblyId = 0; + uint16_t HVP_info_usageId = 0; + uint16_t HVP_info_subUsageId = 0; + uint8_t HVP_info_platformType = 0; + uint32_t HVP_info_appCrc = 0; + uint64_t HVP_info_bootGitHash = 0; + uint8_t HVP_info_bootUdsProtoVersion = 0; + uint32_t HVP_info_bootCrc = 0; uint8_t HVP_shuntHwMia = 0; uint16_t HVP_dcLinkVoltage = 0; uint16_t HVP_packVoltage = 0;