diff --git a/Software/src/battery/NISSAN-LEAF-BATTERY.cpp b/Software/src/battery/NISSAN-LEAF-BATTERY.cpp index 5b9459cf..b46a93dc 100644 --- a/Software/src/battery/NISSAN-LEAF-BATTERY.cpp +++ b/Software/src/battery/NISSAN-LEAF-BATTERY.cpp @@ -453,6 +453,128 @@ void NissanLeafBattery::handle_incoming_can_frame(CAN_frame rx_frame) { } } + if (group_7bb == 0x06) //Balancing resistor status + { + if (rx_frame.data.u8[0] == 0x10) { //First frame (10 1A 61 06 [14 55 55 51]) + // Byte 4 (bits 0-7) + battery_balancing_shunts[0] = (rx_frame.data.u8[4] & 0b00000001); + battery_balancing_shunts[1] = (rx_frame.data.u8[4] & 0b00000010) >> 1; + battery_balancing_shunts[2] = (rx_frame.data.u8[4] & 0b00000100) >> 2; + battery_balancing_shunts[3] = (rx_frame.data.u8[4] & 0b00001000) >> 3; + battery_balancing_shunts[4] = (rx_frame.data.u8[4] & 0b00010000) >> 4; + battery_balancing_shunts[5] = (rx_frame.data.u8[4] & 0b00100000) >> 5; + battery_balancing_shunts[6] = (rx_frame.data.u8[4] & 0b01000000) >> 6; + battery_balancing_shunts[7] = (rx_frame.data.u8[4] & 0b10000000) >> 7; + // Byte 5 (bits 8-15) + battery_balancing_shunts[8] = (rx_frame.data.u8[5] & 0b00000001); + battery_balancing_shunts[9] = (rx_frame.data.u8[5] & 0b00000010) >> 1; + battery_balancing_shunts[10] = (rx_frame.data.u8[5] & 0b00000100) >> 2; + battery_balancing_shunts[11] = (rx_frame.data.u8[5] & 0b00001000) >> 3; + battery_balancing_shunts[12] = (rx_frame.data.u8[5] & 0b00010000) >> 4; + battery_balancing_shunts[13] = (rx_frame.data.u8[5] & 0b00100000) >> 5; + battery_balancing_shunts[14] = (rx_frame.data.u8[5] & 0b01000000) >> 6; + battery_balancing_shunts[15] = (rx_frame.data.u8[5] & 0b10000000) >> 7; + // Byte 6 (bits 16-23) + battery_balancing_shunts[16] = (rx_frame.data.u8[6] & 0b00000001); + battery_balancing_shunts[17] = (rx_frame.data.u8[6] & 0b00000010) >> 1; + battery_balancing_shunts[18] = (rx_frame.data.u8[6] & 0b00000100) >> 2; + battery_balancing_shunts[19] = (rx_frame.data.u8[6] & 0b00001000) >> 3; + battery_balancing_shunts[20] = (rx_frame.data.u8[6] & 0b00010000) >> 4; + battery_balancing_shunts[21] = (rx_frame.data.u8[6] & 0b00100000) >> 5; + battery_balancing_shunts[22] = (rx_frame.data.u8[6] & 0b01000000) >> 6; + battery_balancing_shunts[23] = (rx_frame.data.u8[6] & 0b10000000) >> 7; + // Byte 7 (bits 24-31) + battery_balancing_shunts[24] = (rx_frame.data.u8[7] & 0b00000001); + battery_balancing_shunts[25] = (rx_frame.data.u8[7] & 0b00000010) >> 1; + battery_balancing_shunts[26] = (rx_frame.data.u8[7] & 0b00000100) >> 2; + battery_balancing_shunts[27] = (rx_frame.data.u8[7] & 0b00001000) >> 3; + battery_balancing_shunts[28] = (rx_frame.data.u8[7] & 0b00010000) >> 4; + battery_balancing_shunts[29] = (rx_frame.data.u8[7] & 0b00100000) >> 5; + battery_balancing_shunts[30] = (rx_frame.data.u8[7] & 0b01000000) >> 6; + battery_balancing_shunts[31] = (rx_frame.data.u8[7] & 0b10000000) >> 7; + } + if (rx_frame.data.u8[0] == 0x21) { // Second frame (21 [50 55 41 2B 56 54 15]) + // Byte 1 (bits 32-39) + battery_balancing_shunts[32] = (rx_frame.data.u8[1] & 0b00000001); + battery_balancing_shunts[33] = (rx_frame.data.u8[1] & 0b00000010) >> 1; + battery_balancing_shunts[34] = (rx_frame.data.u8[1] & 0b00000100) >> 2; + battery_balancing_shunts[35] = (rx_frame.data.u8[1] & 0b00001000) >> 3; + battery_balancing_shunts[36] = (rx_frame.data.u8[1] & 0b00010000) >> 4; + battery_balancing_shunts[37] = (rx_frame.data.u8[1] & 0b00100000) >> 5; + battery_balancing_shunts[38] = (rx_frame.data.u8[1] & 0b01000000) >> 6; + battery_balancing_shunts[39] = (rx_frame.data.u8[1] & 0b10000000) >> 7; + // Byte 2 (bits 40-47) + battery_balancing_shunts[40] = (rx_frame.data.u8[2] & 0b00000001); + battery_balancing_shunts[41] = (rx_frame.data.u8[2] & 0b00000010) >> 1; + battery_balancing_shunts[42] = (rx_frame.data.u8[2] & 0b00000100) >> 2; + battery_balancing_shunts[43] = (rx_frame.data.u8[2] & 0b00001000) >> 3; + battery_balancing_shunts[44] = (rx_frame.data.u8[2] & 0b00010000) >> 4; + battery_balancing_shunts[45] = (rx_frame.data.u8[2] & 0b00100000) >> 5; + battery_balancing_shunts[46] = (rx_frame.data.u8[2] & 0b01000000) >> 6; + battery_balancing_shunts[47] = (rx_frame.data.u8[2] & 0b10000000) >> 7; + // Byte 3 (bits 48-55) + battery_balancing_shunts[48] = (rx_frame.data.u8[3] & 0b00000001); + battery_balancing_shunts[49] = (rx_frame.data.u8[3] & 0b00000010) >> 1; + battery_balancing_shunts[50] = (rx_frame.data.u8[3] & 0b00000100) >> 2; + battery_balancing_shunts[51] = (rx_frame.data.u8[3] & 0b00001000) >> 3; + battery_balancing_shunts[52] = (rx_frame.data.u8[3] & 0b00010000) >> 4; + battery_balancing_shunts[53] = (rx_frame.data.u8[3] & 0b00100000) >> 5; + battery_balancing_shunts[54] = (rx_frame.data.u8[3] & 0b01000000) >> 6; + battery_balancing_shunts[55] = (rx_frame.data.u8[3] & 0b10000000) >> 7; + //Byte 4 + battery_balancing_shunts[56] = (rx_frame.data.u8[4] & 0b00000001); + battery_balancing_shunts[57] = (rx_frame.data.u8[4] & 0b00000010) >> 1; + battery_balancing_shunts[58] = (rx_frame.data.u8[4] & 0b00000100) >> 2; + battery_balancing_shunts[59] = (rx_frame.data.u8[4] & 0b00001000) >> 3; + battery_balancing_shunts[60] = (rx_frame.data.u8[4] & 0b00010000) >> 4; + battery_balancing_shunts[61] = (rx_frame.data.u8[4] & 0b00100000) >> 5; + battery_balancing_shunts[62] = (rx_frame.data.u8[4] & 0b01000000) >> 6; + battery_balancing_shunts[63] = (rx_frame.data.u8[4] & 0b10000000) >> 7; + //Byte 5 + battery_balancing_shunts[64] = (rx_frame.data.u8[5] & 0b00000001); + battery_balancing_shunts[65] = (rx_frame.data.u8[5] & 0b00000010) >> 1; + battery_balancing_shunts[66] = (rx_frame.data.u8[5] & 0b00000100) >> 2; + battery_balancing_shunts[67] = (rx_frame.data.u8[5] & 0b00001000) >> 3; + battery_balancing_shunts[68] = (rx_frame.data.u8[5] & 0b00010000) >> 4; + battery_balancing_shunts[69] = (rx_frame.data.u8[5] & 0b00100000) >> 5; + battery_balancing_shunts[70] = (rx_frame.data.u8[5] & 0b01000000) >> 6; + battery_balancing_shunts[71] = (rx_frame.data.u8[5] & 0b10000000) >> 7; + //Byte 6 + battery_balancing_shunts[72] = (rx_frame.data.u8[6] & 0b00000001); + battery_balancing_shunts[73] = (rx_frame.data.u8[6] & 0b00000010) >> 1; + battery_balancing_shunts[74] = (rx_frame.data.u8[6] & 0b00000100) >> 2; + battery_balancing_shunts[75] = (rx_frame.data.u8[6] & 0b00001000) >> 3; + battery_balancing_shunts[76] = (rx_frame.data.u8[6] & 0b00010000) >> 4; + battery_balancing_shunts[77] = (rx_frame.data.u8[6] & 0b00100000) >> 5; + battery_balancing_shunts[78] = (rx_frame.data.u8[6] & 0b01000000) >> 6; + battery_balancing_shunts[79] = (rx_frame.data.u8[6] & 0b10000000) >> 7; + //Byte 7 + battery_balancing_shunts[80] = (rx_frame.data.u8[7] & 0b00000001); + battery_balancing_shunts[81] = (rx_frame.data.u8[7] & 0b00000010) >> 1; + battery_balancing_shunts[82] = (rx_frame.data.u8[7] & 0b00000100) >> 2; + battery_balancing_shunts[83] = (rx_frame.data.u8[7] & 0b00001000) >> 3; + battery_balancing_shunts[84] = (rx_frame.data.u8[7] & 0b00010000) >> 4; + battery_balancing_shunts[85] = (rx_frame.data.u8[7] & 0b00100000) >> 5; + battery_balancing_shunts[86] = (rx_frame.data.u8[7] & 0b01000000) >> 6; + battery_balancing_shunts[87] = (rx_frame.data.u8[7] & 0b10000000) >> 7; + } + if (rx_frame.data.u8[0] == 0x22) { //Third frame (22 51 FF FF FF FF FF FF) + //Byte 7 + battery_balancing_shunts[88] = (rx_frame.data.u8[1] & 0b00000001); + battery_balancing_shunts[89] = (rx_frame.data.u8[1] & 0b00000010) >> 1; + battery_balancing_shunts[90] = (rx_frame.data.u8[1] & 0b00000100) >> 2; + battery_balancing_shunts[91] = (rx_frame.data.u8[1] & 0b00001000) >> 3; + battery_balancing_shunts[92] = (rx_frame.data.u8[1] & 0b00010000) >> 4; + battery_balancing_shunts[93] = (rx_frame.data.u8[1] & 0b00100000) >> 5; + battery_balancing_shunts[94] = (rx_frame.data.u8[1] & 0b01000000) >> 6; + battery_balancing_shunts[95] = (rx_frame.data.u8[1] & 0b10000000) >> 7; + memcpy(datalayer_battery->status.cell_balancing_status, battery_balancing_shunts, 96 * sizeof(bool)); + } + + if (rx_frame.data.u8[0] == 0x23) { //Fourth frame (23 FF FF FF FF FF FF FF) + } + } + if (group_7bb == 0x83) //BatteryPartNumber { if (rx_frame.data.u8[0] == 0x10) { //First frame (101A6183334E4B32) @@ -704,7 +826,7 @@ void NissanLeafBattery::transmit_can(unsigned long currentMillis) { if (!stop_battery_query) { // Move to the next group - PIDindex = (PIDindex + 1) % 6; // 6 = amount of elements in the PIDgroups[] + PIDindex = (PIDindex + 1) % 7; // 7 = amount of elements in the PIDgroups[] LEAF_GROUP_REQUEST.data.u8[2] = PIDgroups[PIDindex]; transmit_can_frame(&LEAF_GROUP_REQUEST, can_interface); diff --git a/Software/src/battery/NISSAN-LEAF-BATTERY.h b/Software/src/battery/NISSAN-LEAF-BATTERY.h index 18cff8a9..2edf8578 100644 --- a/Software/src/battery/NISSAN-LEAF-BATTERY.h +++ b/Software/src/battery/NISSAN-LEAF-BATTERY.h @@ -82,7 +82,7 @@ class NissanLeafBattery : public CanBattery { .ID = 0x1D4, .data = {0x6E, 0x6E, 0x00, 0x04, 0x07, 0x46, 0xE0, 0x44}}; // Active polling messages - uint8_t PIDgroups[6] = {0x01, 0x02, 0x04, 0x83, 0x84, 0x90}; + uint8_t PIDgroups[7] = {0x01, 0x02, 0x04, 0x06, 0x83, 0x84, 0x90}; uint8_t PIDindex = 0; CAN_frame LEAF_GROUP_REQUEST = {.FD = false, .ext_ID = false, @@ -156,6 +156,7 @@ class NissanLeafBattery : public CanBattery { bool stop_battery_query = true; uint8_t hold_off_with_polling_10seconds = 2; //Paused for 20 seconds on startup uint16_t battery_cell_voltages[97]; //array with all the cellvoltages + bool battery_balancing_shunts[97]; //array with all the balancing resistors uint8_t battery_cellcounter = 0; uint16_t battery_min_max_voltage[2]; //contains cell min[0] and max[1] values in mV uint16_t battery_HX = 0; //Internal resistance diff --git a/Software/src/datalayer/datalayer.h b/Software/src/datalayer/datalayer.h index 2fdd84f4..f4860502 100644 --- a/Software/src/datalayer/datalayer.h +++ b/Software/src/datalayer/datalayer.h @@ -81,6 +81,11 @@ typedef struct { * Use with battery.info.number_of_cells to get valid data. */ uint16_t cell_voltages_mV[MAX_AMOUNT_CELLS]; + /** All balancing resistors status inside the pack, either on(1) or off(0). + * Use with battery.info.number_of_cells to get valid data. + * Not available for all battery manufacturers. + */ + bool cell_balancing_status[MAX_AMOUNT_CELLS]; /** The "real" SOC reported from the battery, in integer-percent x 100. 9550 = 95.50% */ uint16_t real_soc; /** The SOC reported to the inverter, in integer-percent x 100. 9550 = 95.50%.