Skip to content

Alternator Health

What the system does

It answers one question: is your alternator still as strong as it used to be?

Raw amps can't answer that, because output depends on conditions. 30 amps might be excellent at idle and weak at cruise. So the system only ever compares output against what this same alternator produced under the same conditions. It is advisory: no safety logic depends on it.

How it works

The matrix. When the machine runs steadily, the XREG-010 records "under these conditions, X amps." The space of operating conditions is divided into cells — one cell per distinct combination of engine speed, field strength, battery voltage, and temperature. Each cell keeps the best sustained output ever seen there. At fixed conditions, alternator output is largely determined by the machine itself, so the best sustained output previously observed is a useful healthy reference — and because records only move upward, later degradation cannot teach the system that degraded output is normal.

The grade. Once a second, the system looks up what the matrix says the current conditions should produce and divides actual output by it. Near 100% means healthy; a slide below it means the machine is falling short of its own past self. A green dot means the current conditions land in a recorded cell (Measured); a blue dot means the value was interpolated from nearby cells (Estimated); when the matrix has no trustworthy data near the current conditions, no number is shown at all. Both sides of the division are the same kind of number: a trailing 2-second average — dividing an instantaneous reading by a best-ever multi-second average would read a few percent low on a perfectly healthy machine.

The history. Steady-run grades accumulate into engine-hour buckets. Each completed hour commits two numbers to the trend: the average of that hour's grades, and the low-10% level — the value the worst tenth of the hour falls below. An hour without enough steady running shows a gap rather than an invented point. The trend is the signal: a healthy unit reads near 100 and roughly flat; a steady decline is the early warning.

Steadiness. A record is written only while every watched signal — engine speed, field drive, battery voltage, output current, and temperature — has held still for several seconds, with temperature required to hold much longer so records lean toward thermal equilibrium. The exact signals, filters, and allowances are in the implementation section below.

The four axes

The quantity being learned is output amps, as a function of four equal input axes:

Axis Notes
RPM engine/alternator speed
Excitation temperature-normalized field-strength proxy, exc = (duty × Vbus) / (1 + α·(T_C − 25)), with α the copper temperature coefficient
Bus voltage charging bus volts
Alternator temperature from the alternator temperature sensor — the digital probe, or the thermistor when that is the selected source (TempSource)

Output amps is valid in every charge mode (bulk/current-control, absorption/voltage-control, manual) because the physics amps = f(rpm, excitation, temp, Vbus) is the same regardless of why the regulator chose a given field — the mode only decides where in (RPM, excitation) space it operates.

Temperature must be available

If the global ignore temperature setting is on, the entire alternator-health system is disabled — temperature is one of the four axes, so without it there is no valid matrix.

Implementation details

Everything below is mechanics. The sections above are the complete conceptual picture; read on only if you want the internals.

How records are collected

The detector is the shared steady-run engine (Episode in the firmware, fed for the alternator from altFold_tick()), the same machinery the sailing-performance system uses. A record comes from a steady run, not a fixed time slice.

Sampling. Once per control tick — RPM, field duty, Vbus, temperature, measured amps — after the control loop has settled the field; off/fault/shutdown states exclude themselves. The fast inputs get a short low-pass filter (0.5 s EMA) so the limits below are sized for real operating movement, not sensor noise; temperature is read directly. Output current and bus voltage are then held back by 0.40 s before being paired with engine speed: the alternator answers where the engine is heading rather than where it has been, and without that shift a speeding-up engine appears to make more current than it really can at the speed shown.

Steadiness. The question is not whether the machine held still — it is whether it moved smoothly. Engine speed, field drive and output current are each fitted with a straight line across their window, and what must be small is the wobble about that line, not the line's own slope. A boat accelerating steadily out of a harbour is smooth but never still; it is a perfectly good measurement, and the old stillness rule threw all of it away. Bus voltage and temperature are still judged by plain spread, because a moving bus is a load event rather than a ramp, and case temperature has no ramp worth fitting. Defaults:

Signal Filter Steady requirement
Engine speed 0.5 s smoothing wobble ≤ 12 RPM about its straight line over 3 s, line no steeper than 250 RPM/s
Field drive (% of full field) 0.5 s smoothing wobble ≤ 0.4 points about its straight line over 3 s, drifting no faster than 1 point/s
Battery voltage 0.5 s smoothing spread (highest minus lowest) ≤ 0.20 V over 3 s
Alternator output current 0.5 s smoothing wobble ≤ 0.5% of reading (0.4 A minimum) about its straight line over 3 s, at any slope
Alternator temperature none (raw) spread ≤ 4 °F over the last 40 s

