Peak shaving with the water boiler

In the post about heating water the water boiler moved to the cheapest hours of the day. This part is about a different number. Not when the house uses energy, but how much at once.

Why the peak matters

A smart meter does not only count kWh. It also records the average power of every quarter hour (:00, :15, :30, :45). Austrian grid tariffs are moving towards charging for that peak, so the highest quarter hour of the month would cost money on its own, no matter how much energy you use.

What the peak will cost me once my grid operator charges for it gets its own update in 2027.

I set myself a target of 4 kW. In the 90 days before I started, the house went over it in 9 quarter hours, and over 3.5 kW in 20.

The water boiler is the obvious lever. It draws about 2 kW, and nobody notices if it pauses for 15 minutes. It hangs on a Shelly Pro 1PM (ad) relay, so openHAB can switch it at any time.

The rule

The Shelly 3EM reports the grid power about every 15 seconds. An openHAB rule adds it up per quarter hour, just like the meter does, and projects where the quarter hour will end:

// energy so far in this quarter hour + current power for the rest of it
val long remaining = windowStart + 900 - t
val double projected = (windowEnergy + p * remaining) / 900.0

If the projection goes over the limit (3.5 kW, as a margin to the 4 kW target), the rule switches the boiler off. It stays off for at least 15 minutes, so a short load cannot switch it back on right away. Then it goes back on as soon as the house plus the boiler fits under 3.2 kW for a full quarter hour. And if anything else switches the boiler in between (the price window ends, someone presses the button in the kitchen), the rule lets go and does not touch it any more.

Every action ends up in the log, and Grafana shows the shed periods as annotations on the power graph.

The first week

It worked. No quarter hour went over 4 kW, the highest was 2.94 kW. But the log looked strange:

12:00:25  Boiler off: quarter hour projected at 3822 W (now 3851 W, boiler 2072 W)
12:15:25  Boiler on again
12:15:40  Boiler off: quarter hour projected at 3736 W (now 3893 W, boiler 1986 W)
12:30:55  Boiler on again
13:00:08  Boiler off: quarter hour projected at 3601 W (now 3601 W, boiler 2026 W)

Every shed happened in the first seconds of a quarter hour. Of course. At :00 the “projection” is just the current power, extrapolated for 15 minutes. A kettle or a cloud over the panels is enough.

For every shed I estimated what the quarter hour would have reached without it: the measured average plus the boiler power for the minutes it was off. Only one of seven sheds was actually needed. Five would have stayed below 3.5 kW anyway.

Shedding as late as possible

The fix was to turn the question around. Not “will this quarter hour go over the limit?”, but “is this the last moment at which switching off the boiler can still prevent it?”

Switching the boiler off now saves its power times the remaining seconds. As long as that is more than the projected excess, there is no need to act yet. The kettle may be done in a minute. Only when the saving barely covers the excess does the rule switch off, with a reserve of two minutes:

val double excess = (projected - LIMIT_W) * 900.0          // Ws over the limit
val double saving = bw * Math.max(remaining - RESERVE_S, 0) // Ws saved by switching off now
if (bw > MIN_BOILER_W && excess > 0 && saving <= excess) {
    // switch the boiler off
}

Testing it against 90 days of history

One week of live data is not enough to compare two rules. But InfluxDB has every grid reading of the last years. So I wrote a small Python script that replays both rules against the 90 days before peak shaving existed: 638,000 grid readings and 146,000 boiler readings. Whenever the simulated rule sheds the boiler, its measured power is subtracted from the grid power until it is back on.

The script has about 130 lines, plain Python without dependencies, and works for any setup with a grid meter and a load you can switch: peak_shaving_replay.py.

First a sanity check. Without any shedding, the replay has to reproduce reality, and it does: 20 quarter hours over 3.5 kW and 9 over 4 kW, exactly as measured.

RuleShedsBoiler offQuarter hours > 3.5 kW> 4 kW
no peak shaving00 h209
shed at projection, 3.5 kW8121.7 h43
shed at projection, 3.8 kW6216.7 h53
shed as late as possible246.1 h43

The same protection with 70% fewer interventions. And simply raising the limit, my first idea, would have been worse in both columns.

The two-minute reserve is no guess either. The grid power arrives every 15 seconds, and 99.9% of the gaps are shorter than 27 seconds.

The three quarter hours nobody can fix

Three quarter hours over 4 kW remain in every variant, so I looked at each of them:

Quarter hourAverageBoiler
7 July, 11:004.44 kWoff
7 July, 11:305.46 kWoff
11 July, 11:455.91 kWoff

The boiler was off, so there was nothing to shed. The PV produced as usual. In 5-minute steps, the grid import jumped to over 7 kW for about ten minutes, shortly before noon. Almost certainly cooking. No boiler rule can do anything about that.

What helps is a warning. The rule now sends a push notification when a quarter hour will go over 4 kW even with the boiler switched off. Same trick as above: the warning comes at the last moment at which switching off 2 kW within three minutes still saves the quarter hour. In the replay, all three quarter hours were warned about 15 minutes ahead, with 4 false alarms in 90 days. A plain “projection over 4 kW” would have sent 15.

A bug the replay did not show

While reading the logs, I found one more thing. An older rule switches the boiler off 4 hours after it was switched on, as a safety limit. But every restore after a shed counted as “switched on”, so each one started another 4-hour timer:

15:00  price window ends, boiler off
15:15  OFF   (timer from the 11:15 restore)
16:15  OFF   (timer from the 12:15 restore)
16:30  OFF   ...
17:15  OFF
18:30  OFF

Harmless while the boiler is off. But hot water from the kitchen button at 16:00 would have been cut short 15 minutes later. Now there is one timer per boiler run, a restore after a shed keeps the old deadline, and every real switch-off cancels it.

Two weeks live

The new rule has been running since 11 October. In the first 13 days it switched the boiler off 14 times, always for one quarter hour, and it waited as planned. The log shows how much of the quarter hour was left at the switch-off, from 166 seconds when a little excess came late, up to 876 seconds on a day the house was heading for 6 kW:

14:11:39  Boiler off: quarter hour projected at 3686 W, 201 s left (now 3762 W, boiler 2007 W)
14:26:48  Boiler on again: now -234 W + boiler 2007 W, quarter hour projected at 212 W

No quarter hour went over 4 kW, and only one over 3.5 kW: 3.58 kW on 23 October at 13:30, when the washing machine was heating its water at 2.2 kW in the boiler window. The rule switched the boiler off at 13:32 and on again at 13:47. In the 90 days before, there were 20 quarter hours over 3.5 kW and 9 over 4 kW.

The first warning came on 22 October at 12:04, the quarter hour heading for 5.6 kW even without the boiler. I knew it was the oven and that it would be done soon, and the quarter hour ended at 2.92 kW.

Links marked (ad) are Amazon affiliate links. If you buy through them, I get a small commission, the price stays the same for you. As an Amazon Associate I earn from qualifying purchases (Als Amazon-Partner verdiene ich an qualifizierten Verkäufen).

Bookmark the permalink.

One Comment

  1. Pingback: openHAB, InfluxDB and Grafana: all energy data in one place – tl-photography

Leave a Reply

Your email address will not be published. Required fields are marked *