Welcome to ned Productions

by . Last updated .

Welcome to ned Productions (non-commercial personal website, for commercial company see ned Productions Limited). Please choose an item you are interested in on the left hand side, or continue down for Niall’s virtual diary.

Niall’s virtual diary:

Started all the way back in 1998 when there was no word ‘blog’ yet, hence ‘virtual diary’.

Original content has undergone multiple conversions Microsoft FrontPage => Microsoft Expression Web, legacy HTML tag soup => XHTML, XHTML => Markdown, and with a ‘various codepages’ => UTF-8 conversion for good measure. Some content, especially the older stuff, may not have entirely survived intact, especially in terms of broken links or images.

Latest entries: Feed icon

Word count: 4792. Estimated reading time: 23 minutes.
Summary:
A detailed technical diary entry is presented. The imposition of new EU tariffs on small packages from China is discussed, and the resulting costs are detailed. Furthermore, various electronic components — including PWM dimmers and ESP32 development boards — are reviewed. Technical issues, such as fuse failure in DC-DC converters and fibre network testing setups, are also explained.
Thursday 25 June 2026:
14:08.
Word count: 4792. Estimated reading time: 23 minutes.
Summary:
A detailed technical diary entry is presented. The imposition of new EU tariffs on small packages from China is discussed, and the resulting costs are detailed. Furthermore, various electronic components — including PWM dimmers and ESP32 development boards — are reviewed. Technical issues, such as fuse failure in DC-DC converters and fibre network testing setups, are also explained.
Five days remain until the EU brings in a new tariff on small packages entering the EU which has been designed to stem the flow of direct-to-EU-consumer small packages being sent from lower cost countries, with the overwhelming majority (91%!) coming from China. On the one hand, yes sending four billion small packages per year each on a 10,000 km trip is environmental insanity, but the fact that it is economically viable at all is 100% the result of legacy international treaties around postage and the taxes levied on EU based warehousing i.e. it’s purely a consequence of past choices made. Rather than change either of those stupidities, the EU decided to raise the cost of small packages rather than reduce the cost of their taxation and treaty choices which led to direct to consumer in the first place. The attractiveness of this choice is no doubt partially revenue raising, but it is also geopolitical: the EU wanted to fire a shot across the bow of China before later this year beginning to threaten tariffs on ALL imports from China – the idea being that this should concentrate minds in China, as they have until now been dismissive of EU concerns about anti-dumping.

This new tariff has been designed to be especially awkward and annoying: the foreign seller must collect a tariff deposit in advance, then pay it to the EU based delivery service who then may ALSO charge an additional administration fee. There are already reports of some EU national postal services charging over €20 as their admin fee, then the tariff is €3 + VAT per type of item, and that is on top of the original price in China plus EU VAT. This will render most small packages from outside the EU utterly uncompetitive in price, never mind lots of faffing around, delivery delays, and hassle.

Anyway, all that is a separate story told better elsewhere than this website, rather, this diary entry is about the end of an era: the Chinese direct to consumer market was primarily about price, but it was also about choice because sites such as Aliexpress often had components you simply couldn’t get elsewhere in small quantities, or indeed sometimes you couldn’t get them at all anywhere else. I, having known that this tariff was coming and being almost certain that the two weeks beforehand would be just a mess, got my ‘last ever’ Aliexpress order in by end of May, and the last of everything was successfully delivered without any hassles nor problems more than a week ago. This diary entry will review some of those recent orders.

I put ‘last ever’ in quotes because I will almost certainly buy some items from Aliexpress et al in the future, specifically items where I can’t get them anywhere else at all, or in reasonably sized quantities, or where even with the tariff they’re still cheaper than say Amazon which lists many of the same items, just 15-20% more expensive (I note that the Amazon commission is 15% for most items, as compared to 8% for Aliexpress). So let’s call this a review of my ‘last ever cheap Aliexpress order’.

Missing bits for the house

I had previously made large orders during the Singles Day sales, having spent thousands of euro on things like LED strips and DC PWM dimmer wall switches. I saved an absolute fortune over buying locally, but as the house design reached completeness we had become short in a few items e.g. DC PWM dimmer wall switches, as we had added a few more. I therefore made an order for the balance:

These had all gone up in price by about 20% since the original order three years ago, apart from the BTS7960 H-bridges which were actually marginally cheaper. 20% is probably about the amount of accumulated price inflation during those three years, plus I was buying now in non-sale times whereas previously during the biggest and deepest annual Aliexpress sale. So, methinks fair enough.

This wasn’t an expensive order, I had had to keep meaning to get round to it for yonks, but the coming tariff made me get it done.

New type of DC PWM dimmer wall switch

While I was searching for my previously bought DC PWM dimmer wall switches in order to buy more of them, I found a model I hadn’t previously seen, and at under €12 inc VAT each they were nearly half the price of the ‘fancy’ ones I’ve standardised upon. I reckoned buying one was worth a punt so I could test it, and here it is:

The front panel is glass, which is surprising at that price point, and the knob is some sort of metal infused plastic which looks cheap and I’m not sure if the silver isn’t paint which would rub off over time. The build quality is noticeably below that of my ‘fancy’ model, and the circuit board is clearly simplified, however for a less often used location I think it would last years well enough. On the circuit board, there is a single 80N03 MOSFET – which is surprising as eighty amps seems rather overkill for this – and a 8S003F3P6 STM8 microprocessor, which is also surprising as it’s quite expensive relatively speaking at US$0.32 per unit. I unfortunately didn’t take a picture of the rear where the voltage converter obviously must live given the three pins pointing through, but it would be surprising if it’s much different to other DC PWM dimming wall switches: it’ll take something like zero to thirty volts input and output something between 3v and 5v (the STM8 will work with anything in that range). I certainly can confirm it works fine with 5v inputs as well as with 24v inputs.

How well does it perform? It turns out really well …

Yup, that’s a 80 kHz PWM being emitted there, which is ten times better than my ‘fancy’ switches which put out an 8 kHz PWM – and that’s great compared to cheap PWM dimmers some of which can run as low as 0.5 kHz. For this price point, that’s stunningly good, in fact it’s the best PWM dimmer off Aliexpress that I’ve ever personally seen. Why they don’t advertise this quality in the listing I don’t know, but certainly the choice of the expensive STM8 which has a 16 Mhz clock speed makes it trivially easy to emit an 80 kHz PWM, even if that is just a dumb loop manually pumping an output. The STM8 does have three hardware PWM outputs, it’ll do a divisor up to 32,768 on your choice of either a 16 Mhz or a 128 kHz internal clock. I’ve no idea how they implemented it, but such an overkill choice of expensive microcontroller makes very high quality PWM a cinch.

I can also tell you that there are exactly twenty stops on the dial between fully on and fully off, and when it’s off it connects everything to ground and puts itself to sleep (I can tell this, because I can see the noise from the AC-DC converter when the switch is set to off). I assume it writes its last known value to flash, as across a power cut it restores its brightness before losing power. As you can see on the oscilloscope, there is a nasty negative voltage flyback on PWM down, but as LEDs are also diodes and the negative flyback voltage is within 2x of the LED strip voltage, it should be fine. The ‘fancy’ switches reviewed nearly three years ago also have some negative flyback voltage, but more controlled than you see here.

For €12 inc VAT there is a lot to like here. If the knob were just a touch better quality, this model would be a no hesitation recommendation, and they are nearly half the price of my fancy model, so this is a whole load of DC PWM dimming knob for your money. I would still prefer my ‘fancy’ model not just for the better build quality, but also because it shows a dot LED when off so people can find it in the dark, and it does also show a percentage on a LED display, which is fancy.

Ultra ultra cheap PWM LED dimmer

Ever wondered to yourself how bad these ultra ultra cheap inline PWM LED dimmers are when you buy them in bags of ten or more and they come out at less than sixty cent each delivered (well, before the EU tariff anyway)?

The case is actually heat shrink wrapped plastic, and they have a standard DC plug. They can not only dim, but also do various flashing patterns. They do remember their last setting after power loss, but I know from experience with these cheap parts in the past that after a while they forget their last setting after power loss, no doubt due to flash write wear as they’ll use a single location for storage and not update a ringbuffer which you’d do to greatly extend life. At sixty cents each, you just replace them if the memory loss annoys you.

I wasn’t expecting much, but they turned out to be okay:

That is a 1 kHz PWM, not great but also not terrible. Some with sensitive eyes might see flicker if this were driving a large, bright, LED, but in general you would use these inline dimmers in something like a desk light or other small lighting solution. So flicker shouldn’t be that noticeable, even to those sensitive to PWM flicker.

The irony is not lost on me that this ultra ultra cheap PWM dimmer produces the cleanest oscilloscope graph of any of the PWM dimmers tested. Of course the sedate 1 Khz clock rate helps hugely with that, controlling flyback with a 80 kHz PWM clock rate is much harder than for 1 kHz. However, my picture also tells lies – this unit actually oscillates between really bad flyback and clean over time, and my picture shows it when it is behaving. Again, back voltage remains under 1.5x of LED strip voltage, so it’ll be fine, but you get what you pay for.

