#ConnectData.InterfaceId := "Local~PROFINET_interface_1";
#ConnectData.ID := USINT_TO_WORD(#fbIPAddress.IPParam.IPAddress[3]);
#ConnectData.ConnectionType := 11;
#ConnectData.ActiveEstablished := True;
#Modbus.Mode := 103; //read only at present, use 116 to write
#ConnectData.RemoteAddress.ADDR[1] := #fbIPAddress.IPParam.IPAddress[0];
#ConnectData.RemoteAddress.ADDR[2] := #fbIPAddress.IPParam.IPAddress[1];
#ConnectData.RemoteAddress.ADDR[3] := #fbIPAddress.IPParam.IPAddress[2];
#ConnectData.RemoteAddress.ADDR[4] := #fbIPAddress.IPParam.IPAddress[3];
#ConnectData.RemotePort := 502;
#ConnectData.LocalPort := 0;
IF #ModbusSeq[#iDriveIndex] AND NOT #bStartEdgeStore THEN
#ParamStateMachine.bStart := True;
END_IF;
#bStartEdgeStore := #ModbusSeq[#iDriveIndex];
CASE #ParamStateMachine.iState OF
0:
//modbus idle wait for start
#Modbus.bREQ := False;
#Modbus.bDISCONNECT := true;
IF #ParamStateMachine.bStart THEN
#iRetVal:=RD_SYS_T(#dtThen);
#ParamStateMachine.iState += 1;
END_IF;
1:
//skip if menu is -1
IF #aParameterList[#iListIndex].iMenuNumber = -1 THEN
#ParamStateMachine.iState := 100;
ELSE
#Modbus.bREQ := True;
#Modbus.bDISCONNECT := False;
#Modbus.diModbusAddress := 16384 + (100 * #aParameterList[#iListIndex].iMenuNumber) + (#aParameterList[#iListIndex].iParameterNumber - 1);
IF (#Modbus.wStatus = 16#7000) OR (#Modbus.wStatus = 16#7004) OR (#Modbus.wStatus = 16#0) THEN
#ParamStateMachine.iState += 1;
END_IF;
END_IF;
IF #fbTimeOut.Q THEN
#ParamStateMachine.iState := 100;
#ParamStateMachine.iErrorState := #ParamStateMachine.iState;
#aParameterList[#iListIndex].wErrorCode := 16#FFFF;
END_IF;
2: //read modbus data
#Modbus.bREQ := TRUE;
#Modbus.bDISCONNECT := False;
IF #Modbus.bDone THEN
#aParameterList[#iListIndex].diValue := #Modbus.aModbusData[1];
#aParameterList[#iListIndex].wErrorCode := #Modbus.wStatus;
#ParamStateMachine.iState += 1;
ELSE
//if error then skip to next
IF WORD_TO_INT(#Modbus.wStatus) < 0 THEN
#aParameterList[#iListIndex].wErrorCode := #Modbus.wStatus;
#ParamStateMachine.iErrorState := #ParamStateMachine.iState;
#ParamStateMachine.iState := 100;
END_IF;
END_IF;
IF #fbTimeOut.Q THEN
#ParamStateMachine.iState := 100;
#ParamStateMachine.iErrorState := #ParamStateMachine.iState;
#aParameterList[#iListIndex].wErrorCode := 16#FFFF;
END_IF;
3:
#Modbus.bREQ := false;
#Modbus.bDISCONNECT := False;
IF WORD_TO_INT(#Modbus.wStatus) = 16#7004 THEN
#ParamStateMachine.iState += 1;
ELSE
IF WORD_TO_INT(#Modbus.wStatus) < 0 THEN
#ParamStateMachine.iState := 100;
#ParamStateMachine.iErrorState := #ParamStateMachine.iState;
END_IF;
END_IF;
IF #fbTimeOut.Q THEN
#ParamStateMachine.iState := 100;
#ParamStateMachine.iErrorState := #ParamStateMachine.iState;
#aParameterList[#iListIndex].wErrorCode := 16#FFFF;
END_IF;
4,100:
#iListIndex += 1;
#bEndOfList := True;
WHILE (#iListIndex <= #PARAM_LIST_SIZE) DO
IF (#aParameterList[#iListIndex].iMenuNumber <> -1) THEN //if menu no = -1 then skip entry
#bEndOfList := False;
EXIT; //break out of while
ELSE
#iListIndex += 1;
END_IF;
END_WHILE;
IF #bEndOfList THEN //all parameters read for current drive, move on to next drive
#iRetVal := RD_SYS_T(#dtNow);
#tParamReadTime := T_DIFF(IN1:=#dtNow, IN2:=#dtThen);
#iListIndex := 1;
#ParamStateMachine.bStart := False; //stop modbus client processing for this drive
#ModbusSeq[#iDriveIndex] := False;
IF #iDriveIndex = #iLastIndex THEN //if at last drive then start proccessing for first drive
#ModbusSeq[1] := True;
ELSE
#ModbusSeq[#iDriveIndex+1] := True; //move on to next drive
END_IF;
#ParamStateMachine.iState := 0;
ELSE
#ParamStateMachine.iState := 1;
END_IF;
ELSE
#ParamStateMachine.iState := 0;
END_CASE;
//timout if stuck in state machine
#fbTimeOut(IN := ((#ParamStateMachine.iState <> 0) AND (#ParamStateMachine.iState = #ParamStateMachine.iPreviousState)),
PT := t#1s);
#ParamStateMachine.iPreviousState:=#ParamStateMachine.iState;