Here is everything that doc has to say on battery capacity calculation. Doesn't really demystify how the BMS actually calculates CAC, but gives a good overview of the high level stuff:
Battery Capacity/Range Calculations
General
The range of the vehicle, typically displayed in miles or kilometers, is a function of many parameters in the vehicle to provide the most accurate assessment of range remaining. We do this to prevent the customer from running out of charge prematurely. The voltage of the pack is directly correlated to the State of Charge (SOC) of the vehicle. This is indicated by the bar in the UI. However the capacity of the pack changes over time which means 100% SOC will always be 100% but the range can change based on the battery capacity. The capacity is tracked by the HVBMS in a value called Calculated Amp-hour Capacity (CAC).
Theory of Operation
The range calculation can be shown using the simple flowchart below.
Starting from left to right, we can see the first important number that comes into the equation is CAC. This number can viewed in logs and Garage and is constantly changing from HVBMS calculations to update the value to reflect energy capabilities in the pack. Note that this value is the Ah capacity for a single brick. All bricks have their capacities calculated and the minimum brick is used for the range calculation as is the brick that will at the end limit the pack capacity. As seen earlier, the parallel count of cells (brick) defines the pack energy storage capacity and the series count its power output.
Now to get the full capacity of the entire battery the value will need to be multiplied. Multiplied by the average brick voltage will give the kWh value. *Note that this full pack energy does take into account temperature in a small amount; therefore a really cold pack will have slightly less full pack energy.
The full pack energy is then just multiplied by the SOC of the pack. Therefore 50% SOC means .5 (or half) of the full pack energy.
The energy is then divided by a fixed Watt-hour per mile (whpm) value that is hard-coded into the pack based on the rated range setting and vehicle configuration. This is the average efficiency found during the EPA drive cycle testing (or EU/APAC equivalent standard). The final number will appear in units of distance and this is what is displayed on the MCU.
Capacity Specifications
As shown above, the capacity of the pack has a direct correlation to the final range displayed to the customer. CAC is calculated by the HVBMS by monitoring voltage change as well as current leaving and entering the pack. The simplified CAC calculation is indicated in the diagram below:
The pack shunt is used to count amp-hour over a certain amount of time. That value and on the delta SOC for that amp-hour amount is used to determine CAC. [JH5] This calculation is done whenever there is a drive or charge cycle however values are only stored when the calculation is deemed accurate. There are many complex parameters that factor into the accuracy of that number, and the HVBMS decides when the number is accurate enough to update CAC. One of these parameters is rest time before and after the drive/charge cycle. Notice in the figure above that the SOC was flat for a long time before and after the drive, this results in the most accurate voltage/SOC measurement which makes the CAC calculation accurate. Therefore in a worst case example, if a driver constantly charged and drove without ever letting the vehicle rest at a fixed SOC, then CAC algorithm will not update during that time.
Brick Balancing
Note that the capacity of a pack is limited by the brick with the lowest capacity. When that brick is charging, it will gain voltage faster than other bricks. The HVBMS will stop charge when any brick reaches its ceiling voltage (~4.2V). If one brick has a significantly lower capacity that others, the pack will be limited by that brick which will get to 4.2V faster than the other ones. We refer to the brick with the lowest capacity as: min CAC. In periscope, its value can be seen by viewing the signal: 'BMS_cacMin'
Another limitation could come from bricks being imbalanced, or some bricks with a voltage higher/lower than others. This would limit ability to charge the pack as the brick with a higher voltage than others would reach the ceiling voltage early. Same idea when discharging, the brick with the lowest voltage would hit the floor voltage early which would cause the HVBMS to open contactors from low power
To mitigate this imbalance, Batman has some bleed resistor that can be placed and removed in parallel of each brick via a FET relay. Batman can put that resistor across the brick with the highest voltage which would slightly discharge that brick and bring it back to the level of the other bricks. Batman closes a FET which puts that resistor across the brick. The HVBMS will order Batman to put that bleed resistor across the brick with the highest voltage when Delta V is > 5mv MinBrickV > 4.0v (~85% SOC) && HVBMS State == STAND BY.
Note that Batman can also do balancing when the HVBMS is asleep
![Smile :) :)](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
.
The best way to balance the Model 3 pack is to set charge limit to 90% or higher and let the vehicle sit idle for hours (plugged in or not). 24 hours of balancing can reduce imbalance by 1mV.