Implement CurrentLimiter and spare power mode
This commit is contained in:
@@ -101,41 +101,9 @@ namespace TestApp.Configuration
|
|||||||
ChargerDriver = Settings.DEFAULT_CHARGER_DRIVER,
|
ChargerDriver = Settings.DEFAULT_CHARGER_DRIVER,
|
||||||
ChargerAddress = Settings.DEFAULT_CHARGER_ADDRESS,
|
ChargerAddress = Settings.DEFAULT_CHARGER_ADDRESS,
|
||||||
ChargerPort = Settings.DEFAULT_CHARGER_PORT,
|
ChargerPort = Settings.DEFAULT_CHARGER_PORT,
|
||||||
|
MaxCurrent = Settings.DEFAULT_MAX_CURRENT,
|
||||||
|
MinNegativePower = Settings.DEFAULT_MIN_NEGATIVE_POWER,
|
||||||
Mode = 1,
|
Mode = 1,
|
||||||
ModeSettings = new ModeSettings[] {
|
|
||||||
new ModeSettings
|
|
||||||
{
|
|
||||||
ProcessVariable = ProcessVariable.ActivePowerPositive,
|
|
||||||
SetPoint = 32,
|
|
||||||
NegativePid = new PidSetting() {
|
|
||||||
KP = 0,
|
|
||||||
KI = 1,
|
|
||||||
KD = 0,
|
|
||||||
},
|
|
||||||
PositivePid = new PidSetting()
|
|
||||||
{
|
|
||||||
KP = 0,
|
|
||||||
KI = 1,
|
|
||||||
KD = 0,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new ModeSettings
|
|
||||||
{
|
|
||||||
ProcessVariable = ProcessVariable.ActivePowerNegative,
|
|
||||||
SetPoint = 100,
|
|
||||||
NegativePid = new PidSetting() {
|
|
||||||
KP = 0,
|
|
||||||
KI = 1,
|
|
||||||
KD = 0,
|
|
||||||
},
|
|
||||||
PositivePid = new PidSetting()
|
|
||||||
{
|
|
||||||
KP = 0,
|
|
||||||
KI = 1,
|
|
||||||
KD = 0,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,207 +5,16 @@
|
|||||||
internal const string DEFAULT_CHARGER_DRIVER = "VestelEvc04";
|
internal const string DEFAULT_CHARGER_DRIVER = "VestelEvc04";
|
||||||
internal const string DEFAULT_CHARGER_ADDRESS = "192.168.178.100";
|
internal const string DEFAULT_CHARGER_ADDRESS = "192.168.178.100";
|
||||||
internal const int DEFAULT_CHARGER_PORT = 512;
|
internal const int DEFAULT_CHARGER_PORT = 512;
|
||||||
|
internal const double DEFAULT_MAX_CURRENT = 32;
|
||||||
|
internal const double DEFAULT_MIN_NEGATIVE_POWER = 100;
|
||||||
|
|
||||||
public string? ChargerDriver { get; set; }
|
public string? ChargerDriver { get; set; }
|
||||||
public string? ChargerAddress { get; set; }
|
public string? ChargerAddress { get; set; }
|
||||||
public int? ChargerPort { get; set; }
|
public int? ChargerPort { get; set; }
|
||||||
|
|
||||||
|
public double? MaxCurrent { get; set; }
|
||||||
|
public double? MinNegativePower { get; set; }
|
||||||
|
|
||||||
public int Mode { get; set; }
|
public int Mode { get; set; }
|
||||||
|
|
||||||
public ModeSettings[]? ModeSettings { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class PidSetting {
|
|
||||||
public double KP { get; set; }
|
|
||||||
public double KI { get; set; }
|
|
||||||
public double KD { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ModeSettings {
|
|
||||||
public ProcessVariable ProcessVariable { get; set; }
|
|
||||||
public double SetPoint { get; set; }
|
|
||||||
public PidSetting? PositivePid { get; set; }
|
|
||||||
public PidSetting? NegativePid { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ProcessVariable
|
|
||||||
{
|
|
||||||
/// <summary>in W</summary>
|
|
||||||
ActivePowerPositive,
|
|
||||||
|
|
||||||
/// <summary>in Wh</summary>
|
|
||||||
ActiveEnergyPositive,
|
|
||||||
|
|
||||||
/// <summary>in W</summary>
|
|
||||||
ActivePowerNegative,
|
|
||||||
|
|
||||||
/// <summary>in Wh</summary>
|
|
||||||
ActiveEnergyNegative,
|
|
||||||
|
|
||||||
/// <summary>in var</summary>
|
|
||||||
ReactivePowerPositive,
|
|
||||||
|
|
||||||
/// <summary>in varh</summary>
|
|
||||||
ReactiveEnergyPositive,
|
|
||||||
|
|
||||||
/// <summary>in var</summary>
|
|
||||||
ReactivePowerNegative,
|
|
||||||
|
|
||||||
/// <summary>in varh</summary>
|
|
||||||
ReactiveEnergyNegative,
|
|
||||||
|
|
||||||
/// <summary>in VA</summary>
|
|
||||||
ApparentPowerPositive,
|
|
||||||
|
|
||||||
/// <summary>in VAh</summary>
|
|
||||||
ApparentEnergyPositive,
|
|
||||||
|
|
||||||
/// <summary>in VA</summary>
|
|
||||||
ApparentPowerNegative,
|
|
||||||
|
|
||||||
/// <summary>in VAh</summary>
|
|
||||||
ApparentEnergyNegative,
|
|
||||||
|
|
||||||
/// <summary>in -</summary>
|
|
||||||
PowerFactor,
|
|
||||||
|
|
||||||
/// <summary>in Hz</summary>
|
|
||||||
SupplyFrequency,
|
|
||||||
|
|
||||||
/// <summary>in W</summary>
|
|
||||||
ActivePowerPositiveL1,
|
|
||||||
|
|
||||||
/// <summary>in Wh</summary>
|
|
||||||
ActiveEnergyPositiveL1,
|
|
||||||
|
|
||||||
/// <summary>in W</summary>
|
|
||||||
ActivePowerNegativeL1,
|
|
||||||
|
|
||||||
/// <summary>in Wh</summary>
|
|
||||||
ActiveEnergyNegativeL1,
|
|
||||||
|
|
||||||
/// <summary>in var</summary>
|
|
||||||
ReactivePowerPositiveL1,
|
|
||||||
|
|
||||||
/// <summary>in varh</summary>
|
|
||||||
ReactiveEnergyPositiveL1,
|
|
||||||
|
|
||||||
/// <summary>in var</summary>
|
|
||||||
ReactivePowerNegativeL1,
|
|
||||||
|
|
||||||
/// <summary>in varh</summary>
|
|
||||||
ReactiveEnergyNegativeL1,
|
|
||||||
|
|
||||||
/// <summary>in VA</summary>
|
|
||||||
ApparentPowerPositiveL1,
|
|
||||||
|
|
||||||
/// <summary>in VAh</summary>
|
|
||||||
ApparentEnergyPositiveL1,
|
|
||||||
|
|
||||||
/// <summary>in VA</summary>
|
|
||||||
ApparentPowerNegativeL1,
|
|
||||||
|
|
||||||
/// <summary>in VAh</summary>
|
|
||||||
ApparentEnergyNegativeL1,
|
|
||||||
|
|
||||||
/// <summary>in A</summary>
|
|
||||||
CurrentL1,
|
|
||||||
|
|
||||||
/// <summary>in V</summary>
|
|
||||||
VoltageL1,
|
|
||||||
|
|
||||||
/// <summary>in -</summary>
|
|
||||||
PowerFactorL1,
|
|
||||||
|
|
||||||
/// <summary>in W</summary>
|
|
||||||
ActivePowerPositiveL2,
|
|
||||||
|
|
||||||
/// <summary>in Wh</summary>
|
|
||||||
ActiveEnergyPositiveL2,
|
|
||||||
|
|
||||||
/// <summary>in W</summary>
|
|
||||||
ActivePowerNegativeL2,
|
|
||||||
|
|
||||||
/// <summary>in Wh</summary>
|
|
||||||
ActiveEnergyNegativeL2,
|
|
||||||
|
|
||||||
/// <summary>in var</summary>
|
|
||||||
ReactivePowerPositiveL2,
|
|
||||||
|
|
||||||
/// <summary>in varh</summary>
|
|
||||||
ReactiveEnergyPositiveL2,
|
|
||||||
|
|
||||||
/// <summary>in var</summary>
|
|
||||||
ReactivePowerNegativeL2,
|
|
||||||
|
|
||||||
/// <summary>in varh</summary>
|
|
||||||
ReactiveEnergyNegativeL2,
|
|
||||||
|
|
||||||
/// <summary>in VA</summary>
|
|
||||||
ApparentPowerPositiveL2,
|
|
||||||
|
|
||||||
/// <summary>in VAh</summary>
|
|
||||||
ApparentEnergyPositiveL2,
|
|
||||||
|
|
||||||
/// <summary>in VA</summary>
|
|
||||||
ApparentPowerNegativeL2,
|
|
||||||
|
|
||||||
/// <summary>in VAh</summary>
|
|
||||||
ApparentEnergyNegativeL2,
|
|
||||||
|
|
||||||
/// <summary>in A</summary>
|
|
||||||
CurrentL2,
|
|
||||||
|
|
||||||
/// <summary>in V</summary>
|
|
||||||
VoltageL2,
|
|
||||||
|
|
||||||
/// <summary>in -</summary>
|
|
||||||
PowerFactorL2,
|
|
||||||
|
|
||||||
/// <summary>in W</summary>
|
|
||||||
ActivePowerPositiveL3,
|
|
||||||
|
|
||||||
/// <summary>in Wh</summary>
|
|
||||||
ActiveEnergyPositiveL3,
|
|
||||||
|
|
||||||
/// <summary>in W</summary>
|
|
||||||
ActivePowerNegativeL3,
|
|
||||||
|
|
||||||
/// <summary>in Wh</summary>
|
|
||||||
ActiveEnergyNegativeL3,
|
|
||||||
|
|
||||||
/// <summary>in var</summary>
|
|
||||||
ReactivePowerPositiveL3,
|
|
||||||
|
|
||||||
/// <summary>in varh</summary>
|
|
||||||
ReactiveEnergyPositiveL3,
|
|
||||||
|
|
||||||
/// <summary>in var</summary>
|
|
||||||
ReactivePowerNegativeL3,
|
|
||||||
|
|
||||||
/// <summary>in varh</summary>
|
|
||||||
ReactiveEnergyNegativeL3,
|
|
||||||
|
|
||||||
/// <summary>in VA</summary>
|
|
||||||
ApparentPowerPositiveL3,
|
|
||||||
|
|
||||||
/// <summary>in VAh</summary>
|
|
||||||
ApparentEnergyPositiveL3,
|
|
||||||
|
|
||||||
/// <summary>in VA</summary>
|
|
||||||
ApparentPowerNegativeL3,
|
|
||||||
|
|
||||||
/// <summary>in VAh</summary>
|
|
||||||
ApparentEnergyNegativeL3,
|
|
||||||
|
|
||||||
/// <summary>in A</summary>
|
|
||||||
CurrentL3,
|
|
||||||
|
|
||||||
/// <summary>in V</summary>
|
|
||||||
VoltageL3,
|
|
||||||
|
|
||||||
/// <summary>in -</summary>
|
|
||||||
PowerFactorL3,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
67
TestApp/CurrentLimitter.cs
Normal file
67
TestApp/CurrentLimitter.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using TestApp.Configuration;
|
||||||
|
using TestApp.Driver;
|
||||||
|
|
||||||
|
namespace TestApp
|
||||||
|
{
|
||||||
|
internal class CurrentLimitter
|
||||||
|
{
|
||||||
|
private readonly ConfigurationManager _ConfigurationManager;
|
||||||
|
private readonly EnergyManager _EnergyManager;
|
||||||
|
|
||||||
|
public CurrentLimitter(ConfigurationManager configurationManager, EnergyManager energyManager)
|
||||||
|
{
|
||||||
|
_ConfigurationManager = configurationManager;
|
||||||
|
_EnergyManager = energyManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double GetLimitedCurrent(IChargerDriver chargerDriver, double current) {
|
||||||
|
var maxCurrent = _ConfigurationManager.Settings.MaxCurrent ?? Settings.DEFAULT_MAX_CURRENT;
|
||||||
|
|
||||||
|
var wallBoxCurrents = chargerDriver.GetCurrents();
|
||||||
|
var measuredCurrents = _EnergyManager.GetCurrents();
|
||||||
|
|
||||||
|
var maxWithoutCharger = GetMaximumCurrentWithoutWallBox(measuredCurrents, wallBoxCurrents);
|
||||||
|
var freeCurrent = maxCurrent - maxWithoutCharger;
|
||||||
|
|
||||||
|
if (freeCurrent < current) {
|
||||||
|
return freeCurrent;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double GetMaximumCurrentWithoutWallBox((double I1, double I2, double I3) measuredCurrent, (double I1, double I2, double I3) wallBoxCurrent)
|
||||||
|
{
|
||||||
|
return GetPermutations(wallBoxCurrent)
|
||||||
|
.Where(wbc => IsValidCombinition(measuredCurrent, wbc))
|
||||||
|
.Select(wbc => GetDifference(measuredCurrent, wbc))
|
||||||
|
.Select(c => GetMax(c))
|
||||||
|
.Max();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<(double I1, double I2, double I3)> GetPermutations((double I1, double I2, double I3) current) {
|
||||||
|
yield return (current.I1, current.I2, current.I3);
|
||||||
|
yield return (current.I1, current.I3, current.I2);
|
||||||
|
yield return (current.I2, current.I3, current.I1);
|
||||||
|
yield return (current.I2, current.I1, current.I3);
|
||||||
|
yield return (current.I3, current.I1, current.I2);
|
||||||
|
yield return (current.I3, current.I2, current.I1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsValidCombinition((double I1, double I2, double I3) measuredCurrent, (double I1, double I2, double I3) wallBoxCurrent) {
|
||||||
|
if (measuredCurrent.I1 < wallBoxCurrent.I1) { return false; } // even this is not correct if a PV is generating power !
|
||||||
|
if (measuredCurrent.I2 < wallBoxCurrent.I2) { return false; }
|
||||||
|
if (measuredCurrent.I3 < wallBoxCurrent.I3) { return false; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (double I1, double I2, double I3) GetDifference((double I1, double I2, double I3) x, (double I1, double I2, double I3) y) {
|
||||||
|
return (x.I1 - y.I1, x.I2 - y.I2, x.I3 - y.I3);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double GetMax((double I1, double I2, double I3) currents) {
|
||||||
|
return Math.Max(Math.Max(currents.I1, currents.I2), currents.I3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,8 @@
|
|||||||
string HostAddress { get; set; }
|
string HostAddress { get; set; }
|
||||||
int Port { get; set; }
|
int Port { get; set; }
|
||||||
|
|
||||||
|
(double I1, double I2, double I3) GetCurrents();
|
||||||
|
|
||||||
void SetLoadingCurrent(double value);
|
void SetLoadingCurrent(double value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using NModbus;
|
using NModbus;
|
||||||
|
using System.ComponentModel.Design.Serialization;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
|
||||||
namespace TestApp.Driver
|
namespace TestApp.Driver
|
||||||
@@ -83,6 +84,21 @@ namespace TestApp.Driver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public (double I1, double I2, double I3) GetCurrents()
|
||||||
|
{
|
||||||
|
if (_Modbus is null)
|
||||||
|
{
|
||||||
|
Connect();
|
||||||
|
}
|
||||||
|
if (_Modbus is null) { return (double.NaN, double.NaN, double.NaN); }
|
||||||
|
|
||||||
|
var i1 = _Modbus.ReadHoldingRegisters(255, 1008, 1)[0];
|
||||||
|
var i2 = _Modbus.ReadHoldingRegisters(255, 1010, 1)[0];
|
||||||
|
var i3 = _Modbus.ReadHoldingRegisters(255, 1012, 1)[0];
|
||||||
|
|
||||||
|
return (0.001 * i1, 0.001 * i2, 0.001 * i3);
|
||||||
|
}
|
||||||
|
|
||||||
public void SetLoadingCurrent(double value)
|
public void SetLoadingCurrent(double value)
|
||||||
{
|
{
|
||||||
if (!_Running) { return; }
|
if (!_Running) { return; }
|
||||||
|
|||||||
182
TestApp/EMVariable.cs
Normal file
182
TestApp/EMVariable.cs
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
namespace TestApp
|
||||||
|
{
|
||||||
|
public enum EMVariable
|
||||||
|
{
|
||||||
|
/// <summary>in W</summary>
|
||||||
|
ActivePowerPositive,
|
||||||
|
|
||||||
|
/// <summary>in Wh</summary>
|
||||||
|
ActiveEnergyPositive,
|
||||||
|
|
||||||
|
/// <summary>in W</summary>
|
||||||
|
ActivePowerNegative,
|
||||||
|
|
||||||
|
/// <summary>in Wh</summary>
|
||||||
|
ActiveEnergyNegative,
|
||||||
|
|
||||||
|
/// <summary>in var</summary>
|
||||||
|
ReactivePowerPositive,
|
||||||
|
|
||||||
|
/// <summary>in varh</summary>
|
||||||
|
ReactiveEnergyPositive,
|
||||||
|
|
||||||
|
/// <summary>in var</summary>
|
||||||
|
ReactivePowerNegative,
|
||||||
|
|
||||||
|
/// <summary>in varh</summary>
|
||||||
|
ReactiveEnergyNegative,
|
||||||
|
|
||||||
|
/// <summary>in VA</summary>
|
||||||
|
ApparentPowerPositive,
|
||||||
|
|
||||||
|
/// <summary>in VAh</summary>
|
||||||
|
ApparentEnergyPositive,
|
||||||
|
|
||||||
|
/// <summary>in VA</summary>
|
||||||
|
ApparentPowerNegative,
|
||||||
|
|
||||||
|
/// <summary>in VAh</summary>
|
||||||
|
ApparentEnergyNegative,
|
||||||
|
|
||||||
|
/// <summary>in -</summary>
|
||||||
|
PowerFactor,
|
||||||
|
|
||||||
|
/// <summary>in Hz</summary>
|
||||||
|
SupplyFrequency,
|
||||||
|
|
||||||
|
/// <summary>in W</summary>
|
||||||
|
ActivePowerPositiveL1,
|
||||||
|
|
||||||
|
/// <summary>in Wh</summary>
|
||||||
|
ActiveEnergyPositiveL1,
|
||||||
|
|
||||||
|
/// <summary>in W</summary>
|
||||||
|
ActivePowerNegativeL1,
|
||||||
|
|
||||||
|
/// <summary>in Wh</summary>
|
||||||
|
ActiveEnergyNegativeL1,
|
||||||
|
|
||||||
|
/// <summary>in var</summary>
|
||||||
|
ReactivePowerPositiveL1,
|
||||||
|
|
||||||
|
/// <summary>in varh</summary>
|
||||||
|
ReactiveEnergyPositiveL1,
|
||||||
|
|
||||||
|
/// <summary>in var</summary>
|
||||||
|
ReactivePowerNegativeL1,
|
||||||
|
|
||||||
|
/// <summary>in varh</summary>
|
||||||
|
ReactiveEnergyNegativeL1,
|
||||||
|
|
||||||
|
/// <summary>in VA</summary>
|
||||||
|
ApparentPowerPositiveL1,
|
||||||
|
|
||||||
|
/// <summary>in VAh</summary>
|
||||||
|
ApparentEnergyPositiveL1,
|
||||||
|
|
||||||
|
/// <summary>in VA</summary>
|
||||||
|
ApparentPowerNegativeL1,
|
||||||
|
|
||||||
|
/// <summary>in VAh</summary>
|
||||||
|
ApparentEnergyNegativeL1,
|
||||||
|
|
||||||
|
/// <summary>in A</summary>
|
||||||
|
CurrentL1,
|
||||||
|
|
||||||
|
/// <summary>in V</summary>
|
||||||
|
VoltageL1,
|
||||||
|
|
||||||
|
/// <summary>in -</summary>
|
||||||
|
PowerFactorL1,
|
||||||
|
|
||||||
|
/// <summary>in W</summary>
|
||||||
|
ActivePowerPositiveL2,
|
||||||
|
|
||||||
|
/// <summary>in Wh</summary>
|
||||||
|
ActiveEnergyPositiveL2,
|
||||||
|
|
||||||
|
/// <summary>in W</summary>
|
||||||
|
ActivePowerNegativeL2,
|
||||||
|
|
||||||
|
/// <summary>in Wh</summary>
|
||||||
|
ActiveEnergyNegativeL2,
|
||||||
|
|
||||||
|
/// <summary>in var</summary>
|
||||||
|
ReactivePowerPositiveL2,
|
||||||
|
|
||||||
|
/// <summary>in varh</summary>
|
||||||
|
ReactiveEnergyPositiveL2,
|
||||||
|
|
||||||
|
/// <summary>in var</summary>
|
||||||
|
ReactivePowerNegativeL2,
|
||||||
|
|
||||||
|
/// <summary>in varh</summary>
|
||||||
|
ReactiveEnergyNegativeL2,
|
||||||
|
|
||||||
|
/// <summary>in VA</summary>
|
||||||
|
ApparentPowerPositiveL2,
|
||||||
|
|
||||||
|
/// <summary>in VAh</summary>
|
||||||
|
ApparentEnergyPositiveL2,
|
||||||
|
|
||||||
|
/// <summary>in VA</summary>
|
||||||
|
ApparentPowerNegativeL2,
|
||||||
|
|
||||||
|
/// <summary>in VAh</summary>
|
||||||
|
ApparentEnergyNegativeL2,
|
||||||
|
|
||||||
|
/// <summary>in A</summary>
|
||||||
|
CurrentL2,
|
||||||
|
|
||||||
|
/// <summary>in V</summary>
|
||||||
|
VoltageL2,
|
||||||
|
|
||||||
|
/// <summary>in -</summary>
|
||||||
|
PowerFactorL2,
|
||||||
|
|
||||||
|
/// <summary>in W</summary>
|
||||||
|
ActivePowerPositiveL3,
|
||||||
|
|
||||||
|
/// <summary>in Wh</summary>
|
||||||
|
ActiveEnergyPositiveL3,
|
||||||
|
|
||||||
|
/// <summary>in W</summary>
|
||||||
|
ActivePowerNegativeL3,
|
||||||
|
|
||||||
|
/// <summary>in Wh</summary>
|
||||||
|
ActiveEnergyNegativeL3,
|
||||||
|
|
||||||
|
/// <summary>in var</summary>
|
||||||
|
ReactivePowerPositiveL3,
|
||||||
|
|
||||||
|
/// <summary>in varh</summary>
|
||||||
|
ReactiveEnergyPositiveL3,
|
||||||
|
|
||||||
|
/// <summary>in var</summary>
|
||||||
|
ReactivePowerNegativeL3,
|
||||||
|
|
||||||
|
/// <summary>in varh</summary>
|
||||||
|
ReactiveEnergyNegativeL3,
|
||||||
|
|
||||||
|
/// <summary>in VA</summary>
|
||||||
|
ApparentPowerPositiveL3,
|
||||||
|
|
||||||
|
/// <summary>in VAh</summary>
|
||||||
|
ApparentEnergyPositiveL3,
|
||||||
|
|
||||||
|
/// <summary>in VA</summary>
|
||||||
|
ApparentPowerNegativeL3,
|
||||||
|
|
||||||
|
/// <summary>in VAh</summary>
|
||||||
|
ApparentEnergyNegativeL3,
|
||||||
|
|
||||||
|
/// <summary>in A</summary>
|
||||||
|
CurrentL3,
|
||||||
|
|
||||||
|
/// <summary>in V</summary>
|
||||||
|
VoltageL3,
|
||||||
|
|
||||||
|
/// <summary>in -</summary>
|
||||||
|
PowerFactorL3,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
using MQTTnet;
|
using MQTTnet;
|
||||||
using MQTTnet.Client;
|
using MQTTnet.Client;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using TestApp.Configuration;
|
|
||||||
|
|
||||||
namespace TestApp
|
namespace TestApp
|
||||||
{
|
{
|
||||||
@@ -79,67 +78,75 @@ namespace TestApp
|
|||||||
return factor * value;
|
return factor * value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double GetValue(ProcessVariable processVariable) {
|
public (double I1, double I2, double I3) GetCurrents() {
|
||||||
return processVariable switch {
|
return (
|
||||||
ProcessVariable.ActivePowerPositive => GetValue(1099528667391UL, 0.001),
|
GetValue(EMVariable.CurrentL1),
|
||||||
ProcessVariable.ActiveEnergyPositive => GetValue(1099528929535UL, 0.001),
|
GetValue(EMVariable.CurrentL2),
|
||||||
ProcessVariable.ActivePowerNegative => GetValue(1099545444607UL, 0.001),
|
GetValue(EMVariable.CurrentL3)
|
||||||
ProcessVariable.ActiveEnergyNegative => GetValue(1099545706751UL, 0.001),
|
);
|
||||||
ProcessVariable.ReactivePowerPositive => GetValue(1099562221823UL, 0.001),
|
}
|
||||||
ProcessVariable.ReactiveEnergyPositive => GetValue(1099562483967UL, 0.001),
|
|
||||||
ProcessVariable.ReactivePowerNegative => GetValue(1099578999039UL, 0.001),
|
public double GetValue(EMVariable variable) {
|
||||||
ProcessVariable.ReactiveEnergyNegative => GetValue(1099579261183UL, 0.001),
|
return variable switch {
|
||||||
ProcessVariable.ApparentPowerPositive => GetValue(1099662885119UL, 0.001),
|
EMVariable.ActivePowerPositive => GetValue(1099528667391UL, 0.001),
|
||||||
ProcessVariable.ApparentEnergyPositive => GetValue(1099663147263UL, 0.001),
|
EMVariable.ActiveEnergyPositive => GetValue(1099528929535UL, 0.001),
|
||||||
ProcessVariable.ApparentPowerNegative => GetValue(1099679662335UL, 0.001),
|
EMVariable.ActivePowerNegative => GetValue(1099545444607UL, 0.001),
|
||||||
ProcessVariable.ApparentEnergyNegative => GetValue(1099679924479UL, 0.001),
|
EMVariable.ActiveEnergyNegative => GetValue(1099545706751UL, 0.001),
|
||||||
ProcessVariable.PowerFactor => GetValue(1099729993983UL, 0.001),
|
EMVariable.ReactivePowerPositive => GetValue(1099562221823UL, 0.001),
|
||||||
ProcessVariable.SupplyFrequency => GetValue(1099746771199UL, 0.001),
|
EMVariable.ReactiveEnergyPositive => GetValue(1099562483967UL, 0.001),
|
||||||
ProcessVariable.ActivePowerPositiveL1 => GetValue(1099864211711UL, 0.001),
|
EMVariable.ReactivePowerNegative => GetValue(1099578999039UL, 0.001),
|
||||||
ProcessVariable.ActiveEnergyPositiveL1 => GetValue(1099864473855UL, 0.001),
|
EMVariable.ReactiveEnergyNegative => GetValue(1099579261183UL, 0.001),
|
||||||
ProcessVariable.ActivePowerNegativeL1 => GetValue(1099880988927UL, 0.001),
|
EMVariable.ApparentPowerPositive => GetValue(1099662885119UL, 0.001),
|
||||||
ProcessVariable.ActiveEnergyNegativeL1 => GetValue(1099881251071UL, 0.001),
|
EMVariable.ApparentEnergyPositive => GetValue(1099663147263UL, 0.001),
|
||||||
ProcessVariable.ReactivePowerPositiveL1 => GetValue(1099897766143UL, 0.001),
|
EMVariable.ApparentPowerNegative => GetValue(1099679662335UL, 0.001),
|
||||||
ProcessVariable.ReactiveEnergyPositiveL1 => GetValue(1099898028287UL, 0.001),
|
EMVariable.ApparentEnergyNegative => GetValue(1099679924479UL, 0.001),
|
||||||
ProcessVariable.ReactivePowerNegativeL1 => GetValue(1099914543359UL, 0.001),
|
EMVariable.PowerFactor => GetValue(1099729993983UL, 0.001),
|
||||||
ProcessVariable.ReactiveEnergyNegativeL1 => GetValue(1099914805503UL, 0.001),
|
EMVariable.SupplyFrequency => GetValue(1099746771199UL, 0.001),
|
||||||
ProcessVariable.ApparentPowerPositiveL1 => GetValue(1099998429439UL, 0.001),
|
EMVariable.ActivePowerPositiveL1 => GetValue(1099864211711UL, 0.001),
|
||||||
ProcessVariable.ApparentEnergyPositiveL1 => GetValue(1099998691583UL, 0.001),
|
EMVariable.ActiveEnergyPositiveL1 => GetValue(1099864473855UL, 0.001),
|
||||||
ProcessVariable.ApparentPowerNegativeL1 => GetValue(1100015206655UL, 0.001),
|
EMVariable.ActivePowerNegativeL1 => GetValue(1099880988927UL, 0.001),
|
||||||
ProcessVariable.ApparentEnergyNegativeL1 => GetValue(1100015468799UL, 0.001),
|
EMVariable.ActiveEnergyNegativeL1 => GetValue(1099881251071UL, 0.001),
|
||||||
ProcessVariable.CurrentL1 => GetValue(1100031983871UL, 0.001),
|
EMVariable.ReactivePowerPositiveL1 => GetValue(1099897766143UL, 0.001),
|
||||||
ProcessVariable.VoltageL1 => GetValue(1100048761087UL, 0.001),
|
EMVariable.ReactiveEnergyPositiveL1 => GetValue(1099898028287UL, 0.001),
|
||||||
ProcessVariable.PowerFactorL1 => GetValue(1100065538303UL, 0.001),
|
EMVariable.ReactivePowerNegativeL1 => GetValue(1099914543359UL, 0.001),
|
||||||
ProcessVariable.ActivePowerPositiveL2 => GetValue(1100199756031UL, 0.001),
|
EMVariable.ReactiveEnergyNegativeL1 => GetValue(1099914805503UL, 0.001),
|
||||||
ProcessVariable.ActiveEnergyPositiveL2 => GetValue(1100200018175UL, 0.001),
|
EMVariable.ApparentPowerPositiveL1 => GetValue(1099998429439UL, 0.001),
|
||||||
ProcessVariable.ActivePowerNegativeL2 => GetValue(1100216533247UL, 0.001),
|
EMVariable.ApparentEnergyPositiveL1 => GetValue(1099998691583UL, 0.001),
|
||||||
ProcessVariable.ActiveEnergyNegativeL2 => GetValue(1100216795391UL, 0.001),
|
EMVariable.ApparentPowerNegativeL1 => GetValue(1100015206655UL, 0.001),
|
||||||
ProcessVariable.ReactivePowerPositiveL2 => GetValue(1100233310463UL, 0.001),
|
EMVariable.ApparentEnergyNegativeL1 => GetValue(1100015468799UL, 0.001),
|
||||||
ProcessVariable.ReactiveEnergyPositiveL2 => GetValue(1100233572607UL, 0.001),
|
EMVariable.CurrentL1 => GetValue(1100031983871UL, 0.001),
|
||||||
ProcessVariable.ReactivePowerNegativeL2 => GetValue(1100250087679UL, 0.001),
|
EMVariable.VoltageL1 => GetValue(1100048761087UL, 0.001),
|
||||||
ProcessVariable.ReactiveEnergyNegativeL2 => GetValue(1100250349823UL, 0.001),
|
EMVariable.PowerFactorL1 => GetValue(1100065538303UL, 0.001),
|
||||||
ProcessVariable.ApparentPowerPositiveL2 => GetValue(1100333973759UL, 0.001),
|
EMVariable.ActivePowerPositiveL2 => GetValue(1100199756031UL, 0.001),
|
||||||
ProcessVariable.ApparentEnergyPositiveL2 => GetValue(1100334235903UL, 0.001),
|
EMVariable.ActiveEnergyPositiveL2 => GetValue(1100200018175UL, 0.001),
|
||||||
ProcessVariable.ApparentPowerNegativeL2 => GetValue(1100350750975UL, 0.001),
|
EMVariable.ActivePowerNegativeL2 => GetValue(1100216533247UL, 0.001),
|
||||||
ProcessVariable.ApparentEnergyNegativeL2 => GetValue(1100351013119UL, 0.001),
|
EMVariable.ActiveEnergyNegativeL2 => GetValue(1100216795391UL, 0.001),
|
||||||
ProcessVariable.CurrentL2 => GetValue(1100367528191UL, 0.001),
|
EMVariable.ReactivePowerPositiveL2 => GetValue(1100233310463UL, 0.001),
|
||||||
ProcessVariable.VoltageL2 => GetValue(1100384305407UL, 0.001),
|
EMVariable.ReactiveEnergyPositiveL2 => GetValue(1100233572607UL, 0.001),
|
||||||
ProcessVariable.PowerFactorL2 => GetValue(1100401082623UL, 0.001),
|
EMVariable.ReactivePowerNegativeL2 => GetValue(1100250087679UL, 0.001),
|
||||||
ProcessVariable.ActivePowerPositiveL3 => GetValue(1100535300351UL, 0.001),
|
EMVariable.ReactiveEnergyNegativeL2 => GetValue(1100250349823UL, 0.001),
|
||||||
ProcessVariable.ActiveEnergyPositiveL3 => GetValue(1100535562495UL, 0.001),
|
EMVariable.ApparentPowerPositiveL2 => GetValue(1100333973759UL, 0.001),
|
||||||
ProcessVariable.ActivePowerNegativeL3 => GetValue(1100552077567UL, 0.001),
|
EMVariable.ApparentEnergyPositiveL2 => GetValue(1100334235903UL, 0.001),
|
||||||
ProcessVariable.ActiveEnergyNegativeL3 => GetValue(1100552339711UL, 0.001),
|
EMVariable.ApparentPowerNegativeL2 => GetValue(1100350750975UL, 0.001),
|
||||||
ProcessVariable.ReactivePowerPositiveL3 => GetValue(1100568854783UL, 0.001),
|
EMVariable.ApparentEnergyNegativeL2 => GetValue(1100351013119UL, 0.001),
|
||||||
ProcessVariable.ReactiveEnergyPositiveL3 => GetValue(1100569116927UL, 0.001),
|
EMVariable.CurrentL2 => GetValue(1100367528191UL, 0.001),
|
||||||
ProcessVariable.ReactivePowerNegativeL3 => GetValue(1100585631999UL, 0.001),
|
EMVariable.VoltageL2 => GetValue(1100384305407UL, 0.001),
|
||||||
ProcessVariable.ReactiveEnergyNegativeL3 => GetValue(1100585894143UL, 0.001),
|
EMVariable.PowerFactorL2 => GetValue(1100401082623UL, 0.001),
|
||||||
ProcessVariable.ApparentPowerPositiveL3 => GetValue(1100669518079UL, 0.001),
|
EMVariable.ActivePowerPositiveL3 => GetValue(1100535300351UL, 0.001),
|
||||||
ProcessVariable.ApparentEnergyPositiveL3 => GetValue(1100669780223UL, 0.001),
|
EMVariable.ActiveEnergyPositiveL3 => GetValue(1100535562495UL, 0.001),
|
||||||
ProcessVariable.ApparentPowerNegativeL3 => GetValue(1100686295295UL, 0.001),
|
EMVariable.ActivePowerNegativeL3 => GetValue(1100552077567UL, 0.001),
|
||||||
ProcessVariable.ApparentEnergyNegativeL3 => GetValue(1100686557439UL, 0.001),
|
EMVariable.ActiveEnergyNegativeL3 => GetValue(1100552339711UL, 0.001),
|
||||||
ProcessVariable.CurrentL3 => GetValue(1100703072511UL, 0.001),
|
EMVariable.ReactivePowerPositiveL3 => GetValue(1100568854783UL, 0.001),
|
||||||
ProcessVariable.VoltageL3 => GetValue(1100719849727UL, 0.001),
|
EMVariable.ReactiveEnergyPositiveL3 => GetValue(1100569116927UL, 0.001),
|
||||||
ProcessVariable.PowerFactorL3 => GetValue(1100736626943UL, 0.001),
|
EMVariable.ReactivePowerNegativeL3 => GetValue(1100585631999UL, 0.001),
|
||||||
|
EMVariable.ReactiveEnergyNegativeL3 => GetValue(1100585894143UL, 0.001),
|
||||||
|
EMVariable.ApparentPowerPositiveL3 => GetValue(1100669518079UL, 0.001),
|
||||||
|
EMVariable.ApparentEnergyPositiveL3 => GetValue(1100669780223UL, 0.001),
|
||||||
|
EMVariable.ApparentPowerNegativeL3 => GetValue(1100686295295UL, 0.001),
|
||||||
|
EMVariable.ApparentEnergyNegativeL3 => GetValue(1100686557439UL, 0.001),
|
||||||
|
EMVariable.CurrentL3 => GetValue(1100703072511UL, 0.001),
|
||||||
|
EMVariable.VoltageL3 => GetValue(1100719849727UL, 0.001),
|
||||||
|
EMVariable.PowerFactorL3 => GetValue(1100736626943UL, 0.001),
|
||||||
_ => double.NaN,
|
_ => double.NaN,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using TestApp.Configuration;
|
using TestApp.Configuration;
|
||||||
using TestApp.Driver;
|
using TestApp.Driver;
|
||||||
|
|
||||||
@@ -9,8 +10,7 @@ namespace TestApp
|
|||||||
private static ConfigurationManager _ConfigurationManager;
|
private static ConfigurationManager _ConfigurationManager;
|
||||||
private static IChargerDriver? _Driver;
|
private static IChargerDriver? _Driver;
|
||||||
private static EnergyManager _EnergyManager;
|
private static EnergyManager _EnergyManager;
|
||||||
private static ProcessVariable _ProcessVariable;
|
private static CurrentLimitter _CurrentLimitter;
|
||||||
private static PidController _PidController;
|
|
||||||
|
|
||||||
|
|
||||||
static async Task Main(string[] args)
|
static async Task Main(string[] args)
|
||||||
@@ -26,17 +26,24 @@ namespace TestApp
|
|||||||
}
|
}
|
||||||
|
|
||||||
_EnergyManager = await EnergyManager.Create();
|
_EnergyManager = await EnergyManager.Create();
|
||||||
|
_CurrentLimitter = new CurrentLimitter(_ConfigurationManager, _EnergyManager);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// TODO I1, I2, I3 von Wallbox mit I1-3 von Zähler per Kombinatorik max vom Haus ausrechnen
|
if (_Driver is null) {
|
||||||
// newLoadingCurrent = maxSicherung - maxHaus
|
Thread.Sleep(1000);
|
||||||
var measurement = _EnergyManager.GetValue(_ProcessVariable);
|
continue;
|
||||||
var newLoadingCurrent = _PidController.Update(measurement);
|
}
|
||||||
//if (newLoadingCurrent < 6) { newLoadingCurrent = 0; }
|
|
||||||
_Driver?.SetLoadingCurrent(newLoadingCurrent);
|
var newCurrent = double.MaxValue;
|
||||||
|
if (_ConfigurationManager.Settings.Mode == 2) {
|
||||||
|
newCurrent = GetMode2LoadingCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
newCurrent = _CurrentLimitter.GetLimitedCurrent(_Driver, newCurrent);
|
||||||
|
_Driver?.SetLoadingCurrent(newCurrent);
|
||||||
} catch (Exception ex)
|
} catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Error in main loop: {ex.Message}");
|
Console.WriteLine($"Error in main loop: {ex.Message}");
|
||||||
@@ -45,10 +52,26 @@ namespace TestApp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static double GetMode2LoadingCurrent()
|
||||||
|
{
|
||||||
|
var minNegativePower = _ConfigurationManager.Settings.MinNegativePower ?? Settings.DEFAULT_MIN_NEGATIVE_POWER;
|
||||||
|
|
||||||
|
var negativePower = _EnergyManager.GetValue(EMVariable.ActivePowerNegative);
|
||||||
|
|
||||||
|
if (negativePower < minNegativePower) { return 0; }
|
||||||
|
|
||||||
|
var sparePower = negativePower - minNegativePower;
|
||||||
|
|
||||||
|
var i1 = sparePower / _EnergyManager.GetValue(EMVariable.VoltageL1);
|
||||||
|
var i2 = sparePower / _EnergyManager.GetValue(EMVariable.VoltageL2);
|
||||||
|
var i3 = sparePower / _EnergyManager.GetValue(EMVariable.VoltageL3);
|
||||||
|
|
||||||
|
return Math.Min(Math.Min(i1, i2), i3);
|
||||||
|
}
|
||||||
|
|
||||||
private static void OnSettingsChanged(object? sender, Settings settings)
|
private static void OnSettingsChanged(object? sender, Settings settings)
|
||||||
{
|
{
|
||||||
UpdateDriverSettings(settings);
|
UpdateDriverSettings(settings);
|
||||||
UpdateControllerSettings(settings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UpdateDriverSettings(Settings settings) {
|
private static void UpdateDriverSettings(Settings settings) {
|
||||||
@@ -84,35 +107,5 @@ namespace TestApp
|
|||||||
_Driver.Port = settings.ChargerPort ?? Settings.DEFAULT_CHARGER_PORT;
|
_Driver.Port = settings.ChargerPort ?? Settings.DEFAULT_CHARGER_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UpdateControllerSettings(Settings settings)
|
|
||||||
{
|
|
||||||
var allModeSettings = settings.ModeSettings ?? Array.Empty<ModeSettings>();
|
|
||||||
if (!allModeSettings.Any()) {
|
|
||||||
allModeSettings = new ModeSettings[]{
|
|
||||||
new ModeSettings() {
|
|
||||||
ProcessVariable = ProcessVariable.ActivePowerPositive,
|
|
||||||
SetPoint = 0,
|
|
||||||
PositivePid = new PidSetting(),
|
|
||||||
NegativePid = new PidSetting(),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var mode = settings.Mode;
|
|
||||||
if (mode < 0) { mode = 0; }
|
|
||||||
if (mode >= allModeSettings.Length) { mode = allModeSettings.Length - 1; }
|
|
||||||
|
|
||||||
var modeSetting = allModeSettings[mode];
|
|
||||||
|
|
||||||
if (_ProcessVariable != modeSetting.ProcessVariable)
|
|
||||||
{
|
|
||||||
_PidController = new PidController();
|
|
||||||
_ProcessVariable = modeSetting.ProcessVariable;
|
|
||||||
}
|
|
||||||
|
|
||||||
_PidController.SetPoint = modeSetting.SetPoint;
|
|
||||||
_PidController.PositiveSettings = modeSetting.PositivePid ?? new PidSetting();
|
|
||||||
_PidController.NegativeSettings = modeSetting.NegativePid ?? new PidSetting();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user