And also in that vein, this dimmer only has eight levels of dimming! This may be too few for some, but for sixty cents each they’re good value for money.

Thermistor surge protection

I don’t think that I’ve mentioned on here an issue with one of my 480w DC-DC converters which keeps blowing its fuse – what’s weird is that I have several of those converters in use, and only one location keeps blowing its fuse. I opened one of the failed units to discover why:

One of the blown DC-DC converters with its resin scraped out by me to determine why it failed

As you can see, it has a 20 amp automotive fast blow fuse on its 48-60v input, and from inspection I can see that is has blown. There appear to be two Aishi R series 63v 330 μF capacitors on the input side, and two LF ET series 25v 470 μF capacitors on the output side. The input side capacitors have a 0.041 ohm impedance at 100 kHz, and a rated ripple current of 1500 mA. I must admit some surprise that the fuse blows, as a 20 amp automative fuse actually has this blow curve (italic values are inferred by continuing the slope of the line on the datasheet):

Amps Duration to blow
30 5 seconds
40 400 milliseconds
50 200 milliseconds
70 100 milliseconds
100 50 milliseconds
125 25 milliseconds
150 12 milliseconds
175 6 milliseconds
200 3 milliseconds
225 1.6 milliseconds
250 0.8 milliseconds
275 0.4 milliseconds
300 0.2 milliseconds

For 54v DC to create a current above 20 amps would require a resistance below 2.7 ohms, but the lower the resistance the shorter the duration of surge current. Let’s say that the resistance is one ohm, then from 660 μF of capacitance the surge current would be 54 amps and it would last 3.3 milliseconds – nowhere near long enough to blow that fuse. Therefore, the resistance must be way lower, enough to generate such a massive current flow that it could melt that fuse. Let’s divide by ten and see what happens:

Resistance Surge Current Surge Duration
1 ohm 54 amps 3.3 milliseconds
0.2 ohm 270 amps 0.66 milliseconds
0.1 ohm 540 amps 0.33 milliseconds

And now I think we have our cause: you would need to get that resistance down to the 0.1 ohm range to blow that fuse. I have a 16 mm2 cable feeding that power supply, and now I come to think of it that is unique: all the other power supplies have a much thinner wire connecting them, and maybe that is just enough to have protected them so far?

In any case, back when I bought the thermistors I wondered if I could ‘soft start’ the DC-DC converter using a thermistor and prevent the fuse blowing? Aliexpress lets you buy small bags of basic electrical components easily and cheaply, so a bag of fifty of these turned up for only a few euro delivered:

This is the MF72 2.5D13 thermistor, and it has 2.5 Ohms of resistance when cold (25 C) and 0.088 Ohms at 200 C, which it should reach quickly. At its steady state current of six amps once at 200 C, it would therefore dissipate about 3.17 watts of power. As a variable resistor, it therefore initially restrains current when first switched on, then it heats up, and as its resistance falls more current is allowed to pass and the heating of the thermistor reduces until it reaches a steady temperature.

I hadn’t figured out the cause of the DC power supply blowing its fuse at the time of ordering, so to be honest I sized those based on knowing that if the input voltage is 54v and a 20 amp fuse is getting blown, then a 2.5 ohm resistor ought to cap current flowing to 21.6 amps. As exterior temperatures in Ireland are very rarely 25 C at night time, you should actually get a good bit less than 20 amps in the real world. The D13 size came from the steady state current of six amps, which as 70% of the maximum draw of this DC converter (~8.5 amps of 54v) would be the likely maximum load I would allocate to these.

Now that I do know the cause, the thermistor is definitely oversized. You only need 0.1 ohms of additional resistance to not melt the fuse, so a MF72 0.7D25 thermistor would be a better choice as it would waste up to six times less power. Still, losing a few watts on a 200w load seems reasonable if it saves me having to constantly replace DC power converters.

How quickly does the thermistor get hot? I got out my backup 54v DC power supply, and put one of these thermistors between the 54v supply and the 48-60v to 24v DC-DC converter. I then placed my battery load and capacity tester on the 24v output. It’s probably easier to show pictures of the test setup:

The power supply actually outputs 55.4v, and yes I did confirm this during testing. My battery load tester will only load up to 184 watts, so I firstly ran a test at 0.1 amps which is 2.4 watts on the output side. With conversion losses, that is at least 2.67 watts going through the thermistor:

With the thermistor at ~23 C, one should be getting around 2.5 ohms resistance so if the voltage drop is 0.198v and the current flowing is 0.048 amps, resistance should be 4.13 ohms. That’s obviously a lot more than expected, however at very low current flows the relative losses in the DC-DC converter will be high, so if say current flowing on the input side were actually 0.07 amps now you’re getting a resistance of 2.83 ohms and that feels more like it. If so, power lost to heat would be 0.014 watts, or 0.6% – this being so low because the thermistor does not radiate much heat into the environment.

Ramping it up to the maximum 180 watts which is about 200 watts on the thermistor:

The thermistor is now a toasty 130 C and the voltage drop is 0.66v. Current flowing through the thermistor should be around 3.61 amps, so power lost to heat would now be 2.38 watts, or about 1.2%. Resistance should be about 0.183 ohms, or about twice the resistance if the thermistor were at 200 C according to its datasheet.

When I first applied the 200w load, I noticed the voltage drop across the thermistor was momentarily 4.3v before rapidly falling within a second or two to less than 0.7v. If so, resistance was somewhere around the 1.2 ohm mark for whatever fraction of a second that was, and power lost to heat would have been 15.5 watts. No wonder that the thermistor gets hot so quickly!

If you leave the load tester off, the thermistor sits at about 20 C just over the ambient temperature. The parasitic draw of the unloaded DC-DC converter wastes very little heat in the thermistor. This is good to know. At a 100w draw which is probably around 110w for the thermistor, it reaches 92 C (I didn’t take a voltage drop).

Most of these DC-DC converters will be deployed into the LED strips for the outdoor lighting. The easiest solution is to run thinner wires to them which will offer the necessary protection against current surges: let’s say I fit 1.0 mm2 diameter wire, this would have a max amperage of 8-17 amps with a 4.24 volts per amp drop per 100 metres. 10 metres of such cable would offer 0.166 ohms of resistance, plenty more than the 0.1 ohms we need – so if I make sure I fit at least five meters of no thicker wire than 1.0 mm2 diameter, no more fuses will blow!

Modern fibre network testing with the Fluke LRAT-2000

Many years ago I picked up at vast cost a used Fluke LRAT-2000 which is an ethernet wiring validation tool. The LRAT-2000 was launched around year 2012, and it cost many thousands of euro – you could buy a used car for the price of a new LRAT-2000. Even used on eBay today fourteen years later, they still cost over a thousand euro which is quite remarkable given that all they do is (i) test each of the wires for being correctly connected (ii) helps you figure out which cable in a bundle is connected to which (iii) test that TCP traffic flows over the cable (iv) test PoE power loads. Why did I splash out such money like so many others on eBay still do for such legacy hardware? Simple: the quality is guaranteed to be there, so when it tells you that an ethernet cable has a break eighteen metres along, you can be confident that is where the break is before you take a kanga hammer to your wall.

One feature that it supports is fibre network testing. For this you need to insert a compatible fibre transceiver into the LRAT-2000’s SFP cage. As this is such old hardware, the fastest network supported is 1 Gbps and it turns out that a gigabit speed fibre transceiver in the legacy SFP format costs about €45 each even off Aliexpress, and of course you need two of them. €90 felt a bit steep for testing the eight or so fibre cables which are likely to be installed in my future house, so I looked for an alternative.

A few years ago I fitted 2.5G fibre transceivers as the backhaul between my Wifi 6 access points, these being the fastest possible for the legacy SFP (not the newer SFP+) cage – these were under €10 each, and they run with a relatively low power draw and very much tick the box for the problem they solve (distance backhaul). Years ago I bought a tray of those transceivers enough for all my future needs lest they fall out of production and become expensive, however of course the LRAT-2000 is too old to use those (it does recognise them if you plug one in, but it can’t find a network). What I therefore needed was some sort of box which let me connect the LRAT-2000 to a newer fibre transceiver, and it turns out that Aliexpress has exactly such an item: a cheap dumb media converter box which sends layer 2 network frames from one SFP+ cage to another. You then plug in whichever transceivers you want to have fibre to fibre, ethernet to fibre or ethernet to ethernet. There are also variants with a single SFP+ cage, and a RJ45 ethernet port.

(To be clear, you can also get branded media converter boxes from all the usual vendors e.g. TP-Link, but the unbranded models – which appear to be physically identical from pictures apart from a printed logo – are, or at least were before the tariffs, a good bit cheaper)

I ended up buying the following before the tariffs came in:

  1. Two 10G ethernet to SFP+ media converter boxes each for €38.33 inc VAT delivered.
  2. Two 10G single mode LC fibre transceivers for a fairly astonishing €7.71 inc VAT delivered. Yes, that’s a 5 km capable 1310nm wavelength ten gigabit transceiver for under a tenner.

And while this solution involves more wiring and power adapters than I would prefer, it does solve testing fibre connections with the LRAT-2000:

This was about the same cost as two of the legacy 1G fibre transceivers, so I didn’t save money – however I think this spend of ~€100 better bang for the buck.

High speed fibre transceivers have become ridiculously cheap in recent years: 40G fibre transceivers cost about €12 each, even 100G fibre transceivers are just €25 each. That makes 100G networking very feasible for a home network, which is just madness: the entire country of Ireland had 25G of international connectivity as late as year 2003. That’s 4x the entire former international connectivity of Ireland in your home!

What remains expensive is > 10G wired ethernet, as are > 10G switches. You can avoid expensive wired ethernet by fitting an inexpensive PCIe to SFP+ cage adapter to your PCs/servers and running fibre between everything, but a 10G switch with SFP+ cages is still a fair sum of money: Amazon currently lists an eight 10G ethernet port switch with SFP+ cage for €136 (albeit, it is managed not unmanaged). If you want faster than a 10G switch, used commercial switches are in the hundreds of euro range, but they are very loud and burn a lot of electricity; if you want something quiet and power efficient, it currently costs many thousands of euro. Given this, you may actually be better off building a cheap low power PC and filling it with PCIe to SFP+ cage adapters, however 40G ethernet SFP+ transceivers are not cheap nor do they sip power. One option is a switch of 40G SFP+ cages, these appear to be on sale used for about €500 right now, so you could probably build something somewhat quiet and power efficient for under a thousand euro if you populated that exclusively with 40G fibre transceivers. Still, that’s a thousand euro! Better than 10G networking remains a four figure cost for now.

And to finish, yet another bag of ESP32 dev boards …

If there is any iconic product line where Aliexpress has been absolutely stonking value for money it has been ESP32 dev boards. Two years ago I bought a bag of ESP32-C3 ‘Super Mini’ dev boards delivered and including VAT for €1.50 each. As described at the time, there were even cheaper dev boards on Aliexpress, the very decent RP2040 cost just €1.29 inc VAT delivered, but in terms of compatibility with a large existing microcontroller software ecosystem the ESP32 is hard to beat.

Before cheap Aliexpress went away forever, I therefore had a look around to see if any of the higher end ESP32 dev boards had come down to bargain basement prices, and indeed they had: there is now an ESP32-C6 ‘Super Mini’ dev board with most of the worst design mistakes in the C3 ‘Super Mini’ dev board fixed and those also come in bag sized quantities for tens of euro:

Comparing the C3 and C6 models directly:

BoardPrice I paidCPUsRAMFlashWifiBluetoothLR-WPANGPIOAdditional
ESP32-C3 Super Mini€1.50 inc VAT in 20241x 160 Mhz RISC-V400 Kb4 Mbv4 (2.4Ghz)5.0No13Blue LED
ESP32-C6 Super Mini€2.74 inc VAT in 20261x 160 Mhz
+ 1x 20 Mhz RISC-V
512 Kb4 Mbv6 (2.4Ghz)5.3Yes (Zigbee, Thread etc)17 sides + 5 centralRGB LED,
Battery charge

The C6 is about 60% more expensive after adjusting for inflation. The C6 board is also available with a 8Mb flash variant (and it costs 4x more) which is useful if you want to run a Zigbee controller. But in essence, the C6 is the C3 except with a modern 2.4 Ghz radio hardware module implementing IEEE 802.15.4 which is a software defined wireless networking. This lets software easily implement many wireless networking protocols, such as Zigbee, Thread, Matter or anything similar. Wifi also gets modernised in the C3, going from Wifi 4 to Wifi 6, albeit still with only a 2.4 Ghz radio. And I suppose that the dev board does have 70% more i/o exposed, plus a lithium battery charge controller, if any of those things matter to you then the +60% cost may be worth it. Here is the C6 board right next to a C3 board for comparison:

For me, the main attraction of the C6 is for Zigbee routers (these extend a Zigbee network) and battery powered Zigbee end devices. Zigbee active consumes about 23-80 mA, and a Zigbee router needs to always be active, so one of my 3000 mAh lithium batteries would last only one hundred hours – still, if you had a Zigbee dead zone, firing in one of these with a bit of wire soldered onto its antenna to greatly extend range would bridge the issue, with low running costs when wired in for power.

Probably more exciting are battery powered Zigbee end devices e.g. a temperature sensor which could be dropped wherever you need them without having to wire them in. Zigbee end devices can deep sleep between periodic wakes to push data. Deep sleep on the C6 ‘Super Mini’ dev board can get down to 55 uA if you remove the RGB LED which always burns 330 uA even when off AND make sure you supply at least 3.6v to the battery pin/5v power input, otherwise the voltage buck converter burns current and it’ll horse through your battery quickly. If running off a battery, make sure to monitor the battery voltage and self disable if it gets below a certain minimum e.g. 3.4v, otherwise this board will happily run your battery down to damaging levels of empty.

The C6 has a proper low power 20 Mhz CPU for deciding whether to wake the board up or not which might be useful. The C3 has fixed function wake logic, so for example you might say ‘if pin A rises wake me’ which you can also do on the C6, but only wake the 20 Mhz CPU. It only has 16 kB of RAM accessible to it, but it CAN speak i2c and UART which is good enough to deal with a large subset of sensor boards. You could do fairly complex filtering or decision making with the 20 Mhz CPU, and wake the 160 Mhz CPU and wireless stack only if it were really necessary. This could shave off a few more percent of battery consumption.

According to real world numbers I researched from the internet, one of my 3000 mAh batteries fitted to a sleepy Zigbee end device and with a typical i2c sensor waking every ten minutes might last 10,000 hours = 1.14 years. When its battery gets low, you simply plug it in via USB and it’ll charge itself to full, then you can redeploy it. I can’t currently think of when I might use such a thing, but for the few euro to buy a bag of the C6s now before cheap Aliexpress ends it is definitely worth the hedge.

What’s next?

Most of this entry was written at the site while popups were installed. Expect a full write up and lots of pictures next entry!

#aliexpress #esp32-c3 #esp32-c6




Word count: 1446. Estimated reading time: 7 minutes.
Summary:
The input is a combined diary entry and a highly technical guide. A dark theme implementation is described, where pure CSS variables are utilised. Automatic switching based on the operating system’s theme can be achieved using @media queries. Furthermore, a manual override is demonstrated via checkbox hacks, although significant code duplication must be accepted for the feature to be fully operational.
Thursday 18 June 2026:
07:40.
Word count: 1446. Estimated reading time: 7 minutes.
Summary:
The input is a combined diary entry and a highly technical guide. A dark theme implementation is described, where pure CSS variables are utilised. Automatic switching based on the operating system’s theme can be achieved using @media queries. Furthermore, a manual override is demonstrated via checkbox hacks, although significant code duplication must be accepted for the feature to be fully operational.
I am typing to you now from the cabin on my site where popups installation continues apace. We should be about three quarters done by end of today. It is currently raining outside but will clear later – the lads soldier on as if you didn’t you’d never get any construction in Ireland. But I have the luxury of being able to wait inside until it stops raining later today, so I’m writing this diary entry instead.

This post introduces the most radical style change to this website since the Hugo conversion back in March 2019: a dark theme which is automatically chosen by your web browser if your system’s theme is dark. If your system is configured to switch between light and dark themes based on time of day, so will this website. If you wish to override the current light-dark theme chosen, there is now a floating theme override button in the top right of the page. It works identically on mobile and desktop, and requires no Javascript: it is pure CSS only.

Major browsers gained this ability around 2020 and it works like this: Firstly, we replace all the colours in all the CSS with CSS variables, which have been available in major browsers from 2017 onwards:

/* light */
:root {
    color-scheme: light dark;

    --c-body-bg: #fff;
    --c-body-fg: #000;
    --c-navbar-bg: #fff;
    --c-navbar-divider-bg: #000;
    --c-hover-bg: rgba(0,0,0,0.1);
    --c-hover-fg: #FF0000;
    --c-hover-glow: #aa0000;
    --c-tooltip-bg: beige;
    --c-tooltip-fg: #000;
    --c-tooltip-border: chocolate;
    --c-tooltip-arrow: #000;
    --c-pre-bg: rgba(0,0,0,0.05);
    --c-quote-bg: rgba(0,0,0,0.05);
    --c-shadow: #aaa;
    --c-shadow-heavy: #000;
    --c-affiliate-border: #000;
    --c-post-details-border: #000;
    --c-link: #00e;
    --c-link-visited: rgba(85, 26, 139, 1.0);
    --c-toggle-bg: rgba(255,255,255,0.33);
    --c-toggle-fg: rgba(48,48,48,0.66);
    --c-toggle-border: rgba(48,48,48,0.33);
    --c-toggle-shadow: rgba(0,0,0,0.33);
    --c-toggle-hover-bg: #fff;
    --c-toggle-hover-fg: #333;
}

I actually had Step 3.7 Flash do most of this work, and it chose for the CSS variable names a c- prefix for reasons I don’t precisely understand, but equally it seemed a safer thing to do so I left it.

We now use the prefers-color-scheme CSS feature to tell the browser to overwrite those variables when the system theme is dark:

/* Experimental CSS5 stuff */
@media (prefers-color-scheme: dark) {
    /* dark */
    :root {
        --c-body-bg: #000;
        --c-body-fg: #fff;
        --c-navbar-bg: #000;
        --c-navbar-divider-bg: #aaa;
        --c-hover-bg: rgba(255,255,255,0.2);
        --c-hover-fg: #FF0000;
        --c-hover-glow: #ff6666;
        --c-tooltip-bg: #2d2d2d;
        --c-tooltip-fg: #d4d4d4;
        --c-tooltip-border: #555555;
        --c-tooltip-arrow: #555555;
        --c-pre-bg: rgba(255,255,255,0.2);
        --c-quote-bg:rgba(255,255,255,0.2);
        --c-shadow: #333;
        --c-shadow-heavy: #000;
        --c-affiliate-border: #444444;
        --c-post-details-border: #555555;
        --c-link: lightskyblue;
        --c-link-visited: #ad8bcd;
        --c-toggle-bg: rgba(32,32,32,0.33);
        --c-toggle-fg: rgba(240,240,240,0.66);
        --c-toggle-border: rgba(240,240,240,0.33);
        --c-toggle-shadow: rgba(255,255,255,0.33);
        --c-toggle-hover-bg: #222;
        --c-toggle-hover-fg: #eee;
    }

Finally, you add to the <head> stanza to tell the browser that you support automatic theme switching <meta name="color-scheme" content="light dark">, and you will now have automatic theme switching, where the default theme is light.

Making the theme user toggleable

Sometimes you might not want the theme to be dark or light depending on use case, so being able to override it manually is a must. You can do this trivially easy using four lines of Javascript, but I wanted to avoid Javascript so that unfortunately means stamping out quite a lot more CSS:

/* CSS-only dark mode toggle overrides via checkbox */
/* light */
#theme-toggle:not(:checked) ~ #page {
    --c-body-bg: #fff;
    --c-body-fg: #000;
    --c-navbar-bg: #fff;
    --c-navbar-divider-bg: #000;
    --c-hover-bg: rgba(0,0,0,0.1);
    --c-hover-fg: #FF0000;
    --c-hover-glow: #aa0000;
    --c-tooltip-bg: beige;
    --c-tooltip-fg: #000;
    --c-tooltip-border: chocolate;
    --c-tooltip-arrow: #000;
    --c-pre-bg: rgba(0,0,0,0.05);
    --c-quote-bg: rgba(0,0,0,0.05);
    --c-shadow: #aaa;
    --c-shadow-heavy: #000;
    --c-affiliate-border: #000;
    --c-post-details-border: #000;
    --c-link: #00e;
    --c-link-visited: rgba(85, 26, 139, 1.0);
    --c-toggle-bg: rgba(255,255,255,0.33);
    --c-toggle-fg: rgba(48,48,48,0.66);
    --c-toggle-border: rgba(48,48,48,0.33);
    --c-toggle-shadow: rgba(0,0,0,0.33);
    --c-toggle-hover-bg: #fff;
    --c-toggle-hover-fg: #333;
}

/* dark */
#theme-toggle:checked ~ #page {
    --c-body-bg: #000;
    --c-body-fg: #eee;
    --c-navbar-bg: #000;
    --c-navbar-divider-bg: #aaa;
    --c-hover-bg: rgba(255,255,255,0.2);
    --c-hover-fg: #FF0000;
    --c-hover-glow: #ff6666;
    --c-tooltip-bg: #2d2d2d;
    --c-tooltip-fg: #d4d4d4;
    --c-tooltip-border: #555555;
    --c-tooltip-arrow: #555555;
    --c-pre-bg: rgba(255,255,255,0.2);
    --c-quote-bg: rgba(255,255,255,0.2);
    --c-shadow: #333;
    --c-shadow-heavy: #000;
    --c-affiliate-border: #444444;
    --c-post-details-border: #555555;
    --c-link: lightskyblue;
    --c-link-visited: #ad8bcd;
    --c-toggle-bg: rgba(32,32,32,0.33);
    --c-toggle-fg: rgba(240,240,240,0.66);
    --c-toggle-border: rgba(240,240,240,0.33);
    --c-toggle-shadow: rgba(255,255,255,0.33);
    --c-toggle-hover-bg: #222;
    --c-toggle-hover-fg: #eee;
}

This is unfortunately very copy-and-paste, but I am unaware of doing better using pure CSS. In any case, we now overwrite those CSS variables based on whether the toggle theme checkbox is checked or not. Unfortunately we are not yet done with the copy-and-paste:

/* Experimental CSS5 stuff */
@media (prefers-color-scheme: dark) {
    /* CSS-only dark mode toggle overrides via checkbox */
    /* dark */
    #theme-toggle:not(:checked) ~ #page {
        --c-body-bg: #000;
        --c-body-fg: #eee;
        --c-navbar-bg: #000;
        --c-navbar-divider-bg: #aaa;
        --c-hover-bg: rgba(255,255,255,0.2);
        --c-hover-fg: #FF0000;
        --c-hover-glow: #ff6666;
        --c-tooltip-bg: #2d2d2d;
        --c-tooltip-fg: #d4d4d4;
        --c-tooltip-border: #555555;
        --c-tooltip-arrow: #555555;
        --c-pre-bg: rgba(255,255,255,0.2);
        --c-quote-bg: rgba(255,255,255,0.2);
        --c-shadow: #333;
        --c-shadow-heavy: #000;
        --c-affiliate-border: #444444;
        --c-post-details-border: #555555;
        --c-link: lightskyblue;
        --c-link-visited: #ad8bcd;
        --c-toggle-bg: rgba(32,32,32,0.33);
        --c-toggle-fg: rgba(240,240,240,0.66);
        --c-toggle-border: rgba(240,240,240,0.33);
        --c-toggle-shadow: rgba(255,255,255,0.33);
        --c-toggle-hover-bg: #222;
        --c-toggle-hover-fg: #eee;
    }

    /* light */
    #theme-toggle:checked ~ #page {
        --c-body-bg: #fff;
        --c-body-fg: #000;
        --c-navbar-bg: #fff;
        --c-navbar-divider-bg: #000;
        --c-hover-bg: rgba(0,0,0,0.1);
        --c-hover-fg: #FF0000;
        --c-hover-glow: #aa0000;
        --c-tooltip-bg: beige;
        --c-tooltip-fg: #000;
        --c-tooltip-border: chocolate;
        --c-tooltip-arrow: #000;
        --c-pre-bg: rgba(0,0,0,0.05);
        --c-quote-bg: rgba(0,0,0,0.05);
        --c-shadow: #aaa;
        --c-shadow-heavy: #000;
        --c-affiliate-border: #000;
        --c-post-details-border: #000;
        --c-link: #00e;
        --c-link-visited: rgba(85, 26, 139, 1.0);
        --c-toggle-bg: rgba(255,255,255,0.33);
        --c-toggle-fg: rgba(48,48,48,0.66);
        --c-toggle-border: rgba(48,48,48,0.33);
        --c-toggle-shadow: rgba(0,0,0,0.33);
        --c-toggle-hover-bg: #fff;
        --c-toggle-hover-fg: #333;
    }
}

What we are doing here is flipping the handling of the toggle theme checkbox being ticked based on the system’s current theme i.e. you get the system’s current theme on page load, if the system theme changes the website also changes its theme, and the toggle theme checkbox being ticked therefore means ‘the opposite theme of the system theme’. Next we need a theme toggle:

    <input type="checkbox" id="theme-toggle" class="theme-toggle" aria-label="Toggle dark mode">
    <div id="page">
      <label for="theme-toggle" class="theme-toggle-label" aria-label="Toggle dark mode">
        <span class="icon-moon" aria-hidden="true">🌙</span>
        <span class="icon-sun" aria-hidden="true">☀️</span>
      </label>
      ...
    </div>

Thanks to Unicode, the sun and the moon no longer need dedicated image assets like we would do in the bad old days. Nowadays, you just use the appropriate Unicode codepoint, dead simple.

The next thing is to make our toggle theme button NOT have a visible checkbox, and to style its label so it shows the moon or the sun and that floats at the top right with a transparency so it doesn’t get in the way of reading text:

/* Visually hidden checkbox but keyboard-accessible */
.theme-toggle {
    position: fixed !important;
    top: 0;
    right: 0;
    height: 1px;
    width: 1px;
    overflow: hidden;
    clip: rect(1px, 1px, 1px, 1px);
}

