Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ramped charge value for Tesla #100

Merged
merged 8 commits into from
Nov 22, 2023
Merged

Add ramped charge value for Tesla #100

merged 8 commits into from
Nov 22, 2023

Conversation

dalathegreat
Copy link
Owner

@dalathegreat dalathegreat commented Nov 19, 2023

What

This PR adds a new feature for Tesla batteries, smoothing of charge max value for when battery approaches 100%

Why

@Newevg noticed that when trying to charge their LFP Tesla battery to 100%, charging it with 15kW all the way up to 100% was not possible. To reach 100%, the charge needs to taper off, otherwise the contactors would open, and the BMS would flag a fault.

How

The .header file now has a configurable max value, MAXCHARGEPOWERALLOWED. This value, which defaults to 15000W, will be used when battery is between 0-95%. When battery reaches 95%, it ramps between MAXCHARGEPOWERALLOWED-> 0 in the 95-100% range. This should allow the battery to more gracefully reach 100%.

lenvm
lenvm previously approved these changes Nov 20, 2023
@@ -156,7 +156,7 @@ static const char* hvilStatusState[] = {"NOT OK",
#define MIN_CELL_VOLTAGE_NCA_NCM 2950 //Battery is put into emergency stop if one cell goes below this value
#define MAX_CELL_DEVIATION_NCA_NCM 500 //LED turns yellow on the board if mv delta exceeds this value

#define MAX_CELL_VOLTAGE_LFP 3450 //Battery is put into emergency stop if one cell goes over this value
#define MAX_CELL_VOLTAGE_LFP 3500 //Battery is put into emergency stop if one cell goes over this value
#define MIN_CELL_VOLTAGE_LFP 2800 //Battery is put into emergency stop if one cell goes over this value
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change "goes over this value" to "goes under this value".

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6801e83

Comment on lines 200 to 201
} else if (SOC > 9500) { // When battery is between 95-99.99%, ramp the value between Max<->0
max_target_charge_power = MAXCHARGEPOWERALLOWED * (1 - (SOC - 9500) / 500.0);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since SOC is different from real SOC of the pack, this ramp will need to change depending on the difference between these 2 as well. For example, if the user only wants to change the battery to 70% real SOC (which will be 100% inverter SOC) we may not even need the curve.

So I think this needs to be re-implemented to take the value of MAXPERCENTAGE into account.

But even better, ideally what we want to do a feedback loop that looks at the voltage of the most charged cell group and scale down charge power to bring it slightly below the max voltage, and scale up charge power if the voltage gets lower than (max voltage - some threshold). That is the most efficient way to charge a battery. Even if MAXPERCENTAGE is something like 80% this method will ensure that the pack will be charged the quickest to that SOC.

I think we should ignore the SOC that the battery reports (which is based on a calculation) and just go off max cell voltage for the ramp.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Max cell voltage will be proportional to charge speed, so basing the ramp on max cell voltage might cause oscillations.

I instead propose we use SOC_VI for the ramp. That way incase user limits battery to between 20-80%, the value will never ramp. And incase user extends the range closer to 0-100%, we will use a ramped value at the extremes.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK makes sense, basing the ramp on the real SOC is the way to go. Also how is the 95% number derived? Seems like this number will change based the max charge power and battery capacity. So for some configurations we may want to start ramping at 90% for example.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matvey83 The 95% number comes from watching multiple different battery vendors throttle charging at end of SOC%. Fastcharging usually starts throttling at 80%, but AC slowcharging is ~95% where it starts to taper off.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

@dalathegreat
Copy link
Owner Author

@matvey83 and @lenvm , I reworked the ramp logic to avoid having users that restrict their battery encounter slow charging.

I also added an extra safety check in bf292a1

@@ -193,12 +193,17 @@ void update_values_tesla_model_3_battery() { //This function maps all the value
} else {
max_target_discharge_power = temporaryvariable;
}
if (SOC < 20) { // When battery is lower than 0.20% , set allowed discharge W to 0
Copy link
Collaborator

@lenvm lenvm Nov 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of hardcoding the value 20 (representing 0.20%), shouldn’t this be based on MINPERCENTAGE?

Copy link
Collaborator

@lenvm lenvm Nov 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also change these lines into one if, else if statement that defines the max_target_discharge_power, rather than two separate if statements.

Additionally let's define MAXDISCHARGEPOWERALLOWED as 60000.

Suggested code:

// Define the allowed discharge power
max_target_discharge_power = (max_discharge_current * volts);
// Cap the allowed discharge power if real SOC is lower than the minimum percentage, or discharge power is higher than the maximum discharge power allowed
if (soc_vi < MINPERCENTAGE) {  // When real SOC is lower than the minimum percentage, set allowed discharge power to 0
  max_target_discharge_power = 0;
else if (max_target_discharge_power > MAXDISCHARGEPOWERALLOWED) {
  max_target_discharge_power = MAXDISCHARGEPOWERALLOWED;
}

This also removes the need for the temporaryvariable.

Additionally I would like to suggest to define, in another pull request, a convention how SOC and other percentages are defined, either 20.0% as 200 (as is the case for MINPERCENTAGE and soc_vi), or 20.00% as 2000 (as is the case for SOC), such that we don't make conversion mistakes.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lenvm fixed in e2d3c4f , I decided against using MINPERCENTAGE, and going for the simpler if SOC=0 check, since that is what other battery types use! Nice bonus with the temporaryvariable removed!

if (soc_vi > 950) { // When battery is between 95-99.99% real SOC, ramp the value between Max<->0
max_target_charge_power = MAXCHARGEPOWERALLOWED * (1 - (soc_vi - 950) / 50.0);
}
if (SOC == 10000) { // When battery is defined as 100% full, set allowed charge W to 0
Copy link
Collaborator

@lenvm lenvm Nov 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of two separate if statements, I suggest using one large if, else if, else statement:

if (SOC == 10000) {  // When SOC is 100%, set allowed charge power to 0
  max_target_charge_power = 0;
} else if (soc_vi > 950) {  // When real SOC is between 95-99.99%, ramp the value between Max<->0
  max_target_charge power = MAXCHARGEPOWERALLOWED * (1 - (soc_vi - 950) / 50.0);
} else {
  max_target_charge_power = MAXCHARGEPOWERALLOWED;
}

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good improvement, fixed in 36deffd

@lenvm lenvm self-requested a review November 21, 2023 20:21
@lenvm lenvm dismissed their stale review November 21, 2023 20:22

PR changed

@lenvm
Copy link
Collaborator

lenvm commented Nov 21, 2023

Another way to implement the charge power limit, is to use the charge limit that is reported by the battery on CAN.

According to this repository, message 594 = 0x252 reports the BMS charge and discharge limits.

0x252 is already read from CAN, including the BMS charge and discharge power limits, in https://github.com/dalathegreat/BYD-Battery-Emulator-For-Gen24/blob/baa7841f324ab6b21207d3e9aab67eac3c71d250/Software/src/battery/TESLA-MODEL-3-BATTERY.cpp#L376-L377

Can these values not be used directly as max_target_charge_power and max_target_discharge_power?

@dalathegreat
Copy link
Owner Author

@lenvm For some reason the Tesla packs are not satisfied, and will show 0kW on regenerative_limit
bild

So this is why we need the ramp, for now!

@rjsc rjsc merged commit 65a126d into main Nov 22, 2023
32 checks passed
@rjsc rjsc deleted the feature/charge-ramp-tesla branch November 22, 2023 22:14
@rjsc rjsc restored the feature/charge-ramp-tesla branch November 22, 2023 22:50
@dalathegreat dalathegreat deleted the feature/charge-ramp-tesla branch November 25, 2023 09:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants