Add more CAN findings

This commit is contained in:
Daniel Öster 2025-04-15 00:05:02 +03:00
parent 99f78dadfb
commit 881a6e7630
3 changed files with 119 additions and 39 deletions

View file

@ -191,9 +191,12 @@ static unsigned long previousMillis10 = 0; // will store last time a 10ms CAN
static unsigned long previousMillis20 = 0; // will store last time a 20ms CAN Message was sent
static unsigned long previousMillis50 = 0; // will store last time a 50ms CAN Message was sent
static unsigned long previousMillis100 = 0; // will store last time a 100ms CAN Message was sent
static uint8_t mux = 0;
static uint16_t battery_voltage = 3700;
static uint8_t HVIL_signal = 0;
static uint8_t serialnumbers[28] = {0};
static uint16_t maximum_cell_voltage = 3700;
static uint16_t discharge_power_allowed = 0;
void update_values_battery() { //This function maps all the values fetched via CAN to the correct parameters used for modbus
datalayer.battery.status.soh_pptt;
@ -208,7 +211,7 @@ void update_values_battery() { //This function maps all the values fetched via
datalayer.battery.status.remaining_capacity_Wh = static_cast<uint32_t>(
(static_cast<double>(datalayer.battery.status.real_soc) / 10000) * datalayer.battery.info.total_capacity_Wh);
datalayer.battery.status.max_discharge_power_W;
datalayer.battery.status.max_discharge_power_W = discharge_power_allowed * 100;
datalayer.battery.status.max_charge_power_W;
@ -216,15 +219,18 @@ void update_values_battery() { //This function maps all the values fetched via
datalayer.battery.status.temperature_max_dC;
datalayer.battery.status.cell_min_voltage_mV;
datalayer.battery.status.cell_min_voltage_mV = maximum_cell_voltage -10; //TODO: Fix once we have min value
datalayer.battery.status.cell_max_voltage_mV;
datalayer.battery.status.cell_max_voltage_mV = maximum_cell_voltage;
if (HVIL_signal > 0) {
set_event(EVENT_HVIL_FAILURE, HVIL_signal);
} else {
clear_event(EVENT_HVIL_FAILURE);
}
//Update webserver more battery info page
memcpy(datalayer_extended.geometryC.BatterySerialNumber, serialnumbers, sizeof(serialnumbers));
}
void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
@ -242,61 +248,120 @@ void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
//frame7, CRC
//frame6, low byte counter 0-F
break;
case 0x178: //10ms
case 0x178: //10ms (64 13 88 00 0E 30 0A 85)
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
battery_voltage = ((rx_frame.data.u8[4] & 0x0F) << 8) | rx_frame.data.u8[5]; //TODO, test?
//frame7, CRC
//frame6, low byte counter 0-F
break;
case 0x179: //20ms (3E 52 BA 5D A4 3F 0C D9)
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
//2BA = 69.8 //Potentially charge power allowed
//frame7, CRC
//frame6, low byte counter 0-F
break;
case 0x17A: //100ms (01 B4 52 28 4A 46 6E AE)
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
//frame7, CRC
//frame6, low byte counter 0-F
break;
case 0x179: //20ms
case 0x17B: //20ms (00 00 10 00 0F FE 03 C9)
//frame7, CRC
//frame6, low byte counter 0-F
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x17A: //100ms
case 0x210: //100ms (38 04 3A 01 38 22 22 39)
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
discharge_power_allowed = ((rx_frame.data.u8[1] & 0x0F) << 8) | rx_frame.data.u8[2]; //TODO, not confirmed
//43A = 108.2kW potentially discharge power allowed
//frame7, CRC
//frame6, counter 0 - 0x22
break;
case 0x211: //100ms (00 D8 C6 00 00 00 0F 3A)
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
//frame7, CRC
//frame6, low byte counter 0-F
break;
case 0x212: //500ms (Completely empty)
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x17B: //20ms
battery_voltage = ((rx_frame.data.u8[4] & 0x0F) << 8) | rx_frame.data.u8[5]; //TODO: NOT CONFIRMED
case 0x351: //100ms (4A 31 71 B8 6E F8 84 00)
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x210: //100ms
case 0x352: //500ms (76 78 00 00 82 FF FF 00)
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
//82 = 13.1 potentially 12V voltage?
break;
case 0x353: //500ms (00 00 00 00 62 00 EA 5D)
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
//EA5D = 59997 Wh, potentially capacity remaining
break;
case 0x354: //500ms (Completely empty)
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x211: //100ms
case 0x355: //500ms (89 4A 03 5C 39 06 04 00)
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x212: //500ms
case 0x356: //1s (6B 09 0C 69 0A F1 D3 86)
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x351: //100ms
case 0x357: //20ms (18 17 6F 20 00 00 00 00)
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
//Frame 0 and 1 seems to count something large
break;
case 0x358: //1s (03 DF 10 3C DA 0E 20 DE)
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x352: //500ms
case 0x359: //1s (1F 40 00 00 00 00 00 36)
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
//Frame7 loops 01-21-22-36-01-21...
break;
case 0x353: //500ms
case 0x35B: //200ms (Serialnumbers)
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
mux = rx_frame.data.u8[0];
switch (mux)
{
case 0x01:
serialnumbers[0] = rx_frame.data.u8[1];
serialnumbers[1] = rx_frame.data.u8[2];
serialnumbers[2] = rx_frame.data.u8[3];
serialnumbers[3] = rx_frame.data.u8[4];
serialnumbers[4] = rx_frame.data.u8[5];
serialnumbers[5] = rx_frame.data.u8[6];
serialnumbers[6] = rx_frame.data.u8[7];
break;
case 0x02:
serialnumbers[7] = rx_frame.data.u8[1];
serialnumbers[8] = rx_frame.data.u8[2];
serialnumbers[9] = rx_frame.data.u8[3];
serialnumbers[10] = rx_frame.data.u8[4];
serialnumbers[11] = rx_frame.data.u8[5];
serialnumbers[12] = rx_frame.data.u8[6];
serialnumbers[13] = rx_frame.data.u8[7];
break;
case 0x03:
serialnumbers[14] = rx_frame.data.u8[1];
serialnumbers[15] = rx_frame.data.u8[2];
serialnumbers[16] = rx_frame.data.u8[3];
serialnumbers[17] = rx_frame.data.u8[4];
serialnumbers[18] = rx_frame.data.u8[5];
serialnumbers[19] = rx_frame.data.u8[6];
serialnumbers[20] = rx_frame.data.u8[7];
break;
case 0x04:
serialnumbers[21] = rx_frame.data.u8[1];
serialnumbers[22] = rx_frame.data.u8[2];
serialnumbers[23] = rx_frame.data.u8[3];
serialnumbers[24] = rx_frame.data.u8[4];
serialnumbers[25] = rx_frame.data.u8[5];
serialnumbers[26] = rx_frame.data.u8[6];
serialnumbers[27] = rx_frame.data.u8[7];
break;
default:
break;
}
break;
case 0x354: //500ms
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x355: //500ms
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x356: //1s
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x357: //20ms
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x358: //1s
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x359: //1s
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x35B: //200ms
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x424: //500ms
case 0x424: //500ms (24 10 01 01 02 00 00 00)
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
default:
@ -402,7 +467,7 @@ void setup_battery(void) { // Performs one time setup at startup
strncpy(datalayer.system.info.battery_protocol, "Geely Geometry C", 63);
datalayer.system.info.battery_protocol[63] = '\0';
datalayer.system.status.battery_allows_contactor_closing = true;
datalayer.battery.info.number_of_cells = 96;
datalayer.battery.info.number_of_cells = 102; //70kWh pack has 102S
datalayer.battery.info.max_design_voltage_dV = MAX_PACK_VOLTAGE_70_DV; //Startup in extreme ends
datalayer.battery.info.min_design_voltage_dV = MIN_PACK_VOLTAGE_53_DV; //Before pack size determined
datalayer.battery.info.max_cell_voltage_mV = MAX_CELL_VOLTAGE_MV;

View file

@ -252,6 +252,12 @@ typedef struct {
bool warning_Charger_not_responding = false;
} DATALAYER_INFO_CELLPOWER;
typedef struct {
/** uint8_t */
/** Battery serial numbers, stores raw HEX values for ASCII chars */
uint8_t BatterySerialNumber[28] = {0};
} DATALAYER_INFO_GEELY_GEOMETRY_C;
typedef struct {
uint8_t total_cell_count = 0;
int16_t battery_12V = 0;
@ -734,6 +740,7 @@ class DataLayerExtended {
DATALAYER_INFO_BMWI3 bmwi3;
DATALAYER_INFO_BYDATTO3 bydAtto3;
DATALAYER_INFO_CELLPOWER cellpower;
DATALAYER_INFO_GEELY_GEOMETRY_C geometryC;
DATALAYER_INFO_KIAHYUNDAI64 KiaHyundai64;
DATALAYER_INFO_TESLA tesla;
DATALAYER_INFO_NISSAN_LEAF nissanleaf;

View file

@ -432,6 +432,14 @@ String advanced_battery_processor(const String& var) {
String(falseTrue[datalayer_extended.cellpower.warning_Charger_not_responding]) + "</h4>";
#endif //CELLPOWER_BMS
#ifdef GEELY_GEOMETRY_C_BATTERY
char readableSerialNumber[29]; // One extra space for null terminator
memcpy(readableSerialNumber, datalayer_extended.geometryC.BatterySerialNumber,
sizeof(datalayer_extended.geometryC.BatterySerialNumber));
readableSerialNumber[15] = '\0'; // Null terminate the string
content += "<h4>Serial number: " + String(readableSerialNumber) + "</h4>";
#endif //GEELY_GEOMETRY_C_BATTERY
#ifdef KIA_HYUNDAI_64_BATTERY
content += "<h4>Cells: " + String(datalayer_extended.KiaHyundai64.total_cell_count) + "S</h4>";
content += "<h4>12V voltage: " + String(datalayer_extended.KiaHyundai64.battery_12V / 10.0, 1) + "</h4>";
@ -1446,7 +1454,7 @@ String advanced_battery_processor(const String& var) {
!defined(TESLA_BATTERY) && !defined(NISSAN_LEAF_BATTERY) && !defined(BMW_I3_BATTERY) && \
!defined(BYD_ATTO_3_BATTERY) && !defined(RENAULT_ZOE_GEN2_BATTERY) && !defined(CELLPOWER_BMS) && \
!defined(MEB_BATTERY) && !defined(VOLVO_SPA_BATTERY) && !defined(VOLVO_SPA_HYBRID_BATTERY) && \
!defined(KIA_HYUNDAI_64_BATTERY) //Only the listed types have extra info
!defined(KIA_HYUNDAI_64_BATTERY) && !defined(GEELY_GEOMETRY_C_BATTERY) //Only the listed types have extra info
content += "No extra information available for this battery type";
#endif