/* Fixed floating dark-mode toggle button */
.theme-toggle-label {
    position: fixed;
    top: 1rem;
    right: 1rem;
    z-index: 9999;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    background: var(--c-toggle-bg);
    color: var(--c-toggle-fg);
    border: 2px solid var(--c-toggle-border);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font-size: 1.2rem;
    line-height: 1;
    box-shadow: 0px 0px 8px var(--c-toggle-shadow);
}

.theme-toggle-label:hover {
    background: var(--c-toggle-hover-bg);
    color: var(--c-toggle-hover-fg);
    border-color: var(--c-hover-fg);
}

.icon-moon,
.icon-sun {
    display: inline;
}

Finally, we need the toggle theme icon to be the correct one in all circumstances, which unfortunately requires yet more copy-and-paste CSS:

.theme-toggle:checked ~ #page .icon-moon {
    display: none;
}
.theme-toggle:not(:checked) ~ #page .icon-sun {
    display: none;
}

@media (prefers-color-scheme: dark) {
  .theme-toggle:checked ~ #page .icon-moon {
      display: inline;
  }
  .theme-toggle:not(:checked) ~ #page .icon-sun {
      display: inline;
  }
  .theme-toggle:checked ~ #page .icon-sun {
      display: none;
  }
  .theme-toggle:not(:checked) ~ #page .icon-moon {
      display: none;
  }
}

And that’s basically it – an unfortunate amount of duplication in the main CSS file, but it does get served to users gzip compressed so all that text duplication matters little to website load times. Most processors are so fast at parsing text that the extra verbiage doesn’t really matter either. As I mentioned above, you could use a few lines of Javascript and save yourself all this duplication, but I personally configure my web browser with Javascript disabled by default and I enable it on a per-site basis – only if I absolutely must use a site and it’s broken without Javascript do I enable it. If it’s a site I don’t care hugely about and it won’t load without Javascript I generally just close the tab, not worth the effort.

As mentioned above, Step 3.7 Flash did almost all of the work here. It didn’t get quite all the way there on its own though, because I wouldn’t let it install web page to image rendering via which it could debug its work. So I took it manually for the final stage of debugging and tweaking to get the last of it over the line. But I understand from reading online that if I had allowed it to visualise the results of its work and to click around the web page by itself, it should have successfully completed its task in full. The reason I didn’t give it the power to browse and interact with web pages by its itself alone is probably obvious: I hadn’t set up safety containerisation for it on my Mac, so it was effectively operating as if me.

It’ll probably be popups installation in my next diary entry. Depends on when they get it completed and what the weather will be like in the next few days. We shall see!

#website #theming




Word count: 1723. Estimated reading time: 9 minutes.
Summary:
The final entry regarding the balcony solar installation has been written. After delays caused by smart meter outages, data analysis was completed. It is found that the solar panels contribute to bill reduction. An annual saving of €204, representing an 11% decrease in electricity costs, is estimated. The return on investment period has been calculated at 2.54 years.
Monday 15 June 2026:
17:02.
Word count: 1723. Estimated reading time: 9 minutes.
Summary:
The final entry regarding the balcony solar installation has been written. After delays caused by smart meter outages, data analysis was completed. It is found that the solar panels contribute to bill reduction. An annual saving of €204, representing an 11% decrease in electricity costs, is estimated. The return on investment period has been calculated at 2.54 years.
I am finally able to write up the third and final part of my series of diary entries on ‘balcony solar’ installations in Ireland. The first entry went into some detail about the hardware and the theory behind ‘balcony solar’ installations in Ireland, and the second entry discussed issues around local measurement and control of the balcony solar installation. As mentioned in those posts, we needed to wait until we were into June before I could write this final entry which answers the crucial question:

How much money is this ‘balcony solar’ installation saving me in terms of bills?

This is because the Irish ESB Networks makes public your smart meter data with a delay of a few days, but not infrequently they have outages which delays that data by weeks. We unfortunately had one of those outages end of May, and I didn’t get complete smart meter data for analysis until today.

Quick recap

You will remember from the first post that current electricity costs and tariff distribution are as follows:

PeriodCurrent cost per kWhSummer daily avrgWinter daily avrg
Peak rate: 5pm - 7pm€0.38
(+65% over night rate)
1.93 kWh (€0.73)2.41 kWh (€0.92)
Day rate: 8am - 5pm, 7pm - 11pm€0.33
(+43% over night rate)
8.81 kWh (€2.91)9.80 kWh (€3.23)
Night rate: 11pm - 8am€0.233.15 kWh (€0.72)3.30 kWh (€0.76)

And that:

  1. 66.7% of the bill goes on day rate electricity.
  2. 16.7% of the bill goes on peak rate electricity.
  3. 16.5% of the bill goes on night rate electricity.

So, from a bills perspective, you only really care about day rate and peak rate electricity as that is 83.5% of your electricity bill.

Furthermore, that two solar panels were first hooked into the house mains from around mid-April, with those being initially ground mounted and left to run for a few weeks while I debugged the setup and made sure it would all work before going to the bother of installing them onto the outhouse roof. From the 8th May onwards I had all four panels mounted onto the outhouse roof and contributing power. The configuration is that three panels are connected to the battery storage and one panel is connected to the inverter on its second input – from 9.30am each morning the battery charges to full and a single panel supplements household electricity usage; once the battery is charged, all four panels supplement the household usage; from 5pm onwards the battery discharges at 220 watts with the single panel supplementing, until 11pm when everything turns off until 8am in the morning when the battery again outputs 220 watts with the single panel supplementing. One should therefore save at least two kWh of day and peak rate electricity per day in the summer months, and I had been expecting a theoretical saving of around twenty percent of day + peak rate electricity usage during those summer months. That, based on the 83.5% of my electricity bill above, should reduce my bill by 16.7%, or about €25 per month, but again only during the summer months where there is enough free energy falling from the sky to fully charge the 1.6 kWh battery storage each day.

The last two years at the mains meter box

Note that the Irish ESB only provide the last two years of detailed data from your smart meter:

I’ve separated daylight savings time (DST) months from winter months (GMT) because the seven months of DST are the only ones from which you’ll get much off solar panels, and even then March has been considerably better than October for solar radiation in the past two years. DST also matters because you switch on lights earlier and later in the day, so you tend to use more power during GMT months. Which leads me into …

Confounding factors

The most natural thing to do would be to compare last year’s electricity consumption to this year’s, however last year before June I had the main developer workstation turned on daily, and this year past I mostly don’t have it turned on daily as my Macbook is enough for most of the things I need to do if I’m not earning money (e.g. right now, I’m writing this on the laptop plugged into the developer workstation’s large 4k monitor, because spinning up the dev workstation to type text is way overkill). In 2024, an average typical summer day + peak rate used 11.62 kWh and an average typical winter day used 12.25 kWh, whereas after unemployment an average typical summer day + peak rate used 9.67 kWh (-16.82%) and an average typical winter day used 12.18 kWh (-0.6%).

I must admit a little surprise that I had the developer workstation turned on so frequently during the most recent winter months, but that does match my memory – I remember being quite grateful, as I am every year, for the free space heating my office gets from the developer workstation being turned on. The fact that this adds more than one eighth to my total household electricity bill is a little sobering, but at least heat generated by the workstation is a more productive use of that electricity than an electric bar heater.

I should also mention that immediately after my employment ended, I particularly was not at home as I was out riding bikes and climbing mountains during June and July 2025, so the electricity for those months was lower than it likely will be this year where I’m more accustomed to having my freedom, for example.

What is the estimated reduction of my electricity bill?

Obviously the yellow bars in the summer months chart above for April, May and June 2026 are our reductions from the ‘balcony solar’. After adjustment for my unemployment reducing power consumption anyway, I reckon that the solar panels contributed a reduction in peak and day rate electricity consumption according to the ESB meter box as follows:

Month Reduction
June 2026 -22.96%
May 2026 -13.89%
April 2026 -2.54%

May is probably lower than it should be because my APSystems EZ1 inverter’s MPTT1 input died, so I had to route everything through its MPTT2 input only. That reduced efficiency by a bit – judging by June’s results so far, by quite a bit in fact. In June a replacement was installed and the original sent back as RMA, so we’ll see how things go in the next few months.

Assuming that you will only get much from the panels for seven months, and that winter months use more power, I reckon I might get an annual electricity bill reduction of around eleven percent. That is, in my case and with current electricity prices, equal to €204 saved in bills per year. That is a return on investment period of 2.54 years, a bit longer than I had originally intended (a year!).

Why so low? This 2023-era low voltage system is particularly inefficient, I reckon it loses a good 20-25% of the power it captures, plus it doesn’t charge optimally, nor does it discharge optimally. A 2025-era or later system based on dual inverters so it is capable of simultaneous charge and discharge would be considerably less stupid with power distribution, and it would respond to changes in household consumption rapidly, rather than wastefully sitting at a constant discharge rate between fixed time periods irrespective of the weather outside.

