[Ovmsdev] Remaining Charge calculator

Michael Geddes frog at bunyip.wheelycreek.net
Sat Dec 31 18:10:43 HKT 2022


Ok,
so I've reviewed my current charge curve and have another idea as to what
was happening... which is that the charger itself was dynamically changing
the power-available to be used for charging .. and stepping up and down in
increments.  This makes sense of the difference between the two charge
sessions I recorded by hand, and the stepped nature of the curve I recorded.

The only  vehicle code that takes temperature into account is the roadster
.. which is definitely not generic... and is doing calculations in miles
and degrees Celsius (weird) and is possibly not going to be relevant or
easy to leverage.  All other code  (apart from VWUP) uses:
* A custom function (no table)
* a single flat value or
* a version of the flat stepped code with percent ranges.

I'll move mine to use a (calculated) gradient between points and lose
the dependence on voltage.

I don't see that your code significantly reduces the number of division
operations used (though I totally understand that aim) since it uses it for
the first and last soc section only.

What might actually be better is a temperature efficiency gradient centred
around 20 degrees. Either a single one - or in the table. See below.

//.ichael

----8<--


// Charging profile//  - Must be from lowest to highest to%.//  - max
watts is at optimal temperature.//  - MaxWattsUsed = maxChargeWatts *
1-(|battery_temp - tempOptimal| * tempDegrade)
// 0.0182 means degrades by 40% of original at zero degress// -
GUESTIMATE ONLY needs data.
charging_step_t ioniq5_chargesteps[] = {
  //  to     max  optimal temp degrade
  //   %   watts  deg C   gradient
  {   10, 220000,    22,  0.0182 },
  {   25, 210000,    22,  0.0182 },
  {   45, 200000,    22,  0.0182 },
  {   75, 150000,    22,  0.0182 },
  {   80,  80000,    22,  0.0182 },
  {   85,  60000,    22,  0.0182 },
  {   90,  40000,    22,  0.0182 },
  {   95,  25000,    22,  0.0182 },
  {  100,   7200,    22,  0.0182 },
  { 0, 0, 0, 0},
};/** Calculate the remaining minutes to charge.
  * Works on the premise that the charge curve applies to the MAXIMUM only.
  * Each section is calculated such that the 'max watts' is
effectively the 'end' value at that 'to'..
  * and the power use is assumed to be a gradient from the last 'to'
value to the end 'to' value.*/int CalcRemainingChargeMins(int
chargeVolt, float chargewatts, float availwatts, bool adjustTemp,
float tempCelcius, int fromSoc, int toSoc, int batterySizeWh,
charging_step_t charge_steps[])
{
  if (chargewatts <= 0 || fromSoc >= toSoc)
    return 0;
  if (availwatts < chargewatts) // encompasses '0' case.
    availwatts = chargewatts;

  int last_to_soc = fromSoc;
  int last_speed = chargewatts;

  // Track the sum of percent/kw.  Reduces floating point operations.
  // The 'batterySizeWh' * 60 / 100 would be used on every sum.. so
factored to the end.
  float sumval = 0;
  for (int i = 0; charge_steps[i].maxChargeWatts > 0; ++i) {
    const charging_step_t &step = charge_steps[i];
    if (/*step.voltage <= chargeVolt &&*/ step.toPercent > last_to_soc) {
      int next_to_soc = std::min(toSoc, step.toPercent);
      int percents_In_Step = next_to_soc - last_to_soc;
      float maxCharge = step.maxChargeWatts ;
      if (adjustTemp && step.tempOptimal > 0)
        maxCharge *= 1-(std::abs(tempCelcius - step.tempOptimal) *
step.tempDegrade);
      float endSpeed = std::min(availwatts, maxCharge);
      // Keep it as a doubled value here to avoid a /2 which becomes *2 below.
      float curSpeedDbl = last_speed + endSpeed;

      // our one division.
      sumval += ( percents_In_Step * 2) / curSpeedDbl;
      last_to_soc = next_to_soc;
      last_speed = endSpeed;
    }
  }
  if (last_to_soc < toSoc) {
    sumval +=  (toSoc - last_to_soc) / last_speed;
  }
  // convert to minutes (summary value to minutes)
  return (int)((batterySizeWh * sumval * 0.6/* 60/100 */) + 0.5);
}



On Fri, 30 Dec 2022 at 07:59, Michael Geddes <frog at bunyip.wheelycreek.net>
wrote:

