From dc259095e09bc3272a1d0c33f94eed5513f58977 Mon Sep 17 00:00:00 2001 From: ig Date: Wed, 5 Apr 2023 13:05:38 +0200 Subject: [PATCH] add SystemControl as a dedicated Device --- csharp/InnovEnergy.sln | 15 +- .../Trumpf/SystemControl/AlarmMessage.cs | 18 + .../Trumpf/SystemControl/ControlRecord.cs | 84 +++++ .../Trumpf/SystemControl/ErrorPolicy.cs | 7 + .../Trumpf/SystemControl/StatusRecord.cs | 43 +++ .../SystemControl/SubSlavesErrorPolicy.cs | 8 + .../Trumpf/SystemControl/SystemControl.csproj | 7 + .../SystemControl/SystemControlDevice.cs | 324 ++++++++++++++++++ .../SystemControl/SystemControlRegisters.cs | 83 +++++ .../Trumpf/TruConvertAc/WarningMessage.cs | 24 +- 10 files changed, 596 insertions(+), 17 deletions(-) create mode 100644 csharp/Lib/Devices/Trumpf/SystemControl/AlarmMessage.cs create mode 100644 csharp/Lib/Devices/Trumpf/SystemControl/ControlRecord.cs create mode 100644 csharp/Lib/Devices/Trumpf/SystemControl/ErrorPolicy.cs create mode 100644 csharp/Lib/Devices/Trumpf/SystemControl/StatusRecord.cs create mode 100644 csharp/Lib/Devices/Trumpf/SystemControl/SubSlavesErrorPolicy.cs create mode 100644 csharp/Lib/Devices/Trumpf/SystemControl/SystemControl.csproj create mode 100644 csharp/Lib/Devices/Trumpf/SystemControl/SystemControlDevice.cs create mode 100644 csharp/Lib/Devices/Trumpf/SystemControl/SystemControlRegisters.cs diff --git a/csharp/InnovEnergy.sln b/csharp/InnovEnergy.sln index 8d368b9cb..bababc313 100644 --- a/csharp/InnovEnergy.sln +++ b/csharp/InnovEnergy.sln @@ -60,20 +60,20 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Channels", "Lib/Channels/Ch EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Backend", "App/Backend/Backend.csproj", "{A56F58C2-B265-435B-A985-53B4D6F49B1A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Units", "Lib/Units/Units.csproj", "{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Units", "Lib\Units\Units.csproj", "{C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemControl", "Lib/Devices/Trumpf/SystemControl/SystemControl.csproj", "{B816BB44-E97E-4E02-B80A-BEDB5B923A96}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Meta", "Meta", "{AED84693-C389-44C9-B2C0-ACB560189CF2}" ProjectSection(SolutionItems) = preProject InnovEnergy.props = InnovEnergy.props - App\InnovEnergy.App.props = App\InnovEnergy.App.props - Lib\InnovEnergy.Lib.props = Lib\InnovEnergy.Lib.props + App/InnovEnergy.App.props = App/InnovEnergy.App.props + Lib/InnovEnergy.Lib.props = Lib/InnovEnergy.Lib.props InnovEnergy.sln.DotSettings = InnovEnergy.sln.DotSettings - ..\.gitignore = ..\.gitignore + ../.gitignore = ../.gitignore EndProjectSection EndProject - Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -180,6 +180,10 @@ Global {C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}.Debug|Any CPU.Build.0 = Debug|Any CPU {C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}.Release|Any CPU.ActiveCfg = Release|Any CPU {C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7}.Release|Any CPU.Build.0 = Release|Any CPU + {B816BB44-E97E-4E02-B80A-BEDB5B923A96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B816BB44-E97E-4E02-B80A-BEDB5B923A96}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B816BB44-E97E-4E02-B80A-BEDB5B923A96}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B816BB44-E97E-4E02-B80A-BEDB5B923A96}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {CF4834CB-91B7-4172-AC13-ECDA8613CD17} = {145597B4-3E30-45E6-9F72-4DD43194539A} @@ -211,5 +215,6 @@ Global {A56F58C2-B265-435B-A985-53B4D6F49B1A} = {145597B4-3E30-45E6-9F72-4DD43194539A} {C04FB6DA-23C6-46BB-9B21-8F4FBA32FFF7} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854} {4A67D79F-F0C9-4BBC-9601-D5948E6C05D3} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854} + {B816BB44-E97E-4E02-B80A-BEDB5B923A96} = {DDDBEFD0-5DEA-4C7C-A9F2-FDB4636CF092} EndGlobalSection EndGlobal diff --git a/csharp/Lib/Devices/Trumpf/SystemControl/AlarmMessage.cs b/csharp/Lib/Devices/Trumpf/SystemControl/AlarmMessage.cs new file mode 100644 index 000000000..d63b5dfb8 --- /dev/null +++ b/csharp/Lib/Devices/Trumpf/SystemControl/AlarmMessage.cs @@ -0,0 +1,18 @@ +using System.Diagnostics.CodeAnalysis; + +namespace InnovEnergy.Lib.Devices.Trumpf.SystemControl; + +[SuppressMessage("ReSharper", "UnusedMember.Global")] +public enum AlarmMessage +{ + NoAlarm = 0, + BmsCommunicationTimeoutHasOccured = 40302, // BMS communication timeout has occured. + Rs485CommunicationAlarm = 40303, // RS-485 communication alarm. + SoftwareVersionsOfSystemControlAndModulesDoNotMatch1 = 40412, // Software versions of system control and module(s) do not match. + SoftwareVersionsOfSystemControlAndModulesDoNotMatch2 = 40413, // Software versions of system control and module(s) do not match. + SoftwareVersionsOfSystemControlAndModulesDoNotMatch3 = 40414, // Software versions of system control and module(s) do not match. + SoftwareVersionsOfSystemControlAndModulesDoNotMatch4 = 40415, // Software versions of system control and module(s) do not match. + SoftwareVersionsOfSystemControlAndModulesDoNotMatch5 = 40416, // Software versions of system control and module(s) do not match. + NoSlaveModuleWasFoundPleaseCheckRs485Connection = 40304, // No slave module was found, please check RS-485 connection(s). + NumberOfOrCombinationOfConnectedSlaveTypesNotSupported = 40305, // Number of or combination of connected slave types not supported. +} \ No newline at end of file diff --git a/csharp/Lib/Devices/Trumpf/SystemControl/ControlRecord.cs b/csharp/Lib/Devices/Trumpf/SystemControl/ControlRecord.cs new file mode 100644 index 000000000..b5879384e --- /dev/null +++ b/csharp/Lib/Devices/Trumpf/SystemControl/ControlRecord.cs @@ -0,0 +1,84 @@ +namespace InnovEnergy.Lib.Devices.Trumpf.SystemControl; + +public record ControlRecord +{ + private static readonly TimeSpan DefaultCommunicationTimeOut = TimeSpan.FromSeconds(10); + + // TODO + + // public UInt32 Date { get; init;} + // public UInt32 Time { get; init;} + // public UInt32 IpAddress { get; init;} //= 0x C0A80102; + // public UInt32 Subnet { get; init;} //= 0x FFFFFF00; + // public UInt32 Gateway { get; init;} //= 0x C0A80102; + // public Boolean ResetParamToDefault { get; init;} = false ; // Coil + // public TimeSpan CommunicationTimeout { get; init;} = DefaultCommunicationTimeOut; + // public Boolean FactoryResetParameters { get; init;} = false; + // public SystemConfig ConnectedSystemConfig { get; init;} = 0; + // public UInt16 UpdateSwTrigger { get; init;} = 0; + // public UInt16 AutomaticSwUpdate { get; init;} = 0; + // public UInt16 CustomerValuesSaveReset { get; init;} = 0; + // public UInt16 SerialNumberSystemControl { get; init;} = 0; + // public UInt16 SerialNumberAcDc { get; init;} = 0; + // public UInt16 IntegrationLevel { get; init;} = 0; + // public UInt16 IlBuildnumber { get; init;} = 0; + // public Boolean PowerStageEnable { get; init;} = true; + // public SymmetricAcOperationMode SetValueConfig { get; init;} = 0; + // public Boolean ResetsAlarmAndWarning { get; init;} = false; + // public PreChargeDcLinkConfig PreChargeDcLinkConfig { get; init;} = (PreChargeDcLinkConfig)0; + // public PowerFactorConvention PowerFactorConvention { get; init;} = 0; //0 = producer + // public UInt16 SlaveAddress { get; init;} = Slave.Broadcast; + // public ErrorPolicy ErrorHandlingPolicy { get; init;} = 0; + // public AcDcGridType GridType { get; init;} = 0; + // public UInt16 SubSlaveAddress { get; init;} = 0; + // public Boolean UseModbusSlaveIdForAddressing { get; init;} = false; + // public UInt16 SubSlaveErrorPolicy { get; init;} = 0; // must be an enum + // public Decimal SignedPowerNominalValue { get; init;} = 0; // resolution 0.001 and Unit kva, + // public Decimal SignedPowerSetValueL1 { get; init;} = 0; // resolution 0.001 and Unit kva, + // public Decimal SignedPowerSetValueL2 { get; init;} = 0; // resolution 0.001 and Unit kva, + // public Decimal SignedPowerSetValueL3 { get; init;} = 0; // resolution 0.001 and Unit kva, + // public Decimal PowerSetValue { get; init;} = 0; // resolution 0.001 and Unit kva, + // public Decimal PowerSetValueL1 { get; init;} = 0; // resolution 0.001 and Unit kva, + // public Decimal PowerSetValueL2 { get; init;} = 0; // resolution 0.001 and Unit kva, + // public Decimal PowerSetValueL3 { get; init;} = 0; // resolution 0.001 and Unit kva, + // public Decimal MaximumGridCurrentRmsL1 { get; init;} = 0; // resolution : 0.01 + // public Decimal MaximumGridCurrentRmsL2 { get; init;} = 0; // resolution : 0.01 + // public Decimal MaximumGridCurrentRmsL3 { get; init;} = 0; // resolution : 0.01 + // public Decimal CosPhiSetValueL1 { get; init;} = 0; // resolution : 0.01 + // public Decimal CosPhiSetValueL2 { get; init;} = 0; // resolution : 0.01 + // public Decimal CosPhiSetValueL3 { get; init;} = 0; // resolution : 0.01 + // public Boolean PhaseL1IsCapacitive { get; init;} = true; // True = Capacitive, false = Inductive + // public Boolean PhaseL2IsCapacitive { get; init;} = true; // True = Capacitive, false = Inductive + // public Boolean PhaseL3IsCapacitive { get; init;} = true; // True = Capacitive, false = Inductive + // public Boolean PhasesAreCapacitive { get; init;} = true; // True = Capacitive, false = Inductive + // public Double SetPointCosPhi { get; init;} = 0; // resolution 0.01 + // public Double SetPointSinPhi { get; init;} = 0; // resolution 0.01 + // public Double SetPointSinPhiL1 { get; init;} = 0; // resolution 0.01 + // public Double SetPointSinPhiL2 { get; init;} = 0; // resolution 0.01 + // public Double SetPointSinPhiL3 { get; init;} = 0; // resolution 0.01 + // public Decimal FrequencyOffsetIm { get; init;} = 0; // resolution 0.01 + // public UInt16 VoltageAdjustmentFactorIm { get; init;} = 0; + // public UInt16 PreChargeDcLinkVoltage { get; init;} = 0; + // public Decimal MaxPeakCurrentVoltageControlL1 { get; init;} = 0; // resolution 0.01 + // public Decimal MaxPeakCurrentVoltageControlL2 { get; init;} = 0; // resolution 0.01 + // public Decimal MaxPeakCurrentVoltageControlL3 { get; init;} = 0; // resolution 0.01 + // public UInt16 GridFormingMode { get; init;} = 1; // 0 = not grid-forming (grid-tied) ,1 = grid-forming + // public UInt16 DcLinkRefVoltage { get; init;} = 800; + // public UInt16 DcLinkMinVoltage { get; init;} = 780; + // public UInt16 DcLinkMaxVoltage { get; init;} = 820; + // public UInt16 DcVoltageRefUs { get; init;} = 900; + // public UInt16 DcMinVoltageUs { get; init;} = 880; + // public UInt16 DcMaxVoltageUs { get; init;} = 920; + // // Need to discuss this with Ivo + // // public UInt16 FrequencySlopeIslandMode { get; init;} = 200; // resolution 0.01 + // // public UInt16 VoltageSlopeIslandMode { get; init;} = 500; // resolution 0.01 + // public UInt16 AcDcGcBypassMode { get; init;} = 0; + // public UInt16 AcDcGcPMaxThresholdPercent { get; init;} = 0; // resolution 0.01 + // public UInt16 AcDcGcStartupRampEnable { get; init;} = 0; + // public DcStageConfiguration DcConfigModule { get; init;} = 0; // this must be an enum + // public UInt16 DcDcPowerDistribution { get; init;} = 0; // 0.1 resolution + // public AcDcDistributionMode AcDcDistributionMode { get; init;} = 0; + + + +} \ No newline at end of file diff --git a/csharp/Lib/Devices/Trumpf/SystemControl/ErrorPolicy.cs b/csharp/Lib/Devices/Trumpf/SystemControl/ErrorPolicy.cs new file mode 100644 index 000000000..9a57a9f3d --- /dev/null +++ b/csharp/Lib/Devices/Trumpf/SystemControl/ErrorPolicy.cs @@ -0,0 +1,7 @@ +namespace InnovEnergy.Lib.Devices.Trumpf.SystemControl; + +public enum ErrorPolicy : UInt16 +{ + Relaxed = 0, // 0 = relaxed (System keeps running even if some slaves are in error state.) + Strict = 1, // 1 = strict (System shuts down as soon as one component is in error state.) +} \ No newline at end of file diff --git a/csharp/Lib/Devices/Trumpf/SystemControl/StatusRecord.cs b/csharp/Lib/Devices/Trumpf/SystemControl/StatusRecord.cs new file mode 100644 index 000000000..511019b83 --- /dev/null +++ b/csharp/Lib/Devices/Trumpf/SystemControl/StatusRecord.cs @@ -0,0 +1,43 @@ +namespace InnovEnergy.Lib.Devices.Trumpf.SystemControl; + +using AlarmMessages = IReadOnlyList; +using WarningMessages = IReadOnlyList; + + +// ReSharper disable UnusedAutoPropertyAccessor.Global +#pragma warning disable CS8618 + + +public record StatusRecord +{ + + // TODO + + // public MainState MainState { get; init; } + // public String SerialNumber { get; init; } + // public AcDcGridType GridType { get; init; } + // public WarningMessages Warnings { get; init; } + // public AlarmMessages Alarms { get; init; } + // public Decimal NumberOfConnectedSlaves { get; init; } + // public Decimal NumberOfConnectedSubSlaves { get; init; } + // public Frequency AcDcNominalGridFrequency { get; init; } + // public Voltage AcDcNominalGridVoltage { get; init; } + // public Power AcDcActNominalPower { get; init; } + // public Decimal AcDcPowerLimitingStatusAct { get; init; } // TODO: enum + // public Voltage AcDcDcVoltageReference { get; init; } + // public Voltage AcDcDcLinkVoltageMinAct { get; init; } + // public Voltage AcDcDcLinkVoltageMaxAct { get; init; } + // public Voltage AcDcDcLinkChargedMinVoltage { get; init; } + // public Decimal AcDcStmActCustomer { get; init; } + // public Decimal AcDcOverloadIntegratorStatusL1 { get; init; } + // public Decimal AcDcOverloadIntegratorStatusL2 { get; init; } + // public Decimal AcDcOverloadIntegratorStatusL3 { get; init; } + // public Power AcSignedPowerValue { get; init; } + // public Voltage ActualDcLinkVoltageUpperHalf { get; init; } + // public Voltage ActualDcLinkVoltageLowerHalf { get; init; } + // public Voltage ActualDcLinkVoltageUpperHalfExt { get; init; } + // public Voltage ActualDcLinkVoltageLowerHalfExt { get; init; } + // public Voltage VoltageIntNtoPe { get; init; } + // public Voltage VoltageExtNtoPe { get; init; } + // public Temperature InletAirTemperature { get; init; } +} diff --git a/csharp/Lib/Devices/Trumpf/SystemControl/SubSlavesErrorPolicy.cs b/csharp/Lib/Devices/Trumpf/SystemControl/SubSlavesErrorPolicy.cs new file mode 100644 index 000000000..107b6b42b --- /dev/null +++ b/csharp/Lib/Devices/Trumpf/SystemControl/SubSlavesErrorPolicy.cs @@ -0,0 +1,8 @@ +namespace InnovEnergy.Lib.Devices.Trumpf.SystemControl; + +public enum SubSlavesErrorPolicy : UInt16 +{ + Strict = 0, // (AC-DC module switches to error state if at least one submodules is in error state + Relaxed = 1, // (AC-DC module switches to error state if all submodules are in error state.) + Off = 2, // (If possible AC-DC module continues operation even if all submodules are in error state. +} \ No newline at end of file diff --git a/csharp/Lib/Devices/Trumpf/SystemControl/SystemControl.csproj b/csharp/Lib/Devices/Trumpf/SystemControl/SystemControl.csproj new file mode 100644 index 000000000..be34f2198 --- /dev/null +++ b/csharp/Lib/Devices/Trumpf/SystemControl/SystemControl.csproj @@ -0,0 +1,7 @@ + + + + + + + diff --git a/csharp/Lib/Devices/Trumpf/SystemControl/SystemControlDevice.cs b/csharp/Lib/Devices/Trumpf/SystemControl/SystemControlDevice.cs new file mode 100644 index 000000000..cc3e94af0 --- /dev/null +++ b/csharp/Lib/Devices/Trumpf/SystemControl/SystemControlDevice.cs @@ -0,0 +1,324 @@ +using System.Diagnostics.CodeAnalysis; +using InnovEnergy.Lib.Protocols.Modbus.Clients; +using InnovEnergy.Lib.Protocols.Modbus.Connections; +using InnovEnergy.Lib.Utils; +using static InnovEnergy.Lib.Devices.Trumpf.SystemControl.SystemControlRegisters; + + +namespace InnovEnergy.Lib.Devices.Trumpf.SystemControl; + +[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] +public class SystemControlDevice +{ + private ModbusTcpClient ModbusTcpClient { get; } + + public SystemControlDevice(String hostname, UInt16 port = ModbusTcpClient.DefaultPort, Byte slaveAddress = 0) + { + var connection = new ModbusTcpConnection(hostname, port); + ModbusTcpClient = new ModbusTcpClient(connection, slaveAddress); + } + + + public void WriteControl(ControlRecord c) + { + /* + WriteRegs(AcControlRegisters.Date, new List { c.Date.ConvertTo()}); + WriteRegs(AcControlRegisters.Time, new List { c.Time.ConvertTo()}); + WriteRegs(AcControlRegisters.IpAddress, new List { c.IpAddress.ConvertTo()}); + WriteRegs(AcControlRegisters.Subnet, new List { c.Subnet.ConvertTo()}); + WriteRegs(AcControlRegisters.Gateway, new List { c.Gateway.ConvertTo()}); + WriteCoils(AcControlRegisters.ResetParamToDefault, c.ResetParamToDefault); + WriteCoils(AcControlRegisters.FactoryResetParameters, c.FactoryResetParameters); + ModbusTcpClient.WriteRegisters(AcControlRegisters.UpdateSwTrigger, c.UpdateSwTrigger, c.AutomaticSwUpdate, c.CustomerValuesSaveReset); + */ + + + WriteRegs(CommunicationTimeout, c.CommunicationTimeout.TotalSeconds.ConvertTo()); + + WriteRegs(ConnectedSystemConfig, c.ConnectedSystemConfig); + + + WriteCoils(PowerStageConfig, c.PowerStageEnable, + c.SetValueConfig.ConvertTo(), + c.ResetsAlarmAndWarning); + WriteRegs(PreChargeDcLinkConfigR, c.PreChargeDcLinkConfig, + c.PowerFactorConvention, c.SlaveAddress, + c.ErrorHandlingPolicy, + c.GridType, c.SubSlaveAddress); + WriteCoils(ModbusSlaveId, c.UseModbusSlaveIdForAddressing); + WriteRegs(SubSlaveErrorPolicy, c.SubSlaveErrorPolicy); + + WriteRegs(SignedPowerNominalValue, -1.0m, c.SignedPowerNominalValue);/*, c.SignedPowerSetValueL1, + c.SignedPowerSetValueL2, c.SignedPowerSetValueL3, + c.PowerSetValue, c.PowerSetValueL1, + c.PowerSetValueL2, c.PowerSetValuesL3);*/ + + + WriteRegs(MaximumGridCurrentRmsL1, 0.01m, c.MaximumGridCurrentRmsL1, c.MaximumGridCurrentRmsL2, + c.MaximumGridCurrentRmsL3, c.CosPhiSetValueL1, + c.CosPhiSetValueL2, c.CosPhiSetValueL3); + + WriteCoils(PhaseL1IsCapacitive, c.PhaseL1IsCapacitive, + c.PhaseL2IsCapacitive, + c.PhaseL3IsCapacitive, + c.PhasesAreCapacitive); + + /* WriteRegs(SetPointCosPhi, 0.01m, c.SetPointCosPhi.ConvertTo(), + c.SetPointSinPhi.ConvertTo(), + c.SetPointSinPhiL1.ConvertTo(), + c.SetPointSinPhiL2.ConvertTo(), + c.SetPointSinPhiL3.ConvertTo(), + c.FrequencyOffsetIm);*/ + + WriteRegs(VoltageAdjustmentFactorIm, c.VoltageAdjustmentFactorIm); + WriteRegs(PreChargeDcLinkVoltage, c.PreChargeDcLinkVoltage); + WriteRegs(MaxPeakCurrentVoltageControlL1, 0.01m, c.MaxPeakCurrentVoltageControlL1, + c.MaxPeakCurrentVoltageControlL2, + c.MaxPeakCurrentVoltageControlL3); + WriteRegs(GridFormingMode, c.GridFormingMode, c.DcLinkRefVoltage, + c.DcLinkMinVoltage, c.DcLinkMaxVoltage, + c.DcVoltageRefUs, c.DcMinVoltageUs, c.DcMaxVoltageUs); + WriteRegs(AcDcGcBypassMode, c.AcDcGcBypassMode); + WriteRegs(AcDcGcPMaxThresholdPercent, 0.01m, c.AcDcGcPMaxThresholdPercent); + WriteRegs(AcDcGcStartupRampEnable, c.AcDcGcStartupRampEnable); + WriteRegs(DcConfigModule, c.DcConfigModule); + WriteRegs(DcDcPowerDistribution, 0.1m, c.DcDcPowerDistribution); + WriteRegs(SystemControlRegisters.AcDcDistributionMode, c.AcDcDistributionMode); + } + + private void WriteRegs (UInt16 a, Decimal res = 1.0m, params Decimal[] regs) => ModbusTcpClient.WriteRegisters(a, regs.ToUInt16(res)); + private void WriteRegs (UInt16 a, params IConvertible[] regs) => ModbusTcpClient.WriteRegisters(a, regs.Select(v => v.ConvertTo()).ToArray()); + private void WriteRegs (UInt16 a, params UInt16[] regs) => ModbusTcpClient.WriteRegisters(a, regs); + private void WriteCoils(UInt16 a, params Boolean[] coils) => ModbusTcpClient.WriteMultipleCoils(a, coils); + + private static Decimal GetPhi(Decimal cosPhi) => cosPhi.Clamp(-1m, 1m).Apply(ACos); + + public StatusRecord? ReadStatus() + { + try + { + return TryReadStatus(); + } + catch (Exception e) + { + ModbusTcpClient.CloseConnection(); + Console.WriteLine("Failed to read inverter status"); + e.Message.WriteLine(); + + return null; + } + } + + private StatusRecord TryReadStatus() + { + // Console.WriteLine("Reading Ac Device"); + + var acSerialNumber = ModbusTcpClient.ReadInputRegisters(2009, 2); + var acActualMain = ModbusTcpClient.ReadInputRegisters(5001, 3); + var acActualAcDc = ModbusTcpClient.ReadInputRegisters(5021, 9); + var acActualAcDc2 = ModbusTcpClient.ReadInputRegisters(5031, 1); + var acActualAcDc3 = ModbusTcpClient.ReadInputRegisters(5131, 6); + var acActualMeasurement = ModbusTcpClient.ReadInputRegisters(5141, 3); + var acActualMeasurement1 = ModbusTcpClient.ReadInputRegisters(5151, 3); + var acActualMeasurement2 = ModbusTcpClient.ReadInputRegisters(5161, 3); + var acActualMeasurement3 = ModbusTcpClient.ReadInputRegisters(5171, 3); + var acActualMeasurement4 = ModbusTcpClient.ReadInputRegisters(5187, 2); + var acActualMeasurement5 = ModbusTcpClient.ReadInputRegisters(5189, 2); + var acActualMeasurement6 = ModbusTcpClient.ReadInputRegisters(5191, 2); + var acActualMeasurement7 = ModbusTcpClient.ReadInputRegisters(5201, 1); + var acActualMeasurement8 = ModbusTcpClient.ReadInputRegisters(5211, 4); + var acActualMeasurement9 = ModbusTcpClient.ReadInputRegisters(5221, 2); + var acActualTemp = ModbusTcpClient.ReadInputRegisters(5501, 1); + var acWarningValues = ModbusTcpClient.ReadInputRegisters(2402, 22); + var acAlarmValues = ModbusTcpClient.ReadInputRegisters(2809, 22); + var acSetValues = ModbusTcpClient.ReadInputRegisters(4196, 1); + + var warnings = Enumerable + .Range(2404, 20) + .Select(n => acWarningValues.GetUInt16((UInt16)n).ConvertTo()) + .ToArray(); + + var alarms = Enumerable + .Range(2811, 20) + .Select(n => acAlarmValues.GetUInt16((UInt16)n).ConvertTo()) + .Where(m => m != AlarmMessage.NoAlarm) + .ToArray(); + + + var dcPower = acActualMeasurement.GetInt16(5141) * 1m + acActualMeasurement.GetInt16(5142) * 1m + acActualMeasurement.GetInt16(5143) * 1m; + var dcVoltage = acActualMeasurement8.GetUInt16(5214) + acActualMeasurement8.GetUInt16(5213); + var dcCurrent = dcVoltage != 0m + ? dcPower / dcVoltage + : 0m; + + + // //acActualMeasurement + // PowerAcL1 = acActualMeasurement.GetInt16(5141) * 1m, // in Watt + // PowerAcL2 = acActualMeasurement.GetInt16(5142) * 1m, // in Watt + // PowerAcL3 = acActualMeasurement.GetInt16(5143) * 1m, // in Watt + // + //acActualMeasurement1 + // PhaseCurrentL1 = acActualMeasurement1.GetUInt16(5151) * 0.01m, + // PhaseCurrentL2 = acActualMeasurement1.GetUInt16(5152) * 0.01m, + // PhaseCurrentL3 = acActualMeasurement1.GetUInt16(5153) * 0.01m, + + //acActualMeasurement2 + // GridVoltageL1 = acActualMeasurement2.GetUInt16(5161) * 0.1m, + // GridVoltageL2 = acActualMeasurement2.GetUInt16(5162) * 0.1m, + // GridVoltageL3 = acActualMeasurement2.GetUInt16(5163) * 0.1m, + + //acActualMeasurement3 + // CosPhiL1 = acActualMeasurement3.GetInt16(5171) * 0.01m, + // CosPhiL2 = acActualMeasurement3.GetInt16(5172) * 0.01m, + // CosPhiL3 = acActualMeasurement3.GetInt16(5173) * 0.01m, + + // //acActualMeasurement4 + // SumPowerL1 = acActualMeasurement4.GetUInt32(5187) * 1m, // in Watt + // //acActualMeasurement5 + // SumPowerL2 = acActualMeasurement5.GetUInt32(5189) * 1m, // in Watt + // //acActualMeasurement6 + // SumPowerL3 = acActualMeasurement6.GetUInt32(5191) * 1m, // in Watt + // //acActualMeasurement9 + // GridFrequency = acActualMeasurement7.GetInt16(5201) * 0.01m, + + //acActualMeasurement11 + // VoltageIntNtoPE = acActualMeasurement9.GetInt16(5221) * 0.1m, + // VoltageExtNtoPE = acActualMeasurement9.GetInt16(5222) * 0.1m, + + // + // ApparentPowerAcL1 = acActualAcDc3.GetUInt16(5131) * 1m, // in VA + // ApparentPowerAcL2 = acActualAcDc3.GetUInt16(5132) * 1m, // in VA + // ApparentPowerAcL3 = acActualAcDc3.GetUInt16(5133) * 1m, // in VA + + var apparentPowerAcL1 = acActualAcDc3.GetUInt16(5131) * 1m; + var apparentPowerAcL2 = acActualAcDc3.GetUInt16(5132) * 1m; + var apparentPowerAcL3 = acActualAcDc3.GetUInt16(5133) * 1m; + + var powerAcL1 = acActualMeasurement.GetInt16(5141) * 1m; // in Watt + var powerAcL2 = acActualMeasurement.GetInt16(5142) * 1m; // in Watt + var powerAcL3 = acActualMeasurement.GetInt16(5143) * 1m; // in Watt + + var phaseCurrentL1 = acActualMeasurement1.GetUInt16(5151) * 0.01m; + var phaseCurrentL2 = acActualMeasurement1.GetUInt16(5152) * 0.01m; + var phaseCurrentL3 = acActualMeasurement1.GetUInt16(5153) * 0.01m; + + var gridVoltageL1 = acActualMeasurement2.GetUInt16(5161) * 0.1m; + var gridVoltageL2 = acActualMeasurement2.GetUInt16(5162) * 0.1m; + var gridVoltageL3 = acActualMeasurement2.GetUInt16(5163) * 0.1m; + + var gridFrequency = acActualMeasurement7.GetInt16(5201) * 0.01m; + + return new StatusRecord + { + Ac = new Ac3Bus + { + Frequency = gridFrequency, + + L1 = new AcPhase + { + Voltage = gridVoltageL1, + Current = phaseCurrentL1, + Phi = ACos(powerAcL1 / apparentPowerAcL1), // TODO: 2pi + }, + L2 = new AcPhase + { + Voltage = gridVoltageL2, + Current = phaseCurrentL2, + Phi = ACos(powerAcL2 / apparentPowerAcL2), // TODO: 2pi + }, + L3 = new AcPhase + { + Voltage = gridVoltageL3, + Current = phaseCurrentL3, + Phi = ACos(powerAcL3 / apparentPowerAcL3), // TODO: 2pi + } + }, + Dc = new DcBus + { + Current = dcCurrent, + Voltage = dcVoltage, + }, + + MainState = acActualMain.GetInt16(5001).ConvertTo(), + Alarms = alarms, + Warnings = warnings, + GridType = acActualAcDc.GetUInt16(5024).ConvertTo(), + SerialNumber = acSerialNumber.GetInt32(2009).ToString(), // TODO: why tostring ? + NumberOfConnectedSlaves = acActualMain.GetUInt16(5002), + NumberOfConnectedSubSlaves = acActualMain.GetUInt16(5003), + AcDcNominalGridFrequency = acActualAcDc.GetUInt16(5021) * 0.1m, + AcDcNominalGridVoltage = acActualAcDc.GetUInt16(5022), + AcDcActNominalPower = acActualAcDc.GetUInt16(5023), + AcDcPowerLimitingStatusAct = acActualAcDc.GetUInt16(5025), + AcDcDcVoltageReference = acActualAcDc.GetUInt16(5026), // DC link reference + AcDcDcLinkVoltageMinAct = acActualAcDc.GetUInt16(5027), // DC link min voltage + AcDcDcLinkVoltageMaxAct = acActualAcDc.GetUInt16(5028), // DC link max voltage + AcDcDcLinkChargedMinVoltage = acActualAcDc.GetUInt16(5029) * 0.01m, + AcDcStmActCustomer = acActualAcDc2.GetUInt16(5031), //need to check + AcDcOverloadIntegratorStatusL1 = acActualAcDc3.GetUInt16(5134) * 0.1m, + AcDcOverloadIntegratorStatusL2 = acActualAcDc3.GetUInt16(5135) * 0.1m, + AcDcOverloadIntegratorStatusL3 = acActualAcDc3.GetUInt16(5136) * 0.1m, + AcSignedPowerValue = acSetValues.GetInt16(4196) * -1.0m, // this is also used for control + ActualDcLinkVoltageUpperHalf = acActualMeasurement8.GetUInt16(5211), + ActualDcLinkVoltageLowerHalf = acActualMeasurement8.GetUInt16(5212), + ActualDcLinkVoltageUpperHalfExt = acActualMeasurement8.GetUInt16(5213), + ActualDcLinkVoltageLowerHalfExt = acActualMeasurement8.GetUInt16(5214), + VoltageIntNtoPe = acActualMeasurement9.GetInt16(5221) * 0.1m, + VoltageExtNtoPe = acActualMeasurement9.GetInt16(5222) * 0.1m, + InletAirTemperature = acActualTemp.GetInt16(5501) * 0.1m, + + }; + + + + // ( + // Ac: new Ac3Bus + // ( + // new AcPhase(gridVoltageL1,phaseCurrentL1, ACos(powerAcL1/apparentPowerAcL1)), + // new AcPhase(gridVoltageL2,phaseCurrentL2, ACos(powerAcL2/apparentPowerAcL2)), + // new AcPhase(gridVoltageL3,phaseCurrentL3, ACos(powerAcL3/apparentPowerAcL3)), + // gridFrequency // Gird Frequency + // ), + // Dc: new DcConnection(dcVoltage, dcCurrent), + // + // SerialNumber : acSerialNumber.GetInt32(2009).ToString(), + // + // // acActualMainValues + // MainState : acActualMain.GetInt16(5001).ConvertTo(), + // NumberOfConnectedSlaves : acActualMain.GetUInt16(5002), + // NumberOfConnectedSubSlaves : acActualMain.GetUInt16(5003), + // + // //acActualAcDc + // AcDcNominalGridFrequency : acActualAcDc.GetUInt16(5021) * 0.1m, + // AcDcNominalGridVoltage : acActualAcDc.GetUInt16(5022), + // AcDcActNominalPower : acActualAcDc.GetUInt16(5023), + // AcDcActiveGridType : acActualAcDc.GetUInt16(5024).ConvertTo(), + // AcDcPowerLimitingStatusAct : acActualAcDc.GetUInt16(5025), + // AcDcDcVoltageReference : acActualAcDc.GetUInt16(5026), // DC link reference + // AcDcDcLinkVoltageMinAct : acActualAcDc.GetUInt16(5027), // DC link min voltage + // AcDcDcLinkVoltageMaxAct : acActualAcDc.GetUInt16(5028), // DC link max voltage + // AcDcDcLinkChargedMinVoltage : acActualAcDc.GetUInt16(5029) * 0.01m, + // + // //ac Actual AcDc 2 + // AcDcStmActCustomer : acActualAcDc2.GetUInt16(5031), //need to check + // AcDcOverloadIntegratorStatusL1 : acActualAcDc3.GetUInt16(5134) * 0.1m, + // AcDcOverloadIntegratorStatusL2 : acActualAcDc3.GetUInt16(5135) * 0.1m, + // AcDcOverloadIntegratorStatusL3 : acActualAcDc3.GetUInt16(5136) * 0.1m, + // AcSignedPowerValue : acSetValues.GetInt16(4196) * -1.0m, // this is also used for control + // + // //acActualMeasurement10 + // ActualDcLinkVoltageUpperHalf : acActualMeasurement8.GetUInt16(5211), + // ActualDcLinkVoltageLowerHalf : acActualMeasurement8.GetUInt16(5212), + // ActualDcLinkVoltageUpperHalfExt : acActualMeasurement8.GetUInt16(5213), + // ActualDcLinkVoltageLowerHalfExt : acActualMeasurement8.GetUInt16(5214), + // + // VoltageIntNtoPe : acActualMeasurement9.GetInt16(5221) * 0.1m, + // VoltageExtNtoPe : acActualMeasurement9.GetInt16(5222) * 0.1m, + // //acActualTemp + // InletAirTemperature : acActualTemp.GetInt16(5501) * 0.1m, + // + // Warnings : warnings, + // Alarms : alarms + // ); + } +} \ No newline at end of file diff --git a/csharp/Lib/Devices/Trumpf/SystemControl/SystemControlRegisters.cs b/csharp/Lib/Devices/Trumpf/SystemControl/SystemControlRegisters.cs new file mode 100644 index 000000000..6ab3817f2 --- /dev/null +++ b/csharp/Lib/Devices/Trumpf/SystemControl/SystemControlRegisters.cs @@ -0,0 +1,83 @@ +namespace InnovEnergy.Lib.Devices.Trumpf.SystemControl; + +public static class SystemControlRegisters +{ + + // TODO + + // public const UInt16 Date = 1001; + // public const UInt16 Time = 1003; + // public const UInt16 IpAddress = 1005; + // public const UInt16 Subnet = 1007; + // public const UInt16 Gateway = 1009; + // public const UInt16 ResetParamToDefault = 1011; + // public const UInt16 CommunicationTimeout = 1017; + // public const UInt16 RestartFlag = 1018; + // public const UInt16 ConnectedSystemConfig = 1019; + // public const UInt16 UpdateSwTrigger = 1027; + // public const UInt16 AutomaticSwUpdate = 1028; + // public const UInt16 CustomerValuesSaveReset = 1029; + // public const UInt16 SerialNumberSystemControl = 2001; + // public const UInt16 SerialNumberAcDc = 2009; + // public const UInt16 IntegrationLevel = 2051; + // public const UInt16 IlBuildnumber = 2052; + // public const UInt16 PowerStageConfig = 4001; + // public const UInt16 SetValueConfig = 4002; + // public const UInt16 ResetsAlarmAndWarning = 4003; + // public const UInt16 PreChargeDcLinkConfigR = 4006; + // public const UInt16 ReferenceFrameConvention = 4007; + // public const UInt16 SlaveAddress = 4008; + // public const UInt16 ErrorHandlingPolicy = 4009; + // public const UInt16 GridType = 4010; + // public const UInt16 SubSlaveAddress = 4011; + // public const UInt16 ModbusSlaveId = 4012; + // public const UInt16 SubSlaveErrorPolicy = 4013; + // public const UInt16 SignedPowerNominalValue = 4196; + // public const UInt16 SignedPowerSetValueL1 = 4197; + // public const UInt16 SignedPowerSetValueL2 = 4198; + // public const UInt16 SignedPowerSetValueL3 = 4199; + // public const UInt16 PowerSetValue = 4200; + // public const UInt16 PowerSetValueL1 = 4201; + // public const UInt16 PowerSetValueL2 = 4202; + // public const UInt16 PowerSetValueL3 = 4203; + // public const UInt16 MaximumGridCurrentRmsL1 = 4204; + // public const UInt16 MaximumGridCurrentRmsL2 = 4205; + // public const UInt16 MaximumGridCurrentRmsL3 = 4206; + // public const UInt16 CosPhiSetValueL1 = 4207; + // public const UInt16 CosPhiSetValueL2 = 4208; + // public const UInt16 CosPhiSetValueL3 = 4209; + // public const UInt16 PhaseL1IsCapacitive = 4214; // True = Capacitive, false = Inductive + // public const UInt16 PhaseL2IsCapacitive = 4215; // True = Capacitive, false = Inductive + // public const UInt16 PhaseL3IsCapacitive = 4216; // True = Capacitive, false = Inductive + // public const UInt16 PhasesAreCapacitive = 4217; // True = Capacitive, false = Inductive + // public const UInt16 SetPointCosPhi = 4218; + // public const UInt16 SetPointSinPhi = 4219; + // public const UInt16 SetPointSinPhiL1 = 4220; + // public const UInt16 SetPointSinPhiL2 = 4221; + // public const UInt16 SetPointSinPhiL3 = 4222; + // public const UInt16 FrequencyOffsetIm = 4223; //Im: Island mode + // public const UInt16 VoltageAdjustmentFactorIm = 4224; //Im: Island mode + // public const UInt16 PreChargeDcLinkVoltage = 4226; + // public const UInt16 MaxPeakCurrentVoltageControlL1 = 4227; + // public const UInt16 MaxPeakCurrentVoltageControlL2 = 4228; + // public const UInt16 MaxPeakCurrentVoltageControlL3 = 4229; + // public const UInt16 GridFormingMode = 4230; + // public const UInt16 DcLinkReferenceVoltage = 4231; + // public const UInt16 DcLinkMinVoltage = 4232; + // public const UInt16 DcLinkMaxVoltage = 4233; + // public const UInt16 AcDcDcVoltageRefUs = 4234; + // public const UInt16 AcDcMinDcLinkVoltageUs = 4235; + // public const UInt16 AcDcMaxDcLinkVoltageUs = 4236; + // // public const UInt16 FrequencySlopeIslandMode = 4237, // Function fN = f(active grid-power) of droop control + // // public const UInt16 VoltageSlopeIslandMode = 4238, // VN = f(reactive grid power) of droop control in island operation. + // public const UInt16 AcDcGcBypassMode = 4281; + // public const UInt16 AcDcGcPMaxThresholdPercent = 4282; // res + // public const UInt16 AcDcGcStartupRampEnable = 4283; + // public const UInt16 DcConfigModule = 4301; // 0 = DC module is off, battery voltage can be measured + // // 1 = DC module is active (DC link voltage control) + // // 2 = DC module is active(current source mode orin DC droop mode) + // public const UInt16 DcDcPowerDistribution = 4304; + // public const UInt16 AcDcDistributionMode = 4307; +} + + diff --git a/csharp/Lib/Devices/Trumpf/TruConvertAc/WarningMessage.cs b/csharp/Lib/Devices/Trumpf/TruConvertAc/WarningMessage.cs index 2fb74b947..4ceffc228 100644 --- a/csharp/Lib/Devices/Trumpf/TruConvertAc/WarningMessage.cs +++ b/csharp/Lib/Devices/Trumpf/TruConvertAc/WarningMessage.cs @@ -8,17 +8,17 @@ namespace InnovEnergy.Lib.Devices.Trumpf.TruConvertAc; public enum WarningMessage { - ERR_WARN_FAN =10500, //AC-DC module warning - ERR_WARN_I_OFFSET =10503, //AC-DC module warning - ERR_WARN_VG_OFFSET =10504, //AC-DC module warning - ERR_WARN_VC_OFFSET =10505, //AC-DC module warning - ERR_WARN_DC_OFFSET =10506, //AC-DC module warning - ERR_WARN_NTC_PROTECT =10507, //DC-link circuit need more time for cool down - ERR_WARN_AIR_TEMP =10508, //Overtemperature inlet air: power is derated - SurgeDetected =10509, //Temporary overvoltage in grid measurement detected (surge) - ERR_WARN_TEMP_DERATING =11021, //Temperature derating active - ERR_WARN_OVERLOAD =11022, //Overload handling is active - ERR_WARN_RUNTIME_EEPROM =11023, //AC-DC module warning - ERR_WARN_OVERCURRENT =11024 //Overcurrent handling is active + ERR_WARN_FAN = 10500, //AC-DC module warning + ERR_WARN_I_OFFSET = 10503, //AC-DC module warning + ERR_WARN_VG_OFFSET = 10504, //AC-DC module warning + ERR_WARN_VC_OFFSET = 10505, //AC-DC module warning + ERR_WARN_DC_OFFSET = 10506, //AC-DC module warning + ERR_WARN_NTC_PROTECT = 10507, //DC-link circuit need more time for cool down + ERR_WARN_AIR_TEMP = 10508, //Overtemperature inlet air: power is derated + SurgeDetected = 10509, //Temporary overvoltage in grid measurement detected (surge) + ERR_WARN_TEMP_DERATING = 11021, //Temperature derating active + ERR_WARN_OVERLOAD = 11022, //Overload handling is active + ERR_WARN_RUNTIME_EEPROM = 11023, //AC-DC module warning + ERR_WARN_OVERCURRENT = 11024 //Overcurrent handling is active }