As covered in previous posts in this series, for a little more money you can get FAR better kit, modern stuff instead of this 2023-era kit that I ended up with thanks to Aliexpress sending me not what I had thought I had ordered. As we’ll probably be out of this rented house within 2.5 years – well, hopefully! – I’m going to lose money on this project. But for anybody reading, if you expect to still be living where you are right now for more than two years, you really ought to be very strongly considering installing micro solar generation into your house. Even in Ireland’s typically overcast skies! Solar battery storage has gotten so cheap it’s a no brainer.

This is despite zero subsidies from the government (indeed, a 23% VAT tax on all the equipment!), and zero payment for excess power contributed to the grid. Even with those very unfavourable conditions, microgeneration solar is face palm obviously the right move with a two year payback period, as year three onwards is pure gravy.

What’s next?

The popups installation for my site has begun! I’ve been waking at 4am to be onsite for 6.30am this week to help out, as I will be tomorrow morning. Thank God I am unemployed! And expect an entry on here with pictures when it’s all done.

I asked the Step 3.7 Flash LLM how it would improve this website. It gave a long list of modern web page design ideas, none of which interested me, bar one: a dark-light theme which auto switches based on your viewing device’s dark-light theme setting (apparently this landed with CSS v5, I don’t pay attention to new web standards until somebody – or some LLM – points stuff out to me). So I went ahead and implemented that dark-light theme for this website, and you can expect an entry on that soon.

My ‘end of an era’ special on Chinese direct to consumer sales platforms like Aliexpress is probably after the dark-light theme entry, though an entry on the site popups installation might beat it. In any case, I hope to get that end of an era entry up before the end of the month when the EU tariff comes in as then would be timely.

Other than those three, I don’t have any particular plans for diary entries here. School for the kids ends tomorrow week, after which I’ll be on childcare until end of August, and I’ve been tempering my expectations about getting anything else done appropriately. I expect plenty of bicycling around North Cork’s spectacular scenery on the e-Bikes as with last year, but also upcycling furniture (the kids will be learning how) and painting walls (the kids will also be learning how). I’m sure between all that the summer will fly and before we know it they’ll be back to school.

Who knows if my builder will turn up and erect my house by then! I suspect it very unlikely, but we’ll find out.

#solar #solarpanels #balcony-solar




Word count: 757. Estimated reading time: 4 minutes.
Summary:
An annual comparison of storage pricing has been presented. It is observed that both SSD and HDD costs have dramatically increased, reaching levels seen in previous years. This unprecedented price surge is attributed to the massive spending on AI infrastructure. The current high costs are believed to be unsustainable, though they may continue for another year.
Monday 1 June 2026:
15:28.
Word count: 757. Estimated reading time: 4 minutes.
Summary:
An annual comparison of storage pricing has been presented. It is observed that both SSD and HDD costs have dramatically increased, reaching levels seen in previous years. This unprecedented price surge is attributed to the massive spending on AI infrastructure. The current high costs are believed to be unsustainable, though they may continue for another year.
Here is the annual update to my periodic comparison of storage bytes per inflation adjusted dollar for magnetic hard drives and flash SSDs (you can find all the past posts here), which I have done every June since 2012:

Raw data: http://www.nedprod.com/studystuff/SSDsVsHardDrives.xlsx

What an astonishing year it has been for storage pricing! SSDs are more than double their cost last year – as if we had returned to 2019! Hard drives also more than doubled their cost of last year, and we have returned to 2020 pricing in terms of bytes per inflation adjusted dollar. I certainly have never seen such a massive price increase like this before, nor ever in the historical data apart from when those floods in Thailand took out a good portion of hard drive supply, and that affected hard drives only, whereas this dramatic price surge affects everything. It is unprecedented, to my knowledge.

This time last year I said:

This time two years ago I predicted a recession would cause storage prices to tumble. Here looks like that recession, but so far it hasn’t appeared in the wider US economy, though it has in the wider European and Asian economies.

As regular readers here will remember, I recently picked up a factory recertified 28Tb hard drive recently for a dedicated AI inferencing machine for the site’s security cameras. I got that drive delivered for €400. That might seem a lot, but minus sales taxes (23%) and delivery (maybe €30) that 28Tb enterprise hard drive cost about €300. That same drive cost nearer a grand after taxes this time last year. It’s madness just how much hard drive prices have fallen in a single year. I can’t remember anything like it in recent memory.

And one year later, hard price pricing has lurched violently in the opposite direction, despite that outside of AI the general tech industry is definitely in recession along with all of the US, European and Asian economies if you exclude the AI investment boom.

The AI investment boom is of course responsible for the surge in storage pricing, it has also doubled or more the cost of RAM, CPUs, anything computer related really. Right now is a terrible time to buy new computer hardware, though it’s an excellent time to be within the supply chain for manufacturing computer hardware. Such is the level of spending on AI infrastructure that it’s holding up the US economy and stockmarket, and probably also the Asian economies who would otherwise be in deep recession. They think US$400 billion was spent on AI infrastructure last year, and US$725 billion is the current projection for 2026 – and this omits the estimated injection of funding into their AI companies by the Chinese government as direct financial supports. Landing humans on the moon cost about US$250 billion in today’s money; the whole Vietnam war all in cost around US$1,125 billion in today’s money, but they spent that over twenty years and the tech industry is spending that in just two years. The sums involved are breathtaking, and of course, unsustainable.

Based on Q1 2026 reported results, Meta is now in net debt with the balance sheets of Microsoft and Amazon seeing significant deterioration in the past year. While Meta is in trouble, Microsoft and Amazon have enough cash they can probably carry on spending like this for another year, but after that, they’re going to have to decide if they can justify continuing. In contrast, Google and Bytedance look very healthy and could keep spending like this for years to come, and probably therefore will outlast everybody else when the stack of cards falls down (which I currently assume will be either or both of OpenAI and Anthropic collapsing when investors stop lending more money to them, which will set off a chain of capital withdrawal across the industry).

It is entirely feasible therefore that we have a full twelve more months of this sort of spending on AI infrastructure, and therefore this annual update this time next year will also report historically expensive storage. But I would be very surprised if this remains the case in 2028. I also think that the rest of the economy may become a noose around the neck of tech later this year, there is a fair chance of the financial system doing a wobbly again, maybe in private credit markets or even possibly sovereign debt. That might bring the party to an end before the end of 2026.

I guess we should know by this time next year!

#ssdsvsharddrives




Word count: 3954. Estimated reading time: 19 minutes.
Summary:
A detailed account of an Irish micro solar installation is presented. Technical aspects regarding the “balcony solar” system are discussed, including measurement methods and control via an Anker Solix unit. Legal constraints regarding grid export are addressed, while optimization strategies for bill reduction are detailed. The role of an LLM in system design is also described.
Friday 29 May 2026:
20:03.
Word count: 3954. Estimated reading time: 19 minutes.
Summary:
A detailed account of an Irish micro solar installation is presented. Technical aspects regarding the “balcony solar” system are discussed, including measurement methods and control via an Anker Solix unit. Legal constraints regarding grid export are addressed, while optimization strategies for bill reduction are detailed. The role of an LLM in system design is also described.
Last diary entry I went into a fair bit of detail about the hardware and the theory behind ‘balcony solar’ installations in Ireland, and I was hopefully persuasive about the theoretical potential reduction in electricity bills and theoretical return on investment of under two years.

One major caveat is that we cannot legally export power to the grid in Ireland without gaining prior approval, for which a registered electrician has to submit the appropriate documentation for what they have personally installed. This rules out the type of DIY installed micro solar installation called ‘balcony solar’ which is based on pushing power in the opposite direction via a standard household appliance plug, up to 800 watts as per the legal maximum in many EU countries such as Germany.

As a result, one needs to script and control the overall system to:

  1. Maximise the electricity not consumed from the grid.
  2. Minimise the electricity exported to the grid (which is wasted, but also illegal).

The next post in this series (but not the immediately next post, which will be my annual review of hard drive and SSD storage prices) will look at the empirically measured results at the mains meter i.e. bills actually reduced. For that though, I need at least a month of measurements to draw any definitive conclusions, so that last post of the three in the series will necessarily have to wait until sometime next month.

So what is the first thing that we need to ensure we do not export to the mains grid? As mentioned last entry, everybody in Ireland with a smart meter can retrieve the last two years of their electricity usage from https://www.esbnetworks.ie/services/manage-my-meter/view-my-smart-meter-usage with a thirty minute granularity, along with exact counts of kWh used for day rate (8am - 5pm, 7pm - 11pm), peak rate (5pm - 7pm), and night rate (11pm - 8am). For non-obvious reasons, these lag by four days or so, so if I went to that site right now I could see usage data only up to the 24th or 25th. This is useful for checking if a solution is accurate, but it is not the solution itself. What we need is a much more immediate way of reading current mains grid consumption power.

