@@ -10,6 +10,7 @@ static uint8_t stillAliveCAN = 6; //counter for checking if CAN is still alive
1010CAN_frame_t TESLA_221_1 = {.FIR = {.B = {.DLC = 8 ,.FF = CAN_frame_std,}},.MsgID = 0x221 ,.data = {0x41 , 0x11 , 0x01 , 0x00 , 0x00 , 0x00 , 0x20 , 0x96 }};
1111CAN_frame_t TESLA_221_2 = {.FIR = {.B = {.DLC = 8 ,.FF = CAN_frame_std,}},.MsgID = 0x221 ,.data = {0x61 , 0x15 , 0x01 , 0x00 , 0x00 , 0x00 , 0x20 , 0xBA }};
1212
13+ static uint32_t temporaryvariable = 0 ;
1314static uint32_t total_discharge = 0 ;
1415static uint32_t total_charge = 0 ;
1516static uint16_t volts = 0 ; // V
@@ -40,18 +41,28 @@ static uint16_t soc_min = 0;
4041static uint16_t soc_max = 0 ;
4142static uint16_t soc_vi = 0 ;
4243static uint16_t soc_ave = 0 ;
44+ static uint16_t cell_max_v = 0 ;
45+ static uint16_t cell_min_v = 0 ;
46+ static uint16_t cell_deviation_mV = 0 ; // contains the deviation between highest and lowest cell in mV
47+ static uint8_t max_vno = 0 ;
48+ static uint8_t min_vno = 0 ;
4349static uint8_t contactor = 0 ; // State of contactor
4450static uint8_t hvil_status = 0 ;
4551static uint8_t packContNegativeState = 0 ;
4652static uint8_t packContPositiveState = 0 ;
4753static uint8_t packContactorSetState = 0 ;
4854static uint8_t packCtrsClosingAllowed = 0 ;
4955static uint8_t pyroTestInProgress = 0 ;
50- static const char * contactorText[] = {" UNKNOWN0" ," OPEN" ," CLOSING" ," BLOCKED" ," OPENING" ," CLOSED" ," UNKNOWN6" ," WELDED" ," POS_CL" ," NEG_CL" ," UNKNOWN10" ," UNKNOWN11" ," UNKNOWN12" };
51- static const char * contactorState[] = {" SNA" ," OPEN" ," PRECHARGE" ," BLOCKED" ," PULLED_IN" ," OPENING" ," ECONOMIZED" ," WELDED" };
56+ static const char * contactorText[] = {" UNKNOWN(0)" ," OPEN" ," CLOSING" ," BLOCKED" ," OPENING" ," CLOSED" ," UNKNOWN(6)" ," WELDED" ," POS_CL" ," NEG_CL" ," UNKNOWN(10)" ," UNKNOWN(11)" ," UNKNOWN(12)" };
57+ static const char * contactorState[] = {" SNA" ," OPEN" ," PRECHARGE" ," BLOCKED" ," PULLED_IN" ," OPENING" ," ECONOMIZED" ," WELDED" ," UNKNOWN(8)" ," UNKNOWN(9)" ," UNKNOWN(10)" ," UNKNOWN(11)" };
58+ static const char * hvilStatusState[] = {" NOT OK" ," STATUS_OK" ," CURRENT_SOURCE_FAULT" ," INTERNAL_OPEN_FAULT" ," VEHICLE_OPEN_FAULT" ," PENTHOUSE_LID_OPEN_FAULT" ," UNKNOWN_LOCATION_OPEN_FAULT" ," VEHICLE_NODE_FAULT" ," NO_12V_SUPPLY" ," VEHICLE_OR_PENTHOUSE_LID_OPENFAULT" ," UNKNOWN(10)" ," UNKNOWN(11)" ," UNKNOWN(12)" ," UNKNOWN(13)" ," UNKNOWN(14)" ," UNKNOWN(15)" };
59+
5260
5361#define MAX_SOC 1000 // BMS never goes over this value. We use this info to rescale SOC% sent to inverter
5462#define MIN_SOC 0 // BMS never goes below this value. We use this info to rescale SOC% sent to inverter
63+ #define MAX_CELL_VOLTAGE 4250 // Battery is put into emergency stop if one cell goes over this value (These values might need tweaking based on chemistry)
64+ #define MIN_CELL_VOLTAGE 2950 // Battery is put into emergency stop if one cell goes below this value (These values might need tweaking based on chemistry)
65+ #define MAX_CELL_DEVIATION 500 // LED turns yellow on the board if mv delta exceeds this value
5566
5667void update_values_tesla_model_3_battery ()
5768{ // This function maps all the values fetched via CAN to the correct parameters used for modbus
@@ -81,10 +92,24 @@ void update_values_tesla_model_3_battery()
8192
8293 remaining_capacity_Wh = (expected_energy_remaining * 100 ); // Scale up 60.3kWh -> 60300Wh
8394
84- max_target_discharge_power = max_discharge_current;
95+ // Calculate the allowed discharge power, cap it if it gets too large
96+ temporaryvariable = (max_discharge_current * volts);
97+ if (temporaryvariable > 60000 ){
98+ max_target_discharge_power = 60000 ;
99+ }
100+ else {
101+ max_target_discharge_power = temporaryvariable;
102+ }
103+
104+ // Calculate the allowed charge power, cap it if it gets too large
105+ temporaryvariable = (max_charge_current * volts);
106+ if (temporaryvariable > 60000 ){
107+ max_target_charge_power = 60000 ;
108+ }
109+ else {
110+ max_target_charge_power = temporaryvariable;
111+ }
85112
86- max_target_charge_power = max_charge_current;
87-
88113 stat_batt_power = (volts * amps); // TODO, check if scaling is OK
89114
90115 min_temp = (min_temp * 10 );
@@ -106,6 +131,22 @@ void update_values_tesla_model_3_battery()
106131 stillAliveCAN--;
107132 }
108133
134+ if (cell_max_v >= MAX_CELL_VOLTAGE){
135+ bms_status = FAULT;
136+ Serial.println (" CELL OVERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!" );
137+ }
138+ if (cell_min_v <= MIN_CELL_VOLTAGE){
139+ bms_status = FAULT;
140+ Serial.println (" CELL UNDERVOLTAGE!!! Stopping battery charging and discharging. Inspect battery!" );
141+ }
142+
143+ cell_deviation_mV = (cell_max_v - cell_min_v);
144+
145+ if (cell_deviation_mV > MAX_CELL_DEVIATION){
146+ LEDcolor = YELLOW;
147+ Serial.println (" HIGH CELL DEVIATION!!! Inspect battery!" );
148+ }
149+
109150 #ifdef DEBUG_VIA_USB
110151 if (packCtrsClosingAllowed == 0 )
111152 {
@@ -119,7 +160,7 @@ void update_values_tesla_model_3_battery()
119160 Serial.print (" Contactor: " );
120161 Serial.print (contactorText[contactor]); // Display what state the contactor is in
121162 Serial.print (" , HVIL: " );
122- Serial.print (hvil_status);
163+ Serial.print (hvilStatusState[ hvil_status] );
123164 Serial.print (" , NegativeState: " );
124165 Serial.print (contactorState[packContNegativeState]);
125166 Serial.print (" , PositiveState: " );
@@ -134,6 +175,12 @@ void update_values_tesla_model_3_battery()
134175 Serial.println (" Battery values: " );
135176 Serial.print (" Vi SOC: " );
136177 Serial.print (soc_vi);
178+ Serial.print (" SOC max: " );
179+ Serial.print (soc_max);
180+ Serial.print (" SOC min: " );
181+ Serial.print (soc_min);
182+ Serial.print (" SOC avg: " );
183+ Serial.print (soc_ave);
137184 Serial.print (" , Battery voltage: " );
138185 Serial.print (volts);
139186 Serial.print (" , Battery amps: " );
@@ -142,18 +189,6 @@ void update_values_tesla_model_3_battery()
142189 Serial.print (discharge_limit);
143190 Serial.print (" , Charge limit battery (kW): " );
144191 Serial.print (regenerative_limit);
145- Serial.print (" , Nominal full energy (XX.XkWh): " );
146- Serial.print (nominal_full_pack_energy);
147- Serial.print (" , Nominal energy remain: " );
148- Serial.print (nominal_energy_remaining);
149- Serial.print (" , Expected energy remain: " );
150- Serial.print (expected_energy_remaining);
151- Serial.print (" , Ideal energy remaining: " );
152- Serial.print (ideal_energy_remaining);
153- Serial.print (" , Energy to charge complete: " );
154- Serial.print (energy_to_charge_complete);
155- Serial.print (" , Energy buffer: " );
156- Serial.print (energy_buffer);
157192 Serial.print (" , Fully charged?: " );
158193 Serial.print (full_charge_complete);
159194 Serial.print (" , Min discharge voltage allowed: " );
@@ -165,6 +200,15 @@ void update_values_tesla_model_3_battery()
165200 Serial.print (" , Max discharge current (A): " );
166201 Serial.println (max_discharge_current);
167202
203+ Serial.print (" Cellstats, Max mV: " );
204+ Serial.print (cell_max_v);
205+ Serial.print (" , on cell no#: " );
206+ Serial.print (max_vno);
207+ Serial.print (" , Min mV: " );
208+ Serial.print (cell_min_v);
209+ Serial.print (" , on cell no#: " );
210+ Serial.println (min_vno);
211+
168212 Serial.print (" HighVoltage Output Pins: " );
169213 Serial.print (high_voltage);
170214 Serial.print (" , V, Low Voltage:" );
@@ -246,13 +290,18 @@ void receive_can_tesla_model_3_battery(CAN_frame_t rx_frame)
246290 break ;
247291 case 0x332 :
248292 // min/max hist values
249- mux = rx_frame.data .u8 [0 ];
250- mux = mux & 0x03 ;
293+ mux = (rx_frame.data .u8 [0 ] & 0x03 );
251294
252295 if (mux == 1 ) // Cell voltages
253296 {
254- // todo handle cell voltages
255- // not required by the Gen24, but nice stats located here!
297+ temp = ((rx_frame.data .u8 [1 ] << 6 ) | (rx_frame.data .u8 [0 ] >> 2 ));
298+ temp = (temp & 0xFFF );
299+ cell_max_v = temp*2 ;
300+ temp = ((rx_frame.data .u8 [3 ] << 8 ) | rx_frame.data .u8 [2 ]);
301+ temp = (temp & 0xFFF );
302+ cell_min_v = temp*2 ;
303+ max_vno = 1 + (rx_frame.data .u8 [4 ] & 0x7F ); // This cell has highest voltage
304+ min_vno = 1 + (rx_frame.data .u8 [5 ] & 0x7F ); // This cell has lowest voltage
256305 }
257306 if (mux == 0 )// Temperature sensors
258307 {
0 commit comments