Merge pull request #1456 from greenoem/tesla-feature-socreset

Tesla: Add SOC reset feature
This commit is contained in:
Daniel Öster 2025-08-29 19:44:19 +03:00 committed by GitHub
commit 681b915faa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 69 additions and 1 deletions

View file

@ -74,6 +74,7 @@ class Battery {
virtual bool supports_clear_isolation() { return false; } virtual bool supports_clear_isolation() { return false; }
virtual bool supports_reset_BMS() { return false; } virtual bool supports_reset_BMS() { return false; }
virtual bool supports_reset_SOC() { return false; }
virtual bool supports_reset_crash() { return false; } virtual bool supports_reset_crash() { return false; }
virtual bool supports_reset_NVROL() { return false; } virtual bool supports_reset_NVROL() { return false; }
virtual bool supports_reset_DTC() { return false; } virtual bool supports_reset_DTC() { return false; }
@ -92,6 +93,7 @@ class Battery {
virtual void clear_isolation() {} virtual void clear_isolation() {}
virtual void reset_BMS() {} virtual void reset_BMS() {}
virtual void reset_SOC() {}
virtual void reset_crash() {} virtual void reset_crash() {}
virtual void reset_contactor() {} virtual void reset_contactor() {}
virtual void reset_NVROL() {} virtual void reset_NVROL() {}

View file

@ -727,10 +727,26 @@ void TeslaBattery::
#ifdef DEBUG_LOG #ifdef DEBUG_LOG
logging.println("ERROR: BMS reset failed due to contactors not being open, or BMS ECU not allowing it"); logging.println("ERROR: BMS reset failed due to contactors not being open, or BMS ECU not allowing it");
#endif //DEBUG_LOG #endif //DEBUG_LOG
stateMachineBMSReset = 0; stateMachineBMSReset = 0xFF;
datalayer.battery.settings.user_requests_tesla_bms_reset = false; datalayer.battery.settings.user_requests_tesla_bms_reset = false;
} }
} }
if (datalayer.battery.settings.user_requests_tesla_soc_reset) {
if (datalayer.battery.status.real_soc < 1500 || datalayer.battery.status.real_soc > 9000) {
//Start the SOC reset statemachine, only if SOC < 15% or > 90%
stateMachineSOCReset = 0;
datalayer.battery.settings.user_requests_tesla_soc_reset = false;
#ifdef DEBUG_LOG
logging.println("SOC reset requested");
#endif //DEBUG_LOG
} else {
#ifdef DEBUG_LOG
logging.println("ERROR: SOC reset failed due to SOC not being less than 15 or greater than 90");
#endif //DEBUG_LOG
stateMachineSOCReset = 0xFF;
datalayer.battery.settings.user_requests_tesla_soc_reset = false;
}
}
//Update 0x333 UI_chargeTerminationPct (bit 16, width 10) value to SOC max value - expose via UI? //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 //One firmware version this was seen at bit 17 width 11
@ -2312,6 +2328,47 @@ void TeslaBattery::transmit_can(unsigned long currentMillis) {
break; break;
} }
} }
if (stateMachineSOCReset != 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
switch (stateMachineSOCReset) {
case 0:
TESLA_602.data = {0x02, 0x27, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00};
transmit_can_frame(&TESLA_602);
stateMachineSOCReset = 1;
break;
case 1:
TESLA_602.data = {0x30, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00};
transmit_can_frame(&TESLA_602);
stateMachineSOCReset = 2;
break;
case 2:
TESLA_602.data = {0x10, 0x12, 0x27, 0x06, 0x35, 0x34, 0x37, 0x36};
transmit_can_frame(&TESLA_602);
stateMachineSOCReset = 3;
break;
case 3:
TESLA_602.data = {0x21, 0x31, 0x30, 0x33, 0x32, 0x3D, 0x3C, 0x3F};
transmit_can_frame(&TESLA_602);
stateMachineSOCReset = 4;
break;
case 4:
TESLA_602.data = {0x22, 0x3E, 0x39, 0x38, 0x3B, 0x3A, 0x00, 0x00};
transmit_can_frame(&TESLA_602);
//Should generate a CAN UDS log message indicating ECU unlocked
stateMachineSOCReset = 5;
break;
case 5:
TESLA_602.data = {0x04, 0x31, 0x01, 0x04, 0x07, 0x00, 0x00, 0x00};
transmit_can_frame(&TESLA_602);
stateMachineSOCReset = 0xFF;
break;
default:
//Something went wrong. Reset all and cancel
stateMachineSOCReset = 0xFF;
break;
}
}
if (stateMachineBMSQuery != 0xFF) { if (stateMachineBMSQuery != 0xFF) {
//This implementation should be rewritten to actually reply to the UDS responses 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 query logic //While this may work, it is not the correct way to implement this query logic

View file

@ -33,6 +33,9 @@ class TeslaBattery : public CanBattery {
bool supports_reset_BMS() { return true; } bool supports_reset_BMS() { return true; }
void reset_BMS() { datalayer.battery.settings.user_requests_tesla_bms_reset = true; } void reset_BMS() { datalayer.battery.settings.user_requests_tesla_bms_reset = true; }
bool supports_reset_SOC() { return true; }
void reset_SOC() { datalayer.battery.settings.user_requests_tesla_soc_reset = true; }
bool supports_charged_energy() { return true; } bool supports_charged_energy() { return true; }
BatteryHtmlRenderer& get_status_renderer() { return renderer; } BatteryHtmlRenderer& get_status_renderer() { return renderer; }
@ -486,6 +489,7 @@ class TeslaBattery : public CanBattery {
uint8_t stateMachineClearIsolationFault = 0xFF; uint8_t stateMachineClearIsolationFault = 0xFF;
uint8_t stateMachineBMSReset = 0xFF; uint8_t stateMachineBMSReset = 0xFF;
uint8_t stateMachineSOCReset = 0xFF;
uint8_t stateMachineBMSQuery = 0xFF; uint8_t stateMachineBMSQuery = 0xFF;
uint16_t sendContactorClosingMessagesStill = 300; uint16_t sendContactorClosingMessagesStill = 300;
uint16_t battery_cell_max_v = 3300; uint16_t battery_cell_max_v = 3300;

View file

@ -152,6 +152,7 @@ struct DATALAYER_BATTERY_SETTINGS_TYPE {
bool user_requests_balancing = false; bool user_requests_balancing = false;
bool user_requests_tesla_isolation_clear = false; bool user_requests_tesla_isolation_clear = false;
bool user_requests_tesla_bms_reset = false; bool user_requests_tesla_bms_reset = false;
bool user_requests_tesla_soc_reset = false;
/* Forced balancing max time & start timestamp */ /* Forced balancing max time & start timestamp */
uint32_t balancing_time_ms = 3600000; //1h default, (60min*60sec*1000ms) uint32_t balancing_time_ms = 3600000; //1h default, (60min*60sec*1000ms)
uint32_t balancing_start_time_ms = 0; //For keeping track when balancing started uint32_t balancing_start_time_ms = 0; //For keeping track when balancing started

View file

@ -25,6 +25,10 @@ std::vector<BatteryCommand> battery_commands = {
[](Battery* b) { [](Battery* b) {
b->reset_BMS(); b->reset_BMS();
}}, }},
{"resetSOC", "SOC reset", "reset SOC?", [](Battery* b) { return b && b->supports_reset_SOC(); },
[](Battery* b) {
b->reset_SOC();
}},
{"resetCrash", "Unlock crashed BMS", {"resetCrash", "Unlock crashed BMS",
"reset crash data? Note this will unlock your BMS and enable contactor closing and SOC calculation.", "reset crash data? Note this will unlock your BMS and enable contactor closing and SOC calculation.",
[](Battery* b) { return b && b->supports_reset_crash(); }, [](Battery* b) { return b && b->supports_reset_crash(); },