← Back to blog

EV charging cost optimization with OpenADR: following the price signal without missing a plug

Eight 60 kW chargers, a three-band OpenADR price signal and one curtailment event. A worked example of why scheduling to the departure deadline, not the plug-in time, cuts the overnight bill from $86.40 to $33.60.

EV charging connector plugged into a socket next to a stepped price curve, illustrating OpenADR price signals for EV charging cost optimizationi4B software engineers discussing an automotive data project at the office

Every charging hub operator can see the same thing on the utility portal: a price or event signal that says electricity is cheap now and expensive in an hour. OpenADR is the industry standard that carries that signal – a price, a request to cut load, a simple event level – from a utility, aggregator or grid operator to whatever sits behind the meter, in a vendor-neutral way so a hub isn't locked into one utility's bespoke integration. What the standard doesn't do is turn that signal into a schedule. In what follows we work through a concrete charging cost example, look at what happens when an event or a lost signal lands mid-session, and lay out what the layer connecting OpenADR to your chargers actually needs to do.

A price signal isn't a charging schedule

OpenADR moves two kinds of information from a Virtual Top Node (VTN) – usually the utility, an aggregator or a grid operator – to a Virtual End Node (VEN) at the site: a price, through a price report, or a request, through a demand response event with a signal level and a start and end time [1]. Which one you get depends on the program; many sites receive both.

A price by itself tells you what a kilowatt-hour costs this quarter-hour. It doesn't tell you how many kilowatt-hours a vehicle needs, or by when. A vehicle plugged in at 18:00 with a five o'clock departure and a vehicle plugged in overnight with no fixed deadline face the same price curve and need completely different schedules.

That's why we don't charge off the cheapest price alone. What we calculate is the cost-optimal allocation across the vehicle's flexibility window: the stretch between when it's actually available to charge and when it has to be unplugged, given how much energy it needs and how fast it can take it.

The other half of the sum is obligation. An OpenADR event can carry a level that means mandatory curtailment, and that overrides the price logic entirely for its duration, regardless of how cheap the quarter-hour looks on paper. A price optimizer that ignores event levels will happily charge straight through a mandatory curtailment.

Then there's the hardware: per-connector current limits, whether the site's transformer or grid connection caps total power below the sum of all connectors, and how much the vehicle will actually accept near a full battery. All of that bounds what the optimizer is allowed to schedule, on top of what the price makes attractive.

The signal also has to be current. A VTN that hasn't been heard from in the last reporting interval is a VTN you can't assume still agrees with your plan. We treat an unacknowledged or late signal as a reason to fall back, not a reason to keep optimizing on stale numbers.

A charging cost example: eight chargers, 480 kW

The numbers are simplified so you can check them yourself. A public charging hub has eight 60 kW chargers behind a 480 kW connection. Overnight, eight vehicles arrive wanting 60 kWh each, available from 22:00 and due out by 06:00.

Where that 06:00 deadline comes from depends on the site. At a captive fleet depot it's already known: the dispatch system has tomorrow's first block for every vehicle, so the deadline is just that trip's start time, read straight from the existing schedule – the same input we used to share power across an electric bus depot. At a public or workplace hub there's no dispatch system to ask, so the driver provides it instead – a departure time entered at the charger, in an app, or as part of a reservation, with a conservative default (end of the posted opening hours, say) if nobody enters one. Either way the number has to come from somewhere before there's a flexibility window to optimize into; a price signal with no deadline is just a price to chase blindly.

Assumptions

Every charger can deliver up to 60 kW; the site as a whole is limited to 480 kW. The utility publishes an OpenADR price signal in three bands: $0.18/kWh from 22:00 to 00:00, $0.07/kWh from 00:00 to 05:00, and $0.22/kWh from 05:00 to 06:00. Energy is measured on the charger's supply side, so the 60 kWh already includes losses, and we ignore the charging curve to keep the maths readable.

Option one: charge on arrival. Every vehicle starts pulling power the moment it's plugged in, like most hubs do today. With eight vehicles and 480 kW available, all eight finish in an hour, from 22:00 to 23:00. Reasonable-looking behaviour, except that hour sits entirely in the $0.18 band. Total cost: 480 kWh × $0.18 = $86.40.

Finishing fast isn't the same as finishing cheap. Nothing about "charge on arrival" looks at the price curve at all; it just happens to land in the expensive band because that's when the vehicles showed up. Delaying the start by two hours would have been enough to reach the cheap window, and nothing about the vehicles' readiness required starting at 22:00.

