Skip to content

Commit

Permalink
Merge pull request #840 from dalathegreat/bugfix/Atto3-temperature
Browse files Browse the repository at this point in the history
BYD Atto 3: Change temperature reading + code cleanup
  • Loading branch information
dalathegreat authored Feb 1, 2025
2 parents 6401001 + 2d49aaf commit 451d767
Showing 1 changed file with 101 additions and 138 deletions.
239 changes: 101 additions & 138 deletions Software/src/battery/BYD-ATTO-3-BATTERY.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
#include "../devboard/utils/events.h"
#include "BYD-ATTO-3-BATTERY.h"

/* TODO:
- Map all values from battery CAN messages
-SOC% still not found (Lets take it from PID poll, not working right yet)
-SOC% is now ESTIMATED. This is bad, and should be fixed as soon as possible with the real value from CAN
/* Notes
- SOC% by default is now ESTIMATED.
- If you have a non-crashed pack, enable using real SOC. See Wiki for info.
- TODO: In the future, we might be able to unlock crashed batteries and get SOC going always
*/

/* Do not change code below unless you are sure what you are doing */
Expand Down Expand Up @@ -135,22 +135,9 @@ void update_values_battery() { //This function maps all the values fetched via

datalayer.battery.status.cell_min_voltage_mV = BMS_lowest_cell_voltage_mV;

// Initialize min and max variables
battery_calc_min_temperature = battery_daughterboard_temperatures[0];
battery_calc_max_temperature = battery_daughterboard_temperatures[0];
datalayer.battery.status.temperature_min_dC = BMS_lowest_cell_temperature * 10; // Add decimals

// Loop through the array of daughterboard temps to find the smallest and largest values
for (int i = 1; i < 10; i++) {
if (battery_daughterboard_temperatures[i] < battery_calc_min_temperature) {
battery_calc_min_temperature = battery_daughterboard_temperatures[i];
}
if (battery_daughterboard_temperatures[i] > battery_calc_max_temperature) {
battery_calc_max_temperature = battery_daughterboard_temperatures[i];
}
}

datalayer.battery.status.temperature_min_dC = battery_calc_min_temperature * 10; // Add decimals
datalayer.battery.status.temperature_max_dC = battery_calc_max_temperature * 10;
datalayer.battery.status.temperature_max_dC = BMS_highest_cell_temperature * 10;

// Update webserver datalayer
datalayer_extended.bydAtto3.SOC_method = SOC_method;
Expand All @@ -163,61 +150,56 @@ void update_values_battery() { //This function maps all the values fetched via
}

void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
switch (rx_frame.ID) { //Log values taken with 422V from battery
case 0x244: //00,00,00,04,41,0F,20,8B - Static, values never changes between logs
switch (rx_frame.ID) {
case 0x244:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x245: //01,00,02,19,3A,25,90,F4 Seems to have a mux in frame0
case 0x245:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
//02,00,90,01,79,79,90,EA // Point of interest, went from 7E,75 to 7B,7C when discharging
//03,C6,88,12,FD,48,90,5C
//04,00,FF,FF,00,00,90,6D
if (rx_frame.data.u8[0] == 0x01) {
battery_temperature_ambient =
(rx_frame.data.u8[4] - 40); // TODO, check if this is actually temperature_ambient
battery_temperature_ambient = (rx_frame.data.u8[4] - 40);
}
break;
case 0x286: //01,FF,FF,FF,FF,FF,FF,04 - Static, values never changes between logs
case 0x286:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x334: //FF,FF,FF,FC,3F,00,F0,D7 - Static, values never changes between logs
case 0x334:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x338: //01,52,02,00,88,13,00,0F
//01,51,02,00,88,13,00,10 407.5V 18deg
//01,4F,02,00,88,13,00,12 408.5V 14deg
case 0x338:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x344: //00,52,02,CC,1F,FF,04,BD
case 0x344:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x345: //27,0B,00,00,00,E0,01,EC - Static, values never changes between logs
case 0x345:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x347: //FF,00,00,F9,FF,FF,FF,0A - Static, values never changes between logs
case 0x347:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x34A: //00,52,02,CC,1F,FF,04,BD
//00,51,02,CC,1F,FF,04,BE //407.5V 18deg
//00,4F,02,CC,1F,FF,04,C0 //408.5V 14deg
case 0x34A:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x35E: //01,00,C8,32,00,63,00,A1 - Flickering between A0 and A1, Could be temperature?
//01,00,64,01,10,63,00,26 //407.5V 18deg
//01,00,64,1C,10,63,00,0B //408.5V 14deg
case 0x35E:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x360: //30,19,DE,D1,0B,C3,4B,EE - Static, values never changes between logs, Last and first byte has F-0 counters
case 0x360:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x36C: //01,57,13,DC,08,70,17,29 Seems to have a mux in frame0 , first message is static, never changes between logs
//02,03,DC,05,C0,0F,0F,3B - Static, values never changes between logs
//03,86,01,40,06,5C,02,D1 - Static, values never changes between logs
//04,57,13,73,04,01,FF,1A - Static, values never changes between logs
//05,FF,FF,FF,FF,FF,FF,00 - Static, values never changes between logs
case 0x36C:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x438: //55,55,01,F6,47,2E,10,D9 - 0x10D9 = 4313
//55,55,01,F6,47,FD,0F,0B //407.5V 18deg
//55,55,01,F6,47,15,10,F2 //408.5V 14deg
case 0x438:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x43A: //7E,0A,B0,1C,63,E1,03,64
//7E,0A,E0,1E,63,E1,03,32 //407.5V 18deg
//7E,0A,66,1C,63,E1,03,AE //408.5V 14deg
case 0x43A:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x43B: //01,3B,06,39,FF,64,64,BD
//01,3B,06,38,FF,64,64,BE
case 0x43B:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x43C: // Daughterboard temperatures reside in this CAN message
case 0x43C:
if (rx_frame.data.u8[0] == 0x00) {
battery_daughterboard_temperatures[0] = (rx_frame.data.u8[1] - 40);
battery_daughterboard_temperatures[1] = (rx_frame.data.u8[2] - 40);
Expand All @@ -233,30 +215,31 @@ void handle_incoming_can_frame_battery(CAN_frame rx_frame) {
battery_daughterboard_temperatures[9] = (rx_frame.data.u8[4] - 40);
}
break;
case 0x43D: //Varies a lot
case 0x43D:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x444: //9E,01,88,13,64,64,98,65
//9A,01,B6,13,64,64,98,3B //407.5V 18deg
//9B,01,B8,13,64,64,98,38 //408.5V 14deg
//lowprecision_SOC = ???
case 0x444:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
battery_voltage = ((rx_frame.data.u8[1] & 0x0F) << 8) | rx_frame.data.u8[0];
//battery_temperature_something = rx_frame.data.u8[7] - 40; resides in frame 7
break;
case 0x445: //00,98,FF,FF,63,20,4E,98 - Static, values never changes between logs
case 0x445:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x446: //2C,D4,0C,4D,21,DC,0C,9D - 0,1,7th frame varies a lot
case 0x446:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x447: // Seems to contain more temperatures, highest and lowest?
//06,38,01,3B,E0,03,39,69
//06,36,02,36,E0,03,36,72,
case 0x447:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
battery_highprecision_SOC = ((rx_frame.data.u8[5] & 0x0F) << 8) | rx_frame.data.u8[4]; // 03 E0 = 992 = 99.2%
battery_lowest_temperature = (rx_frame.data.u8[1] - 40); //Best guess for now
battery_highest_temperature = (rx_frame.data.u8[3] - 40); //Best guess for now
break;
case 0x47B: //01,FF,FF,FF,FF,FF,FF,FF - Static, values never changes between logs
case 0x47B:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x524: //24,40,00,00,00,00,00,9B - Static, values never changes between logs
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE; // Let system know battery is sending CAN
case 0x524:
datalayer.battery.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x7EF: //OBD2 PID reply from battery
switch (rx_frame.data.u8[3]) {
Expand Down Expand Up @@ -316,7 +299,6 @@ void transmit_can_battery() {
ATTO_3_12D.data.u8[2] = 0x00; // Goes from 02->00
ATTO_3_12D.data.u8[3] = 0x22; // Goes from A0->22
ATTO_3_12D.data.u8[5] = 0x31; // Goes from 71->31
// TODO: handle more variations after more seconds have passed if needed
}

// Update the counters in frame 6 & 7 (they are not in sync)
Expand Down Expand Up @@ -441,7 +423,6 @@ void update_values_battery2() { //This function maps all the values fetched via
datalayer.battery2.status.voltage_dV = BMS2_voltage * 10;
}

//datalayer.battery2.status.real_soc = BMS_SOC * 100; //TODO: This is not yet found!
// We instead estimate the SOC% based on the battery2 voltage
// This is a very bad solution, and as soon as an usable SOC% value has been found on CAN, we should switch to that!
datalayer.battery2.status.real_soc = estimateSOC(datalayer.battery2.status.voltage_dV);
Expand All @@ -459,80 +440,60 @@ void update_values_battery2() { //This function maps all the values fetched via

datalayer.battery2.status.cell_min_voltage_mV = BMS2_lowest_cell_voltage_mV;

// Initialize min and max variables
battery2_calc_min_temperature = battery2_daughterboard_temperatures[0];
battery2_calc_max_temperature = battery2_daughterboard_temperatures[0];
datalayer.battery2.status.temperature_min_dC = BMS2_lowest_cell_temperature * 10; // Add decimals

// Loop through the array of daughterboard temps to find the smallest and largest values
for (int i = 1; i < 10; i++) {
if (battery2_daughterboard_temperatures[i] < battery2_calc_min_temperature) {
battery2_calc_min_temperature = battery2_daughterboard_temperatures[i];
}
if (battery2_daughterboard_temperatures[i] > battery2_calc_max_temperature) {
battery2_calc_max_temperature = battery2_daughterboard_temperatures[i];
}
}

datalayer.battery2.status.temperature_min_dC = battery2_calc_min_temperature * 10; // Add decimals
datalayer.battery2.status.temperature_max_dC = battery2_calc_max_temperature * 10;
datalayer.battery2.status.temperature_max_dC = BMS2_highest_cell_temperature * 10;
}

void handle_incoming_can_frame_battery2(CAN_frame rx_frame) {
switch (rx_frame.ID) { //Log values taken with 422V from battery2
case 0x244: //00,00,00,04,41,0F,20,8B - Static, values never changes between logs
switch (rx_frame.ID) {
case 0x244:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x245: //01,00,02,19,3A,25,90,F4 Seems to have a mux in frame0
case 0x245:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
//02,00,90,01,79,79,90,EA // Point of interest, went from 7E,75 to 7B,7C when discharging
//03,C6,88,12,FD,48,90,5C
//04,00,FF,FF,00,00,90,6D
if (rx_frame.data.u8[0] == 0x01) {
battery2_temperature_ambient =
(rx_frame.data.u8[4] - 40); // TODO, check if this is actually temperature_ambient
battery2_temperature_ambient = (rx_frame.data.u8[4] - 40);
}
break;
case 0x286: //01,FF,FF,FF,FF,FF,FF,04 - Static, values never changes between logs
break;
case 0x334: //FF,FF,FF,FC,3F,00,F0,D7 - Static, values never changes between logs
case 0x286:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x338: //01,52,02,00,88,13,00,0F
//01,51,02,00,88,13,00,10 407.5V 18deg
//01,4F,02,00,88,13,00,12 408.5V 14deg
case 0x334 datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE; break; case 0x338:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x344: //00,52,02,CC,1F,FF,04,BD
case 0x344:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x345: //27,0B,00,00,00,E0,01,EC - Static, values never changes between logs
case 0x345:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x347: //FF,00,00,F9,FF,FF,FF,0A - Static, values never changes between logs
case 0x347:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x34A: //00,52,02,CC,1F,FF,04,BD
//00,51,02,CC,1F,FF,04,BE //407.5V 18deg
//00,4F,02,CC,1F,FF,04,C0 //408.5V 14deg
case 0x34A:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x35E: //01,00,C8,32,00,63,00,A1 - Flickering between A0 and A1, Could be temperature?
//01,00,64,01,10,63,00,26 //407.5V 18deg
//01,00,64,1C,10,63,00,0B //408.5V 14deg
case 0x35E:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x360: //30,19,DE,D1,0B,C3,4B,EE - Static, values never changes between logs, Last and first byte has F-0 counters
case 0x360:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x36C: //01,57,13,DC,08,70,17,29 Seems to have a mux in frame0 , first message is static, never changes between logs
//02,03,DC,05,C0,0F,0F,3B - Static, values never changes between logs
//03,86,01,40,06,5C,02,D1 - Static, values never changes between logs
//04,57,13,73,04,01,FF,1A - Static, values never changes between logs
//05,FF,FF,FF,FF,FF,FF,00 - Static, values never changes between logs
case 0x36C:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x438: //55,55,01,F6,47,2E,10,D9 - 0x10D9 = 4313
//55,55,01,F6,47,FD,0F,0B //407.5V 18deg
//55,55,01,F6,47,15,10,F2 //408.5V 14deg
case 0x438:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x43A: //7E,0A,B0,1C,63,E1,03,64
//7E,0A,E0,1E,63,E1,03,32 //407.5V 18deg
//7E,0A,66,1C,63,E1,03,AE //408.5V 14deg
case 0x43A:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x43B: //01,3B,06,39,FF,64,64,BD
//01,3B,06,38,FF,64,64,BE
case 0x43B:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x43C: // Daughterboard temperatures reside in this CAN message
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
if (rx_frame.data.u8[0] == 0x00) {
battery2_daughterboard_temperatures[0] = (rx_frame.data.u8[1] - 40);
battery2_daughterboard_temperatures[1] = (rx_frame.data.u8[2] - 40);
Expand All @@ -548,27 +509,29 @@ void handle_incoming_can_frame_battery2(CAN_frame rx_frame) {
battery2_daughterboard_temperatures[9] = (rx_frame.data.u8[4] - 40);
}
break;
case 0x43D: //Varies a lot
case 0x43D:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x444: //9E,01,88,13,64,64,98,65
//9A,01,B6,13,64,64,98,3B //407.5V 18deg
//9B,01,B8,13,64,64,98,38 //408.5V 14deg
case 0x444:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x445: //00,98,FF,FF,63,20,4E,98 - Static, values never changes between logs
case 0x445:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x446: //2C,D4,0C,4D,21,DC,0C,9D - 0,1,7th frame varies a lot
case 0x446:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x447: // Seems to contain more temperatures, highest and lowest?
//06,38,01,3B,E0,03,39,69
//06,36,02,36,E0,03,36,72,
battery2_highprecision_SOC = ((rx_frame.data.u8[5] & 0x0F) << 8) | rx_frame.data.u8[4]; // 03 E0 = 992 = 99.2%
battery2_lowest_temperature = (rx_frame.data.u8[1] - 40); //Best guess for now
battery2_highest_temperature = (rx_frame.data.u8[3] - 40); //Best guess for now
case 0x447:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
battery2_highprecision_SOC = ((rx_frame.data.u8[5] & 0x0F) << 8) | rx_frame.data.u8[4];
battery2_lowest_temperature = (rx_frame.data.u8[1] - 40);
battery2_highest_temperature = (rx_frame.data.u8[3] - 40);
break;
case 0x47B: //01,FF,FF,FF,FF,FF,FF,FF - Static, values never changes between logs
case 0x47B:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x524: //24,40,00,00,00,00,00,9B - Static, values never changes between logs
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE; // Let system know battery2 is sending CAN
case 0x524:
datalayer.battery2.status.CAN_battery_still_alive = CAN_STILL_ALIVE;
break;
case 0x7EF: //OBD2 PID reply from battery2
switch (rx_frame.data.u8[3]) {
Expand Down

0 comments on commit 451d767

Please sign in to comment.