> Firstly, the Voltage architecture (800V, 400V, 240V 3Phase,  240V 1Phase)
> in use  is going to affect the amount of power able to be delivered because
> the limiting factor will be the current  and possibly the potential
> difference across the individual cell (?)- so it is my _thesis_ that this
> will matter, especially in the mid section of the charging;  I need to get
> more information on this so I have made a plugin to handle gathering data.
> I'm quite happy to ditch it if it doesn't bare out.
> Ah, also there are two more metrics that I should log that you have
> reminded me of: The available power (I think I have that metric) and the
> temperature (? ave of the batteries perhaps).
>
> I'll have to try and get to one of the few 800v chargers available in my
> state again - finding 50kw chargers is pretty easy.
>
> I have mapped by hand the charging 'curve' at an 800V charger (only 150kw
> or so though - so yes, power also matters), and my experience was that it
> was quite 'stepped' - ie it seemed to go in stages.  Though I can see the
> advantage of the gradient, the only time it went to more of a
> curve/gradient is a little bit in the transition areas and  above 90% SOC (
> which I'm not really fussed with being too precise above 90%).
>
>  I'm still a little uncertain how to handle coming from a low SOC as the
> lower SOC charges a bit slower, so still need to manage somehow the maximum
> power available to the charger (which I possibly have as a metric - I
> should probably include that in the logging and in the calculation, and
> yes, that might end up being a better input into the algorithm).
>
> The way I have it working (btw) means that a higher voltage architecture
> defaults to the lower voltage curve (line) if a higher step isn't there. So
> where the curves (lines) converge I don't double up on data in the table.
> The AC Charger seems to be pretty constant right up to 90% for example.
>
> //.ichael
>
> On Fri, 30 Dec 2022 at 02:50, Michael Balzer <dexter at expeedo.de> wrote:
>
>> Michael,
>>
>> while it makes sense to add a general standard utility for this, I don't
>> think the Hyundai/Kia code is a good candidate for this.
>>
>> I find it confusing you need to take the voltage into account rather
>> than the power. Also, the "WattHours" numbers don't seem to make sense
>> -- why would you have different capacities in the same SOC differences,
>> and why depending on the voltage? Also, the calculator seems to need /
>> be based on rectangular steps instead of an actual charge curve?
>>
>> A more natural generalized definition would in my opinion be based on
>> modeling the actual curve, like the one I've implemented for the VW Up,
>> see `OvmsVehicleVWeUp::CalcChargeTime()`. That takes the charge curve as
>> direct (SOC → max power) coordinates, just adding the section gradients
>> as a speed optimization (float divisions are very CPU intense on the
>> ESP32):
>>
>>    struct {
>>      int soc;  float pwr;    float grd;
>>    } ccurve[] = {
>>      {     0,       30.0,    (32.5-30.0) / ( 30-  0) },
>>      {    30,       32.5,    (26.5-32.5) / ( 55- 30) },
>>      {    55,       26.5,    (18.5-26.5) / ( 76- 55) },
>>      {    76,       18.5,    (11.0-18.5) / ( 81- 76) },
>>      {    81,       11.0,    ( 6.5-11.0) / ( 91- 81) },
>>      {    91,        6.5,    ( 3.0- 6.5) / (100- 91) },
>>      {   100,        3.0,    0                       },
>>    };
>>
>> But maybe some other vehicle already has an even more generalized & easy
>> to use approach. My function lacks temperature compensation, but
>> normally delivers sufficiently close results.
>>
>> Regards,
>> Michael
>>
>>
>> Am 29.12.22 um 13:02 schrieb Michael Geddes:
>> > Hi,
>> >
>> > There's a remaining charge calculator currently in the hyundai base
>> > class which I have improved upon.  This configuration allows for the
>> > charge voltage to be part of the equation.  This is the example from
>> > data I collected with the ioniq 5 on 800v charging .. and I've written
>> > a plugin so I can get more charge profile information at other charge
>> > voltages.
>> >
>> > I'm happy to leave it in the Ioniq 5 code, but was wondering if I
>> > should put the implementation in a common area.. vehicle.h maybe?
>> >
>> > //.ichael
>> >
>> > ---8<----------------------
>> >
>> > // Charging profile
>> > //  - Must be from lowest to highest to%.
>> > //  - Higher voltages must come before lower voltages for the same to%
>> > charging_step_t ioniq5_chargesteps[] = {
>> > // voltage, to%, WattHours
>> >   { 750,     10, 100000 },
>> >   { 750,     25, 190000 },
>> >   { 750,     45, 220000 },
>> >   { 750,     75, 120000 },
>> >   { 750,     80,  80000 },
>> >   { 400,     85,  60000 },
>> >   { 400,     90,  40000 },
>> >   { 100,     90,   1100 },
>> >   { 400,     95,  25000 },
>> >   { 100,     95,   7400 },
>> >   { 100,    100,   7200 },
>> >   { 0, 0, 0 },
>> > };
>> >
>> > int CalcRemainingChargeMins(int chargeVolt, float chargespeed, int
>> > fromSoc, int toSoc, int batterySize, charging_step_t charge_steps[])
>> > {
>> >
>> > _______________________________________________
>> > OvmsDev mailing list
>> > OvmsDev at lists.openvehicles.com
>> > http://lists.openvehicles.com/mailman/listinfo/ovmsdev
>>
>> --
>> Michael Balzer * Helkenberger Weg 9 * D-58256 Ennepetal
>> Fon 02333 / 833 5735 * Handy 0176 / 206 989 26
>>
>> _______________________________________________
>> OvmsDev mailing list
>> OvmsDev at lists.openvehicles.com
>> http://lists.openvehicles.com/mailman/listinfo/ovmsdev
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openvehicles.com/pipermail/ovmsdev/attachments/20221231/c0173c47/attachment-0001.htm>


More information about the OvmsDev mailing list