Fixed Modbus register access
This commit is contained in:
@@ -10,11 +10,17 @@ VAR_INPUT
|
||||
rMaxBattPower : REAL := 24_000; // 24kW
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
// Output for SCS DC-Relais
|
||||
xCloseDCRelais AT %Q*: BOOL;
|
||||
rActDCCurrent : REAL;
|
||||
rActDCVoltage : REAL;
|
||||
xError : BOOL;
|
||||
|
||||
// Inverter active
|
||||
xActive : BOOL;
|
||||
|
||||
// FB error
|
||||
xError : BOOL;
|
||||
|
||||
// Current inverter values
|
||||
stCurrentValues : ST_SUNSPEC_CURRENT_VALUES;
|
||||
END_VAR
|
||||
VAR
|
||||
// Current state
|
||||
@@ -41,6 +47,10 @@ VAR
|
||||
// Unscaled limit for converter power
|
||||
_iWMaxLimPct : INT;
|
||||
|
||||
// Reread set power limit
|
||||
_iWMaxLimPctRead : INT;
|
||||
_iWMaxLimPctReadScaled : REAL;
|
||||
|
||||
// Scaling factor for power limiting
|
||||
_iWMaxLimPctSF : INT;
|
||||
|
||||
@@ -71,8 +81,11 @@ VAR
|
||||
// Timer for polling of current values
|
||||
_tonPollingTimer : TON;
|
||||
|
||||
// Current DC values (DCA, DCA_SF, DCV, DCV_SF) in word array for efficient modbus reading
|
||||
_awCurrentDCValues : ARRAY[0..3] OF WORD;
|
||||
// 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..9] OF WORD;
|
||||
|
||||
// Inverter error bits
|
||||
_dwErrorBits : DWORD;
|
||||
@@ -88,7 +101,7 @@ VAR CONSTANT
|
||||
|
||||
// Throttled power register
|
||||
// Size 1, int16 (Range = -32767 .. 32767, Not implemented 0x8000)
|
||||
W_MAX_LIM_PCT_REGISTER : WORD := 40187;
|
||||
W_MAX_LIM_PCT_REGISTER : WORD := 40187;
|
||||
|
||||
// Throttled power register scaling factor
|
||||
// Size 1, sunssf (int16) (Range = -10 .. 10, Not implemented 0x8000)
|
||||
@@ -126,6 +139,10 @@ VAR CONSTANT
|
||||
// Size 4
|
||||
DC_VALUES_START_REGISTER : WORD := 40097;
|
||||
|
||||
// Start of register with the current ac values
|
||||
// SIZE 10
|
||||
AC_VALUES_START_REGISTER : WORD := 40084;
|
||||
|
||||
// Error bits register
|
||||
// Size 2
|
||||
EVT_1_REGISTER : WORD := 40110;
|
||||
@@ -143,6 +160,7 @@ END_IF
|
||||
|
||||
// State machine
|
||||
CASE _iState OF
|
||||
|
||||
0: // Off
|
||||
// If enable and INTLK Ok
|
||||
IF xEnable THEN
|
||||
@@ -172,8 +190,34 @@ CASE _iState OF
|
||||
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;
|
||||
@@ -271,7 +315,7 @@ CASE _iState OF
|
||||
_rWMax := LREAL_TO_REAL(_iWMax * EXPT(10,_iWMaxSF));
|
||||
|
||||
// Calculate power to write to register
|
||||
_iWMaxLimPct := LREAL_TO_INT(rPower * EXPT(10,_iWMaxLimPctSF) / _rWMax);
|
||||
_iWMaxLimPct := LREAL_TO_INT((rPower*100)/(_rWMax * EXPT(10,_iWMaxLimPctSF)));
|
||||
ELSE
|
||||
xError := TRUE;
|
||||
// Goto error state
|
||||
@@ -311,6 +355,32 @@ CASE _iState OF
|
||||
_fbWriteRegister(bExecute := FALSE);
|
||||
END_IF
|
||||
|
||||
// 45: // Read set power
|
||||
// _fbReadRegister(
|
||||
// sIPAddr:= sInverterIPAddr,
|
||||
// nTCPPort:= 502,
|
||||
// nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
||||
// nQuantity:= 1,
|
||||
// nMBAddr:= W_MAX_LIM_PCT_REGISTER,
|
||||
// cbLength:= SIZEOF(_iWMaxLimPctRead),
|
||||
// pDestAddr:= ADR(_iWMaxLimPctRead),
|
||||
// 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
|
||||
// _iWMaxLimPctReadScaled := LREAL_TO_INT(_rWMax * _iWMaxLimPctRead * EXPT(10,_iWMaxLimPctSF)*0.01);
|
||||
// _iState := 50;
|
||||
// END_IF
|
||||
// _fbReadRegister(bExecute := FALSE);
|
||||
// END_IF
|
||||
|
||||
|
||||
50: // Enable Power limiting (THROTTLED)
|
||||
_iErrorInState := _iState;
|
||||
_fbWriteRegister(
|
||||
@@ -369,7 +439,7 @@ CASE _iState OF
|
||||
_fbWriteRegister(bExecute := FALSE);
|
||||
END_IF
|
||||
|
||||
65: // Wait for error polling timer
|
||||
65: // Wait for polling timer
|
||||
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
|
||||
IF _tonPollingTimer.Q THEN
|
||||
_tonPollingTimer(IN := FALSE);
|
||||
@@ -378,6 +448,8 @@ CASE _iState OF
|
||||
_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
|
||||
@@ -428,7 +500,7 @@ CASE _iState OF
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
||||
nQuantity:= 4,
|
||||
nQuantity:= 6,
|
||||
nMBAddr:= DC_VALUES_START_REGISTER,
|
||||
cbLength:= SIZEOF(_awCurrentDCValues),
|
||||
pDestAddr:= ADR(_awCurrentDCValues),
|
||||
@@ -443,9 +515,45 @@ CASE _iState OF
|
||||
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_UINT(_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
|
||||
|
||||
85: // Read current ac values
|
||||
_iErrorInState := _iState;
|
||||
_fbReadRegister(
|
||||
sIPAddr:= sInverterIPAddr,
|
||||
nTCPPort:= 502,
|
||||
nUnitID:= 16#FF, // 16#FF for Modbus TCP
|
||||
nQuantity:= 10,
|
||||
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 := 65;
|
||||
rActDCCurrent := LREAL_TO_REAL(WORD_TO_UINT(_awCurrentDCValues[0]) * EXPT(10,WORD_TO_INT(_awCurrentDCValues[1])));
|
||||
rActDCVoltage := LREAL_TO_REAL(WORD_TO_UINT(_awCurrentDCValues[2]) * EXPT(10,WORD_TO_INT(_awCurrentDCValues[3])));
|
||||
stCurrentValues.rActACPower := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[0]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[1])));
|
||||
stCurrentValues.rActACFreq := LREAL_TO_REAL(WORD_TO_UINT(_awCurrentACValues[2]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[3])));
|
||||
stCurrentValues.rActApparentPower := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[4]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[5])));
|
||||
stCurrentValues.rActReactivePower := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[6]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[7])));
|
||||
stCurrentValues.rActPowerFactor := LREAL_TO_REAL(WORD_TO_INT(_awCurrentACValues[8]) * EXPT(10,WORD_TO_INT(_awCurrentACValues[9])));
|
||||
ELSE
|
||||
// Read error register
|
||||
_iState := 1000;
|
||||
@@ -474,8 +582,8 @@ CASE _iState OF
|
||||
// And there is no error, then continue
|
||||
IF NOT _fbWriteRegister.bError THEN
|
||||
_iState := 210;
|
||||
rActDCCurrent := 0.0;
|
||||
rActDCVoltage := 0.0;
|
||||
stCurrentValues.rActDCCurrent := 0.0;
|
||||
stCurrentValues.rActDCVoltage := 0.0;
|
||||
ELSE
|
||||
// Goto error state
|
||||
_iState := 1000;
|
||||
@@ -572,7 +680,27 @@ CASE _iState OF
|
||||
END_CASE]]></ST>
|
||||
</Implementation>
|
||||
<LineIds Name="FB_PowerSupplySunspec">
|
||||
<LineId Id="774" Count="70" />
|
||||
<LineId Id="774" Count="10" />
|
||||
<LineId Id="1550" Count="0" />
|
||||
<LineId Id="785" Count="28" />
|
||||
<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="1" />
|
||||
<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="33" />
|
||||
<LineId Id="1172" Count="0" />
|
||||
@@ -580,9 +708,19 @@ END_CASE]]></ST>
|
||||
<LineId Id="1173" Count="0" />
|
||||
<LineId Id="913" Count="29" />
|
||||
<LineId Id="1174" Count="0" />
|
||||
<LineId Id="943" Count="28" />
|
||||
<LineId Id="943" Count="4" />
|
||||
<LineId Id="1520" Count="0" />
|
||||
<LineId Id="1522" Count="17" />
|
||||
<LineId Id="1541" Count="0" />
|
||||
<LineId Id="1548" Count="0" />
|
||||
<LineId Id="1542" Count="2" />
|
||||
<LineId Id="1521" Count="0" />
|
||||
<LineId Id="1493" Count="0" />
|
||||
<LineId Id="948" Count="23" />
|
||||
<LineId Id="1175" Count="0" />
|
||||
<LineId Id="972" Count="46" />
|
||||
<LineId Id="972" Count="42" />
|
||||
<LineId Id="1560" Count="1" />
|
||||
<LineId Id="1015" Count="3" />
|
||||
<LineId Id="1127" Count="0" />
|
||||
<LineId Id="1019" Count="25" />
|
||||
<LineId Id="1097" Count="1" />
|
||||
@@ -594,8 +732,17 @@ END_CASE]]></ST>
|
||||
<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="1" />
|
||||
<LineId Id="1739" Count="19" />
|
||||
<LineId Id="1781" Count="0" />
|
||||
<LineId Id="1759" Count="2" />
|
||||
<LineId Id="1774" Count="0" />
|
||||
<LineId Id="1776" Count="1" />
|
||||
<LineId Id="1762" Count="4" />
|
||||
<LineId Id="1738" Count="0" />
|
||||
<LineId Id="1093" Count="1" />
|
||||
<LineId Id="1102" Count="19" />
|
||||
<LineId Id="1166" Count="1" />
|
||||
|
||||
Reference in New Issue
Block a user