changed modbus communication

moved from all requests at the same time to one request after each other through state machine
This commit is contained in:
Markus.Neukirch
2025-09-05 16:20:36 +02:00
parent f0e6143997
commit 755da644bc
3 changed files with 339 additions and 323 deletions

File diff suppressed because one or more lines are too long

View File

@@ -36,6 +36,9 @@ VAR
// Current state // Current state
_iState : INT := 0; _iState : INT := 0;
// current state for cyclic data read
_iStateCyclicData : INT := 0;
// State for startup state machine // State for startup state machine
_iStateStartup : INT := 0; _iStateStartup : INT := 0;
@@ -82,7 +85,7 @@ VAR
_fbReadACValues : FB_MBReadRegs; _fbReadACValues : FB_MBReadRegs;
// Time for polling for current dc values and check for inverter error // Time for polling for current dc values and check for inverter error
_timPollingDelay : TIME := T#1S; _timPollingDelay : TIME := T#500MS;
// Time for setting the current power // Time for setting the current power
_timSetPowerDelay : TIME := T#250MS; _timSetPowerDelay : TIME := T#250MS;
@@ -149,9 +152,6 @@ VAR
// Current PCU state and alarm messages // Current PCU state and alarm messages
_stPCUState : ST_KACU_PCU; _stPCUState : ST_KACU_PCU;
// Current PCU cabinet temperature
_iCabTemp : INT;
// Current PCU state and alarm messages // Current PCU state and alarm messages
_stPCUStateDebug : ST_KACU_PCU; _stPCUStateDebug : ST_KACU_PCU;
@@ -355,7 +355,7 @@ CASE _iState OF
// => 10% = 1000 // => 10% = 1000
// Writing a register with scaling factor = value / (10^SF) // Writing a register with scaling factor = value / (10^SF)
//_iWSetPct := LREAL_TO_INT((_rPowerInternal*100)/(_rWMax * EXPT(10,-2))); //_iWSetPct := LREAL_TO_INT((_rPowerInternal*100)/(_rWMax * EXPT(10,-2)));
_iWSetPct := REAL_TO_INT((_rPowerInternal*100) / (_rWMax * EXPT(10,_iWSetPctSF))); _iWSetPct := LREAL_TO_INT((_rPowerInternal*100) / (_rWMax * EXPT(10,_iWSetPctSF)));
ELSE ELSE
_iWSetPct := 0; _iWSetPct := 0;
END_IF END_IF
@@ -466,118 +466,217 @@ END_IF
// Fetch cyclic data with polling timer // Fetch cyclic data with polling timer
_tonPollingTimer(IN := TRUE, PT := _timPollingDelay); _tonPollingTimer(IN := TRUE, PT := _timPollingDelay);
// Write requested state CASE _iStateCyclicData OF
_fbWriteRequestedState( 0: // init state
sIPAddr:= sInverterIPAddr, IF _tonPollingTimer.Q THEN
nTCPPort:= 502, _tonPollingTimer(IN := FALSE);
nUnitID:= 16#01, _iStateCyclicData := 10;
nMBAddr:= REQUESTED_STATE_REGISTER, END_IF
nValue:= INT_TO_WORD(_eRequestedState),
bExecute:= _tonPollingTimer.Q AND (NOT _fbWriteRequestedState.bBusy),
tTimeout:= _tTimeoutPolling,
bBusy=> ,
bError=> ,
nErrId=> );
IF (NOT _fbWriteRequestedState.bBusy) THEN 10: // Write requested state
IF _fbWriteRequestedState.bError THEN _fbWriteRequestedState(
_iCurrentErrorCountWRS := _iCurrentErrorCountWRS + 1; sIPAddr:= sInverterIPAddr,
_iErrorCountWRS := _iErrorCountWRS + 1; nTCPPort:= 502,
_iErrorIDWRS := _fbWriteRequestedState.nErrId; nUnitID:= 16#01,
ELSE nMBAddr:= REQUESTED_STATE_REGISTER,
_iCurrentErrorCountWRS := 0; nValue:= INT_TO_WORD(_eRequestedState),
END_IF bExecute:= TRUE,
END_IF tTimeout:= _tTimeoutPolling,
bBusy=> ,
bError=> ,
// Write current power command nErrId=> );
_fbWritePowerCommand(
sIPAddr:= sInverterIPAddr, IF (NOT _fbWriteRequestedState.bBusy) THEN
nTCPPort:= 502, _fbWriteRequestedState(bExecute := FALSE);
nUnitID:= 16#01, _iStateCyclicData := 20;
nQuantity := 1, IF _fbWriteRequestedState.bError THEN
nMBAddr:= W_SET_PCT, _iCurrentErrorCountWRS := _iCurrentErrorCountWRS + 1;
cbLength := SIZEOF(_iWSetPct), _iErrorCountWRS := _iErrorCountWRS + 1;
pSrcAddr:= ADR(_iWSetPct), _iErrorIDWRS := _fbWriteRequestedState.nErrId;
bExecute:= _tonPollingTimer.Q AND (NOT _fbWritePowerCommand.bBusy), ELSE
tTimeout:= _tTimeoutPolling, _iCurrentErrorCountWRS := 0;
bBusy=> , END_IF
bError=> , END_IF
nErrId=> );
20: // Write current power command
IF (NOT _fbWritePowerCommand.bBusy) THEN _fbWritePowerCommand(
IF _fbWritePowerCommand.bError THEN sIPAddr:= sInverterIPAddr,
_iCurrentErrorCountWPC := _iCurrentErrorCountWPC + 1; nTCPPort:= 502,
_iErrorCountWPC := _iErrorCountWPC + 1; nUnitID:= 16#01,
_iErrorIDWPC := _fbWritePowerCommand.nErrId; nQuantity := 1,
ELSE nMBAddr:= W_SET_PCT,
_iCurrentErrorCountWPC := 0; cbLength := SIZEOF(_iWSetPct),
END_IF pSrcAddr:= ADR(_iWSetPct),
END_IF bExecute:= TRUE,
tTimeout:= _tTimeoutPolling,
bBusy=> ,
bError=> ,
nErrId=> );
IF (NOT _fbWritePowerCommand.bBusy) THEN
_fbWritePowerCommand(bExecute := FALSE);
_iStateCyclicData := 30;
IF _fbWritePowerCommand.bError THEN
_iCurrentErrorCountWPC := _iCurrentErrorCountWPC + 1;
_iErrorCountWPC := _iErrorCountWPC + 1;
_iErrorIDWPC := _fbWritePowerCommand.nErrId;
ELSE
_iCurrentErrorCountWPC := 0;
END_IF
END_IF
30: // Read current state
_fbReadCurrentState(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#01,
nQuantity:= 1,
nMBAddr:= CURRENT_STATE_REGISTER,
cbLength:= SIZEOF(_eCurrentState),
pDestAddr:= ADR(_eCurrentState),
bExecute:= TRUE,
tTimeout:= _tTimeoutPolling,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
IF (NOT _fbReadCurrentState.bBusy) THEN
_fbReadCurrentState(bExecute := FALSE);
_iStateCyclicData := 40;
IF _fbReadCurrentState.bError THEN
_iCurrentErrorCountRCS := _iCurrentErrorCountRCS + 1;
_iErrorCountRCS := _iErrorCountRCS + 1;
_iErrorIDRCS := _fbReadCurrentState.nErrId;
ELSE
_iCurrentErrorCountRCS := 0;
END_IF
END_IF
40: // Read current pcu status
_fbReadPCUState(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#01,
nQuantity:= 2,
nMBAddr:= PCU_STATUS_START_REGISTER,
cbLength:= SIZEOF(_stPCUState),
pDestAddr:= ADR(_stPCUState),
bExecute:= TRUE,
tTimeout:= _tTimeoutPolling,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
IF (NOT _fbReadPCUState.bBusy) THEN
_fbReadPCUState(bExecute := FALSE);
_iStateCyclicData := 50;
IF _fbReadPCUState.bError THEN
_iCurrentErrorCountRPCUS := _iCurrentErrorCountRPCUS + 1;
_iErrorCountRPCUS := _iErrorCountRPCUS + 1;
_iErrorIDRPCUS := _fbReadPCUState.nErrId;
IF _iCurrentErrorCountRPCUS >= GVL_CONFIG.udiMaxConsecutiveInvError THEN
_xErrorCyclicData := TRUE;
END_IF
ELSE
_iCurrentErrorCountRPCUS := 0;
END_IF
END_IF
50: // Read current dc values
_fbReadDCValues(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#01, // 16#FF for Modbus TCP
nQuantity:= 6,
nMBAddr:= DC_VALUES_START_REGISTER,
cbLength:= SIZEOF(_awCurrentDCValues),
pDestAddr:= ADR(_awCurrentDCValues),
bExecute:= TRUE,
tTimeout:= _tTimeoutPolling,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
// Check if reading modbus register is done
IF (NOT _fbReadDCValues.bBusy) THEN
_fbReadDCValues(bExecute := FALSE);
_iStateCyclicData := 60;
// If there was no error and the converter has no error continue
IF (NOT _fbReadDCValues.bError) THEN
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
// Dont throw comm error here because this is just
// informational data and not process critical
stCurrentValues.rActDCCurrent := 0.0;
stCurrentValues.rActDCVoltage := 0.0;
stCurrentValues.rActDCPower := 0.0;
_iErrorCountRDCV := _iErrorCountRDCV + 1;
_iErrorIDRDCV := _fbReadDCValues.nErrId;
END_IF
END_IF
60: // Read current ac values
_fbReadACValues(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#01, // 16#FF for Modbus TCP
nQuantity:= 22,
nMBAddr:= AC_VALUES_START_REGISTER,
cbLength:= SIZEOF(_awCurrentACValues),
pDestAddr:= ADR(_awCurrentACValues),
bExecute:= TRUE,
tTimeout:= _tTimeoutPolling,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
// Check if reading mudbus register is done
IF (NOT _fbReadACValues.bBusy) THEN
_fbReadACValues(bExecute := FALSE);
_iStateCyclicData := 0;
// If there was no error and the converter has no error continue
IF (NOT _fbReadACValues.bError) THEN
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
// Dont throw comm error here because this is just
// informational data and not process critical
stCurrentValues.rActACCurrent := 0.0;
stCurrentValues.rActtACPhaseACurrent := 0.0;
stCurrentValues.rActtACPhaseBCurrent := 0.0;
stCurrentValues.rActtACPhaseCCurrent := 0.0;
stCurrentValues.rActACPower := 0.0;
stCurrentValues.rActACFreq := 0.0;
stCurrentValues.rActApparentPower := 0.0;
stCurrentValues.rActReactivePower := 0.0;
stCurrentValues.rActPowerFactor := 0.0;
_iErrorCountRACV := _iErrorCountRACV + 1;
_iErrorIDRACV := _fbReadACValues.nErrId;
END_IF
END_IF
END_CASE
// Read current state // evaluate inverter state
_fbReadCurrentState(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#01,
nQuantity:= 1,
nMBAddr:= CURRENT_STATE_REGISTER,
cbLength:= SIZEOF(_eCurrentState),
pDestAddr:= ADR(_eCurrentState),
bExecute:= _tonPollingTimer.Q AND (NOT _fbReadCurrentState.bBusy),
tTimeout:= _tTimeoutPolling,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
IF (NOT _fbReadCurrentState.bBusy) THEN
IF _fbReadCurrentState.bError THEN
_iCurrentErrorCountRCS := _iCurrentErrorCountRCS + 1;
_iErrorCountRCS := _iErrorCountRCS + 1;
_iErrorIDRCS := _fbReadCurrentState.nErrId;
ELSE
_iCurrentErrorCountRCS := 0;
END_IF
END_IF
IF _eCurrentState = E_KACO_CURRENT_STATE.GRID_CONNECTED OR _eCurrentState = E_KACO_CURRENT_STATE.THROTTLED THEN IF _eCurrentState = E_KACO_CURRENT_STATE.GRID_CONNECTED OR _eCurrentState = E_KACO_CURRENT_STATE.THROTTLED THEN
xActive := TRUE; xActive := TRUE;
ELSE ELSE
xActive := FALSE; xActive := FALSE;
END_IF END_IF
// evaluate inverter errors
// Read current pcu status
_fbReadPCUState(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#01,
nQuantity:= 2,
nMBAddr:= PCU_STATUS_START_REGISTER,
cbLength:= SIZEOF(_stPCUState),
pDestAddr:= ADR(_stPCUState),
bExecute:= _tonPollingTimer.Q AND (NOT _fbReadPCUState.bBusy),
tTimeout:= _tTimeoutPolling,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
IF (NOT _fbReadPCUState.bBusy) THEN
IF _fbReadPCUState.bError THEN
_iCurrentErrorCountRPCUS := _iCurrentErrorCountRPCUS + 1;
_iErrorCountRPCUS := _iErrorCountRPCUS + 1;
_iErrorIDRPCUS := _fbReadPCUState.nErrId;
IF _iCurrentErrorCountRPCUS >= GVL_CONFIG.udiMaxConsecutiveInvError THEN
_xErrorCyclicData := TRUE;
END_IF
ELSE
_iCurrentErrorCountRPCUS := 0;
END_IF
END_IF
IF ((_stPCUState.ePCUState = E_KACO_PCU_STATE.ERROR) OR (_stPCUState.ePCUError <> E_KACO_PCU_ERROR.NO_EVENT)) AND (_stPCUState.ePCUError <> 11) THEN IF ((_stPCUState.ePCUState = E_KACO_PCU_STATE.ERROR) OR (_stPCUState.ePCUError <> E_KACO_PCU_ERROR.NO_EVENT)) AND (_stPCUState.ePCUError <> 11) THEN
// ignore undervoltage error when not enabled // ignore undervoltage error when not enabled
_stPCUStateDebug := _stPCUState; _stPCUStateDebug := _stPCUState;
@@ -595,87 +694,7 @@ IF _eCurrentState = E_KACO_CURRENT_STATE.FAULT AND xReleasePower THEN
_xErrorInverter := TRUE; _xErrorInverter := TRUE;
END_IF END_IF
// Read current dc values // evaluate modbus errors
_fbReadDCValues(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#01, // 16#FF for Modbus TCP
nQuantity:= 6,
nMBAddr:= DC_VALUES_START_REGISTER,
cbLength:= SIZEOF(_awCurrentDCValues),
pDestAddr:= ADR(_awCurrentDCValues),
bExecute:= _tonPollingTimer.Q AND (NOT _fbReadDCValues.bBusy),
tTimeout:= _tTimeoutPolling,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
// Check if reading modbus register is done
IF (NOT _fbReadDCValues.bBusy) THEN
// If there was no error and the converter has no error continue
IF (NOT _fbReadDCValues.bError) THEN
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
// Dont throw comm error here because this is just
// informational data and not process critical
stCurrentValues.rActDCCurrent := 0.0;
stCurrentValues.rActDCVoltage := 0.0;
stCurrentValues.rActDCPower := 0.0;
_iErrorCountRDCV := _iErrorCountRDCV + 1;
_iErrorIDRDCV := _fbReadDCValues.nErrId;
END_IF
END_IF
// Read current ac values
_fbReadACValues(
sIPAddr:= sInverterIPAddr,
nTCPPort:= 502,
nUnitID:= 16#01, // 16#FF for Modbus TCP
nQuantity:= 22,
nMBAddr:= AC_VALUES_START_REGISTER,
cbLength:= SIZEOF(_awCurrentACValues),
pDestAddr:= ADR(_awCurrentACValues),
bExecute:= _tonPollingTimer.Q AND (NOT _fbReadACValues.bBusy),
tTimeout:= _tTimeoutPolling,
bBusy=> ,
bError=> ,
nErrId=> ,
cbRead=> );
// Check if reading mudbus register is done
IF (NOT _fbReadACValues.bBusy) THEN
// If there was no error and the converter has no error continue
IF (NOT _fbReadACValues.bError) THEN
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
// Dont throw comm error here because this is just
// informational data and not process critical
stCurrentValues.rActACCurrent := 0.0;
stCurrentValues.rActtACPhaseACurrent := 0.0;
stCurrentValues.rActtACPhaseBCurrent := 0.0;
stCurrentValues.rActtACPhaseCCurrent := 0.0;
stCurrentValues.rActACPower := 0.0;
stCurrentValues.rActACFreq := 0.0;
stCurrentValues.rActApparentPower := 0.0;
stCurrentValues.rActReactivePower := 0.0;
stCurrentValues.rActPowerFactor := 0.0;
_iErrorCountRACV := _iErrorCountRACV + 1;
_iErrorIDRACV := _fbReadACValues.nErrId;
END_IF
END_IF
IF _iCurrentErrorCountRPCUS >= GVL_CONFIG.udiMaxConsecutiveInvError OR IF _iCurrentErrorCountRPCUS >= GVL_CONFIG.udiMaxConsecutiveInvError OR
_iCurrentErrorCountRCS >= GVL_CONFIG.udiMaxConsecutiveInvError OR _iCurrentErrorCountRCS >= GVL_CONFIG.udiMaxConsecutiveInvError OR
_iCurrentErrorCountWPC >= GVL_CONFIG.udiMaxConsecutiveInvError OR _iCurrentErrorCountWPC >= GVL_CONFIG.udiMaxConsecutiveInvError OR
@@ -702,11 +721,6 @@ END_IF
IF _fbCyclicDataAlarm.eConfirmationState = TcEventConfirmationState.WaitForConfirmation AND xReset THEN IF _fbCyclicDataAlarm.eConfirmationState = TcEventConfirmationState.WaitForConfirmation AND xReset THEN
_fbCyclicDataAlarm.Confirm(0); _fbCyclicDataAlarm.Confirm(0);
END_IF
// Reset polling timer
IF _tonPollingTimer.Q THEN
_tonPollingTimer(IN := FALSE);
END_IF]]></ST> END_IF]]></ST>
</Implementation> </Implementation>
</Action> </Action>
@@ -786,7 +800,9 @@ END_VAR
<Implementation> <Implementation>
<ST><![CDATA[_sName := Name; <ST><![CDATA[_sName := Name;
_fbErrorInverterAlarm.ipArguments.Clear().AddString(_sName);]]></ST> _fbErrorInverterAlarm.ipArguments.Clear().AddString(_sName);
_fbCyclicDataAlarm.ipArguments.Clear().AddString(_sName);
_fbHeartBeatAlarm.ipArguments.Clear().AddString(_sName);]]></ST>
</Implementation> </Implementation>
</Set> </Set>
</Property> </Property>

View File

@@ -263,7 +263,7 @@
</System> </System>
<Plc> <Plc>
<Project GUID="{9AE64910-5EB2-4866-93FD-EFE059C38C36}" Name="PLC" PrjFilePath="PLC\PLC.plcproj" TmcFilePath="PLC\PLC.tmc" ReloadTmc="true" AmsPort="851" FileArchiveSettings="#x000e" CopyTmcToTarget="true" CopyTpyToTarget="false" SymbolicMapping="true"> <Project GUID="{9AE64910-5EB2-4866-93FD-EFE059C38C36}" Name="PLC" PrjFilePath="PLC\PLC.plcproj" TmcFilePath="PLC\PLC.tmc" ReloadTmc="true" AmsPort="851" FileArchiveSettings="#x000e" CopyTmcToTarget="true" CopyTpyToTarget="false" SymbolicMapping="true">
<Instance Id="#x08502000" TcSmClass="TComPlcObjDef" KeepUnrestoredLinks="2" TmcHash="{3B474192-ABB3-08F3-5793-A53CD21DF750}" TmcPath="PLC\PLC.tmc"> <Instance Id="#x08502000" TcSmClass="TComPlcObjDef" KeepUnrestoredLinks="2" TmcHash="{B0096793-1726-0903-97E7-B7D9EB7ED965}" TmcPath="PLC\PLC.tmc">
<Name>PLC Instance</Name> <Name>PLC Instance</Name>
<CLSID ClassFactory="TcPlc30">{08500001-0000-0000-F000-000000000064}</CLSID> <CLSID ClassFactory="TcPlc30">{08500001-0000-0000-F000-000000000064}</CLSID>
<Vars VarGrpType="2" AreaNo="1"> <Vars VarGrpType="2" AreaNo="1">