Charging must actually be happening: output at least 2 A and field drive at least 5%. When one signal fails, the run does not discard its history — each signal's sliding window ages out on its own, so the longest still-valid tail keeps counting. A feed gap of more than half a second (a pause, stale data, an ignore temperature toggle) is a hard barrier and restarts the run. The temperature look-back is the exception: it trails the last 40 seconds of running continuously and is not restarted by a dip below the charging floors, because it is a check on thermal equilibrium and not a stopwatch on the run.

Emitting a record. While every signal qualifies, the detector emits at most one record per second; each record is the trailing 2-second average of the run (ALT_EMIT_AVG_MS, the same width the sailing-performance instances use). The averaging window itself must also be clean: it spans the full 2 seconds, and the field drive, bus voltage and temperature across it — with the most extreme ~5% of samples per tail dropped (trimmedRange()) — stay within what their own rules allow over that window, a ramping signal being allowed the travel its rate limit permits. A handful of stray samples rides inside the average; a real shift in operating point fails the check. Engine speed and output current are exempt, since a highest-minus-lowest test on them would quietly reinstate the stillness rule the straight-line test replaced. A fresh run's first record lands one full window after qualifying, not instantly. Each stored record keeps the raw inputs plus the derived axis — {RPM, duty, Vbus, temp, excitation, amps} — so a bad record can be diagnosed later.

Two steadiness tiers. A lighter session-steady gate (half-length temperature look-back, 20 s default) gates the dots on the session plot. The stricter full-steady gate (full dwell, 40 s default, altThermSec) writes the matrix and feeds the trend. Both dwell lengths follow from the single altThermSec setting.

Live grading uses the same window. The once-per-second health % takes both its amps and its four cell coordinates from the same trailing window the records use; when that window is empty (the run has only just become eligible, or output is under the admission floor), it falls back to the fast filtered reading.

The trend. Built only from full-steady runs graded against the active matrix, throttled to one sample per roughly ten seconds (altTrendFeedSec); an engine-hour commits only after at least two graded samples (altTrendMinSamp); the in-progress bucket persists across a reboot, so a partial hour resumes instead of restarting.

The matrix in code

The matrix is stored as a sparse set of support points (the best-ever front, FrontStore in code) — memory scales with where you have actually operated, not with the size of the condition space. For display, the firmware fits the local slope of the matrix through the nearby records (a locally weighted linear fit) instead of averaging neighbors: a convex average is biased high at the edge of the visited region — where every neighbor is a stronger operating point — which is exactly where an engine idles for long stretches.

  • Keep only new bests. A finished run is kept only if its amps beat the matrix at its cell (the bar is the more conservative of the neighbor average and the local fit); otherwise it is discarded. One exception: the first record in a previously unvisited cell is admitted unconditionally — it opens that cell at its true value, so rarely visited operating regimes are never locked out.
  • State labels are output-blind. Whether a grade shows as Measured, Estimated, or ungraded depends only on where the matrix has records, never on the measured output — a degraded machine cannot relabel itself as "learning."
  • With cloud features enabled, the full history of accepted records is retained in the cloud and the pruned matrix is derived from it as a rebuildable view — the reference ratchets up and never decays.
  • The device evaluates its held matrix locally, so grading works offline between cloud syncs.
  • Two resident matrices. A source toggle (altRefSource) selects which one grades present output: My History, the matrix the unit has learned locally, or Uploaded File, a borrowed matrix (for example from a known-good unit). Learning always writes into My History, regardless of which one is being graded against.
  • Pause. An independent Pause control (altPaused) stops new records entering My History while the engine-hours trend keeps accumulating.

What you see

  • Live health % with a confidence state — the current grade, labeled MEASURED or ESTIMATED, or ungraded ("learning this operating region" / "no reference here yet") when the matrix does not support a fair comparison.
  • A session plot — the graded readings from the current run, points colored by state, shaded where no fair comparison existed. The dashboard collects the dots live, but the regulator also keeps the same series itself (a two-hour RAM ring, served at /altsess.csv), so a page opened part-way through a run, reloaded, or reconnecting after a WiFi dropout pulls the missing stretch back instead of starting blank. The device copy is never written to flash: a session ends at field-off, and a filesystem write there would put flash in the control path.
  • Trend over engine-hours — the two lines described above, the hour's average and its low-10% level, plotted against engine-hours since the Reset / Start Over button last reset the baseline (e.g. after replacing the alternator, belt, or regulator).
  • A high-field alert, independent of the matrix: sustained high field drive with low output raises a console message and dashboard flag even where the gauge is still learning.

The same steady-run/matrix engine powers the boat-speed reference — see Sailing Performance.