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

πŸ”‹πŸ€πŸ—’οΈ Support for EV-initiated Renegotiation & Fine Grain Charging Profiles #71

Closed
7 tasks done
the-bay-kay opened this issue Sep 17, 2024 · 9 comments

Comments

@the-bay-kay
Copy link

the-bay-kay commented Sep 17, 2024

Context

This PR builds off of the work done in Issue #69. These changes include:

  • The addition of ISO 15118-2's "DepartureTime" (DT) and "EAmount"
  • The Integration of an LQR Optimizer to optimize charging sessions

Currently, the LQR Optimizer generates a full schedule from timestamp 0 to DT, and takes a uniform sample of 24 - (SECC_Schedule) points to generate the charging profile. This is not optimal for a variety of reasons -- as such, we are exploring options for updating schedules with a finer resolution.

High Level Goals

ISO 15118-2 defines a protocol for EV initiated Re-Negotiation of charging profiles in several places, such as [V2G2-521] and [V2G2-813]. I've created a diagram outlining a successful re-negotiation, attached below:

Renegotiation Sequence Diagram image

Inspecting iso15118_2_states.py, it appears we have support for this re-negotation, but do not include any new charging profiles. As such, the goal of this issue is to integrate the Optimizer script into this function, such that we can re-negotation regularly (e.g., every 24 seconds, or another fine-grain amount) and more effectively optimize our charging session.

Subsequent Goals

