Earth Notes: On Website Technicals (2026-04)

Updated 2026-04-20.
Tech updates: per-minute Eddi tweaks, Time Machine bug, virtual plug-in solar, merit order, intensity forecast, USB power wrangling, greed...
And more sun: should be net exporters this month... Continued tweaking of our energy system to ensure comfort and low cost for 16WW while maximising climate good, and ease pressure on war-impacted gas supplies just a tad... (And a modest review hidden in here somewhere.)

: Off-grid Greedy

I primarily want to work the off-grid system harder in winter to reduce grid imports a little then (the target is ~0.5kWh/d or ~5%), and rest it in the summer.

But I can still push a little harder than now in summer and skim spare energy from a near-full lead-acid battery when there is not enough grid-tied generation to export. This extra dumping is likely in the evening in particular.

So I have just added a clause to this effect to the 'e' state of powermng to try and keep off-grid approaching ~300Wh/d, which means most of that appearing as a reduction in net grid import.

: Heat Greedy

I have become impatient and greedy, waiting for 7d green and solar and afternoon to arrive all at once to allow top-up to the heat battery.

I just added an extra complication/tier/epicycle to the top-up:

  1. Already top-up was allowed without 7g green and before noon until 'not cold'.
  2. I am now allowing top up with 7d green before noon until 'nearly full'.
  3. Already top-up was allowed to full with 7g green and after noon.

I may back out this epicycle since I really should be making heat via the heat pump as much as possible to make best use of exergy. Think Hormuz! And shellcheck does not like the way I have done the logic...

...
if [ -f "/tmp/heat_battery_not_cold.flag" ] && \
   [ "" != "$(echo "$RESPONSE" | grep -E '"hpri":2')" ]; then
   if [ -f "_gridCarbonIntensityGB.7d.flag" ] || \
       [ -f /tmp/heat_battery_near_full.flag -a \
	 "$(TZ=UTC; export TZ; date "+%H%M")" -lt 1156 ]; then
	echo "STOPPED $ISOUTCDATETIME ${GRD}W postponing Thermino until solar noon or grid 7d green" | tee -a "$STOPLOGFILE" 1>&2
	if [ "6" != "$STATUS" ]; then sh script/myenergi/eddiStop-netrc.sh 0; fi
	exit 1
    fi
fi
...

That now makes for 3 tiers of fill of the heat battery:

  1. To 'not cold': ~1kWh
  2. To 'near full': ~4kWh
  3. To full: ~3kWh

If overspill to the DHW cylinder is allowed, that is another ~3kWh. So over 10kWh of grid-responsive heat storage on top of 6kWh of electric.

By BST the heat battery was nominally full (though still accepting energy) at ~7kWh absorbed.

: Forecast Intensity

I am attempting to make my system more responsive to forecast sharp rises in grid carbon intensity, such as today, to allow filling storage boots if a renewables drought looks likely in the next day or two.

2026-04-12T11:11Z MT 0 GI 70 IT 30 F qP2N ES 3

(As of ~ the heat battery had just become hot enough to be able to supply DHW directly, and had plenty of headroom/capacity left did not get filled, settling at ~33% 'full' overnight...)

In particular this allows (when such a rise is predicted) diversion to the heat battery before noon or not 7d green even when not cold, and to the DHW cylinder even when not doing a pasteurisation cycle.

: powermng Verbose Output

