Finished first implementation of modbus error registers

This commit is contained in:
Matthias Heisig
2025-04-14 19:38:17 +02:00
parent 4a00a4c414
commit f79cf27c0c
19 changed files with 998 additions and 531 deletions

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4026.8">
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4026.12">
<POU Name="FB_PowerSupplySunspec" Id="{a826dd09-442c-45c5-8ae3-9b71f293003c}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FB_PowerSupplySunspec
VAR_INPUT
@@ -27,6 +27,9 @@ VAR
// Current state
_iState : INT := 0;
// Internal power command
_rPowerInternal : REAL;
// FB for reading Modbus holding registers
_fbReadRegister : FB_MBReadRegs;
@@ -67,9 +70,6 @@ VAR
// 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;
@@ -88,9 +88,15 @@ VAR
// Time for polling for current dc values and check for inverter error
_timPollingDelay : TIME := T#500MS;
// Time for setting the current power
_timSetPowerDelay : TIME := T#250MS;
// Timer for polling of current values
_tonPollingTimer : TON;
// Timer for setting the inverter power
_tonSetPowerTimer : 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;
@@ -227,6 +233,7 @@ CASE _iState OF
// If enable and INTLK Ok
IF xEnable THEN
_iState := 10;
_rPowerInternal := 0.0;
_tonPollingTimer(IN := FALSE, PT := _timPollingDelay);
ELSE
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
@@ -598,7 +605,7 @@ CASE _iState OF
_rWMax := LREAL_TO_REAL(_uiWMax * EXPT(10,_iWMaxSF));
// Calculate power to write to register
_iWMaxLimPct := LREAL_TO_INT((rPower*100)/(_rWMax * EXPT(10,_iWMaxLimPctSF)));
_iWMaxLimPct := LREAL_TO_INT((_rPowerInternal*100)/(_rWMax * EXPT(10,_iWMaxLimPctSF)));
ELSE
xError := TRUE;
// Goto error state
@@ -629,7 +636,6 @@ CASE _iState OF
// And there is no error, then continue
IF NOT _fbWriteRegister.bError THEN
_iState := 50;
_rOldPower := rPower;
_uiMaxLimEn := 1;
_uiLastSetPowerLimitErrorCounter := _uiSetPowerLimitErrorCounter;
_uiSetPowerLimitErrorCounter := 0;
@@ -734,8 +740,8 @@ CASE _iState OF
IF NOT _fbWriteRegister.bBusy THEN
// And there is no error, then continue
IF NOT _fbWriteRegister.bError THEN
_iState := 51;
_uiPCSSetOperation := 4;
_iState := 60; // 51
_uiPCSSetOperation := 1; // 4
ELSE
xError := TRUE;
// Goto error state
@@ -764,10 +770,11 @@ CASE _iState OF
// 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;
IF (NOT _fbWriteRegister.bError) THEN
//_uiPCSSetOperation := 1;
_iState := 60;
ELSE
_uiPCSSetOperation := 1;
// Goto error state
_iState := 1000;
END_IF
@@ -806,22 +813,28 @@ CASE _iState OF
65: // Wait for polling timer
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
_tonSetPowerTimer(IN := TRUE, PT := _timSetPowerDelay);
IF _tonPollingTimer.Q THEN
_tonPollingTimer(IN := FALSE);
_iState := 70;
ELSIF (ABS(rPower - _rOldPower) > 0.1) THEN
//_tonPollingTimer(IN := FALSE);
ELSIF (ABS(rPower - _rPowerInternal) > 0.1) AND _tonSetPowerTimer.Q AND xEnable THEN
_tonSetPowerTimer(IN := FALSE);
_rPowerInternal := rPower;
// Calculate power to write to register
_iWMaxLimPct := LREAL_TO_INT((_rPowerInternal*100)/(_rWMax * EXPT(10,_iWMaxLimPctSF)));
// If power has been 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
IF (NOT xEnable) THEN
_uiPCSSetOperation := 3;
_rPowerInternal := 0.0;
_iWMaxLimPct := 0;
// Goto shutdown sequence
_iState := 200;
_iState := 200;
END_IF
@@ -1024,7 +1037,8 @@ CASE _iState OF
_xInverterHBCounterIncremented := FALSE;
END_IF
_iState := 65;
// _iState := 65;
_iState := 93;
ELSE
xError := TRUE;
// Goto error state
@@ -1034,8 +1048,75 @@ CASE _iState OF
_fbReadRegister(bExecute := FALSE);
END_IF
93: // Send current power demand
_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 := 65;
_uiMaxLimEn := 1;
_uiLastSetPowerLimitErrorCounter := _uiSetPowerLimitErrorCounter;
_uiSetPowerLimitErrorCounter := 0;
// Calculate reactive power setting
//_iMaxPowerVar := LREAL_TO_INT((rReactivePower*100)/(_iMaxPowerVar * EXPT(10,_iVarPctSF)));
ELSE
_uiSetPowerLimitErrorCounter := _uiSetPowerLimitErrorCounter + 1;
IF _uiSetPowerLimitErrorCounter > 5 THEN
// Goto error state
_iState := 1000;
ELSE
_iState := 41;
END_IF
END_IF
_fbWriteRegister(bExecute := FALSE);
END_IF
200: // Shutdown sequence
200: // Shutdown send zero power command
_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 := 201;
_uiPCSSetOperation := 3;
ELSE
// Goto error state
_iState := 1000;
END_IF
_fbWriteRegister(bExecute := FALSE);
END_IF
201: // Shutdown sequence
_iErrorInState := _iState;
_fbWriteRegister(
sIPAddr:= sInverterIPAddr,