324 lines
18 KiB
C#
324 lines
18 KiB
C#
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<UInt16> { c.Date.ConvertTo<UInt16>()});
|
|
WriteRegs(AcControlRegisters.Time, new List<UInt16> { c.Time.ConvertTo<UInt16>()});
|
|
WriteRegs(AcControlRegisters.IpAddress, new List<UInt16> { c.IpAddress.ConvertTo<UInt16>()});
|
|
WriteRegs(AcControlRegisters.Subnet, new List<UInt16> { c.Subnet.ConvertTo<UInt16>()});
|
|
WriteRegs(AcControlRegisters.Gateway, new List<UInt16> { c.Gateway.ConvertTo<UInt16>()});
|
|
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<UInt16>());
|
|
|
|
WriteRegs(ConnectedSystemConfig, c.ConnectedSystemConfig);
|
|
|
|
|
|
WriteCoils(PowerStageConfig, c.PowerStageEnable,
|
|
c.SetValueConfig.ConvertTo<Boolean>(),
|
|
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<UInt16>(),
|
|
c.SetPointSinPhi.ConvertTo<UInt16>(),
|
|
c.SetPointSinPhiL1.ConvertTo<UInt16>(),
|
|
c.SetPointSinPhiL2.ConvertTo<UInt16>(),
|
|
c.SetPointSinPhiL3.ConvertTo<UInt16>(),
|
|
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<UInt16>()).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<WarningMessage>())
|
|
.ToArray();
|
|
|
|
var alarms = Enumerable
|
|
.Range(2811, 20)
|
|
.Select(n => acAlarmValues.GetUInt16((UInt16)n).ConvertTo<AlarmMessage>())
|
|
.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<MainState>(),
|
|
Alarms = alarms,
|
|
Warnings = warnings,
|
|
GridType = acActualAcDc.GetUInt16(5024).ConvertTo<AcDcGridType>(),
|
|
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<MainState>(),
|
|
// 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<AcDcGridType>(),
|
|
// 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
|
|
// );
|
|
}
|
|
} |