% /usr/local/bin/powermng -n -v
Verbose mode ($Id: powermng.cpp 67107 2026-04-10 12:19:46Z dhd $).
ISEXPPI=1: Expander Pi is in use.
LOAD POWER (mW): 4242
SS-MPPT-15L Vb_f slow battery voltage (mV): 12623
SS-MPPT-15L Adc_il_f load current (mA): 336
Input flag DUMPING is unset.
SS-MPPT-15L Adc_ic_f battery charge current (mA): 0
NET battery charge current (mA): -336
SS-MPPT-15L T_batt (C): 15, temperature compensation 75mV.
Estimated LA battery impedance: 95mohm.
Estimated LA battery sag/(-rise) from internal impedance, and nominal internal voltage, effective w/ temp comp: -31mV, 12654mV, 12579mV.
Estimated actual battery sag from load (mV): 32mV.
LA/B1 dynamic threshold adjustment for load current -32mV.
B1 and wiring dump load sag allowances 123mV, 194mV.
Battery voltage 1 local (LA) 12363mV.
Supply drop B1 to BV 260mV; implied supply impedance 773mohm.
Adc_vl_f load voltage (mV): 12592
Supply drop B1 to controller load terminals 31mV; implied controller impedance 92mohm.
Supply drop controller to BV 229mV; implied wiring impedance 681mohm.
Input flag EXTERNAL_BATTERY_NOTVHIGH is set.
Input flag EXTERNAL_BATTERY_NOTFULL is set.
Battery voltage 1 basic compensation 43mV.
Battery voltage 1 'very low' threshold 12043mV (raw 12000mV).
Battery voltage 1 'low' threshold 12243mV (raw 12200mV).
Battery voltage 1 dump margin threshold 12393mV (B1 delta 150mV, sag for dump load 123mV).
Battery voltage 1 'not high' threshold 13418mV (raw 13450mV).
Battery voltage 1 'very high' raw threshold 13600mV.
Input flag FORECAST_PV_GEN_GOOD is unset.
Battery extra USoC reserve 5% for poor forecast and/or VHIGH / FULL not recent.
Battery 1 effective/usable SoC 75%, dump thresholds min 25% higher 62% (uncompensated USoC 84%); usable to dump = 1.
SS-MPPT-15L Adc_va_f array voltage (mV): 0
Input flag NODUMP is unset.
Input flag GBGRIDPEAK is unset.
Dumping driven by external factors.
External flag file /tmp/IMPORTING.flag is absent.
Input flag PLEASEDUMP is unset.
LASTDATA: 2026/04/11T21:00:08Z AL 0 B1 12623 B2 -1 P 4242 BV 12363 ST OK - e A1P 0 B1T 15 UC 75 A1V 0

USB power

I bought a USB-A to USB-C "12W" cable (£10, CORE 5056103416045) but still had only ~7W delivered to my MBA, which is somewhat tight. I then splashed out £4 (free delivery) on a JUKU Car Charger With Fixed 1.2M USB-C Cable 12W (2.4A) to see if that gets me closer to a power level that is comfortable to use all summer at least, and comfortable for the off-grid system to supply.

: arrived, not 12W

The JUKU device arrived. It is delivering power at (marginally over) 5V, and just over 7W, so only a minor improvement over the previous USB-A to USB-C cable. Not 12W as advertised. Thus not enough headroom for a bright display or to do a backup, sadly. The sales page should make clear that this is only 5V output, not (say) 12V/5V.

Also the 12V lighter connector barrel is unusually short, so does not work in one of the key 12V outlets by my desk!

The packaging is complex with lots of bits of plastic, some glued, unlikely to recycle well.

This can be a dedicated off-grid power cable for the MBA, even if not meaty enough for all purposes as intended. For now I have offered it up as a phone charger from the off-grid socket in the kitchen, for anyone who wants to use it.

Belkin 20W FTW!

I had another scout online for a ≪30W USB-C PD charger and found the Belkin 20W USB-C PD Car Charger (CCA003btBK) at my local John Lewis, just 1 in stock. Annoyingly neither that nor the manufacturer page will confirm that it does other than 5V, which the MBA seems to limit to 1.5A.

I had to go in person to the shop, and the packet did not mention voltage at all either!

Kindly, the packet was opened for me, and in the lowest contrast tiny text, on the device barrel, under torchlight, I could just make out 5V and 9V. (On closer inspection in the comfort of my own home, the spec seems to be 12V/24V max 2.5A in, 5V@3A or 9V@2.22A out.)

So, dear reader, I took another punt: £15.

And it works: delivers ~19W, and at least when sunny outside, does not seem to cut out from overload, so may do what I need without swapping cables all day!

Snapshot:

Current
1.05A / 2.22A
Voltage
9.08V / 9V
Power
9.5W / 20W

I note that the packaging seems to be entirely recyclable paper and card. Very good! Seems on the surface to be a good piece of kit all round.

Note that this route is possible at all in part because of everything must be able to charge with USB-C EU rules.

I also have a product idea for inventors' club tomorrow!

Product: Belkin 20W USB-C PD Car Charger (CCA003btBK)

20260420 Belkin car charger 20W CCA003btBK 20260420 Belkin car charger 20W CCA003btBK packshot front 20260420 Belkin car charger 20W CCA003btBK packshot back
USB-C PD Car Charger 20W 12V/24V in for 5V@3A or 9V@2.22A out
  • Brand:
  • Colour: black
  • Weight: 17.23g
  • Height: 20mm
  • Width: 20mm
  • Depth: 54.1mm
  • SKU: P-F7U099-S
  • MPN: CCA003btBK
  • InStock
  • valid at/until:
Review summary
  • Belkin 20W USB-C PD Car Charger (CCA003btBK)
  • Has solved a long-standing issue for me charging my MacBook Air from my off-grid system by limiting maximum power draw to 20W. Also good that it is rated up to 24V input so even highs of 15V in the off-grid system in winter should not hurt it. It was a shame that the 5V@3A, 9V@2.22A information (the 9V tier being key) that indicates that it should play nicely with the MBA is not on the manufacturer's site, not on the outer packaging, and is only available written in idiotically small low-contrast text on the barrel of the device itself, requiring opening the security seals to check...
  • Pros:
    • good positive electrical and mechanical contact
    • solves my off-grid charging problem with good elbow room with 20W limit powering a MacBook Air M1 over USB-C PD
    • relatively small, eg shorter than the Veld VC48DG
    • 24V maximum input gives me comfort in this application
  • Cons:
    • output voltage steps not listed at manufacturer's site nor on external packaging
  • Rating: 4.5/5
  • Published:

: Discretionary Off-Grid Load

Plugging in my MBA to off-grid power at my desk (in lowpowermode, and charging its battery from ~50%) via the new shiny USB-C charging cable and the Veld VC48DG car charger shows (snapshot values) in AlDente as Power Adaptor Specs:

Current
2.07A / 2.5A
Voltage
10.38V / 12V
Power
21.52W / 30W

If I crank the screen up too bright or plug in the external HDD or sit wrong then the charger drops out entirely (see how low the voltage is).

