Martin's corner on the web

The clear-sky line

On a cloudy day, my PV production graph tells me almost nothing. Is the array fine and the sky is bad, or is something quietly wrong – dirty panels, a weak string, the inverter derating? I wanted a reference curve in Home Assistant: what the system would be producing right now under a cloud-free sky, drawn on top of what it actually produces.

The obvious candidate is the Forecast.Solar integration, but that is a forecast – it already has weather baked in, which is exactly what I don’t want. Online PV calculators need tilt, azimuth, and loss figures I’d be guessing at. Then it occurred to me that I’m sitting on better data: 3.3 years of hourly statistics from the Fronius GEN24, 28,592 rows of sensor.solarnet_power_photovoltaics in the recorder database. The array is its own best model.

Fitting the envelope

The trick is that clouds only ever subtract. If you bin three years of hourly output by sun position (elevation and azimuth), the top few percent of each bin is what the array does when nothing is in the way – the clear-sky envelope. I fitted a physical model to that envelope: top-of-atmosphere irradiance with the annual distance term, airmass from sun elevation, direct beam attenuated by a seasonal extinction coefficient, a diffuse term, standard transposition onto the panel plane, a temperature derate, and a DC clip:

E0  = 1361 * (1 + 0.033*cos(2pi*(doy-3)/365.25))         solar "constant"
AM  = 0.918 / (sin el + 0.50572*(el + 6.08)^-1.6364)     airmass, 720 m altitude
tau = 0.1122 * (1 - 0.469*cos(2pi*doy/365.25) - 0.010*sin(...))
DNI = E0 * exp(-tau * AM^1.48) * horizon(az)             direct beam
DHI = 0.1394 * E0 * (sin el)^0.6                         diffuse
POA = DNI*cos(AOI) + sky + ground terms                  panel plane, tilt 15deg, az 205deg
P   = min( 4.89 * POA * (1 - 0.0038*(Tamb + 0.032*POA - 25)), 6081 W )

Eleven parameters, all fitted from the data – I never measured the roof. The fit even recovered a horizon mask of about 6° east and 4.6° west, which matches the terrain here, and a seasonal extinction swing that makes winter air roughly twice as transparent as the July haze. Gist of the Python code I used for this: fit_clearsky.py

Validation: on the 29 genuinely clear days in the dataset, the model stays within about 176 W of actual production for any given hour – roughly 6% – and errs slightly high, which is what you want from a ceiling. The best day of every single month lands between 0.94 and 1.01 of the ideal curve, so it holds in January and July alike. The whole thing compiles into one template sensor – the Jinja version agrees with the Python reference to 0.2 W – and I backfilled the statistics to January, so the overlay works backwards in time too.

What it shows

July 27th was a nice demo. From 10:10 to 13:25 the two curves were glued together, 5041 W actual against 4994 W ideal at 12:25 – a certified clear sky. Then clouds rolled in and actual collapsed to 1700 W while the ideal line kept gliding along its arc. A clearness index sensor (actual/ideal) turns that into a single number: 97% on a clear day, 23% in the afternoon murk.

The part I didn’t expect: brief spikes above the ideal line whenever the sun reappears after a longer cloudy spell – 5830 W against a 5140 W clear-sky ceiling at one point, 13% over. Two effects stack there. One is cloud enhancement: droplets scatter light almost straight forward, so a cloud edge near the sun acts as a second light source on top of the direct beam – a 2025 paper measured 10–60% over clear-sky from exactly this. The other one I could verify from my own data: the panels cool toward ambient while shaded, and cool silicon is better silicon. The MPPT voltage gives it away – 294 V during the cloudy spell, 277 V when the sun burst through, settling to 271 V over the next twenty minutes as the cells warmed back up. That voltage decay is a thermometer, and it says the panels were 15–20 K cooler when the sun returned, worth 300–400 W of temporary bonus at the −0.38%/K coefficient the fit found.

Tagged on: ,

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.