Locally reading the mains grid meter

Many years ago we had a thing called an OWL which had an AA battery powered clamp remote unit you could install in the meter box, and its main unit had a big LCD display showing the exact power being used right now. It had a USB port, and you could plug it into a PC and read the live data. It worked very well for about five years, but then one day stopped reading data which I had assumed was the remote unit failing, so it went off to electrical recycling heaven.

OWL seemed to have trebled the price since then, and not upgraded the system so you’re still stuck with its USB interface. This is annoying, the remote unit was a standard 433 Mhz low power transceiver and once upon a time you could cheaply buy a generic USB transceiver for those. But apparently no more – I couldn’t find any of that technology cheaply, and its driver support in Linux was very questionable. In short, it is abandoned hardware and especially at the trebled price it was a bad purchase.

I naturally then gravitated towards something Zigbee or Z-Wave based as both are low power enough to run off AA batteries for months, with Zigbee being the cheaper option, because I can’t install wiring into a rented house so wireless and battery powered is my only option. There are several affordable clamp-based Zigbee meters available, but for some inexplicable reason they all require mains power to work which would require me to rewire the mains meter box. As this isn’t my house, I can’t do that, and because they only take AC 230V, I can’t wire in a battery box either.

I eventually landed on the only cheap option remaining: a pulse counter. Smart mains electricity meters have a little LED on their front which flashes every one thousandth of a kWh. You can attach a pulse counter which records every one of those flashes, and from that can calculate the current number of watts being imported. There are several options for these devices, I went with the Frient Electricity Meter Interface 2 for about €35 inc VAT delivered, and it does exactly what it says on the tin: the meter flashes, it updates its Zigbee state, anything subscribed gets notified. It turns out to be very accurate overall – just 0.72% deviation from the ESB readings over a month – but it is prone to instantaneous overestimation i.e. it’ll report, for a short while, far more mains power usage than is correct. It’ll then self correct, and given enough time it balances out to within one percent of correct:

I have tried to see a pattern to when it deviates, but I can see nothing obvious and the fact that it does recover over time makes me think it’s possibly a suboptimal choice of algorithm. Big overestimation spikes are followed by extended spells of mild underestimation until the total count evens out. That said, I’ve never implemented one of these before, and maybe it’s harder to implement than it looks?

There are obvious limitations to pulse counting: the first is that by definition we cannot detect export to the grid as the meter LED does not flash if exporting power. The second is that resolution is very lousy at low power usage:

Power (watts)      Seconds between pulses (i.e. measurement lag)
1000 3.6
500 7.2
250 14.4
125 28.8
60 60
30 120

As you can see, it must take a minimum of half a minute to detect 125 watts of mains grid usage, and a minimum of two minutes to detect 30 watts of mains grid usage. As is very obvious, this means that the closer we get to exporting to the grid, the exponentially worse instantaneous resolution our pulse counter has. This is very unfortunate, but I am unaware of any better solution under €150 which doesn’t require modifying the wiring in this rented house, so it will have to do.

Getting the Anker Solix Solarbank E1600 data into a local MQTT broker

