From 0b909a4d633101c0d2ca04beef70e8c61d432767 Mon Sep 17 00:00:00 2001 From: rouggy Date: Sun, 30 Aug 2026 13:31:34 +0200 Subject: [PATCH] fix(elecraft): the K3 power meter converts to real watts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The operator measured the whole table: 10 W showed 83, 12 W showed 100, 13 W showed 8 — the bargraph is relative to a meter RANGE that flips at 12 W (0-12 QRP, 0-120 above). A bar percentage was never watts; with the PC setting choosing the range, it converts, and the console prints the watts beside the bar. --- changelog.json | 6 ++++-- frontend/src/components/ElecraftPanel.tsx | 5 +++-- frontend/wailsjs/go/models.ts | 2 ++ internal/cat/kenwood_panel.go | 20 +++++++++++++++++--- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/changelog.json b/changelog.json index c5973ef..011d1bb 100644 --- a/changelog.json +++ b/changelog.json @@ -3,10 +3,12 @@ "version": "0.27.2", "date": "", "en": [ - "Bulk operations work on any size of selection — setting a field, fixing frequencies, deleting, marking uploads and exporting the selection all failed with “too many SQL variables” past a few tens of thousands of QSOs. Statements are now issued in slices." + "Bulk operations work on any size of selection — setting a field, fixing frequencies, deleting, marking uploads and exporting the selection all failed with “too many SQL variables” past a few tens of thousands of QSOs. Statements are now issued in slices.", + "Elecraft console: the power meter reads in real watts. The K3’s bargraph is relative to a range that flips at 12 W — calibrated against a real radio’s full table, the PC setting picks the range and the bar converts to watts." ], "fr": [ - "Les opérations groupées fonctionnent quelle que soit la taille de la sélection — définir un champ, corriger des fréquences, supprimer, marquer les uploads et exporter la sélection échouaient avec « too many SQL variables » au-delà de quelques dizaines de milliers de QSO. Les requêtes sont désormais émises par tranches." + "Les opérations groupées fonctionnent quelle que soit la taille de la sélection — définir un champ, corriger des fréquences, supprimer, marquer les uploads et exporter la sélection échouaient avec « too many SQL variables » au-delà de quelques dizaines de milliers de QSO. Les requêtes sont désormais émises par tranches.", + "Console Elecraft : le wattmètre lit en vrais watts. Le bargraph du K3 est relatif à une gamme qui bascule à 12 W — calibré sur la table complète d’une vraie radio, le réglage PC choisit la gamme et la barre se convertit en watts." ] }, { diff --git a/frontend/src/components/ElecraftPanel.tsx b/frontend/src/components/ElecraftPanel.tsx index 0908c7e..2774a61 100644 --- a/frontend/src/components/ElecraftPanel.tsx +++ b/frontend/src/components/ElecraftPanel.tsx @@ -18,7 +18,7 @@ type KenwoodState = { available: boolean; model?: string; elecraft: boolean; mode?: string; data_sub?: string; transmitting: boolean; split: boolean; split_tx_hz?: number; s_meter: number; s_meter_raw: number; - power_meter: number; swr: number; swr_raw: number; + power_meter: number; power_w?: number; swr: number; swr_raw: number; rf_power: number; af_gain: number; rf_gain: number; mic_gain: number; squelch: number; preamp: boolean; att: boolean; nb: boolean; nr: boolean; agc?: string; filter_hz: number; antenna: number; rit: boolean; xit: boolean; rit_offset: number; key_speed: number; @@ -222,7 +222,8 @@ export function ElecraftPanel({ onReportRST }: { onReportRST?: (rst: string) => onReportRST(sMeterRST(sp.s, sp.over, view.mode)); }} title={t('k3.sMeterHint', { raw: String(view.s_meter_raw) })} /> - + {/* 0 means "not measured", and it must not render as a perfect 1.0: a match that looks ideal on an antenna nobody has measured is the one reading that can cost a radio. */} diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts index 80d7964..3ef7003 100644 --- a/frontend/wailsjs/go/models.ts +++ b/frontend/wailsjs/go/models.ts @@ -1083,6 +1083,7 @@ export namespace cat { s_meter: number; s_meter_raw: number; power_meter: number; + power_w: number; swr: number; swr_raw: number; rf_power: number; @@ -1120,6 +1121,7 @@ export namespace cat { this.s_meter = source["s_meter"]; this.s_meter_raw = source["s_meter_raw"]; this.power_meter = source["power_meter"]; + this.power_w = source["power_w"]; this.swr = source["swr"]; this.swr_raw = source["swr_raw"]; this.rf_power = source["rf_power"]; diff --git a/internal/cat/kenwood_panel.go b/internal/cat/kenwood_panel.go index 72657f2..d032de8 100644 --- a/internal/cat/kenwood_panel.go +++ b/internal/cat/kenwood_panel.go @@ -52,9 +52,15 @@ type KenwoodTXState struct { SMeterRaw int `json:"s_meter_raw"` // PowerMeter is 0-100 while transmitting. SWR is the ratio; 0 means "not // measured", NOT a perfect match. - PowerMeter int `json:"power_meter"` - SWR float64 `json:"swr"` - SWRRaw int `json:"swr_raw"` + PowerMeter int `json:"power_meter"` + // PowerW is the transmit power in WATTS, derived from the bargraph and the + // meter's RANGE. The K3's bar is relative to a range that flips at 12 W — + // calibrated against a real one: 10 W showed 83 (10/12), 100 W showed 83 + // too (100/120). The bar alone never was watts; with the PC setting to + // pick the range, it converts. 0 while receiving. + PowerW int `json:"power_w"` + SWR float64 `json:"swr"` + SWRRaw int `json:"swr_raw"` RFPower int `json:"rf_power"` // watts, the PC setting AFGain int `json:"af_gain"` // 0-100 @@ -162,6 +168,7 @@ func (k *Kenwood) readPanel(mode string, split bool, txHz int64, txNow bool) { // Cleared, not frozen: a power bar left standing after the carrier drops // reads as a live transmission. k.panel.PowerMeter = 0 + k.panel.PowerW = 0 k.panel.SWR, k.panel.SWRRaw = 0, 0 k.powerPeak, k.swrPeak = meterPeak{}, meterPeak{} // The S-meter only means anything while receiving. @@ -341,6 +348,13 @@ func (k *Kenwood) readTXMeters() { defer func() { k.noLatch = false }() if v, ok := k.askNum("BG;", "BG", 2); ok { k.panel.PowerMeter = k.powerPeak.update(kenwoodBargraphPercent(v), now) + if k.elecraft { + scale := 120 + if k.panel.RFPower > 0 && k.panel.RFPower <= 12 { + scale = 12 // the K3's QRP range + } + k.panel.PowerW = k.panel.PowerMeter * scale / 100 + } } // SW; — SETTLED, from Elecraft's own release note: three digits, tenths of a // ratio. "SW023;" is 2.3:1, and "SW999;" is the 99.9:1 it reports instead of