1433 lines
41 KiB
XML
1433 lines
41 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.12">
|
|
<POU Name="FB_PowerSupplySunspec" Id="{a826dd09-442c-45c5-8ae3-9b71f293003c}" SpecialFunc="None">
|
|
<Declaration><![CDATA[FUNCTION_BLOCK FB_PowerSupplySunspec
|
|
VAR_INPUT
|
|
sInverterIPAddr : STRING;
|
|
xEnable : BOOL;
|
|
rPower : REAL;
|
|
rReactivePower : REAL := 0.0;
|
|
xReset : BOOL;
|
|
rMaxBattPower : REAL := 40_000; // 24kW
|
|
END_VAR
|
|
VAR_OUTPUT
|
|
// Inverter active
|
|
xActive : BOOL;
|
|
|
|
// FB error
|
|
xError : BOOL;
|
|
|
|
// Heartbeat ok signal
|
|
xHeartbeatOk : BOOL := TRUE;
|
|
|
|
// Current inverter values
|
|
stCurrentValues : ST_SUNSPEC_CURRENT_VALUES;
|
|
END_VAR
|
|
VAR
|
|
// Current state
|
|
_iState : INT := 0;
|
|
|
|
// FB for reading Modbus holding registers
|
|
_fbReadRegister : FB_MBReadRegs;
|
|
|
|
// FB for writing Modbus holding registers
|
|
_fbWriteRegister : FB_MBWriteRegs;
|
|
|
|
// Timer for checking if the inverter started in a reasonable amount of time
|
|
_tonInverterStartup : TON;
|
|
|
|
// converter max power scaling factor
|
|
_iWMaxSF : INT;
|
|
|
|
// Unscaled converter max power
|
|
_iWMax : UINT;
|
|
|
|
// Scaled converter max power
|
|
_rWMax : REAL;
|
|
|
|
// Unscaled limit for converter power
|
|
_iWMaxLimPct : INT;
|
|
|
|
// Scaling factor for reactive power percent value
|
|
_iVarPctSF : INT;
|
|
|
|
// Reread set power limit
|
|
_iWMaxLimPctRead : INT;
|
|
_iWMaxLimPctReadScaled : REAL;
|
|
|
|
// Scaling factor for power limiting
|
|
_iWMaxLimPctSF : INT;
|
|
|
|
// Unscaled maximum power from type label
|
|
_iWRTGSF : INT;
|
|
|
|
// Scaling for maximum power from type label
|
|
_rWRTGScaling : REAL;
|
|
|
|
// Current state of the inverters internal statemachine
|
|
_uiInverterState : UINT;
|
|
|
|
// Last written power to the inverter
|
|
_rOldPower : REAL;
|
|
|
|
// Value to enable or dissable the Power limiting feature
|
|
_uiMaxLimEn : UINT;
|
|
|
|
// Value for commanding the target state of the inverter
|
|
_uiPCSSetOperation : UINT;
|
|
|
|
// Maximum reactive power
|
|
_iMaxPowerVar : INT := 0;
|
|
|
|
// Enable max reactive power percent controller
|
|
_iMaxVarPct : INt := 1;
|
|
|
|
// Holds the state number in which an error occured
|
|
_iErrorInState : INT;
|
|
|
|
// Time for polling for current dc values and check for inverter error
|
|
_timPollingDelay : TIME := T#500MS;
|
|
|
|
// Timer for polling of current values
|
|
_tonPollingTimer : TON;
|
|
|
|
// Current DC values (DCA, DCA_SF, DCV, DCV_SF, DCW, DCW_SF) in word array for efficient modbus reading
|
|
_awCurrentDCValues : ARRAY[0..5] OF WORD;
|
|
|
|
// Current AC values (W, W_SF, Hz, Hz_SF, VA, VA_SF, VAr, VAr_SF, PF, PF_SF) in word array for efficient modbus reading
|
|
_awCurrentACValues : ARRAY[0..21] OF WORD;
|
|
|
|
// Inverter error bits
|
|
_dwErrorBits : DWORD;
|
|
|
|
// Inverter reset errors command
|
|
_uiResetInverter : UINT := 1;
|
|
|
|
// PLC -> Inverter heartbeat
|
|
_uiPLCToInverterCounter : UINT;
|
|
|
|
// Inverter -> PLC heartbeat
|
|
_uiInverterToPLCCounter : UINT;
|
|
_uiInverterToPLCCounterOld : UINT;
|
|
|
|
// Flag to check if inverter has incremented the heartbeat counter
|
|
_xInverterHBCounterIncremented : BOOL := TRUE;
|
|
|
|
// Inverter alarm
|
|
_fbErrorInverterAlarm : Fb_TcAlarm;
|
|
|
|
// Heartbeat timeout
|
|
_tonHeartbeatTimeout : TON;
|
|
|
|
_sName : STRING;
|
|
|
|
END_VAR
|
|
VAR CONSTANT
|
|
// Inverter statemachine status register
|
|
// Size 1, enum16 (Range = 0 .. 65534, Not implemented = 0xFFFF)
|
|
STATUS_REGISTER : WORD := 40108;
|
|
|
|
// Throttled power register
|
|
// Size 1, int16 (Range = -32767 .. 32767, Not implemented 0x8000)
|
|
W_MAX_LIM_PCT_REGISTER : WORD := 40187;
|
|
|
|
// Throttled power register scaling factor
|
|
// Size 1, sunssf (int16) (Range = -10 .. 10, Not implemented 0x8000)
|
|
W_MAX_LIM_PCT_SF_REGISTER : WORD := 40205;
|
|
|
|
// Control register to enable and dissable if the power throttleing should be active
|
|
// Size1, enum16 (Range = 0 .. 65534, Not implemented = 0xFFFF)
|
|
W_MAX_LIM_EN_REGISTER : WORD := 40191;
|
|
|
|
// Register to reset latched alarms in the inverter
|
|
// Size 1, uint16 (Range = 0 .. 65534, Not implemented = 0xFFFF)
|
|
PCS_ALARM_RESET_REGISTER : WORD := 40230;
|
|
|
|
// Control register to set the target state of the inverters state machine
|
|
// Size 1, enum16 (Range = 0 .. 65534, Not implemented = 0xFFFF)
|
|
PCS_SET_OPERATION_REGISTER : WORD := 40231;
|
|
|
|
// Maximum inverter output power
|
|
// Size 1, uint16 (Range = 0 .. 65534, Not implemented = 0xFFFF)
|
|
W_MAX_REGISTER : WORD := 40152;
|
|
|
|
// Maximum inverter output power scaling factor
|
|
// Size 1, sunssf (int16) (Range = -10 .. 10, Not implemented 0x8000)
|
|
W_MAX_SF_REGISTER : WORD := 40172;
|
|
|
|
// Maximum inverter output power from type label
|
|
// Size 1, uint16 (Range = 0 .. 65534, Not implemented = 0xFFFF)
|
|
W_RTG_REGISTER : WORD := 40125;
|
|
|
|
// Maximum inverter output power from type label scaling factor
|
|
// Size 1, sunssf (int16) (Range = -10 .. 10, Not implemented 0x8000)
|
|
W_RTG_SF_REGISTER : WORD := 40126;
|
|
|
|
// Start of register with the current dc values
|
|
// Size 4
|
|
DC_VALUES_START_REGISTER : WORD := 40097;
|
|
|
|
// Start of register with the current ac values
|
|
// SIZE 10
|
|
AC_VALUES_START_REGISTER : WORD := 40072;
|
|
|
|
// Power factor register in cosine of angle
|
|
// Size 1, int16 (Range = -32767 .. 32767, Not implemented 0x8000)
|
|
//OUT_PF_SET : WORD := 40192;
|
|
|
|
// Enable power factor controller
|
|
// Size 1, enum16 (Range = 0 .. 65534, Not implemented = 0xFFFF)
|
|
//OUT_PF_SET_ENA : WORD := 40196;
|
|
|
|
// Reactive power in percent of W_Max
|
|
// Size 1, int16 (Range = -32767 .. 32767, Not implemented 0x8000)
|
|
VAR_W_MAX_PCT : WORD := 40197;
|
|
|
|
// Enable percent limited var controller
|
|
// Size 1, enum16 (Range = 0 .. 65534, Not implemented = 0xFFFF)
|
|
VAR_PCT_ENA : WORD := 40204;
|
|
|
|
// Register for reactive power percent scaling factor
|
|
// Size 1, sunssf (int16) (Range = -10 .. 10, Not implemented 0x8000)
|
|
VAR_PCT_SF : WORD := 40207;
|
|
|
|
// Error bits register
|
|
// Size 2
|
|
EVT_1_REGISTER : WORD := 40110;
|
|
|
|
// PLC -> Inverter Heartbeat register
|
|
CONTROLLER_HB : WORD := 40229;
|
|
|
|
// Inverter -> PLC heartbeat register
|
|
PCS_HB : WORD := 40228;
|
|
END_VAR
|
|
]]></Declaration>
|
|
<Implementation>
|
|
<ST><![CDATA[// Clamp rPower to maximum allowed power
|
|
IF (rPower > rMaxBattPower) THEN
|
|
rPower := rMaxBattPower;
|
|
END_IF
|
|
|
|
IF (rPower < -rMaxBattPower) THEN
|
|
rPower := -rMaxBattPower;
|
|
END_IF
|
|
|
|
// State machine
|
|
CASE _iState OF
|
|
|
|
0: // Off
|
|
// If enable and INTLK Ok
|
|
IF xEnable THEN
|
|
_iState := 10;
|
|
_tonPollingTimer(IN := FALSE, PT := _timPollingDelay);
|
|
ELSE
|
|
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
|
|
END_IF
|
|
|
|
IF _tonPollingTimer.Q THEN
|
|
_tonPollingTimer(IN := FALSE, PT := _timPollingDelay);
|
|
_iState := 1;
|
|
END_IF
|
|
|
|
|
|
1: // Read inverter status
|
|
_fbReadRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= STATUS_REGISTER,
|
|
cbLength:= SIZEOF(_uiInverterState),
|
|
pDestAddr:= ADR(_uiInverterState),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
cbRead=> );
|
|
|
|
// Check if reading mudbus register is done
|
|
IF NOT _fbReadRegister.bBusy THEN
|
|
IF NOT _fbReadRegister.bError THEN
|
|
_iState := 2;
|
|
ELSE
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbReadRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
2: // IF inverter is not in STANDYB(8) STATE, send command to shutdown inverter
|
|
IF (_uiInverterState = 8) OR (_uiInverterState = 1) OR (_uiInverterState = 7) THEN
|
|
_iState := 3;
|
|
ELSE
|
|
_uiPCSSetOperation := 3;
|
|
_iState := 200;
|
|
END_IF
|
|
|
|
|
|
3: // Read current DC values
|
|
_iErrorInState := _iState;
|
|
_fbReadRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 6,
|
|
nMBAddr:= DC_VALUES_START_REGISTER,
|
|
cbLength:= SIZEOF(_awCurrentDCValues),
|
|
pDestAddr:= ADR(_awCurrentDCValues),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
cbRead=> );
|
|
|
|
// Check if reading mudbus register is done
|
|
IF NOT _fbReadRegister.bBusy THEN
|
|
// If there was no error and the converter has no error continue
|
|
IF NOT _fbReadRegister.bError THEN
|
|
_iState := 4;
|
|
stCurrentValues.rActDCCurrent := LREAL_TO_REAL(WORD_TO_INT(_awCurrentDCValues[0]) * EXPT(10,WORD_TO_INT(_awCurrentDCValues[1])));
|
|
stCurrentValues.rActDCVoltage := LREAL_TO_REAL(WORD_TO_UINT(_awCurrentDCValues[2]) * EXPT(10,WORD_TO_INT(_awCurrentDCValues[3])));
|
|
stCurrentValues.rActDCPower := LREAL_TO_REAL(WORD_TO_INT(_awCurrentDCValues[4]) * EXPT(10,WORD_TO_INT(_awCurrentDCValues[5])));
|
|
ELSE
|
|
// Read error register
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbReadRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
4: // Read current ac values
|
|
_iErrorInState := _iState;
|
|
_fbReadRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 22,
|
|
nMBAddr:= AC_VALUES_START_REGISTER,
|
|
cbLength:= SIZEOF(_awCurrentACValues),
|
|
pDestAddr:= ADR(_awCurrentACValues),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
cbRead=> );
|
|
|
|
// Check if reading mudbus register is done
|
|
IF NOT _fbReadRegister.bBusy THEN
|
|
// If there was no error and the converter has no error continue
|
|
IF NOT _fbReadRegister.bError THEN
|
|
// Go back to polling state
|
|
_iState := 5;
|
|
stCurrentValues.rActACCurrent := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[0]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[4])));
|
|
stCurrentValues.rActtACPhaseACurrent := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[1]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[4])));
|
|
stCurrentValues.rActtACPhaseBCurrent := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[2]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[4])));
|
|
stCurrentValues.rActtACPhaseCCurrent := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[3]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[4])));
|
|
stCurrentValues.rActACPower := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[12]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[13])));
|
|
stCurrentValues.rActACFreq := LREAL_TO_REAL(WORD_TO_UINT(_awCurrentACValues[14]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[15])));
|
|
stCurrentValues.rActApparentPower := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[16]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[17])));
|
|
stCurrentValues.rActReactivePower := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[18]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[19])));
|
|
stCurrentValues.rActPowerFactor := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[20]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[21])));
|
|
ELSE
|
|
// Read error register
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbReadRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
5: // Send heartbeat signal
|
|
_uiPLCToInverterCounter := _uiPLCToInverterCounter + 1;
|
|
_iErrorInState := _iState;
|
|
_fbWriteRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= CONTROLLER_HB,
|
|
cbLength:= SIZEOF(_uiPLCToInverterCounter),
|
|
pSrcAddr:= ADR(_uiPLCToInverterCounter),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> );
|
|
|
|
// If writing modbus register is done
|
|
IF NOT _fbWriteRegister.bBusy THEN
|
|
// And there is no error, then continue
|
|
IF NOT _fbWriteRegister.bError THEN
|
|
_iState := 6;
|
|
ELSE
|
|
xError := TRUE;
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbWriteRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
6: // Check heartbeat signal
|
|
_fbReadRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= PCS_HB,
|
|
cbLength:= SIZEOF(_uiInverterToPLCCounter),
|
|
pDestAddr:= ADR(_uiInverterToPLCCounter),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
cbRead=> );
|
|
|
|
IF NOT _fbReadRegister.bBusy THEN
|
|
IF (NOT _fbReadRegister.bError) THEN
|
|
// Check if counter has been incremented by the inverter
|
|
IF (_uiInverterToPLCCounter - _uiInverterToPLCCounterOld) > 0 THEN
|
|
_xInverterHBCounterIncremented := TRUE;
|
|
|
|
// Safe old value
|
|
_uiInverterToPLCCounterOld := _uiInverterToPLCCounter;
|
|
ELSE
|
|
_xInverterHBCounterIncremented := FALSE;
|
|
END_IF
|
|
|
|
_iState := 0;
|
|
ELSE
|
|
xError := TRUE;
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
|
|
_fbReadRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
10: // Wait for inverter to be online and in state STANDBY(8)
|
|
_fbReadRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= STATUS_REGISTER,
|
|
cbLength:= SIZEOF(_uiInverterState),
|
|
pDestAddr:= ADR(_uiInverterState),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
cbRead=> );
|
|
|
|
// Check if reading mudbus register is done
|
|
IF NOT _fbReadRegister.bBusy THEN
|
|
// If there was no error and the state is STANDBY(8) then continue
|
|
IF NOT _fbReadRegister.bError AND _uiInverterState = 8 THEN
|
|
_iState := 20;
|
|
END_IF
|
|
|
|
// If the inverter is not ready wait some time before polling again
|
|
IF NOT _fbReadRegister.bError AND _uiInverterState <> 8 THEN
|
|
_iState := 15;
|
|
END_IF
|
|
|
|
_fbReadRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
// If not enable, go back to idle
|
|
IF NOT xEnable THEN
|
|
_fbReadRegister(bExecute := FALSE);
|
|
_iState := 0;
|
|
END_IF
|
|
|
|
|
|
15: // Delay polling inverter ready
|
|
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
|
|
IF _tonPollingTimer.Q THEN
|
|
_tonPollingTimer(IN := FALSE);
|
|
_iState := 10;
|
|
END_IF
|
|
|
|
// If not enable, go back to idle
|
|
IF NOT xEnable THEN
|
|
_tonPollingTimer(IN := FALSE);
|
|
_iState := 0;
|
|
END_IF
|
|
|
|
|
|
20: // Read inverter max power scaling
|
|
_iErrorInState := _iState;
|
|
_fbReadRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= W_MAX_SF_REGISTER,
|
|
cbLength:= SIZEOF(_iWMaxSF),
|
|
pDestAddr:= ADR(_iWMaxSF),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
cbRead=> );
|
|
|
|
// Check if reading mudbus register is done
|
|
IF NOT _fbReadRegister.bBusy THEN
|
|
// If there was no error then continue
|
|
IF NOT _fbReadRegister.bError THEN
|
|
_iState := 25;
|
|
// Check for valid value
|
|
IF (_iWMaxSF < -10) OR (_iWMaxSF > 10) OR (_iWMaxSF = 16#8000) THEN
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
ELSE
|
|
xError := TRUE;
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbReadRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
25: // Read inverter Max power limit scaling
|
|
_iErrorInState := _iState;
|
|
_fbReadRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= W_MAX_LIM_PCT_SF_REGISTER,
|
|
cbLength:= SIZEOF(_iWMaxLimPctSF),
|
|
pDestAddr:= ADR(_iWMaxLimPctSF),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
cbRead=> );
|
|
|
|
// Check if reading mudbus register is done
|
|
IF NOT _fbReadRegister.bBusy THEN
|
|
// If there was no error then continue
|
|
IF NOT _fbReadRegister.bError THEN
|
|
_iState := 30;
|
|
// Check for valid value
|
|
IF (_iWMaxLimPctSF < -10) OR (_iWMaxLimPctSF > 10) OR (_iWMaxLimPctSF = 16#8000) THEN
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
ELSE
|
|
xError := TRUE;
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbReadRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
26: // Read inverter scaling factor for reactive power
|
|
_iErrorInState := _iState;
|
|
_fbReadRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= VAR_PCT_SF,
|
|
cbLength:= SIZEOF(_iVarPctSF),
|
|
pDestAddr:= ADR(_iVarPctSF),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
cbRead=> );
|
|
|
|
// Check if reading mudbus register is done
|
|
IF NOT _fbReadRegister.bBusy THEN
|
|
// If there was no error then continue
|
|
IF NOT _fbReadRegister.bError THEN
|
|
_iState := 30;
|
|
// Check for valid value
|
|
IF (_iVarPctSF < -10) OR (_iVarPctSF > 10) OR (_iVarPctSF = 16#8000) THEN
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
ELSE
|
|
xError := TRUE;
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbReadRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
30: // Read inverter max power
|
|
_iErrorInState := _iState;
|
|
_fbReadRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= W_MAX_REGISTER,
|
|
cbLength:= SIZEOF(_iWMax),
|
|
pDestAddr:= ADR(_iWMax),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
cbRead=> );
|
|
|
|
// Check if reading mudbus register is done
|
|
IF NOT _fbReadRegister.bBusy THEN
|
|
// If there was no error then continue
|
|
IF NOT _fbReadRegister.bError THEN
|
|
_iState := 40;
|
|
// Reading a register with scaling factor = value * 10^SF
|
|
_rWMax := LREAL_TO_REAL(_iWMax * EXPT(10,_iWMaxSF));
|
|
|
|
// Calculate power to write to register
|
|
_iWMaxLimPct := LREAL_TO_INT((rPower*100)/(_rWMax * EXPT(10,_iWMaxLimPctSF)));
|
|
ELSE
|
|
xError := TRUE;
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbReadRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
40: // Set power limit
|
|
_iErrorInState := _iState;
|
|
_fbWriteRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= W_MAX_LIM_PCT_REGISTER,
|
|
cbLength:= SIZEOF(_iWMaxLimPct),
|
|
pSrcAddr:= ADR(_iWMaxLimPct),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> );
|
|
|
|
// If writing modbus register is done
|
|
IF NOT _fbWriteRegister.bBusy THEN
|
|
// And there is no error, then continue
|
|
IF NOT _fbWriteRegister.bError THEN
|
|
_iState := 50;
|
|
_rOldPower := rPower;
|
|
_uiMaxLimEn := 1;
|
|
// Calculate reactive power setting
|
|
//_iMaxPowerVar := LREAL_TO_INT((rReactivePower*100)/(_iMaxPowerVar * EXPT(10,_iVarPctSF)));
|
|
ELSE
|
|
xError := TRUE;
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbWriteRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
41: // Set max reactive power in percent
|
|
_iErrorInState := _iState;
|
|
_fbWriteRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= VAR_W_MAX_PCT,
|
|
cbLength:= SIZEOF(_iMaxPowerVar),
|
|
pSrcAddr:= ADR(_iMaxPowerVar),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> );
|
|
|
|
// If writing modbus register is done
|
|
IF NOT _fbWriteRegister.bBusy THEN
|
|
// And there is no error, then continue
|
|
IF NOT _fbWriteRegister.bError THEN
|
|
_iState := 42;
|
|
ELSE
|
|
xError := TRUE;
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbWriteRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
42: // Enable reactive power percent limiting
|
|
_iErrorInState := _iState;
|
|
_fbWriteRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= VAR_PCT_ENA,
|
|
cbLength:= SIZEOF(_iMaxVarPct),
|
|
pSrcAddr:= ADR(_iMaxVarPct),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> );
|
|
|
|
// If writing modbus register is done
|
|
IF NOT _fbWriteRegister.bBusy THEN
|
|
// And there is no error, then continue
|
|
IF NOT _fbWriteRegister.bError THEN
|
|
_iState := 50;
|
|
ELSE
|
|
xError := TRUE;
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbWriteRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
50: // Enable Power limiting (THROTTLED)
|
|
_iErrorInState := _iState;
|
|
_fbWriteRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= W_MAX_LIM_EN_REGISTER,
|
|
cbLength:= SIZEOF(_uiMaxLimEn),
|
|
pSrcAddr:= ADR(_uiMaxLimEn),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> );
|
|
|
|
// If writing modbus register is done
|
|
IF NOT _fbWriteRegister.bBusy THEN
|
|
// And there is no error, then continue
|
|
IF NOT _fbWriteRegister.bError THEN
|
|
_iState := 51;
|
|
_uiPCSSetOperation := 4;
|
|
ELSE
|
|
xError := TRUE;
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbWriteRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
51: // Go to started
|
|
_iErrorInState := _iState;
|
|
_fbWriteRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= PCS_SET_OPERATION_REGISTER,
|
|
cbLength:= SIZEOF(_uiPCSSetOperation),
|
|
pSrcAddr:= ADR(_uiPCSSetOperation),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> );
|
|
|
|
// If writing modbus register is done
|
|
IF NOT _fbWriteRegister.bBusy THEN
|
|
// And there is no error, then continue
|
|
IF NOT _fbWriteRegister.bError THEN
|
|
_uiPCSSetOperation := 1;
|
|
_iState := 60;
|
|
ELSE
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbWriteRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
60: // Switch to THROTTLED mode
|
|
_iErrorInState := _iState;
|
|
_fbWriteRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= PCS_SET_OPERATION_REGISTER,
|
|
cbLength:= SIZEOF(_uiPCSSetOperation),
|
|
pSrcAddr:= ADR(_uiPCSSetOperation),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> );
|
|
|
|
// If writing modbus register is done
|
|
IF NOT _fbWriteRegister.bBusy THEN
|
|
// And there is no error, then continue
|
|
IF NOT _fbWriteRegister.bError THEN
|
|
_iState := 65;
|
|
ELSE
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbWriteRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
65: // Wait for polling timer
|
|
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
|
|
IF _tonPollingTimer.Q THEN
|
|
_tonPollingTimer(IN := FALSE);
|
|
_iState := 70;
|
|
ELSIF ABS(rPower - _rOldPower) > 0.1 THEN
|
|
_tonPollingTimer(IN := FALSE);
|
|
// If power has ben changed, goto set power limit mode
|
|
_iState := 40;
|
|
// Calculate power to write to register
|
|
_iWMaxLimPct := LREAL_TO_INT((rPower*100)/(_rWMax * EXPT(10,_iWMaxLimPctSF)));
|
|
END_IF
|
|
|
|
// check if inverter should shut down
|
|
IF NOT xEnable THEN
|
|
_uiPCSSetOperation := 3;
|
|
// Goto shutdown sequence
|
|
_iState := 200;
|
|
END_IF
|
|
|
|
|
|
70: // Enabled, check for error
|
|
_iErrorInState := _iState;
|
|
_fbReadRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= STATUS_REGISTER,
|
|
cbLength:= SIZEOF(_uiInverterState),
|
|
pDestAddr:= ADR(_uiInverterState),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
cbRead=> );
|
|
|
|
// Check if reading mudbus register is done
|
|
IF NOT _fbReadRegister.bBusy THEN
|
|
// If there was no error and the converter has no error continue
|
|
IF NOT _fbReadRegister.bError AND (_uiInverterState <> 7) THEN
|
|
_iState := 80;
|
|
IF (_uiInverterState = 4) OR (_uiInverterState = 5) THEN
|
|
xActive := TRUE;
|
|
ELSE
|
|
xActive := FALSE;
|
|
END_IF
|
|
ELSE
|
|
xError := TRUE;
|
|
_uiPCSSetOperation := 3;
|
|
// Read error register
|
|
_iState := 200;
|
|
END_IF
|
|
_fbReadRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
80: // Read current DC values
|
|
_iErrorInState := _iState;
|
|
_fbReadRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 6,
|
|
nMBAddr:= DC_VALUES_START_REGISTER,
|
|
cbLength:= SIZEOF(_awCurrentDCValues),
|
|
pDestAddr:= ADR(_awCurrentDCValues),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
cbRead=> );
|
|
|
|
// Check if reading mudbus register is done
|
|
IF NOT _fbReadRegister.bBusy THEN
|
|
// If there was no error and the converter has no error continue
|
|
IF NOT _fbReadRegister.bError THEN
|
|
_iState := 85;
|
|
stCurrentValues.rActDCCurrent := LREAL_TO_REAL(WORD_TO_INT(_awCurrentDCValues[0]) * EXPT(10,WORD_TO_INT(_awCurrentDCValues[1])));
|
|
stCurrentValues.rActDCVoltage := LREAL_TO_REAL(WORD_TO_INT(_awCurrentDCValues[2]) * EXPT(10,WORD_TO_INT(_awCurrentDCValues[3])));
|
|
stCurrentValues.rActDCPower := LREAL_TO_REAL(WORD_TO_INT(_awCurrentDCValues[4]) * EXPT(10,WORD_TO_INT(_awCurrentDCValues[5])));
|
|
ELSE
|
|
// Read error register
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbReadRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
85: // Read current ac values
|
|
_iErrorInState := _iState;
|
|
_fbReadRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 22,
|
|
nMBAddr:= AC_VALUES_START_REGISTER,
|
|
cbLength:= SIZEOF(_awCurrentACValues),
|
|
pDestAddr:= ADR(_awCurrentACValues),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
cbRead=> );
|
|
|
|
// Check if reading mudbus register is done
|
|
IF NOT _fbReadRegister.bBusy THEN
|
|
// If there was no error and the converter has no error continue
|
|
IF NOT _fbReadRegister.bError THEN
|
|
// Go back to polling state
|
|
_iState := 90;
|
|
stCurrentValues.rActACCurrent := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[0]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[4])));
|
|
stCurrentValues.rActtACPhaseACurrent := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[1]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[4])));
|
|
stCurrentValues.rActtACPhaseBCurrent := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[2]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[4])));
|
|
stCurrentValues.rActtACPhaseCCurrent := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[3]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[4])));
|
|
stCurrentValues.rActACPower := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[12]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[13])));
|
|
stCurrentValues.rActACFreq := LREAL_TO_REAL(WORD_TO_UINT(_awCurrentACValues[14]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[15])));
|
|
stCurrentValues.rActApparentPower := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[16]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[17])));
|
|
stCurrentValues.rActReactivePower := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[18]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[19])));
|
|
stCurrentValues.rActPowerFactor := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[20]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[21])));
|
|
ELSE
|
|
// Read error register
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbReadRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
90: // Read current inverter status
|
|
_fbReadRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= STATUS_REGISTER,
|
|
cbLength:= SIZEOF(_uiInverterState),
|
|
pDestAddr:= ADR(_uiInverterState),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
cbRead=> );
|
|
|
|
// Check if reading mudbus register is done
|
|
IF NOT _fbReadRegister.bBusy THEN
|
|
IF NOT _fbReadRegister.bError THEN
|
|
_iState := 91;
|
|
stCurrentValues.uiStatus := _uiInverterState;
|
|
ELSE
|
|
// Read error register
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbReadRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
91: // Send heartbeat signal
|
|
_uiPLCToInverterCounter := _uiPLCToInverterCounter + 1;
|
|
_iErrorInState := _iState;
|
|
_fbWriteRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= CONTROLLER_HB,
|
|
cbLength:= SIZEOF(_uiPLCToInverterCounter),
|
|
pSrcAddr:= ADR(_uiPLCToInverterCounter),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> );
|
|
|
|
// If writing modbus register is done
|
|
IF NOT _fbWriteRegister.bBusy THEN
|
|
// And there is no error, then continue
|
|
IF NOT _fbWriteRegister.bError THEN
|
|
_iState := 92;
|
|
ELSE
|
|
xError := TRUE;
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbWriteRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
92: // Check heartbeat signal
|
|
_fbReadRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= PCS_HB,
|
|
cbLength:= SIZEOF(_uiInverterToPLCCounter),
|
|
pDestAddr:= ADR(_uiInverterToPLCCounter),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
cbRead=> );
|
|
|
|
IF NOT _fbReadRegister.bBusy THEN
|
|
IF (NOT _fbReadRegister.bError) THEN
|
|
// Check if counter has been incremented by the inverter
|
|
IF (_uiInverterToPLCCounter - _uiInverterToPLCCounterOld) > 0 THEN
|
|
_xInverterHBCounterIncremented := TRUE;
|
|
|
|
// Safe old value
|
|
_uiInverterToPLCCounterOld := _uiInverterToPLCCounter;
|
|
ELSE
|
|
_xInverterHBCounterIncremented := FALSE;
|
|
END_IF
|
|
|
|
_iState := 65;
|
|
ELSE
|
|
xError := TRUE;
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
|
|
_fbReadRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
200: // Shutdown sequence
|
|
_iErrorInState := _iState;
|
|
_fbWriteRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= PCS_SET_OPERATION_REGISTER,
|
|
cbLength:= SIZEOF(_uiPCSSetOperation),
|
|
pSrcAddr:= ADR(_uiPCSSetOperation),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> );
|
|
|
|
// If writing modbus register is done
|
|
IF NOT _fbWriteRegister.bBusy THEN
|
|
// And there is no error, then continue
|
|
IF NOT _fbWriteRegister.bError THEN
|
|
_iState := 210;
|
|
ELSE
|
|
// Goto error state
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbWriteRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
210: // Wait for poll timer to
|
|
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
|
|
IF _tonPollingTimer.Q THEN
|
|
_tonPollingTimer(IN := FALSE);
|
|
_iState := 220;
|
|
END_IF
|
|
|
|
|
|
220: // Poll and wait for standby state
|
|
_iErrorInState := _iState;
|
|
_fbReadRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= STATUS_REGISTER,
|
|
cbLength:= SIZEOF(_uiInverterState),
|
|
pDestAddr:= ADR(_uiInverterState),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
cbRead=> );
|
|
|
|
// Check if reading mudbus register is done
|
|
IF NOT _fbReadRegister.bBusy THEN
|
|
// If there was no error and the converter has no error continue
|
|
IF NOT _fbReadRegister.bError THEN
|
|
_iState := 0;
|
|
xActive := FALSE;
|
|
//xCloseDCRelais := FALSE;
|
|
END_IF
|
|
_fbReadRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
990: // Read error register
|
|
_iErrorInState := _iState;
|
|
_fbReadRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 2,
|
|
nMBAddr:= EVT_1_REGISTER,
|
|
cbLength:= SIZEOF(_dwErrorBits),
|
|
pDestAddr:= ADR(_dwErrorBits),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
cbRead=> );
|
|
|
|
// Check if reading mudbus register is done
|
|
IF NOT _fbReadRegister.bBusy THEN
|
|
// If there was no error and the converter has no error continue
|
|
IF NOT _fbReadRegister.bError THEN
|
|
_iState := 1000;
|
|
END_IF
|
|
_fbReadRegister(bExecute := FALSE);
|
|
END_IF
|
|
|
|
|
|
1000: // Error state, wait for reset
|
|
IF xReset AND (NOT xEnable) THEN
|
|
_iState := 1010;
|
|
END_IF
|
|
|
|
|
|
1010: // Try to clear all latched events
|
|
_fbWriteRegister(
|
|
sIPAddr:= sInverterIPAddr,
|
|
nTCPPort:= 502,
|
|
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
|
nQuantity:= 1,
|
|
nMBAddr:= PCS_ALARM_RESET_REGISTER,
|
|
cbLength:= SIZEOF(_uiResetInverter),
|
|
pSrcAddr:= ADR(_uiResetInverter),
|
|
bExecute:= TRUE,
|
|
tTimeout:= T#5S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> );
|
|
|
|
IF NOT _fbWriteRegister.bBusy THEN
|
|
_iState := 0;
|
|
xError := FALSE;
|
|
_fbWriteRegister(bExecute := FALSE);
|
|
END_IF
|
|
END_CASE
|
|
|
|
|
|
// ===============================
|
|
// Heartbeat check
|
|
// ===============================
|
|
_tonHeartbeatTimeout(IN := (NOT _xInverterHBCounterIncremented), PT := T#5S);
|
|
|
|
// Reset heartbeat ok signal
|
|
IF xReset AND (NOT _tonHeartbeatTimeout.Q) THEN
|
|
xHeartbeatOk := TRUE;
|
|
END_IF
|
|
|
|
// Check for heartbeat
|
|
IF _tonHeartbeatTimeout.Q THEN
|
|
xHeartbeatOk := FALSE;
|
|
END_IF
|
|
|
|
|
|
// ===============================
|
|
// Inverter alarm handling
|
|
// ===============================
|
|
|
|
IF xError AND (NOT _fbErrorInverterAlarm.bRaised) THEN
|
|
_fbErrorInverterAlarm.Raise(0);
|
|
END_IF
|
|
|
|
IF (NOT xError) AND _fbErrorInverterAlarm.bRaised THEN
|
|
_fbErrorInverterAlarm.Clear(0, FALSE);
|
|
END_IF
|
|
|
|
IF (_fbErrorInverterAlarm.eConfirmationState = TcEventConfirmationState.WaitForConfirmation) AND xReset THEN
|
|
_fbErrorInverterAlarm.Confirm(0);
|
|
END_IF]]></ST>
|
|
</Implementation>
|
|
<Method Name="FB_init" Id="{a80728a8-68c7-4f6a-87fc-246cb88104d4}">
|
|
<Declaration><![CDATA[METHOD FB_init : BOOL
|
|
VAR_INPUT
|
|
bInitRetains : BOOL; // if TRUE, the retain variables are initialized (warm start / cold start)
|
|
bInCopyCode : BOOL; // if TRUE, the instance afterwards gets moved into the copy code (online change)
|
|
|
|
sName : STRING;
|
|
END_VAR
|
|
]]></Declaration>
|
|
<Implementation>
|
|
<ST><![CDATA[_sName := sName;
|
|
|
|
// Create inverter main alarm
|
|
_fbErrorInverterAlarm.CreateEx(stEventEntry := TC_EVENTS.Inverter.InverterError, bWithConfirmation := TRUE, 0);
|
|
_fbErrorInverterAlarm.ipArguments.Clear().AddString(_sName);]]></ST>
|
|
</Implementation>
|
|
</Method>
|
|
<LineIds Name="FB_PowerSupplySunspec">
|
|
<LineId Id="774" Count="10" />
|
|
<LineId Id="1550" Count="0" />
|
|
<LineId Id="785" Count="3" />
|
|
<LineId Id="2615" Count="0" />
|
|
<LineId Id="790" Count="0" />
|
|
<LineId Id="2614" Count="0" />
|
|
<LineId Id="2613" Count="0" />
|
|
<LineId Id="2616" Count="1" />
|
|
<LineId Id="2906" Count="0" />
|
|
<LineId Id="2618" Count="2" />
|
|
<LineId Id="3661" Count="0" />
|
|
<LineId Id="2621" Count="0" />
|
|
<LineId Id="2623" Count="15" />
|
|
<LineId Id="2622" Count="0" />
|
|
<LineId Id="2639" Count="0" />
|
|
<LineId Id="2644" Count="0" />
|
|
<LineId Id="2641" Count="0" />
|
|
<LineId Id="2643" Count="0" />
|
|
<LineId Id="2642" Count="0" />
|
|
<LineId Id="2721" Count="0" />
|
|
<LineId Id="2640" Count="0" />
|
|
<LineId Id="2645" Count="0" />
|
|
<LineId Id="3660" Count="0" />
|
|
<LineId Id="2646" Count="0" />
|
|
<LineId Id="2648" Count="1" />
|
|
<LineId Id="2651" Count="0" />
|
|
<LineId Id="2722" Count="0" />
|
|
<LineId Id="2652" Count="0" />
|
|
<LineId Id="2650" Count="0" />
|
|
<LineId Id="2653" Count="0" />
|
|
<LineId Id="3659" Count="0" />
|
|
<LineId Id="2656" Count="31" />
|
|
<LineId Id="3658" Count="0" />
|
|
<LineId Id="2688" Count="22" />
|
|
<LineId Id="3862" Count="3" />
|
|
<LineId Id="2711" Count="9" />
|
|
<LineId Id="2654" Count="0" />
|
|
<LineId Id="3422" Count="2" />
|
|
<LineId Id="3438" Count="0" />
|
|
<LineId Id="3440" Count="19" />
|
|
<LineId Id="3464" Count="5" />
|
|
<LineId Id="3439" Count="0" />
|
|
<LineId Id="3425" Count="0" />
|
|
<LineId Id="3474" Count="0" />
|
|
<LineId Id="3426" Count="0" />
|
|
<LineId Id="3475" Count="12" />
|
|
<LineId Id="2655" Count="0" />
|
|
<LineId Id="3488" Count="0" />
|
|
<LineId Id="3607" Count="19" />
|
|
<LineId Id="3489" Count="0" />
|
|
<LineId Id="2647" Count="0" />
|
|
<LineId Id="791" Count="22" />
|
|
<LineId Id="1701" Count="5" />
|
|
<LineId Id="814" Count="1" />
|
|
<LineId Id="1714" Count="0" />
|
|
<LineId Id="1719" Count="0" />
|
|
<LineId Id="1715" Count="0" />
|
|
<LineId Id="1718" Count="0" />
|
|
<LineId Id="1716" Count="1" />
|
|
<LineId Id="1707" Count="0" />
|
|
<LineId Id="3657" Count="0" />
|
|
<LineId Id="1708" Count="0" />
|
|
<LineId Id="1710" Count="2" />
|
|
<LineId Id="1709" Count="0" />
|
|
<LineId Id="1713" Count="0" />
|
|
<LineId Id="1720" Count="0" />
|
|
<LineId Id="1722" Count="1" />
|
|
<LineId Id="1726" Count="0" />
|
|
<LineId Id="1725" Count="0" />
|
|
<LineId Id="1721" Count="0" />
|
|
<LineId Id="1433" Count="0" />
|
|
<LineId Id="816" Count="28" />
|
|
<LineId Id="1171" Count="0" />
|
|
<LineId Id="845" Count="5" />
|
|
<LineId Id="3656" Count="0" />
|
|
<LineId Id="851" Count="27" />
|
|
<LineId Id="1172" Count="0" />
|
|
<LineId Id="879" Count="4" />
|
|
<LineId Id="1981" Count="0" />
|
|
<LineId Id="3655" Count="0" />
|
|
<LineId Id="1982" Count="0" />
|
|
<LineId Id="1991" Count="0" />
|
|
<LineId Id="1993" Count="12" />
|
|
<LineId Id="1992" Count="0" />
|
|
<LineId Id="2006" Count="0" />
|
|
<LineId Id="2008" Count="15" />
|
|
<LineId Id="2007" Count="0" />
|
|
<LineId Id="1983" Count="0" />
|
|
<LineId Id="884" Count="28" />
|
|
<LineId Id="1173" Count="0" />
|
|
<LineId Id="913" Count="5" />
|
|
<LineId Id="3654" Count="0" />
|
|
<LineId Id="919" Count="22" />
|
|
<LineId Id="2024" Count="1" />
|
|
<LineId Id="942" Count="0" />
|
|
<LineId Id="1174" Count="0" />
|
|
<LineId Id="943" Count="4" />
|
|
<LineId Id="1928" Count="3" />
|
|
<LineId Id="1934" Count="18" />
|
|
<LineId Id="1955" Count="5" />
|
|
<LineId Id="1933" Count="0" />
|
|
<LineId Id="2030" Count="0" />
|
|
<LineId Id="3653" Count="0" />
|
|
<LineId Id="2031" Count="0" />
|
|
<LineId Id="2033" Count="25" />
|
|
<LineId Id="2032" Count="0" />
|
|
<LineId Id="3639" Count="0" />
|
|
<LineId Id="948" Count="23" />
|
|
<LineId Id="1175" Count="0" />
|
|
<LineId Id="972" Count="4" />
|
|
<LineId Id="2907" Count="0" />
|
|
<LineId Id="3640" Count="0" />
|
|
<LineId Id="2908" Count="0" />
|
|
<LineId Id="2969" Count="18" />
|
|
<LineId Id="3031" Count="0" />
|
|
<LineId Id="2988" Count="5" />
|
|
<LineId Id="2909" Count="0" />
|
|
<LineId Id="2996" Count="0" />
|
|
<LineId Id="977" Count="28" />
|
|
<LineId Id="3641" Count="0" />
|
|
<LineId Id="1006" Count="8" />
|
|
<LineId Id="1560" Count="1" />
|
|
<LineId Id="1015" Count="3" />
|
|
<LineId Id="1127" Count="0" />
|
|
<LineId Id="1019" Count="3" />
|
|
<LineId Id="3642" Count="0" />
|
|
<LineId Id="1023" Count="21" />
|
|
<LineId Id="1097" Count="1" />
|
|
<LineId Id="1100" Count="1" />
|
|
<LineId Id="1099" Count="0" />
|
|
<LineId Id="1045" Count="0" />
|
|
<LineId Id="1176" Count="0" />
|
|
<LineId Id="2723" Count="0" />
|
|
<LineId Id="1046" Count="5" />
|
|
<LineId Id="3643" Count="0" />
|
|
<LineId Id="1052" Count="0" />
|
|
<LineId Id="1063" Count="20" />
|
|
<LineId Id="1090" Count="0" />
|
|
<LineId Id="1092" Count="0" />
|
|
<LineId Id="1775" Count="0" />
|
|
<LineId Id="1084" Count="4" />
|
|
<LineId Id="1062" Count="0" />
|
|
<LineId Id="1736" Count="0" />
|
|
<LineId Id="3644" Count="0" />
|
|
<LineId Id="1737" Count="0" />
|
|
<LineId Id="1739" Count="19" />
|
|
<LineId Id="1781" Count="0" />
|
|
<LineId Id="1759" Count="0" />
|
|
<LineId Id="4066" Count="7" />
|
|
<LineId Id="1777" Count="0" />
|
|
<LineId Id="1762" Count="4" />
|
|
<LineId Id="1738" Count="0" />
|
|
<LineId Id="3213" Count="0" />
|
|
<LineId Id="3645" Count="0" />
|
|
<LineId Id="3214" Count="0" />
|
|
<LineId Id="3216" Count="15" />
|
|
<LineId Id="3215" Count="0" />
|
|
<LineId Id="3232" Count="0" />
|
|
<LineId Id="3240" Count="0" />
|
|
<LineId Id="3234" Count="0" />
|
|
<LineId Id="3236" Count="2" />
|
|
<LineId Id="3235" Count="0" />
|
|
<LineId Id="3239" Count="0" />
|
|
<LineId Id="3233" Count="0" />
|
|
<LineId Id="3529" Count="0" />
|
|
<LineId Id="3646" Count="0" />
|
|
<LineId Id="3531" Count="47" />
|
|
<LineId Id="3590" Count="0" />
|
|
<LineId Id="3593" Count="9" />
|
|
<LineId Id="3591" Count="0" />
|
|
<LineId Id="3603" Count="0" />
|
|
<LineId Id="3605" Count="1" />
|
|
<LineId Id="3604" Count="0" />
|
|
<LineId Id="3592" Count="0" />
|
|
<LineId Id="3588" Count="1" />
|
|
<LineId Id="3530" Count="0" />
|
|
<LineId Id="1093" Count="0" />
|
|
<LineId Id="3647" Count="0" />
|
|
<LineId Id="1094" Count="0" />
|
|
<LineId Id="1102" Count="24" />
|
|
<LineId Id="1054" Count="0" />
|
|
<LineId Id="1295" Count="0" />
|
|
<LineId Id="3648" Count="0" />
|
|
<LineId Id="1296" Count="3" />
|
|
<LineId Id="1128" Count="0" />
|
|
<LineId Id="1300" Count="1" />
|
|
<LineId Id="3649" Count="0" />
|
|
<LineId Id="1129" Count="0" />
|
|
<LineId Id="1132" Count="20" />
|
|
<LineId Id="1163" Count="0" />
|
|
<LineId Id="1294" Count="0" />
|
|
<LineId Id="1161" Count="1" />
|
|
<LineId Id="1130" Count="1" />
|
|
<LineId Id="3650" Count="0" />
|
|
<LineId Id="1055" Count="0" />
|
|
<LineId Id="1177" Count="20" />
|
|
<LineId Id="1199" Count="1" />
|
|
<LineId Id="1169" Count="0" />
|
|
<LineId Id="1265" Count="0" />
|
|
<LineId Id="3651" Count="0" />
|
|
<LineId Id="1266" Count="1" />
|
|
<LineId Id="1269" Count="2" />
|
|
<LineId Id="3652" Count="0" />
|
|
<LineId Id="1272" Count="0" />
|
|
<LineId Id="1274" Count="11" />
|
|
<LineId Id="1273" Count="0" />
|
|
<LineId Id="1289" Count="1" />
|
|
<LineId Id="1293" Count="0" />
|
|
<LineId Id="2235" Count="0" />
|
|
<LineId Id="1291" Count="1" />
|
|
<LineId Id="12" Count="0" />
|
|
<LineId Id="3629" Count="1" />
|
|
<LineId Id="3628" Count="0" />
|
|
<LineId Id="3631" Count="1" />
|
|
<LineId Id="3524" Count="0" />
|
|
<LineId Id="3633" Count="0" />
|
|
<LineId Id="3525" Count="3" />
|
|
<LineId Id="3516" Count="0" />
|
|
<LineId Id="3627" Count="0" />
|
|
<LineId Id="3521" Count="2" />
|
|
<LineId Id="3635" Count="1" />
|
|
<LineId Id="3634" Count="0" />
|
|
<LineId Id="3637" Count="1" />
|
|
<LineId Id="2418" Count="0" />
|
|
<LineId Id="2417" Count="0" />
|
|
<LineId Id="2419" Count="1" />
|
|
<LineId Id="2422" Count="0" />
|
|
<LineId Id="2421" Count="0" />
|
|
<LineId Id="2423" Count="1" />
|
|
<LineId Id="2426" Count="0" />
|
|
<LineId Id="2425" Count="0" />
|
|
<LineId Id="2427" Count="1" />
|
|
</LineIds>
|
|
<LineIds Name="FB_PowerSupplySunspec.FB_init">
|
|
<LineId Id="15" Count="1" />
|
|
<LineId Id="11" Count="0" />
|
|
<LineId Id="7" Count="1" />
|
|
</LineIds>
|
|
</POU>
|
|
</TcPlcObject> |