Option two: follow the price. The optimizer holds the vehicles back through the expensive band, then runs all eight at 96 kW combined – well under the 480 kW limit – through the five-hour valley from 00:00 to 05:00. 480 kWh × $0.07 = $33.60, finishing a full hour before the 06:00 deadline and before the $0.22 morning band even opens.

Table 1. Cost by scheduling strategy

StrategyWindow usedPrice bandEnergyCost
Charge on arrival22:00–23:00$0.18/kWh480 kWh$86.40
Price-following00:00–05:00$0.07/kWh480 kWh$33.60

Same eight vehicles, same 480 kWh, same 06:00 deadline. $52.80 less by moving the window, nothing else.

THE RULE IN ONE LINE

Schedule to the deadline, not to the plug-in time. A vehicle's flexibility window runs from when it's actually available to when it must leave, and the cost-optimal schedule fills that window from the cheapest band outward, only touching an expensive band when the cheap bands can't fit the energy in time.

Bar chart of total overnight cost for the same 480 kWh: charge on arrival from 22:00 to 23:00 at $0.18/kWh costs $86.40, price-following from 00:00 to 05:00 at $0.07/kWh costs $33.60, a saving of $52.80 or 61%.
Figure 1. Total overnight cost under charge-on-arrival versus price-following scheduling for the same 480 kWh. Own analysis based on hypothetical data consistent with the model assumptions.

The valley window has slack: 96 kW needed against 480 kW available, or 2,400 kWh of headroom across the five hours against 480 kWh of demand. That's not wasted margin, it's room to absorb a curtailment event without missing the deadline.

Schedule to the deadline, not to the plug-in time.

Say an OpenADR event lands at 02:00, limiting the hub to 150 kW for an hour. Because the price-optimal schedule only needed 96 kW of the 480 kW available, the event barely registers: the valley window still has room to deliver the full 480 kWh before 06:00, at the same $0.07 rate, without ever touching the expensive morning band. That headroom isn't free, though – it's a side effect of optimizing for cost instead of racing to finish as fast as possible. A scheduler that greedily charges every vehicle to completion in the first available hour has no such slack left for the event to eat into. If the valley window were shorter, or more vehicles were competing for the same connectors, the same event would cut straight into the schedule's margin – and that's exactly the number we'd want flagged the moment the event is confirmed: how much slack is left, not just whether the event happened.

A real site also has the charging curve and per-vehicle acceptance limits to deal with: above roughly 80% state of charge, a pack accepts less than 60 kW, so the last stretch takes longer than simple division suggests. We left that out here to keep the maths readable, same as the session-to-session variability you'd see on a real night.

Price spikes, events and lost signals

The price curve published at 18:00 holds until the first update from the VTN. The schedule has to be re-run every time something changes: a new price report, an event that starts or escalates, less site power, a vehicle that leaves early.

A critical peak event is the easy case to compute. The VTN calls a high-level event that the program translates into a hard limit of 150 kW for an hour. You know the number and the window, so you just re-solve the schedule around it, same as any other constraint.

What matters is how early the schedule finds out. An event announced at day-ahead notice gets folded into the original plan for free. An event called with ten minutes' notice means re-optimizing against whatever energy is already delivered, which is a much tighter problem and worth flagging to the operator as a live number: this much power lost, this much schedule slack left.

Opt-outs are the case a price optimizer can't solve on its own. OpenADR lets a VEN report that it can't or won't comply, and a site has to be able to say so, loudly, when a fleet's readiness would be at risk. A dispatcher who can override an event and knows exactly what that override costs makes a better call than a system that silently ignores the signal.

Lost comms are the trickiest, same as on the charger side. The VTN goes quiet and you can't tell whether the last price or event you saw still applies. We don't assume either way. We flag the signal as stale after its reporting interval elapses and fall back to the safer of "last known event level" and "default site cap", while someone checks the connection.

What to build it from

You don't have to replace anything you already run. The CSMS knows what's happening on the chargers. The EMS knows how much power the site is allowed to draw. The VEN – often just a role the CSMS or EMS takes on – is what talks to the VTN and receives the price and event signals. What's usually missing is something that turns a price curve, an event and a deadline into a per-connector power target, the kind of single coordinating layer we've described for electric depots.

That's the optimization layer, and OpenADR only covers one of its three inputs [1, 2]. The other two – vehicle readiness and connector or site limits – come from the same places any smart charging system needs them: the CSMS for what's plugged in, and the EMS or site controller for the power envelope.

Targets reach the chargers the same way they do in any smart charging deployment: through the charging profile features of OCPP [4]. Charging profiles with a schedule of power limits over time have been part of OCPP since version 1.6, so this isn't a hardware swap – it's confirming your chargers and CSMS actually support them, for example with an OCPP tester, then watching the meter, not just the accepted command.

