fix: the Yaesu power meter is not linear — calibrate it on three points
One point could not reveal the curve. Scaling 207 = 100 W straight down read 30 W where the radio showed 10, and 75 where it showed 50 — wrong everywhere except at the single point it was fitted to. Three readings taken against the rig's own display give the shape: raw 62 → 10 W raw 155 → 50 W raw 207 → 100 W Interpolating between them reproduces the radio exactly at those points and stays close in between. I did not fit a formula: three samples can be made to support several curves, and the operator can check a table against their own meter. Above the top the last segment's slope continues rather than clamping, so a rig driving an amplifier does not sit pinned at 100 W. A test pins the measured pairs and the monotonicity, so a later change that breaks them fails against the radio rather than against taste.
This commit is contained in:
@@ -118,3 +118,46 @@ func TestMeterPeakHold(t *testing.T) {
|
||||
t.Errorf("settled at %d, want 10 — the meter must converge on the truth", v)
|
||||
}
|
||||
}
|
||||
|
||||
// The power curve, pinned to the readings taken against the rig's own display.
|
||||
//
|
||||
// It is NOT linear, and one calibration point could not show that: scaling
|
||||
// 207 = 100 W straight down read 30 W where the radio showed 10, and 75 where it
|
||||
// showed 50. These are the three measured pairs, so a change to the curve that
|
||||
// breaks them is a regression against the radio, not against a preference.
|
||||
func TestYaesuPowerCurve(t *testing.T) {
|
||||
cases := []struct {
|
||||
raw int
|
||||
watts float64
|
||||
tol float64
|
||||
}{
|
||||
{0, 0, 0.1},
|
||||
{62, 10, 0.5}, // measured
|
||||
{155, 50, 0.5}, // measured
|
||||
{207, 100, 0.5}, // measured
|
||||
// Between the measured points it interpolates, so it must land inside the
|
||||
// bracket rather than shooting past it.
|
||||
{100, 30, 10},
|
||||
{180, 75, 10},
|
||||
}
|
||||
for _, c := range cases {
|
||||
got := yaesuWatts(c.raw)
|
||||
if got < c.watts-c.tol || got > c.watts+c.tol {
|
||||
t.Errorf("yaesuWatts(%d) = %.1f W, want %.1f ±%.1f", c.raw, got, c.watts, c.tol)
|
||||
}
|
||||
}
|
||||
// Monotonic: more meter must never mean less power.
|
||||
prev := -1.0
|
||||
for raw := 0; raw <= 255; raw++ {
|
||||
v := yaesuWatts(raw)
|
||||
if v < prev {
|
||||
t.Fatalf("power fell from %.1f to %.1f at raw=%d", prev, v, raw)
|
||||
}
|
||||
prev = v
|
||||
}
|
||||
// Above the top of the curve it keeps rising rather than flattening at 100 W —
|
||||
// a rig driving an amplifier can read past its own full scale.
|
||||
if v := yaesuWatts(230); v <= 100 {
|
||||
t.Errorf("yaesuWatts(230) = %.1f, want more than 100 — the curve should extend", v)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user