Earth Notes: On Website Technicals (2026-02)

Updated 2026-03-01.
Tech updates: tweaking 16WW energy management, optimisation, data change, moving goal-posts.
Nothing much planned beyond energy efficiency tweaks as insolation increases...

: PV Diversion Goals

This year I am working on improving use of exergy from PV generation, which means in the limit exporting all 'excess' beyond filling the Enphase electric battery, and infrequent pasteurisation cycles. That would be ~500kWh/y less diversion and more exports, possibly corresponding to ~50kgCO2e/y extra emissions avoided.

This extreme position seems a shame given that I have all this shiny kit that I then would not be amortising the embedded carbon emissions (etc) of. But that cost is probably a sunk one, that I should ignore. Though I do like playing with the shiny and trying to provide grid support.

At the moment the merit order setup is to avoid diverting to DHW (Thermino or DHW) or boosting when:

  • grid frequency drops below 49.9Hz (~6% of the time)

Also avoid diverting to DHW (Thermino or DHW) when:

  • local grid voltage is low (<236V)
  • the grid 7-day carbon intensity is red (top quartile)
  • during SSES peak periods and
  • the heat battery is priority and nearly full (~67%, ~4kWh stored), and not yet around solar noon or the grid is not (7-day) green

One drastic change could be to switch that last point from 'nearly full' to 'not cold' when cool enough for water to be bled into the DHW tank without the Intasol mixing it down, ie at or below ~28°C. That would correspond to ~1kWh stored out of ~7kWh nominal capacity, and simplistically could cover half of tank standing losses, or enough to cover typical washing up at the sink and is similar to a dishwasher run. Again simplistically, that would leave most (~3kWh) of daily DHW being produced by the heat pump at a CoP ≫3.

This 28°C temperature is only just above the minimum 25°C heat pump working temperature, eg radiator flow temperature, so probably allows the heat pump to operate at essentially maximum CoP when lifting DHW from that as a starting point entering the main DHW tank.

The Thermino heat battery would only be filled at optimal moments from a grid point of view (low carbon intensity, low demand, likely lots of other PV exporting/spilling). This might rob 16WW of the ability to reduce spill around solar noon. Maybe in PV-poor suburban London that is just not a real issue.

In PV diversion to the Thermino heat battery (h2) was 532kWh. Simply, if never filled above 'not cold' then on ~180 days per year ~1kWh/d PV generation would be diverted to the heat battery (so 180kWh/y), reducing heat pump demand by ~0.5kWh/d (with a CoP ≥2), thus a net ~90kWh/h extra electricity demand per year over no diversion at all.

I have updated the pekoe log-and-control script to send the additional 'not-cold' signal upstream, and the heat battery script to render as a flag file on sencha, and the merit order to use that flag.

So that last bullet is amended to:

  • the heat battery is priority and not cold (~28°C, ~1kWh stored), and not yet around solar noon or the grid is not (7-day) green

: 2kW+ generation spikes

Today there were PV generation peaks of over 2kW even before noon, exceeding house load and the Enphase charge power capacity, so diversion is starting to happen as intended. (Diversion was blocked before while in SSES morning peak.) Incoming mains is ~15°C, so raising the Thermino to ~28°C ('not cold') would use ~20% of nominal capacity, 1–2kWh.

In the end ~0.4kWh was loaded into the Thermino, and extracted when a shower was run, by a little before . The 'not cold' threshold was not reached.

20260225 gridTiePower 20260225 Enphase all flows

: underpowered

The Enphase battery still had ~1kWh in it at , having covered ~75% of the morning DHW run (leaving ~0.3kWh to be imported) and with the sun coming up. It was ~12°C outside and this is a moment that it would have been good for heat pump power to fit within the Enphase power limit, so it may be necessary to move the heat pump to 'more quiet', at least to cover the morning DHW run, maybe ~ to allow me to bring forward morning DHW generation.

A small amount of power above the updated Eddi 300W Export Margin for ~40 minutes after the Enphase had filled up mid-afternoon and that might have been diverted to the heat battery was not, because the grid intensity was then red (top-quartile over 7 days), and after was also (SSES) peak:

STOPPED 2026-02-25T15:27:01Z -277W grid 7d red carbon intensity
STOPPED 2026-02-25T15:28:02Z -394W grid 7d red carbon intensity
STOPPED 2026-02-25T15:29:01Z -339W grid 7d red carbon intensity
STOPPED 2026-02-25T15:30:01Z -362W grid 7d red carbon intensity
STOPPED 2026-02-25T15:31:01Z -538W grid 7d red carbon intensity
STOPPED 2026-02-25T15:32:02Z 140W deferred-unSTOP
STOPPED 2026-02-25T15:33:02Z -347W grid 7d red carbon intensity
...
STOPPED 2026-02-25T16:07:02Z -356W grid 7d red carbon intensity
STOPPED 2026-02-25T16:08:01Z -382W grid 7d red carbon intensity
STOPPED 2026-02-25T16:09:01Z -366W grid 7d red carbon intensity
STOPPED 2026-02-25T16:10:01Z -361W grid 7d red carbon intensity

In total ~0.9kWh was exported of ~9kWh generated (and 1.5kWh was imported).

: Optimisation Bug Discovery

As can happen when scrutinising something to optimise it, bugs (or at least unexpected behaviours) are sometimes encountered.

In this case it was discovered that synth CSV data sets were being overwritten during the precision collapse phase. This was noticed because they were updating but not changing on every run. Those two ways of generating the CSVs give different results. Some of those differences are numeric, eg:

