Add supply current display for Orion MkII (Board 5)

UserADC1 (bytes 55-56) carries current sensor data on the ANAN-8000DLE.
Formula from Thetis: amps = ((adc/4095 * 5000) - 360) / 120 (Voff=360mV,
Sens=120mV/A). Status bar now shows "Supply: 13.8V / 2.3A | PLL OK"
when current is available.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-19 12:29:45 +03:00
co-authored by Claude Sonnet 4.6
parent d823106366
commit d8050576a9
2 changed files with 54 additions and 13 deletions
+17
View File
@@ -392,6 +392,10 @@ function PhaseWordToFreq(PhaseWord: LongWord): Double;
// Returns -1.0 if the board has no supply voltage measurement. // Returns -1.0 if the board has no supply voltage measurement.
function ADCToSupplyVolts(RawADC: Word; BoardType: Integer): Double; function ADCToSupplyVolts(RawADC: Word; BoardType: Integer): Double;
// Convert raw ADC value to supply current in Amps (Board 5 / Orion MkII only)
// Uses UserADC1 (bytes 55-56). Returns -1 for unsupported boards.
function ADCToSupplyCurrent(RawADC: Word; BoardType: Integer): Double;
// Convert raw ADC value to RF power in Watts (ANAN-100) // Convert raw ADC value to RF power in Watts (ANAN-100)
function ADCToWatts100(RawADC: Word): Double; function ADCToWatts100(RawADC: Word): Double;
@@ -454,6 +458,19 @@ begin
end; end;
end; end;
function ADCToSupplyCurrent(RawADC: Word; BoardType: Integer): Double;
begin
// Board 5 (Orion MkII): UserADC1, Vref=5V → mV = adc/4095*5000.
// Current sensor: Voff=360mV, Sens=120mV/A (Thetis defaults, ACS712-style).
// Formula: amps = (mV - Voff) / Sens.
if BoardType = 5 then
begin
Result := ((RawADC / 4095.0) * 5000.0 - 360.0) / 120.0;
if Result < 0.0 then Result := 0.0;
end else
Result := -1.0;
end;
function ADCToWatts100(RawADC: Word): Double; function ADCToWatts100(RawADC: Word): Double;
var var
V: Double; V: Double;
+37 -13
View File
@@ -148,10 +148,11 @@ type
FFwdW: Double; FFwdW: Double;
FSWRV: Double; FSWRV: Double;
FSupplyV: Double; FSupplyV: Double;
FSupplyA: Double;
FPLLLock: Boolean; FPLLLock: Boolean;
FHWPTT: Boolean; FHWPTT: Boolean;
public public
constructor Create(AForm: TObject; FW, SW, SV: Double; PLL, HWPTT: Boolean); constructor Create(AForm: TObject; FW, SW, SV, SA: Double; PLL, HWPTT: Boolean);
procedure Execute; procedure Execute;
end; end;
@@ -244,6 +245,7 @@ type
// Эти значения приходят с HP Status пакетами (50..200 раз/с). UI обновляется // Эти значения приходят с HP Status пакетами (50..200 раз/с). UI обновляется
// из MeterTimerTick (10 Гц), чтобы цифры/полоски не дёргались. // из MeterTimerTick (10 Гц), чтобы цифры/полоски не дёргались.
FLastSupplyV: Double; FLastSupplyV: Double;
FLastSupplyA: Double;
FLastPLLLock: Boolean; FLastPLLLock: Boolean;
// ---- Spectrum / Waterfall view ---- // ---- Spectrum / Waterfall view ----
@@ -460,7 +462,7 @@ type
// Public UI update (called from sync objects) // Public UI update (called from sync objects)
procedure DoAddDevice(const Dev: THPSDRDevice; const Entry: string); procedure DoAddDevice(const Dev: THPSDRDevice; const Entry: string);
procedure DoUpdateStatus(FwdW, SWRV, SupplyV: Double; PLLLock, HWPTT: Boolean); procedure DoUpdateStatus(FwdW, SWRV, SupplyV, SupplyA: Double; PLLLock, HWPTT: Boolean);
procedure UpdateTXMeters; procedure UpdateTXMeters;
procedure DoUpdateDDCSeq(DDCIdx: Integer; Seq: LongWord); procedure DoUpdateDDCSeq(DDCIdx: Integer; Seq: LongWord);
procedure DoUpdateDDCSeqOrNoDevice(DDCIdx: Integer; Seq: LongWord); procedure DoUpdateDDCSeqOrNoDevice(DDCIdx: Integer; Seq: LongWord);
@@ -869,20 +871,21 @@ begin
end; end;
constructor TStatusUISync.Create(AForm: TObject; constructor TStatusUISync.Create(AForm: TObject;
FW, SW, SV: Double; PLL, HWPTT: Boolean); FW, SW, SV, SA: Double; PLL, HWPTT: Boolean);
begin begin
inherited Create; inherited Create;
FForm := AForm; FForm := AForm;
FFwdW := FW; FFwdW := FW;
FSWRV := SW; FSWRV := SW;
FSupplyV := SV; FSupplyV := SV;
FSupplyA := SA;
FPLLLock := PLL; FPLLLock := PLL;
FHWPTT := HWPTT; FHWPTT := HWPTT;
end; end;
procedure TStatusUISync.Execute; procedure TStatusUISync.Execute;
begin begin
TMainForm(FForm).DoUpdateStatus(FFwdW, FSWRV, FSupplyV, FPLLLock, FHWPTT); TMainForm(FForm).DoUpdateStatus(FFwdW, FSWRV, FSupplyV, FSupplyA, FPLLLock, FHWPTT);
end; end;
constructor TDDCSeqSync.Create(AForm: TObject; Idx: Integer; Seq: LongWord); constructor TDDCSeqSync.Create(AForm: TObject; Idx: Integer; Seq: LongWord);
@@ -1298,6 +1301,7 @@ begin
FLastFwdW := 0; FLastFwdW := 0;
FLastSWR := 1; FLastSWR := 1;
FLastSupplyV:= -1; FLastSupplyV:= -1;
FLastSupplyA:= -1;
FLastPLLLock:= False; FLastPLLLock:= False;
FDeviceCount := 0; FDeviceCount := 0;
FDeviceDialog := TDeviceDialog.Create(Self); FDeviceDialog := TDeviceDialog.Create(Self);
@@ -3088,7 +3092,7 @@ const
SWR_CAP = 9.9; SWR_CAP = 9.9;
var var
ExcPwr, FwdPwr, RevPwr: Word; ExcPwr, FwdPwr, RevPwr: Word;
SupplyV, FwdW, SWRV, Rho: Double; SupplyV, SupplyA, FwdW, SWRV, Rho: Double;
IsTx: Boolean; IsTx: Boolean;
Sync: TStatusUISync; Sync: TStatusUISync;
M: TThreadMethod; M: TThreadMethod;
@@ -3096,16 +3100,23 @@ begin
ExcPwr := (Status.ExciterPwr0Hi shl 8) or Status.ExciterPwr0Lo; ExcPwr := (Status.ExciterPwr0Hi shl 8) or Status.ExciterPwr0Lo;
FwdPwr := (Status.FwdPwrAlex0Hi shl 8) or Status.FwdPwrAlex0Lo; FwdPwr := (Status.FwdPwrAlex0Hi shl 8) or Status.FwdPwrAlex0Lo;
RevPwr := (Status.RevPwrAlex0Hi shl 8) or Status.RevPwrAlex0Lo; RevPwr := (Status.RevPwrAlex0Hi shl 8) or Status.RevPwrAlex0Lo;
// Board 5 (Orion MkII) measures supply voltage via UserADC0 (bytes 57-58), // Board 5 (Orion MkII): voltage on UserADC0 (bytes 57-58),
// not the supply_volts field (bytes 49-50) — matching Thetis behaviour. // current on UserADC1 (bytes 55-56) — matching Thetis behaviour.
if FNetwork.Device.BoardType = 5 then if FNetwork.Device.BoardType = 5 then
begin
SupplyV := ADCToSupplyVolts( SupplyV := ADCToSupplyVolts(
(Status.UserADC0Hi shl 8) or Status.UserADC0Lo, (Status.UserADC0Hi shl 8) or Status.UserADC0Lo,
FNetwork.Device.BoardType) FNetwork.Device.BoardType);
else SupplyA := ADCToSupplyCurrent(
(Status.UserADC1Hi shl 8) or Status.UserADC1Lo,
FNetwork.Device.BoardType);
end else
begin
SupplyV := ADCToSupplyVolts( SupplyV := ADCToSupplyVolts(
(Status.SupplyVoltsHi shl 8) or Status.SupplyVoltsLo, (Status.SupplyVoltsHi shl 8) or Status.SupplyVoltsLo,
FNetwork.Device.BoardType); FNetwork.Device.BoardType);
SupplyA := -1.0;
end;
// FLastSMeter обновляется только из WDSP (GetSMeterDBm) в SpectrumTimerTick — // FLastSMeter обновляется только из WDSP (GetSMeterDBm) в SpectrumTimerTick —
// ExciterPwr это мощность TX, не уровень принятого сигнала. // ExciterPwr это мощность TX, не уровень принятого сигнала.
FwdW := ADCToWatts100(FwdPwr); FwdW := ADCToWatts100(FwdPwr);
@@ -3132,7 +3143,7 @@ begin
end else end else
SWRV := 1.0; SWRV := 1.0;
if not IsTx then FwdW := 0; if not IsTx then FwdW := 0;
Sync := TStatusUISync.Create(Self, FwdW, SWRV, SupplyV, Sync := TStatusUISync.Create(Self, FwdW, SWRV, SupplyV, SupplyA,
(Status.StatusBits and HPS_PLL_LOCKED) <> 0, (Status.StatusBits and HPS_PLL_LOCKED) <> 0,
(Status.StatusBits and HPS_PTT) <> 0); (Status.StatusBits and HPS_PTT) <> 0);
try try
@@ -3143,7 +3154,7 @@ begin
end; end;
end; end;
procedure TMainForm.DoUpdateStatus(FwdW, SWRV, SupplyV: Double; PLLLock, HWPTT: Boolean); procedure TMainForm.DoUpdateStatus(FwdW, SWRV, SupplyV, SupplyA: Double; PLLLock, HWPTT: Boolean);
const const
// Thetis/piHPSDR PEP-style баллистика для FwdW и SWR: атака мгновенная // Thetis/piHPSDR PEP-style баллистика для FwdW и SWR: атака мгновенная
// (peak-hold), спад медленный — стрелка «висит» на пике и плавно опускается. // (peak-hold), спад медленный — стрелка «висит» на пике и плавно опускается.
@@ -3177,6 +3188,13 @@ begin
else else
FLastSupplyV := ALPHA_SUPPLY * SupplyV + (1.0 - ALPHA_SUPPLY) * FLastSupplyV; FLastSupplyV := ALPHA_SUPPLY * SupplyV + (1.0 - ALPHA_SUPPLY) * FLastSupplyV;
end; end;
if SupplyA >= 0 then
begin
if FLastSupplyA < 0 then
FLastSupplyA := SupplyA
else
FLastSupplyA := ALPHA_SUPPLY * SupplyA + (1.0 - ALPHA_SUPPLY) * FLastSupplyA;
end;
FLastPLLLock := PLLLock; FLastPLLLock := PLLLock;
// Hardware PTT (foot switch / mic PTT) — обнаружение фронта (нужно делать // Hardware PTT (foot switch / mic PTT) — обнаружение фронта (нужно делать
@@ -3200,8 +3218,14 @@ var
begin begin
if FLastPLLLock then PLLStr := 'PLL OK' else PLLStr := 'PLL?'; if FLastPLLLock then PLLStr := 'PLL OK' else PLLStr := 'PLL?';
if FLastSupplyV >= 0 then if FLastSupplyV >= 0 then
StatusBar1.Panels[2].Text := Format('Supply: %.1fV | %s', [FLastSupplyV, PLLStr]) begin
else if FLastSupplyA >= 0 then
StatusBar1.Panels[2].Text :=
Format('Supply: %.1fV / %.1fA | %s', [FLastSupplyV, FLastSupplyA, PLLStr])
else
StatusBar1.Panels[2].Text :=
Format('Supply: %.1fV | %s', [FLastSupplyV, PLLStr]);
end else
StatusBar1.Panels[2].Text := PLLStr; StatusBar1.Panels[2].Text := PLLStr;
end; end;