The following are an approximation of the work we will need to do in order to support these changes.

  • Within the simulator, we will need to calculate our current timestamp relative to the start time, and ISO 15118-2's departure time.
    • I have yet to investigate where this change will occur, but @shankari mentioned she may be able to shed some light on this!
  • We must adjust the optimizer scripts such that it returns a schedule in linear 24-bit chunks.
    • E.g.: Given a granularity of 1 second, and we've charged for 4 minutes (240 seconds), we'd return the powercurve points for timestamp 241-265
  • We will need to adjust the SASchedule integration such that the fine-grain Profile Schedule is compatible with any PMax values set
    • We will find the set of schedule entries that fall within (timestamp, timestamp + 24*[granularity), and "weave in" the profile schedule between these values
  • Finally, we will a call to the optimizer script within iso15118_2_states.py's ChargingStatus Class. This profile will then be sent to the SECC via the existing PowerDeliveryRequest

Additionally, there are some clean-ups we would like to perform:

  • Currently, the Node-RED UI shows our charger always at "max power". This was a hack to get around a known Node-RED bug, which has since been patched. We would like to
    • Update Node-RED to the latest version, and
    • Revert the changes to the power meter.
  • Currently, the demo works in real time. While this is useful in terms of accuracy, it makes it difficult to showcase our functions in real time (e.g., running a full demo of a 3-Hour departure time would be quite boring...). We hope to add a user input to adjust the simulation timescale, so that we can run demos at 5x / 10x / 100x speed.
@shankari
Copy link
Collaborator

shankari commented Oct 2, 2024

@the-bay-kay One of the new areas that we will need to work on for this change is to keep track of time so that we can figure out when our current set of 24 slots is used up, and we need to renegotiate.

I can think of two ways to accomplish this:

  1. we can keep track of the time and and trigger the renegotiation when we get to the end of the current set of power entries (aka we put in a time-based trigger) OR
  2. we can piggyback on the charging status, which we receive every second
2024-10-01 15:45:00.152940 [INFO] evse_manager_1:  :: EVSE ISO V2G ChargingStatusRes
2024-10-01 15:45:00.896386 [INFO] evse_manager_1:  :: EVSE ISO V2G ChargingStatusRes
2024-10-01 15:45:01.740814 [INFO] evse_manager_1:  :: EVSE ISO V2G ChargingStatusRes
2024-10-01 15:45:02.441191 [INFO] evse_manager_1:  :: EVSE ISO V2G ChargingStatusRes
2024-10-01 15:45:03.166328 [INFO] evse_manager_1:  :: EVSE ISO V2G ChargingStatusRes
2024-10-01 15:45:03.922083 [INFO] evse_manager_1:  :: EVSE ISO V2G ChargingStatusRes

I would suggest that we start with (2) since we know how to trigger things based on a req/res pair.

Even in (2), we need to know what the current time is, so that we can check to see if it has passed.
As far as I can tell, this is maintained in self.comm_session.ongoing_timer
https://github.com/EVerest/ext-switchev-iso15118/blob/b878758bd5571a1f1d93ddb7bfac12719fadaeb1/iso15118/evcc/comm_session_handler.py#L116

If that doesn't work (because it is reset elsewhere), we can just add a similar timer to our code.

I don't think there is a way to speed it up, since ongoing_timer is set based on time()
BUT we can use something like https://github.com/wolfcw/libfaketime

Also contributed by Karl Chen in v0.8 is the option to speed up or slow down the wall clock time for the program which is executed using libfaketime.

For example,

FAKETIME="+1y x2"

will set the faked time one year into the future and will make the clock run twice as fast.

@the-bay-kay
Copy link
Author

the-bay-kay commented Oct 3, 2024

Even in (2), we need to know what the current time is, so that we can check to see if it has passed.
As far as I can tell, this is maintained in self.comm_session.ongoing_timer

I definitely agree that (2) will be the simplest method of implementation. I'm not 100% that the comm session handler is exactly what we're looking for, however -- during the ChargingStatusRes, it appears the timer isn't active:

image

Is this timer then to check for EVCC <-> SECC communication timeouts? I'll do a little digging to see what exactly it's for. Regardless, like you said, this is a good example for how we could implement our own timer!

EDIT: Yeah, we reset the timer after receiving the ChargeParameterDiscoveryRes (link)-- let's implement our own timer

@the-bay-kay
Copy link
Author

We've got a way to track and check time now. We should be able to store the end of our active ProfileScheduleEntry and trigger a re-negotiation once we reach that timestamp. This will require a rewrite of the schedule "weaving" algorithm, let's tackle that after we add the timestamp storage.

image

It should be straight forward to add speed up functionality to our current clock. I'm following the ongoing_timer's model by (i) storing the timestamp of initialization, and (ii) calculating the time elapsed between that value and each ChargingStatusRes. Our renegotiation will look something like...

speed_factor = mqtt_fetch(value) # 
time_elapsed = (time() * speed_up_factor) - self.comm_session.charging_timer
if (time_elapsed > self.comm_session.end_of_schedule):
    # Renegotiate...

@shankari
Copy link
Collaborator

shankari commented Oct 4, 2024

time_elapsed = (time() * speed_up_factor) - self.comm_session.charging_timer

Nice! So we don't have to use libfaketime, we can just handle it directly

@the-bay-kay
Copy link
Author

@shankari , the demo is committed! Took a bit longer than expected to handle the end-of-schedule behavior, but you should be able to run the demo as you did the previous, substituting for this branch. For your convenience...

git clone https://github.com/the-bay-kay/everest-demo.git; cd everest-demo; git checkout demo-renegotiation; bash demo-iso15118-2-ac-plus-ocpp.sh -r $(pwd) -b test-demo -3

@the-bay-kay
Copy link
Author

Some good news: Looking at the latest version of the ISO 15118-2 DC charging, it appears they have already added a method for viewing the ISO15118-2 logs -- we should be be able to use this as a template (or use it in its entirety) to create our own version of these (or expand them to OCPP 2.0.1!)

image

@shankari
Copy link
Collaborator

Yes, that was my prior attempt to have AFS display the logs in node-red (aka "they" is not the ongoing EVerest community).
However, it displays the ISO messages as encoded EXI and does not display OCPP messages at all.

@the-bay-kay
Copy link
Author

the-bay-kay commented Oct 18, 2024

It seems that updating the Power Gauge may be more complicated than updating the functions in Node-RED. Looking at the flows, we can see that we are receiving nothing from the /powermeter/totalKWattHr/ MQTT publication...

PublicationIssues.mp4

... compared to the main demos, in which we are receiving these values. So, let's look at the two modules where this message could be published:

  • YetiDriver/index.js ✘
    • If this comment is to be believed, these publications are depracated... So, let's ignore this and assume that our focus should be...
  • EvseManager/EvseManager.cpp βœ”
    • Given the above information, this is likely to be where our publication is coming from!

So, what's the difference between our demos and the working power gauge from main? Well -- a lot, actually. Looking at the blame history, there have been multiple changes to this module since we branched off...

I think there's two options for how we can proceed forward from here:

  • Spend more time de-bugging our old MQTT messages -- we can look at the broker's logs, re-compile to add some statements into the publications, etc.
  • We proceed ahead with rolling forward the demo to the latest stable release (ideally September, TBD): once we do so, the updates to EvseManager.cpp should clear this up

I am currently leaning pretty strongly to the second option. Even if this doesn't fix everything (I'll almost certainly need to tweak the flows, for example), updating before debugging will at least ensure that we're using a contemporary version of this module. That way, whatever work I do de-bugging will not be "useless" after roll-forward. If we go ahead with the rolling forward, I will close this issue (as my current demo images are working!) and move discussion to the thread linked above.

@the-bay-kay
Copy link
Author

@shankari You were right -- Sebastian already fixed the value transmission issue in this PR! : ) Let me update the flows accordingly before we close this and roll forward.

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

No branches or pull requests

2 participants