- Added robot schift params for aligning etcher 1 position - Added HMI Interface to robot fb - Added machine LED's at main cabinet - Aligner now works in auto mode - Added HMI interface to etcher station - Added cReleaseAlarms to HeatCoolPlates - Added HMI interface to HVTester - STarted tray feeder response parsing - Fixed some packml base state machine bugs
451 lines
11 KiB
XML
451 lines
11 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<TcPlcObject Version="1.1.0.1">
|
|
<POU Name="FB_TFProtocol" Id="{f0c44f0b-70b8-45d0-8720-9bd7e08b6aa6}" SpecialFunc="None">
|
|
<Declaration><![CDATA[FUNCTION_BLOCK FB_TFProtocol
|
|
VAR_INPUT
|
|
sIpAddr : STRING(15);
|
|
udiPort : UDINT;
|
|
xConnect : BOOL := TRUE;
|
|
xReleaseAlarms : BOOL;
|
|
xConfirmAlarms : BOOL;
|
|
END_VAR
|
|
VAR_OUTPUT
|
|
stStatus : ST_TrayFeederStatus;
|
|
xConnected : BOOL;
|
|
xNewResponseReady : BOOL;
|
|
xBusy : BOOL;
|
|
xError : BOOL;
|
|
END_VAR
|
|
VAR
|
|
// Connection settings
|
|
_fbTcpConnection : FB_ClientServerConnection;
|
|
_hSocket : T_HSOCKET;
|
|
_xConnected : BOOL;
|
|
|
|
// Socket send
|
|
_fbSocketSend : FB_SocketSend;
|
|
_iCmdLength : INT;
|
|
_timSendTimeout : TIME := T#5S;
|
|
|
|
// Socket receive
|
|
_fbSocketReceive : FB_SocketReceive;
|
|
_timReceiveTimeout : TIME := T#1M;
|
|
_abyReceivedBuffer : ARRAY[0..100] OF BYTE;
|
|
_sReceivedResponse : STRING(255);
|
|
_udiResponseLength : UDINT;
|
|
_udiReceivedBytes : UDINT;
|
|
_timPollingTime : TIME := T#100MS;
|
|
_tonPollTimer : TON;
|
|
_xEnableReceiveTimeout : BOOL;
|
|
_timReceiveResponseTimeout : TIME := T#5S;
|
|
_tonReceiveTimeout : TON;
|
|
|
|
// Receive state machine
|
|
_iStateReceive : INT;
|
|
|
|
// Command parser
|
|
_fbParser : FB_TrayFeederParser;
|
|
|
|
// Command data
|
|
_uiCmdId : UINT := 1;
|
|
_sCmd : STRING(255);
|
|
_sAck : STRING(11);
|
|
|
|
// Main state machine
|
|
_iState : INT := 0;
|
|
_xRunSMAgain : BOOL;
|
|
_diCounter : DINT;
|
|
_xSendCmd : BOOL;
|
|
_uiRetries : UINT;
|
|
_xCmdReceived : BOOL;
|
|
_xReceivedResponseOk : BOOL;
|
|
_uiReceivedCommandId : UINT;
|
|
|
|
// Alarms
|
|
_fbWrongCmdIdAck : FB_AlarmMessage(stEventEntry := TC_EVENTS.TrayFeeder.WrongCmdIdAck, xWithConfirmation := TRUE);
|
|
_fbResponseNotOk : FB_AlarmMessage(stEventEntry := TC_EVENTS.TrayFeeder.ReceivedResponseNotOk, xWithConfirmation := TRUE);
|
|
_fbWrongResponseIndicator : FB_AlarmMessage(stEventEntry := TC_EVENTS.TrayFeeder.WrongResponseIndicator, xWithConfirmation := TRUE);
|
|
_fbSocketReadError : FB_AlarmMessage(stEventEntry := TC_EVENTS.TrayFeeder.SocketReadError, xWithConfirmation := TRUE);
|
|
_fbSocketWriteError : FB_AlarmMessage(stEventEntry := TC_EVENTS.TrayFeeder.SocketWriteError, xWithConfirmation := TRUE);
|
|
|
|
// Buffer before output
|
|
_sResponse : STRING(255);
|
|
_xBusy : BOOL;
|
|
_xError : BOOL;
|
|
END_VAR
|
|
VAR CONSTANT
|
|
{attribute 'naming' := 'off'}
|
|
MAX_RETRIES : UINT := 3;
|
|
{attribute 'naming' := 'on'}
|
|
END_VAR
|
|
]]></Declaration>
|
|
<Implementation>
|
|
<ST><![CDATA[// Call client server connection fb
|
|
_fbTcpConnection(
|
|
sSrvNetID:= '',
|
|
nMode:= ,
|
|
sRemoteHost:= sIpAddr,
|
|
nRemotePort:= udiPort,
|
|
bEnable:= xConnect,
|
|
tReconnect:= T#2S,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
hSocket=> _hSocket,
|
|
eState=> );
|
|
|
|
// Get connected state
|
|
_xConnected := (_fbTcpConnection.eState = E_SocketConnectionState.eSOCKET_CONNECTED);
|
|
|
|
// Receive timeout after sending a command
|
|
_tonReceiveTimeout(IN := _xEnableReceiveTimeout, PT := _timReceiveResponseTimeout);
|
|
|
|
// Receive state machine
|
|
CASE _iStateReceive OF
|
|
// Main socket not connected
|
|
0:
|
|
IF _xConnected THEN
|
|
_iStateReceive := 10;
|
|
END_IF
|
|
|
|
// Call receive
|
|
10:
|
|
{analysis -64}
|
|
_fbSocketReceive(
|
|
sSrvNetId:= '',
|
|
hSocket:= _hSocket,
|
|
cbLen:= SIZEOF(_abyReceivedBuffer) - _udiReceivedBytes,
|
|
pDest:= ADR(_abyReceivedBuffer) + _udiReceivedBytes,
|
|
bExecute:= TRUE,
|
|
tTimeout:= _timReceiveTimeout,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> ,
|
|
nRecBytes=> );
|
|
{analysis +64}
|
|
|
|
IF (NOT _fbSocketReceive.bBusy) AND (NOT _fbSocketReceive.bError) THEN
|
|
_fbSocketReceive(bExecute := FALSE);
|
|
IF _fbSocketReceive.nRecBytes > 0 THEN
|
|
_udiReceivedBytes := _udiReceivedBytes + _fbSocketReceive.nRecBytes;
|
|
_iStateReceive := 20;
|
|
ELSE
|
|
_iStateReceive := 15;
|
|
END_IF
|
|
END_IF
|
|
|
|
// If we have an error, check if we are connected
|
|
IF _fbSocketReceive.bError THEN
|
|
_fbSocketReceive(bExecute := FALSE);
|
|
_fbSocketReadError.xActive := TRUE;
|
|
_iStateReceive := 0;
|
|
END_IF
|
|
|
|
// Wait some time before rechecking
|
|
15:
|
|
_tonPollTimer(IN := TRUE, PT := _timPollingTime);
|
|
|
|
IF _tonPollTimer.Q THEN
|
|
_tonPollTimer(IN := FALSE);
|
|
_iStateReceive := 10;
|
|
END_IF
|
|
|
|
// Check if we are still connected
|
|
IF (NOT _xConnected) THEN
|
|
_tonPollTimer(IN := FALSE);
|
|
//_asReceivedResponse[] := '';
|
|
_iStateReceive := 0;
|
|
END_IF
|
|
|
|
// Check received data
|
|
20:
|
|
// Get command
|
|
MEMSET(destAddr := ADR(_sReceivedResponse), fillByte := 0, n := SIZEOF(_sReceivedResponse));
|
|
MEMCPY(destAddr := ADR(_sReceivedResponse), srcAddr := ADR(_abyReceivedBuffer), n := _udiReceivedBytes);
|
|
_udiResponseLength := _udiReceivedBytes;
|
|
_udiReceivedBytes := 0;
|
|
_xCmdReceived := TRUE;
|
|
|
|
// Go back to polling wait state
|
|
_iStateReceive := 15;
|
|
|
|
// Error
|
|
90:
|
|
_xError := TRUE;
|
|
|
|
IF xConfirmAlarms THEN
|
|
_fbSocketReadError.xActive := FALSE;
|
|
_iState := 0;
|
|
END_IF
|
|
ELSE
|
|
;
|
|
END_CASE
|
|
|
|
REPEAT
|
|
_xRunSMAgain := FALSE;
|
|
CASE _iState OF
|
|
// Wait for active connection to tray feeder
|
|
0:
|
|
IF _xConnected THEN
|
|
_iState := 10;
|
|
END_IF
|
|
|
|
// Connected and idle
|
|
10:
|
|
// Got to disconnected state if connection is lost
|
|
IF (NOT _xConnected) THEN
|
|
_iState := 0;
|
|
END_IF
|
|
|
|
IF _xSendCmd THEN
|
|
_xSendCmd := FALSE;
|
|
_xCmdReceived := FALSE;
|
|
_xBusy := TRUE;
|
|
_iState := 20;
|
|
END_IF
|
|
|
|
// Check if we received a response without sending a command
|
|
IF _xCmdReceived THEN
|
|
_xCmdReceived := FALSE;
|
|
_xRunSMAgain := TRUE;
|
|
_iState := 50;
|
|
END_IF
|
|
|
|
// Send command
|
|
20:
|
|
_fbSocketSend(
|
|
sSrvNetId:= '',
|
|
hSocket:= _hSocket,
|
|
cbLen:= INT_TO_UDINT(_iCmdLength),
|
|
pSrc:= ADR(_sCmd),
|
|
bExecute:= TRUE,
|
|
tTimeout:= _timSendTimeout,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> );
|
|
|
|
IF (NOT _fbSocketSend.bBusy) AND (NOT _fbSocketSend.bError) THEN
|
|
_fbSocketSend(bExecute := FALSE);
|
|
_xEnableReceiveTimeout := TRUE;
|
|
_iState := 30;
|
|
END_IF
|
|
|
|
IF _fbSocketSend.bError THEN
|
|
_fbSocketSend(bExecute := FALSE);
|
|
_fbSocketWriteError.xActive := TRUE;
|
|
_iState := 90;
|
|
END_IF
|
|
|
|
// Wait for response
|
|
30:
|
|
// Received a response
|
|
IF _xCmdReceived THEN
|
|
_xCmdReceived := FALSE;
|
|
_xEnableReceiveTimeout := FALSE;
|
|
_uiRetries := 0;
|
|
_xRunSMAgain := TRUE;
|
|
_iState := 40;
|
|
END_IF
|
|
|
|
// Didn't receive command ack in time
|
|
// So resend the command if max retries are not reached
|
|
IF _tonReceiveTimeout.Q THEN
|
|
_xEnableReceiveTimeout := FALSE;
|
|
_uiRetries := _uiRetries + 1;
|
|
|
|
// Check if we reached the max number of retries
|
|
IF _uiRetries > MAX_RETRIES THEN
|
|
_iState := 90;
|
|
ELSE
|
|
// Retry by sending command again
|
|
_iState := 20;
|
|
END_IF
|
|
END_IF
|
|
|
|
// Check response
|
|
40:
|
|
// Check for cmd id
|
|
IF (_sReceivedResponse[0] <> UINT_TO_BYTE(_uiCmdId+16#30)) THEN
|
|
// Wrong command id received
|
|
_fbWrongCmdIdAck.xActive := TRUE;
|
|
_iState := 90;
|
|
END_IF
|
|
|
|
// For for response indicator
|
|
IF _sReceivedResponse[1] <> F_ToASC('<') THEN
|
|
// Wrong response indicator
|
|
_fbResponseNotOk.xActive := TRUE;
|
|
_iState := 90;
|
|
END_IF
|
|
|
|
// Check for correct cmd
|
|
_xReceivedResponseOk := TRUE;
|
|
FOR _diCounter := 2 TO 10 DO
|
|
IF _sReceivedResponse[_diCounter] <> _sCmd[_diCounter] THEN
|
|
_xReceivedResponseOk := FALSE;
|
|
EXIT;
|
|
END_IF
|
|
END_FOR
|
|
|
|
IF _xReceivedResponseOk THEN
|
|
_xBusy := FALSE;
|
|
_iState := 10;
|
|
ELSE
|
|
_fbResponseNotOk.xActive := TRUE;
|
|
_iState := 90;
|
|
END_IF
|
|
|
|
// Got command from tray feeder which needs to be acknowledged
|
|
50:
|
|
IF _sReceivedResponse[1] <> F_ToASC('<') THEN
|
|
xNewResponseReady := TRUE;
|
|
MEMSET(ADR(_sResponse), 0, n := SIZEOF(_sResponse));
|
|
MEMCPY(destAddr := ADR(_sResponse), srcAddr := ADR(_sReceivedResponse)+1, n := _udiResponseLength-1);
|
|
END_IF
|
|
|
|
// Copy first 11 bytes
|
|
FOR _diCounter := 0 TO 10 DO
|
|
_sAck[_diCounter] := _sReceivedResponse[_diCounter];
|
|
END_FOR
|
|
|
|
// Switch command indicator to ack indicator
|
|
_sAck[1] := F_ToASC('<');
|
|
|
|
// Check if it is something we need to acknowledge
|
|
IF _sReceivedResponse[1] = F_ToASC('>') THEN
|
|
// Get command id
|
|
_uiReceivedCommandId := _sReceivedResponse[0] - 16#30;
|
|
_xRunSMAgain := TRUE;
|
|
_iState := 70;
|
|
ELSE
|
|
_xRunSMAgain := TRUE;
|
|
_iState := 10;
|
|
END_IF
|
|
|
|
// Send ack response
|
|
70:
|
|
// Ack is always 11 bytes long (11 characters)
|
|
_fbSocketSend(
|
|
sSrvNetId:= '',
|
|
hSocket:= _hSocket,
|
|
cbLen:= 11,
|
|
pSrc:= ADR(_sAck),
|
|
bExecute:= TRUE,
|
|
tTimeout:= _timSendTimeout,
|
|
bBusy=> ,
|
|
bError=> ,
|
|
nErrId=> );
|
|
|
|
IF (NOT _fbSocketSend.bBusy) AND (NOT _fbSocketSend.bError) THEN
|
|
_fbSocketSend(bExecute := FALSE);
|
|
_xEnableReceiveTimeout := TRUE;
|
|
_xBusy := FALSE;
|
|
_iState := 80;
|
|
END_IF
|
|
|
|
IF _fbSocketSend.bError THEN
|
|
_fbSocketSend(bExecute := FALSE);
|
|
_iState := 90;
|
|
END_IF
|
|
|
|
// Parse response
|
|
80:
|
|
_xRunSMAgain := TRUE;
|
|
_fbParser.M_ParseCmd(_sResponse);
|
|
stStatus := _fbParser.stStatus;
|
|
_iState := 10;
|
|
|
|
// Error
|
|
90:
|
|
_xError := TRUE;
|
|
_xBusy := FALSE;
|
|
|
|
IF xConfirmAlarms THEN
|
|
_xError := FALSE;
|
|
_uiRetries := 0;
|
|
_fbWrongCmdIdAck.xActive := FALSE;
|
|
_fbResponseNotOk.xActive := FALSE;
|
|
_fbWrongResponseIndicator.xActive := FALSE;
|
|
_fbSocketWriteError.xActive := FALSE;
|
|
_iState := 0;
|
|
END_IF
|
|
|
|
ELSE
|
|
;
|
|
END_CASE
|
|
UNTIL (NOT _xRunSMAgain)
|
|
END_REPEAT
|
|
|
|
// Handle alarms
|
|
_fbWrongCmdIdAck(
|
|
xRelease:= xReleaseAlarms,
|
|
xAcknowledge:= xConfirmAlarms);
|
|
|
|
_fbResponseNotOk(
|
|
xRelease:= xReleaseAlarms,
|
|
xAcknowledge:= xConfirmAlarms);
|
|
|
|
_fbWrongResponseIndicator(
|
|
xRelease:= xReleaseAlarms,
|
|
xAcknowledge:= xConfirmAlarms);
|
|
|
|
_fbSocketReadError(
|
|
xRelease:= xReleaseAlarms,
|
|
xAcknowledge:= xConfirmAlarms);
|
|
|
|
_fbSocketWriteError(
|
|
xRelease:= xReleaseAlarms,
|
|
xAcknowledge:= xConfirmAlarms);
|
|
|
|
// Copy output buffers to outputs
|
|
stStatus := _fbParser.stStatus;
|
|
xConnected := _xConnected;
|
|
xBusy := _xBusy;
|
|
xError := _xError;]]></ST>
|
|
</Implementation>
|
|
<Method Name="M_GetResponse" Id="{7a67e859-37fc-4044-a956-f01ee59f215c}">
|
|
<Declaration><![CDATA[METHOD M_GetResponse : STRING(255)
|
|
VAR_INPUT
|
|
END_VAR
|
|
]]></Declaration>
|
|
<Implementation>
|
|
<ST><![CDATA[M_GetResponse := _sResponse;
|
|
xNewResponseReady := FALSE;]]></ST>
|
|
</Implementation>
|
|
</Method>
|
|
<Method Name="M_SendCmd" Id="{d00a8c1a-c183-4659-9c9e-be5b30566b7c}">
|
|
<Declaration><![CDATA[METHOD M_SendCmd : BOOL
|
|
VAR_INPUT
|
|
sCmd : STRING(80);
|
|
END_VAR
|
|
]]></Declaration>
|
|
<Implementation>
|
|
<ST><![CDATA[// Check if we are already sending a command
|
|
IF _xBusy OR _xError THEN
|
|
M_SendCmd := FALSE;
|
|
RETURN;
|
|
END_IF
|
|
|
|
// Increment command id
|
|
_uiCmdId := _uiCmdId + 1;
|
|
|
|
// Overflows at 9 and is reset to 1
|
|
IF _uiCmdId > 9 THEN
|
|
_uiCmdId := 1;
|
|
END_IF
|
|
|
|
// Create command with id
|
|
_sCmd := CONCAT(UINT_TO_STRING(_uiCmdId), '>');
|
|
_sCmd := CONCAT(_sCmd, sCmd);
|
|
_iCmdLength := LEN(_sCmd);
|
|
|
|
// start sending command state machine
|
|
_xSendCmd := TRUE;
|
|
_xBusy := TRUE;
|
|
xNewResponseReady := FALSE;
|
|
|
|
M_SendCmd := TRUE;]]></ST>
|
|
</Implementation>
|
|
</Method>
|
|
</POU>
|
|
</TcPlcObject> |