One of the more annoying things about the Anker E1600 battery box is internally it uses bog standard MQTT for pub-sub communication with the Anker cloud and the Anker mobile phone app. That makes it straightforward to write a web client which subscribes to the MQTT feed (https://github.com/thomluther/anker-solix-api is probably the most popular and best supported implementation), including a straightforward ‘replicate this MQTT from the Anker cloud to my local MQTT broker’. The reason that this is annoying is because the Anker cloud is completely unnecessary here, the device could connect to a local MQTT broker and skip the cloud entirely. But no, Anker didn’t enable that trivially easy thing to enable in its firmware, so we are at where we are at.

I took one of the examples from the github repo above and adjusted it to replicate all MQTT updates to a local MQTT broker. This isn’t Niall’s coding at its finest, but it’s been running trouble free for a month now so it’ll do:

#!/usr/bin/env python3
"""Example: E1600 MQTT integration with monitoring and control."""

import asyncio
import logging

from aiohttp import ClientSession
from api.api import AnkerSolixApi  # pylint: disable=no-name-in-module
from api.mqtt_factory import SolixMqttDeviceFactory  # pylint: disable=no-name-in-module
from api.mqtt_solarbank import SolixMqttDeviceSolarbank  # pylint: disable=no-name-in-module
from aiomqtt import Client
import common

_LOGGER: logging.Logger = logging.getLogger(__name__)
CONSOLE: logging.Logger = common.CONSOLE
MODEL = "A17C0"
MQTT_BROKER = "192.168.x.x"
MQTT_PREFIX = "Solarbank"

class Device:
    def __init__(self, queue, mqttdevice : SolixMqttDeviceSolarbank):
         self.mqttdevice = mqttdevice
         self.queue = queue
         self.last_items = {}

    def topic_updated(self, *args, **kwargs):
        for k,v in args[6].items():
            if k not in self.last_items or self.last_items[k] != v:
                self.queue.put_nowait((k, v))
                self.queue._loop._write_to_self()
                self.last_items[k] = v

async def main():
  async with Client(MQTT_BROKER) as client:
    async with ClientSession() as websession:
        myapi = AnkerSolixApi(
            common.user(), common.password(), common.country(), websession, _LOGGER
        )
        CONSOLE.info("Checking for devices...")
        await myapi.update_sites()
        await myapi.get_bind_devices()
        device_sn = None
        for sn, device in myapi.devices.items():
            if device.get("device_pn") == MODEL:
                device_sn = sn
                CONSOLE.info(f"Found device: {sn}")
                break

        if not device_sn:
            CONSOLE.info(f"No device ({MODEL}) found")
            return

        queue = asyncio.Queue()
        device = Device(queue, SolixMqttDeviceFactory(
            api_instance=myapi, device_sn=device_sn
        ).create_device())
        mqttsession = await myapi.startMqttSession(device.topic_updated)
        if not mqttsession:
            CONSOLE.info("Failed to start MQTT session")
            return
        mqttsession.subscribe(f"dt/anker_power/{MODEL}/{device_sn}/state_info")

        CONSOLE.info("Topic subscribed, awaiting topic updates ...")
        while True:
            for n in range(0, 100):
                k, v = await queue.get()
                CONSOLE.info(f"{MQTT_PREFIX}/{k} => {v}")
                await client.publish(f"{MQTT_PREFIX}/{k}", payload=v)
            # Republish unchanging values periodically
            device.last_items = {}

if __name__ == "__main__":
    try:
        asyncio.run(main(), debug=False)
    except Exception as err:  # pylint: disable=broad-exception-caught  # noqa: BLE001
        CONSOLE.info(f"{type(err)}: {err}")

I wrapped that into a docker image and wrote a little docker compose stanza for it so it launches with OpenHAB, and that’s how I built the OpenHAB dashboard you saw in the last post – it’s just values from MQTT. OpenHAB has been told to record readings into a SQLite database, and from that I generated the graph above comparing the Frient pulse counter readings to those from ESB Networks.

Controlling the system

You may remember from a few posts ago me extolling the virtues of a 196b LLM called Step 3.5 Flash which is designed to work well on consumer hardware. Well, it turns out not only does it name personally members of the Chinese Communist party when describing alleged incidents of impropriety, it’s also not half bad at software engineering. So I plugged it into Visual Studio Code as my coding assistant, and told it to go research a design which would solve controlling this system. It went off scouring the web including reading through all the German Balkonkraftwerk discussion forums AND all the datasheets for my specific devices, and then constructed a very feasible design plan. I prompted it with a few ‘stupid’ questions to help it improve its design, then I let it loose implementing the solution.

Step 3.5 Flash isn’t very good at writing code, it makes a lot of mistakes, but it realises its mistakes quickly enough and keeps iterating until they’re all fixed. That, combined with voluminous thinking token output, means it burns through the tokens quickly. It certainly chewed through 500 million tokens with ease, costing me about $14, and it ran for a few hours including live running the control program against the real hardware, interpreting the log output and/or launching the program under the debugger, fixing bugs and improving its test suite, until it declared that it felt it had a working control program.

I was suitably impressed if I am honest. This LLM runs well on consumer hardware with enough RAM e.g. a Mac Book with >= 128Gb of RAM. It’s not up there with Claude Opus, it makes far more mistakes and generates oodles of thinking tokens, but if I’m not paying by the token this is something you can give it a job to do, go to bed and when you wake up it’ll have something potentially production ready to go. That’s impressive and it gets me excited about the future for when I need working code and I don’t really care about its performance nor security e.g. local device control code.

Step 3.5 Flash was released last February, and by pure sheer coincidence its next iteration landed this morning: Step 3.7 Flash. It’s better across every metric whilst staying within the 200bn parameter limit, it’s still fast on consumer hardware with at least 128Gb of RAM, and it can now also see (i.e. it has gained vision). It writes better quality code first time, outputs far less thinking tokens, and unsurprisingly local LLM enthusiasts are all very excited – I myself was busy poring through the benchmarks and documentation at 7.30am this morning despite being just awake. I’m sure I’ll be writing here more about that LLM, but to return to the point, Step 3.5 Flash did a pretty good job at getting this solved with minimal oversight from me.

Unfortunately, as I mentioned last diary entry, we came foul of the Anker box finding the APSystems inverter controlling output to be unacceptable and the cause of occasional error states where all output power is cut until somebody clears the error by pressing the button on the front of the box. So my $16 of OpenRouter spend ended up being wasted, which was annoying, though it did gain me my first experience of end-to-end agentic AI software design and implementation.

Controlling the Anker storage output instead

The Anker battery storage can be told to output any wattage value you choose with a ten watt granularity, but it is via its timed program facility i.e. you tell the Anker cloud that between X time and Y time the battery shall output Z watts. The next time that the device pushes an update to the Anker cloud, it’ll look at the current output and if it is not what it is supposed to be, it pushes a command to the storage to adjust its output. This seems to have an update frequency no better than one minute, and more usually like ninety seconds. Given that the Frient meter has a lag of a minute or so, and so does output control, and that most large electrical loads like an oven work by a relay switching on and off (i.e. all on, all off), by the time you’ve told the system to increase output the device consuming it will have stopped, and now you’re exporting to the grid and wasting power.

As mentioned last post, you can control the Anker battery storage via Bluetooth instead, and at least there you can push new output levels pretty much instantly and they’ll apply. I read online that the Anker device responds within seconds, so IF you had a sensitive and responsive mains power clamp AND you controlled this via Bluetooth, I think zero export power is achievable. But I am missing both, so that won’t work in my situation. We will need an alternative solution!

Back to the drawing board

Throughout all this high systems engineering, I began to wonder if I am overcomplicating the control of this system? Yes, in a traditional battery storage powered inverter you want to have the system output as close to what the house is using so mains power consumption is as close to zero as possible. But this particular micro solar installation has a unique aspect: it has just 1.6 kWh of battery storage. And here’s the revelation: it doesn’t matter which day and peak hour kWh you offset, they all cost the most.

If you therefore have the battery discharge at a low, fixed, rate during day and peak hour rates after the sun goes down so that it is empty by end of day rate, you don’t need to do anything more. You’re already maximising your bill savings. So complicated control programs aren’t necessary so long as that low, fixed, rate is at or below the house’s baseline power consumption.

I’ve ended up configuring the system as follows: at 5pm when peak rate begins, the battery always starts to discharge at 220 watts. After conversion losses, that turns into almost exactly 200 watts being pushed by the inverter into the house. You may remember from the last post that I wired my best panel directly into the inverter, and the other three panels into the battery storage, so during daylight hours you typically see 80-300 watts from that single panel while the battery storage charges, after it is full you see a varying depending on cloud cover 240-700 watts from all four panels up to 5pm each day, then you get the ~200 watts from the battery plus whatever the single panel adds during the beginning of peak rate hours.

At a 220 watt discharge rate, and given that the battery stops discharging at 5% capacity, you will consume the battery after 6.91 hours. If starting at 5pm and stopping at 11pm, you should have 17.5% of battery capacity remaining of which 12.5% is usable. The battery turns on again at 8am, and usually reaches the 5% shut off a little after 9am (it depends on how much charging it does 6am - 8am).

This should be fairly optimal from a bills reduction perspective. It could be better, but it’s also not terrible: a kWh is a kWh, so long as our 200 watts battery output doesn’t exceed what the house uses.

As we saw in the half hourly electricity consumption graph last entry, we’re usually using at least 400 watts from 3pm onwards each day. So we’re all good on the bills reduction part, except of course for what happens between the battery getting full and 5pm each day.

To clamp output or not to clamp: that is the question

You can tell the Anker box to clamp its output after its battery is full so one never exports to the grid. However, if you think about that, that isn’t bill minimising: what you actually want to do between battery full and 5pm each day to minimise bills is push into the house everything the solar panels can gather. Then if say somebody runs the dishwasher, or the dryer, as many billed day rate kWh as possible get offset even if it means contributing kWh to the grid for no compensation. After all, once the battery storage is full, any kWh not reaped from the solar panels goes to waste in any case, so if they might potentially reduce your mains grid consumption you’re better off expending them on that than not using them at all.

Obviously that would be illegal, so you shouldn’t do that. However reading online I find that for low contributions, the ESB’s monitoring equipment at the nearest substation will never notice anything as other houses on the same ring will consume any power you export. So the only thing which could notice is your smart meter, and for some reason in Ireland the smart meters are explicitly configured to not count exported kWh unless activated remotely to do so. You can check your smart meter’s counts for day, peak, night and export by pressing the button on its front.

So, in other words, the ESB have configured their smart meters to intentionally not notice any kWh exported unless you get your connection upgraded to an export counting connection. Or, put another way, they’re apparently glad to take free electricity if they don’t have to pay you for it, so long as it is amounts that are less than what their substation emits (from reading online, if a substation ever sees negative flow it shuts down, triggering alarms at ESB Networks HQ, which I assume means that the installed capacity of solar power exporters per substation can never exceed half that of the substation).

What’s next?

The next entry will be my traditional annual entry on the inflation adjusted history of storage prices for spinning rust and flash memory. I’ll likely write that tomorrow or Monday.

I have the spreadsheets set up to analyse the ESB Networks raw data, so I should have some pretty graphs to show in the next entry in this series on balcony inverters which reveal just how much bill savings there were in the months of April and May. Expect that sometime in June.

If anything happens with the house build – ha! – it might gain mention here.

Finally, at the end of June will be the end of an era, and I think I’m going to do a special diary entry on here about it. The EU will be introducing a €3 per item tariff on small packages from outside the EU after the end of June. This means the end of cheap stuff imported directly by EU consumers, and in my particular case it’ll mostly mean the end of me buying stuff from the likes of Aliexpress as they won’t be cheap anymore.

Knowing that this is coming, I have been wracking my brains thinking of what to buy from Aliexpress before the deadline (the items must cross the EU border before 1st July to avoid the tariff, so I can’t really order anything new after the end of May). I have bought the following items recently:

  • Any components that the house would use which hadn’t been purchased yet in sufficient quantity, which turned out after a survey to be: seven more DC dimmer switches, thirteen more BTS7960 H-bridges for the ventilation boost fans, and sixteen more GA12 N20 blind motors. Not much cost – if bought now – so I’m glad that’s done.
  • Current inrush thermistors to perhaps prevent some of the 54v to 24v DC converters from blowing their fuses which has been happening occasionally on the site. These are very cheap components – on Aliexpress – and may solve the problem.
  • Two new types of DC dimmer, one a wall switch type cheaper than the ones I’ll be fitting to the house, and one ultra cheap inline wire type.
  • A snubber to fix the transient voltage shutdown problem at the site where if I try using the power washer, the Sungrow inverter cuts out complaining about overvoltage. I think that is caused by inductive voltage spikes from its motor. In any case, I’ll be constructing a plug in snubber box to work around the issue which I’ll show and tell here.
  • Many years ago now I expensed to the business the purchase of a used Fluke LRAT-2000. It has a SFP cage and can test fibre, but I’d never got round to getting a compatible SFP fibre transceiver for it, so I thought I ought to get that solved before the Aliexpress close deadline as I’ll need to assemble several small parts each of which would get a €3 tariff later.
  • And lastly, and it’s a bit silly but shows exactly why the loss of cheap Aliexpress is going to be a pain, I will be doing some furniture work to convert an old TV cabinet from my father’s house into a set of drawers. I have a sheet of Chinese coated plywood for the new shelves and back, and to fix the back and those shelves I’ll be using some cheap fixings from Aliexpress which cost very little, but aren’t things you can get over here easily or if you can, they are priced with a very hefty markup.

And that’s the annoying thing with this new EU tariff: I totally get that it puts EU based vendors at a disadvantage as they can’t compete on price. But they sell the exact same Chinese made stuff as Aliexpress, just usually with a 50-100% markup e.g. Amazon is chock full of identical items to Aliexpress, just usually a good bit more expensive. So we’re all going to have to pay more for the same stuff going forwards which does feel rather like the Corn Laws in the 19th century. It certainly is worse for the majority, to the benefit of a few.

I do expect to continue to use Aliexpress for items you just can’t get elsewhere: those DC PWM dimmers are an excellent example, the only other source for those I found was German units costing €120 each whereas the high end model from Aliexpress cost €17 each delivered. I also remember a fun time trying to find little metal cogs for the blind motors, and they were utterly unsourceable in quantities less than a thousand except from Aliexpress. For this type of thing, Aliexpress will remain king going forwards, and I’ll just have to pay the €3 tariff.

#solar #solarpanels #balcony-solar




Click here to see older entries


Contact the webmaster: Niall Douglas @ webmaster2<at symbol>nedprod.com (Last updated: 2019-03-20 20:35:06 +0000 UTC)