Meanwhile, powermng reports (snapshot values)( B1 13135 and P 42873 and A1P 26559, so the voltage drop is largely in the wiring towards my desk and is not hurting the off-grid battery at all.

With care this might allow shifting another ~500Wh/d load off-grid, realistically more like half that given that I sleep, even in winter.

To make this less painful it would be useful to limit power draw by the MBA.

Using the USB-A port on the Veld (or another charger) shows:

Current
1.44A / 1.5A
Voltage
4.87V / 5V
Power
7W / 8W

This is easier to keep from cutting out, but limits draw to ~200Wh/d, maybe more realistically ~100Wh/d, and is barely enough to charge the battery, do backups, etc; really only steady-state non-intensive use is likely to work!

Ideally I can find a way of limiting charge power to (say) 15W, but that is apparently not possible in software.

'u' status

I have added a 'u' status for when power from the primary array is going unused, as detected by the array voltage exceeding 32V, ie not being pulled down by MPPT.

I do not expect this status to be seen very often, and so I may eventually remove it again (and merge it into 'e').

uptime

 12:20:34 up 219 days, 23:51,  1 user,  load average: 4.06, 2.62, 1.53

: Supergreen Merit

I have extended the merit order to allow PV diversion to roll over from a full Thermino to the DHW cylinder in the case that the grid is 7-day 'supergreen' and in all other ways good.

The DHW cylinder has the highest standing losses, but if the grid really is running over with renewables, this has the virtue of almost certainly avoiding the next heat pump DHW run.

: Virtual Plug-in Solar

Approximate mid-winter (December and January) monthly kWh values:

  • Grid non-netted imports (imp): 340
  • Household gross consumption (con): 360
  • Heat (space and DHW) electrical input (eheat): 180
  • PV generation (gen): 50
  • Off-grid primary array PV generation (geno): 2
  • Potential max plug-in solar generation ~1kWp@90° (PVGIS): 43
  • Potential max gen from ~0.5kWk off-grid primary array (PVGIS): 22
  • Potential aggressive use of off-grid 'dump' load (router): 9

A crude thought experiment only! How in winter some energy might be diverted from off-grid to support the house (with no additional exports, eg turned off outside winter) (Ki-CAD directory).

Getting permission to attach more plug-in solar to trim winter grid imports may require all sorts of permissions (eg from FiT admin, DNO, my partner), and CAPEX. Tweaking the existing off-grid system to power the router round the clock with lower safety margins and more wear on the lead-acid battery, requiring only some software adjustments, gains ~25% of potential grid-draw plug-in solar reduction (~50% of the maximum potential of the off-grid primary array) but needing neither capital nor permissions.

Thus I shall have a go at this 'virtual plug-in solar' first, which likely only requires a set of (aggressive) parameter changes in powermng. These could be stronger in winter months, ie when the weather is cold and the heat-pump needed, or while (say) rolling daily imports exceed exports significantly as a more direct measure. Months with significant net imports are October to February inclusive.

Off-grid stats have been disappointingly feeble since the latest battery replacement, likely due to fairly conservative battery use.

The aim of this 'liberated' energy is to lower net (winter) imports preserving maximum exergy, and not (say) be turned into heat by DHW immersion. I also expect this to, counter-intuitively, show up as more off-grid generation (geno) as there will be more space made in the battery to accept such charge from the main array.

An initial parameter change has been enabled with, in powermng.h:

static constexpr bool LESS_DoD = false;

Next will be to allow sag below the normal lower threshold while dumping, to avoid premature cut-off.

: significant imports

Dumping, ie shifting the router load off-grid, should be strongly encouraged when there is / has recently been significant (eg ~100W or higher) import.

% cat data/eddi/log/live/20260405.log | \
    sed -e 's/^.*"grd":\([-0-9]*\).*$/\1/' | \
    awk '$1>100' | wc -l
16
% cat data/eddi/log/live/20251221.log | \
    sed -e 's/^.*"grd":\([-0-9]*\).*$/\1/' | \
    awk '$1>100' | wc -l
137
% wc -l data/eddi/log/live/20251221.log
144 data/eddi/log/live/20251221.log

The threshold is set at ~100W because even when everything is running off the Enphase battery or PV the Eddi tends to show ~50W import.

I have adjusted the per-minute Eddi frequency monitoring script to set/clear IMPORTING.flag or EXPORTING.flag files in a RAM-disc area if (according to the Eddi) 16WW is significantly importing from or exporting to grid.

It may be better to move this to the every-10-minutes Eddi logging to reduce CPU load, especially in the depths of winter, but for now this means that the import/export flag is fresh within a minute or so when powermng runs.

: it moves

The new powermng scheme seems to be working reasonably well. The router 'dump' load was taken off-grid for 30 minutes this morning in response to the import caused by the DHW heat up starting at BST:

...
2026/04/08T05:10:06Z AL 0 B1 12623 B2 -1 P 897 BV 12503 ST OK - e A1P 0 B1T 16 UC 73 A1V 13089
2026/04/08T05:20:07Z AL 0 B1 12623 B2 -1 P 897 BV 12495 ST OK D e A1P 0 B1T 16 UC 73 A1V 13196
2026/04/08T05:30:06Z AL 0 B1 12342 B2 -1 P 11898 BV 11924 ST OK D T A1P 0 B1T 15 UC 31 A1V 15030
2026/04/08T05:40:07Z AL 10 B1 12354 B2 -1 P 11972 BV 12003 ST OK D e A1P 136 B1T 15 UC 34 A1V 21039
2026/04/08T05:50:06Z AL 39 B1 12357 B2 -1 P 12222 BV 11968 ST OK - e A1P 469 B1T 15 UC 34 A1V 21821
2026/04/08T06:00:06Z AL 63 B1 12665 B2 -1 P 925 BV 12547 ST OK - t A1P 831 B1T 15 UC 78 A1V 22315
2026/04/08T06:10:06Z AL 90 B1 12732 B2 -1 P 777 BV 12591 ST OK - e A1P 1103 B1T 15 UC 91 A1V 22608
...

Each 10-minute record above corresponds to ~2Wh load shifted off-grid!

For the whole day (UTC):
  • Approx Wh primary-array generation: 179
  • Approx Wh load: 147
  • Approx Wh dump load (59/144 samples) shifted from grid: 118

: PLEASEDUMP

20260409 battV

At ~Z I set the new PLEASEDUMP flag to try to force a reasonable efforts round-the-clock dump. This will establish if any further limits need to be moved to allow it, albeit at 20°C!

For the whole day (UTC):
  • Approx Wh primary-array generation: 189
  • Approx Wh load: 305
  • Approx Wh dump load (141/144 samples) shifted from grid: 282

The dump load did not come off, and final battery voltage was 12.357V, at a reported ~31% effective usable capacity.

I will leave PLEASEDUMP set for at least another 24h to observe behaviour. So far this is in line with expectations or a little better than hoped.

: MBA load

20260410 battV

I have just added my MBA as an off-grid load (screen dim, lowpowermode, to avoid tripping out the car charger!), in particular recharging it from ~50% full, with ~25Wh needed for that.

In spite of such extra loads on top of the continuous ~12W 'dump' router load, the system reached FULL.

  • Approx Wh primary-array generation: 315
  • Approx Wh load: 357
  • Approx Wh dump load (144/144 samples) shifted from grid: 288

I removed the PLEASEDUMP flag the following morning ( BST) with B1 12314. When present this is shifting maybe an extra ~0.15kWh/d load off-grid right now with plenty of sunshine around.

More aggressive 'dumping' does seem to make room to absorb more generation.

: MBA again

MBA run off-grid all day ~130Wh, no use of PLEASEDUMP:

  • Approx Wh primary-array generation: 268
  • Approx Wh load: 274
  • Approx Wh dump load (60/144 samples) shifted from grid: 120

: MBA again

MBA run off-grid all day ~100Wh, no use of PLEASEDUMP:

  • Approx Wh primary-array generation: 207
  • Approx Wh load: 214
  • Approx Wh dump load (55/144 samples) shifted from grid: 110

: not at home

I was not at home most of the day (and thus neither was my MBA off-grid). Today was fairly overcast.

  • Approx Wh primary-array generation: 188
  • Approx Wh load: 168
  • Approx Wh dump load (57/144 samples) shifted from grid: 114

: Cannot Eject Time Machine HDD

Ever since the upgrade to macOS Tahoe 26.4 it has not been possible to normally eject and disconnect the external USB (spinning run) hard drive that I use for Time Machine once a backup has completed. The mds process keeps something open (shown by lsof) even after many hours of idle time, including zero traffic to/from the drive shown by iostat.

Having to do a forced eject each time is clearly risking damage.

(: having not backed up for several days, and having done so this morning, eject worked fine on the backup HDD this time...)

(: after many hours of busy I/O after finishing a backup this morning, even once nominally quiet, eject is being blocked again.)

(: after upgrading to macOS Tahoe 26.4.1 and doing a backup, ejecting the HDD worked.)

Grid frequency hysteresis

Currently the Eddi stops diverting to the Thermino (or boosting) when grid frequency drops below 49.9Hz, which is ~6% of each day. It may be useful to add some hysteresis, eg not resume diverting until frequency is maybe >49.95Hz, to reduce STOP mode chattering, and thus repeated swings in export power. That would likely reduce diversion further overall, but be slightly kinder to the grid and the Eddi, though helping induce limit-cycle behaviour would not be a win! [meng2020FFR]

Note the range of frequencies reported yesterday (from 10-minute samples), implying that at least 49.91, 49.94 and 49.95 are available as upper frequency:

% cat data/eddi/log/live/20260404.log | \
    sed -n -e 's/^.*"frq":\([0-9.]*\),.*$/\1/p' | \
    sort -urn
50.2
50.16
50.15
50.14
50.13
50.12
50.11
50.09
50.08
50.04
50.03
50.02
50.01
50
49.97
49.96
49.95
49.94
49.91
49.9
49.89
49.88
49.87
49.84
49.83
49.76

Export Delay trim

Having the Eddi Export Delay set at 30s means we export less smooth power to the grid than historically, especially with broken cloud scudding over. 5s was not a disaster before, though probably some overshoot from the Enphase did get absorbed by diversion that would have been better spilled to grid. So I am notching this value back to 11s (yes, prime).

Heat battery charge restrictions

Currently the heat battery is only allowed to charge to full by diversion when the grid is 7-day-green by FUELINST metrics (amongst other restrictions). The coincidence of the grid being FUELINST green (usually lots of wind) and there being excess PV generation to divert is rarer than expected. So this scheme is very slightly reducing world demand for gas beyond plan...

: Off-grid Winter Unused Energy

It seems as if there may be ~1h/d over winter when the off-grid system is not able to use all the power from the main ~510Wp of panels and lets them float to ~30V+.

% egrep ' A1V 3[0-9][0-9][0-9][0-9]' /var/log/powermng/202511??.log | wc -l | awk '{print ($1/30)/6}'
1.12778
% egrep ' A1V 3[0-9][0-9][0-9][0-9]' /var/log/powermng/202512??.log | wc -l | awk '{print ($1/31)/6}'
0.903226
% egrep ' A1V 3[0-9][0-9][0-9][0-9]' /var/log/powermng/202601??.log | wc -l | awk '{print ($1/31)/6}'
1.51613
% egrep ' A1V 3[0-9][0-9][0-9][0-9]' /var/log/powermng/202602??.log | wc -l | awk '{print ($1/28)/6}'
1.83929

: Uptime

sencha% uptime
 20:41:31 up 212 days,  8:12,  1 user,  load average: 0.52, 0.38, 0.37

Eddi control tweaks

I adjusted the places where the per-minute Eddi control script, nominally for grid frequency response, script/myenergi/eddiFreqResponse-netrc.sh, delays STOP-ing (going into grid expected peak hours) and un-STOP-ing (coming out of STOP mode eg once frequency is OK). I pushed up the randomised maximum delay up by ~20s to over 40s.

This aims to reduce herding effects in each case.

References