% cat data/consolidated/energy/std/eheat/Y/eheat-Y.csv
#YYYY,device,coverage,eheat
#synth,"Eddi.h1+Eddi.h2+Eddi.hph4"
2022,synth,0.850943,842.678
2023,synth,0.999888,1345.49
2024,synth,0.163314,1440.32
2025,synth,0.990575,1642.63
2026,synth,0.0833333,195.87
% diff data/consolidated/energy/std/eheat/Y/eheat-Y.csv OLD/std/eheat/Y/eheat-Y.csv
1,2c1,3
< #YYYY,device,coverage,eheat
< #synth,"Eddi.h1+Eddi.h2+Eddi.hph4"
---
> #YYYY,device,coverage,eheat,comment
> #collapse,"MtoY"
> #input,"data/consolidated/energy/std/eheat/M/synth/eheat-M-synth.csv"
5c6
< 2024,synth,0.163314,1440.32
---
> 2024,synth,0.996648,1440.32

A more complex example:

% diff r data/consolidated/energy/std/flow/Y/synth/flow-Y-synth.csv OLD/std/flow/Y/synth/flow-Y-synth.csv
1,6c1,3
< #YYYY,device,coverage,flow
< #synth,"meter.imp+meter.exp"
< 2005,synth,,9800
< 2006,synth,,9800
< 2007,synth,,6968
< 2008,synth,0.16,409
---
> #YYYY,device,coverage,flow,comment
> #collapse,"MtoY"
> #input,"data/consolidated/energy/std/flow/M/synth/flow-M-synth.csv"
8,12c5,9
< 2010,synth,1,4264.5
< 2011,synth,1,4572.5
< 2012,synth,1,4266.2
< 2013,synth,1,4306.7
< 2014,synth,1,4538.3
---
> 2010,synth,1,4278.5
> 2011,synth,1,4575.5
> 2012,synth,1,4309.4
> 2013,synth,1,4308.7
> 2014,synth,1,4537.7
15,19c12,16
< 2017,synth,1,4429.2
< 2018,synth,1,4357.2
< 2019,synth,1,3691.9
< 2020,synth,1,3776.1
< 2021,synth,1,3301.4
---
> 2017,synth,1,4429.3
> 2018,synth,1,4349.4
> 2019,synth,1,3682.7
> 2020,synth,1,3813.1
> 2021,synth,1,3361.4
21,22c18,19
< 2023,synth,1,2960.4
< 2024,synth,1,2909.2
---
> 2023,synth,1,2959.4
> 2024,synth,1,2906.5
23a21
> 2026,synth,0.0833333,302.5

I am prepared to believe for now that the 'new' values are reasonable. Avoiding the recalculation will save a little more processing time and churn.

I have taken the opportunity to add the formula for synthetic variables, and an (unconditional) * Partial/unknown coverage explanatory footnote, to energy series sub-pages.

More avoiding rebuilding CSVs that are already up to date, this time in the consolidation/merging stage. Has brought the M1 runtime down to under 6s.

: moar

Pushing the "do not do rebuilds that are not needed" thing a bit further now has the MBA run-time down to ~5s, RPi ~24s.

: Recreational Optimisation

To avoid doing something more useful, I finally recreationally parallelised (with xargs) the initial direct data extraction part of script/updateConsolidatedEnergyOutputs.sh. This reduced overall run time on my MBA M1 (not in lowpowermode) from ~17s to ~10s.

On the main RPi server the run time is now down to ~52s.

This required relatively few (<~50) lines of new code, mainly replicated boiler-plate in, and movement of ~20 core lines to, a new wrapper script to allow easy job control via xargs.

I reduced the rebuild time of the energy series page and sub-pages on my MBA from ~17s to ~4s in the case where the source data CSVs for the sub-pages have not changed and so are still up to date, per make. Most CSVs remain unchanged most days. This does have a fallback forcing a rebuild if the trigger file, also used in the makefile to rebuild all main pages, has been updated.

This has to take account of which sub-page set (desktop, lite, offline) is being built.

: up-to-date check

I have created an optional mechanism for a direct-extraction script to declare its input data files, so that the caller can determine if the output is likely already up to date and the script then need not be called at all. That has been implemented for the ~14 (out of 30) slowest scripts, and has shaved ~2s off the wall-clock runtime for the M1 (now under 8s). On the RPi server runtime is now ~30s.

: Insolation Up

We are getting noticeably more sunshine this month, which means the batteries are getting used and are covering a little demand from onwards already.

Various scripts have already been tweaked and tuned to use less CoP 1 DHW by diversion (and boost), and to better shape net grid demand to match SSES [govUK2024electricity] [govUK2025ESA]. The heat pump load profile work is part of that. The mild anti-herding improvements around the edges of STOP mode are too. 16WW's typical ~1kW grid-friendly load-adjustment capacity is not going to be the saviour of the GB grid, but should help just a tiny bit!

One motivator for this work is to leave a larger net generation surplus so that our energy carbon footprint will stay negative in less good years. I hear that HMRC wants to treat anything over 20% surplus as taxable 'profit', though I hope that several years at once can be taken into consideration given fluctuations in insolation and use (remember lockdowns?), and that our FiTs may be immune. I brought up this potential issue with the Energy Minister (Ed Davey) when he visited well over a decade ago! That magic 120% is also the level at which Octopus' Zero Bills tariff can work I was told.

References

(Count: 2)