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; //xCloseDCRelais := TRUE; _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) 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:= 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 := 0; 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; 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 // 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( 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:= 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 := 90; 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; 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 := 65; stCurrentValues.uiStatus := _uiInverterState; ELSE // Read error register _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 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]]>