Innovenergy_trunk/csharp/App/SaliMax/src/System/Controller.cs

483 lines
13 KiB
C#

using InnovEnergy.App.SaliMax.Ess;
using InnovEnergy.App.SaliMax.SaliMaxRelays;
using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc;
using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc;
using static InnovEnergy.Lib.Devices.Trumpf.SystemControl.DataTypes.GridType;
namespace InnovEnergy.App.SaliMax.System;
public static class Controller
{
private static Int32 GetSystemState(this StatusRecord r)
{
var relays = r.Relays;
if (relays is null)
return 101; // Message = "Panic: relay device is not available!",
var acDcs = r.AcDc;
if (acDcs.NotAvailable())
return 102;
var k4 = acDcs.AllGridTied() ? 0
: acDcs.AllIsland() ? 1
: 4;
var k5 = acDcs.AllDisabled() ? 0
: acDcs.AllEnabled() ? 1
: 4;
if (k4 == 4 || k5 == 4)
return 103; //Message = "Panic: ACDCs have unequal grid types or power stage",
var nInverters = r.AcDc.Devices.Count;
var k1 = relays.K1GridBusIsConnectedToGrid ? 1 : 0;
var k2 = relays.K2IslandBusIsConnectedToGridBus ? 1 : 0;
var k3 = relays.K3InverterIsConnectedToIslandBus.Take(nInverters).Any(c => c) ? 1 : 0;
// states as defined in states excel sheet
return 1 * k1
+ 2 * k2
+ 4 * k3
+ 8 * k4
+ 16 * k5;
}
public static Boolean ControlSystemState(this StatusRecord s)
{
s.StateMachine.State = s.GetSystemState();
return s.StateMachine.State switch
{
0 => State0(s),
1 => State1(s),
3 => State3(s),
4 => State4(s),
6 => State6(s),
8 => State8(s),
9 => State9(s),
13 => State13(s),
19 => State19(s),
22 => State22(s),
23 => State23(s),
24 => State24(s),
28 => State28(s),
29 => State29(s),
101 => State101(s),
102 => State102(s),
103 => State103(s),
_ => UnknownState(s)
};
}
private static Boolean NotAvailable(this AcDcDevicesRecord acDcs)
{
return acDcs.SystemControl == null || acDcs.Devices.Count == 0;
}
private static Boolean State0(StatusRecord s)
{
s.StateMachine.Message = "Ac/Dc are off. Switching to Island Mode.";
s.DcDc.Disable();
s.AcDc.Disable();
s.AcDc.EnableIslandMode();
s.Relays.DisconnectIslandBusFromGrid();
return false;
// => 8
}
private static Boolean State9(StatusRecord s)
{
s.StateMachine.Message = "Ac/Dc are disconnected from Island Bus. Switching to GridTie Mode.";
s.DcDc.Disable();
s.AcDc.Disable();
s.AcDc.EnableGridTieMode();
s.Relays.DisconnectIslandBusFromGrid();
return false;
// => 1
}
private static Boolean State1(StatusRecord s)
{
s.StateMachine.Message = "Grid Tied mode active, closing k2";
s.DcDc.Disable();
s.AcDc.Disable();
s.AcDc.EnableGridTieMode();
s.Relays.ConnectIslandBusToGrid();
return false;
// => 3
}
private static Boolean State3(StatusRecord s)
{
s.StateMachine.Message = "K2 closed, Turning on Ac/Dc";
s.DcDc.Enable();
s.AcDc.Enable();
s.AcDc.EnableGridTieMode();
s.Relays.ConnectIslandBusToGrid();
return false;
// => 19
}
private static Boolean State13(StatusRecord s)
{
s.StateMachine.Message = "Ac/Dc are off. Waiting for them to disconnect from Island Bus.";
s.DcDc.Disable();
s.AcDc.Disable();
s.AcDc.EnableIslandMode();
s.Relays.DisconnectIslandBusFromGrid();
return true;
// => 9
}
private static Boolean State19(StatusRecord s)
{
s.StateMachine.Message = "Waiting for Ac/Dc to connect to Island Bus";
s.DcDc.Enable();
s.AcDc.Enable();
s.AcDc.EnableGridTieMode();
s.Relays.ConnectIslandBusToGrid();
return true;
// => 23
}
private static Boolean State23(StatusRecord s)
{
s.StateMachine.Message = "ESS";
s.DcDc.Enable();
s.AcDc.Enable();
s.AcDc.EnableGridTieMode();
s.EnableDcLinkGridTie();
s.Relays.ConnectIslandBusToGrid();
return true;
// => 22
}
private static Boolean State22(StatusRecord s)
{
s.StateMachine.Message = "K1 opened, switching inverters off";
s.DcDc.Disable();
s.AcDc.Disable();
s.AcDc.EnableGridTieMode();
s.Relays.ConnectIslandBusToGrid();
return true;
// => 6
}
private static Boolean State6(StatusRecord s)
{
s.StateMachine.Message = "Inverters are off, opening K2";
s.DcDc.Disable();
s.AcDc.Disable();
s.AcDc.EnableGridTieMode();
s.Relays.DisconnectIslandBusFromGrid();
return true;
// => 4
}
private static Boolean State4(StatusRecord s)
{
s.StateMachine.Message = "K2 is open, waiting K3 to open";
s.DcDc.Disable();
s.AcDc.Disable();
s.AcDc.EnableGridTieMode();
s.Relays.DisconnectIslandBusFromGrid();
return true;
// => 0
}
private static Boolean State8(StatusRecord s)
{
s.StateMachine.Message = "Ac/Dc are off and in Island Mode.";
s.DcDc.Enable();
s.AcDc.Enable();
s.AcDc.EnableIslandMode();
s.Relays.DisconnectIslandBusFromGrid();
return true;
// => 24
}
private static Boolean State28(StatusRecord s)
{
s.StateMachine.Message = "Island Mode";
s.DcDc.Enable();
s.AcDc.Enable();
s.AcDc.EnableIslandMode();
s.EnableDcLinkIslandMode();
s.Relays.DisconnectIslandBusFromGrid();
return false;
// => 29
}
private static Boolean State29(StatusRecord s)
{
s.StateMachine.Message = "K1 closed, Switching off Inverters and moving to grid tie";
s.DcDc.Disable();
s.AcDc.Disable();
s.AcDc.EnableIslandMode();
s.Relays.DisconnectIslandBusFromGrid();
return false;
// => 13
}
private static Boolean State24(StatusRecord s)
{
s.StateMachine.Message = "Inverter are on waiting for k3 to close";
s.DcDc.Enable();
s.AcDc.Enable();
s.AcDc.EnableIslandMode();
s.Relays.DisconnectIslandBusFromGrid();
return false;
// => 28
}
private static Boolean State101(StatusRecord s)
{
s.StateMachine.Message = "Relay device is not available";
return s.EnableSafeDefaults();
}
private static Boolean State102(StatusRecord s)
{
s.StateMachine.Message = "ACDCs not available";
return s.EnableSafeDefaults();
}
private static Boolean State103(StatusRecord s)
{
s.StateMachine.Message = "Panic: ACDCs have unequal grid types or PowerStage";
return s.EnableSafeDefaults();
}
// private static Boolean State104(StatusRecord s)
// {
// s.StateMachine.Message = "Panic: DCDCs not available";
// return s.EnableSafeDefaults();
// }
private static Boolean UnknownState(StatusRecord s)
{
// "Unknown System State"
return s.EnableSafeDefaults();
}
private static Boolean AllDisabled(this AcDcDevicesRecord acDcs)
{
return acDcs.Devices.All(d => !d.Control.PowerStageEnable);
}
private static Boolean AllEnabled(this AcDcDevicesRecord acDcs)
{
return acDcs.Devices.All(d => d.Control.PowerStageEnable);
}
private static Boolean AllTheSame(this AcDcDevicesRecord acDcs)
{
return acDcs.Devices
.Select(d => d.Control.PowerStageEnable)
.Distinct()
.Count() == 1;
}
private static Boolean AllGridTied(this AcDcDevicesRecord acDcs)
{
return acDcs.Devices.All(d => d.Status.ActiveGridType is GridTied380V60Hz)
|| acDcs.Devices.All(d => d.Status.ActiveGridType is GridTied400V50Hz)
|| acDcs.Devices.All(d => d.Status.ActiveGridType is GridTied480V60Hz);
}
private static Boolean AllIsland(this AcDcDevicesRecord acDcs)
{
return acDcs.Devices.All(d => d.Status.ActiveGridType is Island400V50Hz)
|| acDcs.Devices.All(d => d.Status.ActiveGridType is Island480V60Hz);
}
private static void ForAll<T>(this IEnumerable<T> ts, Action<T> action)
{
foreach (var t in ts)
action(t);
}
private static void Disable(this AcDcDevicesRecord acDc)
{
acDc.Devices
.Select(d => d.Control)
.ForAll(c => c.PowerStageEnable = false);
}
private static void Disable(this DcDcDevicesRecord dcDc)
{
// For Test purpose, The transition from island mode to grid tier and vis versa , may not need to disable Dc/Dc.
// This will keep the Dc link powered.
// dcDc.Devices
// .Select(d => d.Control)
// .ForAll(c => c.PowerStageEnable = false);
}
private static void Enable(this AcDcDevicesRecord acDc)
{
acDc.Devices
.Select(d => d.Control)
.ForAll(c => c.PowerStageEnable = true);
}
private static void Enable(this DcDcDevicesRecord dcDc)
{
dcDc.Devices
.Select(d => d.Control)
.ForAll(c => c.PowerStageEnable = true);
}
private static void EnableGridTieMode(this AcDcDevicesRecord acDc)
{
acDc.Devices
.Select(d => d.Control)
.ForAll(c => c.Ac.GridType = GridTied400V50Hz); // TODO: config grid type
}
private static void EnableIslandMode(this AcDcDevicesRecord acDc)
{
acDc.Devices
.Select(d => d.Control)
.ForAll(c => c.Ac.GridType = Island400V50Hz); // TODO: config grid type
}
// This is must be deleted , not needed anymore
private static void EnableDcLinkIslandMode(this StatusRecord s)
{
// // Dc Link Windows on AcDc +- 60
// s.Config.ReferenceDcLinkVoltageFromAcDc ;
// s.Config.MinDcLinkVoltageFromAcDc ;
// s.Config.MaxDcLinkVoltageFromAcDc ;
//
// // Dc Link Windows on DcDc +-55
// s.Config.ReferenceDcLinkVoltageFromDc = 750;
// s.Config.UpperDcLinkVoltageFromDc = 55;
// s.Config.LowerDcLinkVoltageFromDc = 55;
}
// This is must be deleted , not needed anymore
private static void EnableDcLinkGridTie(this StatusRecord s)
{
// Dc Link Windows on DcDc +-30
//s.Config.ReferenceDcLinkVoltageFromAcDc = 750;
//s.Config.MinDcLinkVoltageFromAcDc = 720;
//s.Config.MaxDcLinkVoltageFromAcDc = 780;
//
//// Dc Link Windows on DcDc +-20
//s.Config.ReferenceDcLinkVoltageFromDc = 750;
//s.Config.UpperDcLinkVoltageFromDc = 20;
//s.Config.LowerDcLinkVoltageFromDc = 20;
}
private static void DisconnectIslandBusFromGrid(this RelaysRecord? relays)
{
if (relays is not null)
relays.K2ConnectIslandBusToGridBus = false;
}
private static void ConnectIslandBusToGrid(this RelaysRecord? relays)
{
if (relays is not null)
relays.K2ConnectIslandBusToGridBus = true;
}
private static Boolean EnableSafeDefaults(this StatusRecord s)
{
// After some tests, the safe state is switch off inverter and keep the last state of K2 , Dc/Dc and Grid type to avoid conflict.
// s.DcDc.Disable();
s.AcDc.Disable();
// s.AcDc.EnableGridTieMode();
// s.Relays.DisconnectIslandBusFromGrid();
return false;
}
public static DcDcDevicesRecord ResetAlarms(this DcDcDevicesRecord dcDcStatus)
{
var sc = dcDcStatus.SystemControl;
if (sc is not null)
sc.ResetAlarmsAndWarnings = sc.Alarms.Any();
foreach (var d in dcDcStatus.Devices)
d.Control.ResetAlarmsAndWarnings = d.Status.Alarms.Any() || d.Status.Warnings.Any();
return dcDcStatus;
}
public static AcDcDevicesRecord ResetAlarms(this AcDcDevicesRecord acDcStatus)
{
var sc = acDcStatus.SystemControl;
if (sc is not null)
sc.ResetAlarmsAndWarnings = sc.Alarms.Any() || sc.Warnings.Any();
foreach (var d in acDcStatus.Devices)
d.Control.ResetAlarmsAndWarnings = d.Status.Alarms.Any() || d.Status.Warnings.Any();
return acDcStatus;
}
}