Standards here keep moving: OpenADR 2.0b is what most utility programs support today, while 3.0 consolidates demand response with other grid-edge signals under one data model, and new regions keep adding their own program variants on top of either.

How to tell cost optimization is working

Readiness comes first, not cost. Every vehicle still has to leave with the energy its next trip needs; a cheap overnight charge that misses that bar isn't a saving, it's an outage with a good invoice. Readiness at departure is the floor metric, checked before anything else.

Once that floor holds, the headline number is cost avoidance against a charge-on-arrival baseline: the same energy delivered, priced at the schedule you'd have gotten without the optimizer, minus what you actually paid. Studies of managed charging measure its value the same way, against unmanaged charging as the reference [3].

Beyond that, we track event compliance (the share of OpenADR events met without an opt-out), how many overrides the dispatcher issued and why, and how closely the forecast price curve ends up matching what the VTN actually sends. A forecast that's consistently wrong is worse than no forecast, because it schedules around a price that never arrives.

If you want to see how this looks at your site, take one ordinary night: arrival times, deadlines, how much energy each vehicle needs, and the published price bands. Work out the charge-on-arrival cost by hand, then the price-following one. If the gap between the two numbers surprises you, that's the case for connecting your CSMS and EMS to the signal you're already receiving. Talk to our engineers about running the same calculation on your own site data and building it into the systems you already run.

FAQ

What is OpenADR in EV charging?

OpenADR (Open Automated Demand Response) is an open standard for sending price signals and demand response events from a utility, aggregator or grid operator to equipment behind the meter. At a charging hub it tells the site what electricity costs and when load must be cut. It does not create a charging schedule; the CSMS or an optimization layer has to turn the signal into per-connector power limits.

What is the difference between a VTN and a VEN in OpenADR?

The Virtual Top Node (VTN) is the sender, usually a utility, aggregator or grid operator, which publishes prices and calls demand response events. The Virtual End Node (VEN) is the receiver at the site, which acknowledges events, can opt out and reports back. In EV charging the VEN is often a role taken on by the charging management system (CSMS) or the site energy management system (EMS).

How much can price-based EV charging save compared with charging on arrival?

It depends on the price spread and how flexible the vehicles are. In our example, eight vehicles need 480 kWh overnight. Charging on arrival puts all of it in the $0.18/kWh band for $86.40. Following a three-band OpenADR price signal moves it into the $0.07/kWh valley for $33.60, 61% less, and still finishes an hour before the 06:00 deadline.

What should a charging site do when the OpenADR signal is lost?

It should not keep optimizing on stale prices. A safe approach is to mark the signal as stale once its reporting interval passes, fall back to the more conservative of the last known event level and the default site power cap, and alert an operator to check the connection. Departure readiness stays the priority: no vehicle should leave short because a price feed went quiet.

Do I need new chargers to follow OpenADR price signals?

Usually not. Power targets reach chargers through OCPP charging profiles, which schedule power limits over time and have been part of OCPP since version 1.6. What you need is a VEN to receive the signal, an optimization layer to turn prices, events and departure deadlines into targets, and a check that your chargers and CSMS really apply the profiles, confirmed on the meter.

Sources and assumptions

  1. OpenADR Alliance. OpenADR 2.0b Profile Specification. Price and event (signal) definitions, Virtual Top Node and Virtual End Node roles.
  2. Piette, M.A., Ghatikar, G., Kiliccote, S. et al., Lawrence Berkeley National Laboratory (2009). Open Automated Demand Response Communications Specification (Version 1.0). California Energy Commission, CEC-500-2009-063.
  3. National Renewable Energy Laboratory (2023). Electric Vehicle Managed Charging: Estimating the Potential Bulk Power System Value. NREL/FS-6A40-86875.
  4. Open Charge Alliance. Open Charge Point Protocol 1.6, Edition 2. Smart Charging section.
  5. Prices, power levels and vehicle numbers in the example are hypothetical and chosen so the arithmetic can be checked by hand; the charging curve and session-to-session variability are left out.

Key takeaway

OpenADR delivers prices and demand response events, not a charging schedule. Schedule each vehicle to its departure deadline, not its plug-in time: in the example, eight vehicles needing 480 kWh cost $86.40 charged on arrival at $0.18/kWh and $33.60 in the $0.07/kWh valley, still an hour before the deadline. Treat mandatory events as hard limits and a stale signal as a reason to fall back to the safe site cap.

← Back to blog
Turn these insights into real results.
contact us
Smiling man with a beard, wearing a yellow corduroy shirt over a teal t-shirt.

Discover our software hub and test working demos

Explore