Fix supply voltage: apply PCB voltage dividers and read correct ADC source

Protocol Appendix A documents only the ADC reference voltage constant;
the PCB voltage divider must also be applied (from Thetis source):
- Boards 1-3 (Hermes/Angelia): ×(4.7+0.82)/0.82 ≈ 6.73, Vref=3.3V
- Board 5 (Orion MkII): ×(22+1)/1.1 ≈ 20.9, Vref=5.0V

For board type 5, supply voltage is measured via UserADC0 (bytes 57-58),
not the supply_volts field (bytes 49-50), matching Thetis behaviour.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-28 19:00:19 +03:00
co-authored by Claude Sonnet 4.6
parent 1502e6ab83
commit a5d08fe3d6
2 changed files with 20 additions and 8 deletions
+10 -6
View File
@@ -440,13 +440,17 @@ end;
function ADCToSupplyVolts(RawADC: Word; BoardType: Integer): Double; function ADCToSupplyVolts(RawADC: Word; BoardType: Integer): Double;
begin begin
// Board 0 (Atlas) has no supply voltage measurement (protocol: "not Atlas bus systems") // Protocol Appendix A gives the ADC reference voltage only.
// Boards 1,2,3 (Hermes/Angelia): V = ADC/4095 * 3.3 (Appendix A) // The PCB voltage divider (from Thetis source) must also be applied.
// Boards 4,5 (Orion): V = ADC/4095 * 5.0 (Appendix A) // Board 0 (Atlas): no supply voltage measurement.
// Boards 1,2,3 (Hermes/Angelia): Vref=3.3V, PCB divider R1=4.7kΩ/R2=0.82kΩ.
// Board 5 (Orion MkII): Vref=5.0V, PCB divider R1=22kΩ/R2=1.1kΩ.
// NOTE: for board 5 caller must pass UserADC0, not supply_volts bytes.
// Board 4 (Orion) and others: not available (return -1).
case BoardType of case BoardType of
1, 2, 3: Result := (RawADC / 4095.0) * 3.3; 1, 2, 3: Result := (RawADC / 4095.0) * 3.3 * ((4.7 + 0.82) / 0.82);
4, 5: Result := (RawADC / 4095.0) * 5.0; 5: Result := (RawADC / 4095.0) * 5.0 * ((22.0 + 1.0) / 1.1);
else Result := -1.0; // not documented or not applicable else Result := -1.0;
end; end;
end; end;
+10 -2
View File
@@ -2461,8 +2461,16 @@ 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;
SupplyV := ADCToSupplyVolts((Status.SupplyVoltsHi shl 8) or Status.SupplyVoltsLo, // Board 5 (Orion MkII) measures supply voltage via UserADC0 (bytes 57-58),
FNetwork.Device.BoardType); // not the supply_volts field (bytes 49-50) — matching Thetis behaviour.
if FNetwork.Device.BoardType = 5 then
SupplyV := ADCToSupplyVolts(
(Status.UserADC0Hi shl 8) or Status.UserADC0Lo,
FNetwork.Device.BoardType)
else
SupplyV := ADCToSupplyVolts(
(Status.SupplyVoltsHi shl 8) or Status.SupplyVoltsLo,
FNetwork.Device.BoardType);
// FLastSMeter обновляется только из WDSP (GetSMeterDBm) в SpectrumTimerTick — // FLastSMeter обновляется только из WDSP (GetSMeterDBm) в SpectrumTimerTick —
// ExciterPwr это мощность TX, не уровень принятого сигнала. // ExciterPwr это мощность TX, не уровень принятого сигнала.
FwdW := ADCToWatts100(FwdPwr); FwdW := ADCToWatts100(FwdPwr);