当前位置: 首页 > news >正文

Beckhoff(倍福) -- MES(ITAC) TCP 通讯

一、主程序里对通讯程序的调用

1、主程序 FBD编程

二、实例化2个容器,配置IP地址、端口

1、通讯程序内容,FBD编程

2、容器1 变量声明

PROGRAM PRG_Cell2_SetupControl_GEN2_Ass1_V2_0
(*---------------------------------------------*)
(*IN variables*)
(*---------------------------------------------*)
VAR_INPUTsIn_CapacityNo			: STRING[cCapNameLen];        //容器数量sIn_IpAddress			: STRING;                     //IP地址   PLC作为服务器uiIn_Port				: UINT;                       //端口
END_VAR(*---------------------------------------------*)
(*OUT variables*)
(*---------------------------------------------*)
VAR_OUTPUTbOUT_SetupComplete	:BOOL;bOUT_OrderDone		:BOOL;bOUT_Connected		:BOOL;
END_VAR(*---------------------------------------------*)
(*IN/OUT variables*)
(*---------------------------------------------*)
VAR_IN_OUTsInOut_BarcodeScanner1		: STRING[33];sInOut_BarcodeMachine			: STRING[33];stInOut_arst_SetupControl		: ST_SetupControl_ITAC_V2_0;stInOut_HMI_SetupControl		: ST_HMI_SetupControl;
END_VAR(*---------------------------------------------*)
(*Local Constants*)
(*---------------------------------------------*)
VAR CONSTANTiNumFeeders	: INT :=1;
END_VAR(*---------------------------------------------*)
(*Local variables*)
(*---------------------------------------------*)
VARi							:INT;j							:INT;MMC_COM						:FB_MMC_COM_V2_5_0; Station_INPUT				:FB_INPUT_V2_2;Station_RemoveBIN			:FB_RemoveBIN_V1_0;afb_Station_Feeder			:ARRAY[1..iNumFeeders] OF FB_FEEDER_V2_0;ab_FeederFull				:ARRAY[1..iNumFeeders] OF BOOL;ab_Feeder_SetupControlOK	:ARRAY[1..iNumFeeders] OF BOOL;iFeeder:INT;bTempUnlockFeeder: BOOL;
END_VAR(*---------------------------------------------*)
(*Lokal temp variables*)
(*---------------------------------------------*)
VAR
END_VAR

3、容器1程序代码

(* Get barcode data                                        *)
(*---------------------------------------------------------*)
IF sInOut_BarcodeScanner1 <> '' THENstInOut_arst_SetupControl.ScannerInput.sBarcodeRead := sInOut_BarcodeScanner1;sInOut_BarcodeScanner1	:= '';
END_IF;(*
IF sBarcodeReadScanner2 <> '' THENstInOut_arst_SetupControl..ScannerInput.sBarcodeRead := sBarcodeReadScanner2;sBarcodeReadScanner2	:= '';
END_IF;*)IF sInOut_BarcodeMachine <> '' THENstInOut_arst_SetupControl.ScannerInput.sBarcodeRead := sInOut_BarcodeMachine;sInOut_BarcodeMachine	:= '';
END_IF;(*---------------------------------------------*)(* Call Input Scanner                  *)
(*---------------------------------------------*)
(* Parameter *)(*Cell1_INPUT.FAMILY_FEEDER[1] 	:= M300.FEEDER_POS[1];	(* material family positions 	*)*)Station_INPUT.STATION 				:= ADR(stInOut_arst_SetupControl);			(* to main data structure 		*)Station_INPUT();(*---------------------------------------------------------*)
(* MMC communication                                  *)
(*---------------------------------------------------------*)MMC_COM (ptIN_STATION_ITAC := ADR(stInOut_arst_SetupControl.ITAC));stInOut_arst_SetupControl.ITAC.sCapacityNo 									:= sIn_CapacityNo;stInOut_arst_SetupControl.ITAC.MMC_Comm.CONVERSION_INTERFACE.uiPort			:= uiIn_Port;stInOut_arst_SetupControl.ITAC.MMC_Comm.CONVERSION_INTERFACE.sAddress		:= sIn_IpAddress;bOUT_Connected	:=  stInOut_arst_SetupControl.ITAC.MMC_Comm.CONVERSION_INTERFACE.bConnected;(*---------------------------------------------------------*)
(*FEEDER                                  *)
(*---------------------------------------------------------*)actFeeder();
(*---------------------------------------------------------*)
(*HMI-Interface                                  *)
(*---------------------------------------------------------*)stInOut_HMI_SetupControl.bDoneFeeder		:=	stInOut_arst_SetupControl.ScannerInput.bDoneFeeder;stInOut_HMI_SetupControl.bDoneMaterial		:=	stInOut_arst_SetupControl.ScannerInput.bDoneMaterial;stInOut_HMI_SetupControl.bDoneOrder			:=	stInOut_arst_SetupControl.ScannerInput.bDoneOrder;stInOut_HMI_SetupControl.bSetupComplete 	:=	stInOut_arst_SetupControl.bSetupComplete;stInOut_HMI_SetupControl.sBarcodeRead		:=	stInOut_arst_SetupControl.ScannerInput.sBarcodeRead;stInOut_HMI_SetupControl.sErrText			:=	stInOut_arst_SetupControl.ScannerInput.sErrText;stInOut_HMI_SetupControl.szBarcodeFeeder	:=	stInOut_arst_SetupControl.ScannerInput.szLastScanBarcodeFeeder;stInOut_HMI_SetupControl.szBarcodeMat		:=	stInOut_arst_SetupControl.ScannerInput.szLastScanBarcodeMat;stInOut_HMI_SetupControl.szBarcodeOrder		:=	stInOut_arst_SetupControl.ScannerInput.szLastScanBarcodeOrder;stInOut_HMI_SetupControl.iMaxFeederStation	:=	cUsedFeederStation;FOR i := 1 TO cMaxFeederStation DOstInOut_HMI_SetupControl.FEEDER[i].bFeederON			:=	stInOut_arst_SetupControl.FEEDER_POS[i].HandShake.bFeederON;stInOut_HMI_SetupControl.FEEDER[i].bFeederSetupIO		:=	stInOut_arst_SetupControl.FEEDER_POS[i].HandShake.bFeederSetupIO;stInOut_HMI_SetupControl.FEEDER[i].bFeederSetupNIO		:=	stInOut_arst_SetupControl.FEEDER_POS[i].HandShake.bFeederSetupNIO;stInOut_HMI_SetupControl.FEEDER[i].sMatNo				:=	stInOut_arst_SetupControl.FEEDER_POS[i].ACT_SETUP.sMatNo;
END_FOR;(*---------------------------------------------------------*)
(*Setup Complete                                 *)
(*---------------------------------------------------------*)
bOUT_SetupComplete := stInOut_arst_SetupControl.bSetupComplete;(*---------------------------------------------------------*)
(*Order Done to machine                                 *)
(*---------------------------------------------------------*)
bOUT_OrderDone := stInOut_arst_SetupControl.ScannerInput.bDoneOrder;

4、容器1代码解读

1. 条形码扫描处理

IF sInOut_BarcodeScanner1 <> '' THENstInOut_arst_SetupControl.ScannerInput.sBarcodeRead := sInOut_BarcodeScanner1;sInOut_BarcodeScanner1 := '';
END_IF;
  • 功能:检测条形码扫描仪输入,将扫描结果存入数据结构 stInOut_arst_SetupControl,并清空输入缓冲区。
  • 多扫描仪支持:代码支持多个扫描仪(Scanner1、Scanner2、Machine),但 Scanner2 被注释,实际使用 Scanner1 和 Machine。

2. 输入扫描处理

Station_INPUT.STATION := ADR(stInOut_arst_SetupControl);
Station_INPUT();
  • 功能:调用 Station_INPUT 功能块,传入数据结构指针,处理扫描到的条形码数据(如解析物料、订单、供料器信息)。

3. MMC 通信控制

MMC_COM (ptIN_STATION_ITAC := ADR(stInOut_arst_SetupControl.ITAC));
  • 功能:通过 MMC_COM 功能块实现与制造执行系统(MES)或上位机的通信,同步生产数据(如产能编号、IP 地址、端口)。
  • 参数设置:配置 ITAC 通信模块的参数,包括容量编号、IP 地址和端口。

4. 供料器管理

actFeeder();
  • 功能:调用 actFeeder() 函数,控制生产线的供料器(如激活、校准、物料分配)。

5. 人机界面(HMI)数据同步

stInOut_HMI_SetupControl.bDoneFeeder := stInOut_arst_SetupControl.ScannerInput.bDoneFeeder;
// 其他HMI变量同步...
  • 功能:将核心数据结构 stInOut_arst_SetupControl 中的状态和结果同步到 HMI 专用数据结构 stInOut_HMI_SetupControl,供操作人员查看。
  • 同步内容:包括条形码扫描状态、错误信息、供料器状态(如是否在线、物料编号)等。

6. 循环同步供料器数据

FOR i := 1 TO cMaxFeederStation DOstInOut_HMI_SetupControl.FEEDER[i].bFeederON := stInOut_arst_SetupControl.FEEDER_POS[i].HandShake.bFeederON;// 其他供料器变量同步...
END_FOR;
  • 功能:遍历所有供料器(1 到最大数量),将每个供料器的状态(如是否开启、物料编号)同步到 HMI。

7. 输出状态信号

bOUT_SetupComplete := stInOut_arst_SetupControl.bSetupComplete;
bOUT_OrderDone := stInOut_arst_SetupControl.ScannerInput.bDoneOrder;
  • 功能:将系统状态输出到外部信号,用于触发后续操作(如生产线启动、订单完成通知)。

三、Station_INPUT  实例

1、变量声明代码     station_INPUT 实例化  FUNCTION_BLOCK_FB_INPUT_V2_2

FUNCTION_BLOCK FB_INPUT_V2_2VAR CONSTANTcStepTime		:TIME 	:= t#60m;cTimeoutMMC		:TIME	:= t#10s;cTimeoutError	:TIME	:= t#10s;cTimeoutUser	:TIME	:= T#10S;cTimeoutMessage	:STRING	:= 'Timout MMC communication';cMessageUser1	:STRING := 'Waiting for feeder scan Timout -> ABORT';cMessageUser2	:STRING := 'Waiting for Material scan Timout -> ABORT';cErrStep		:UINT	:= 499;
END_VARVAR_INPUTSTATION			:POINTER TO ST_SetupControl_ITAC_V2_0;FAMILY_FEEDER	:ARRAY[1..cMaxFamilyFeeder] OF ST_FEEDER_POS;
END_VARVAR_IN_OUTEND_VARVARiBCLen					:INT;uiBCtype				:UINT;			(*Byte 12 of the Barcode which describes the type *)uiBCtypeMat				:UINT;bMatFound				:BOOL;rCode,i,j,k,m,n,w			:INT;feederPreSetup				:INT;iStep,iOldStep			:INT;FB_TON_StepTime			:TON;tTimeInTheStep			:TIME;(* Internal  *)arFeederBomIdx	:ARRAY[1..cMaxFeederStation] OF UINT;sArg1 : STRING[MAX_STRING_LENGTH];sArg2 : STRING[MAX_STRING_LENGTH];sArg3 : STRING[MAX_STRING_LENGTH];(* used FBs *)FormatString	:FB_FormatString;bTemp: BOOL;btestOrderBarcode: BOOL;bTestMaterial: BOOL;
END_VAR

2、Station_INPUT  程序代码 

(*---------------------------------------------*)
(* Check Times *)
(*---------------------------------------------*)actTimingSystem();(*---------------------------------------------*)
(* Check Scanner                               *)
(*---------------------------------------------*)actBarcodeSwitch();actCheckSetupComplete();(*actVerifyPreSetupAktiv;*)IF NOT STATION^.bMoveSetupActive THENactCheckMoveSetupActive();END_IF(*---------------------------------------------*)
(* INIT indices *)
(*---------------------------------------------*)FOR i := 1 TO cMaxFeederStation DO arFeederBomIdx[i] := 0; END_FOR;(*---------------------------------------------*)
(* MainLoop                                    *)
(*---------------------------------------------*)CASE iStep OF0: (* INIT *)STATION^.ScannerInput.uiCodeSelect		:=0;STATION^.ScannerInput.bError			:=FALSE;STATION^.ScannerInput.sErrText			:='';STATION^.ScannerInput.sBarcodeRead		:='';	(* clear scan, operator needed to start from the beginning *)iStep 	:= iStep+1;(*---------------------------------------------*)
(* MAIN DISTRIBUTION HERE                      *)   //在这儿主分配
(*---------------------------------------------*)1: (* wait for something 	*)(*IF bMove_PRE_TO_ACT_SETUP THENbMove_PRE_TO_ACT_SETUP := FALSE;iStep := 400;RETURN;END_IF;*)actCheckSetupComplete(); (*11.11.2018 SD add CheckSetupComplete*)IF NOT STATION^.bMoveSetupActive THENactCheckMoveSetupActive();END_IF(*actVerifyPreSetupAktiv;*)CASE STATION^.ScannerInput.uiCodeSelect OF0:	(* Wait *)IF tTimeInTheStep >  cTimeoutUser THENSTATION^.ScannerInput.bPreSetup	:= FALSE;END_IF;;1:	(* BarCode = Feeder *)STATION^.ScannerInput.sErrText			:= 'Warning: Scan Material FIRST!';iStep := cErrStep;2:	(* BarCode = Order Code *)iStep := 5;3:	(* BarCode = Material Code *)iStep := 100;4:	(* BarCode = PreSetup Code *) (*19.11.2019 SD add PreSetup*)STATION^.ScannerInput.bPreSetup	:= TRUE;STATION^.ScannerInput.uiCodeSelect	:= 0; 		(* unlock Scanner *)iStep := 0 ;ELSESTATION^.ScannerInput.sErrText := 'PROGRAM ERROR: unknown Scanner idx';iStep := cErrStep;END_CASE;(*---------------------------------------------*)
(* SUB Scan Order                              *)     //子订单码
(*---------------------------------------------*)5:STATION^.ScannerInput.bDoneOrder 				:= FALSE;STATION^.ScannerInput.szLastScanBarcodeFeeder 	:= '';(*11.10.2018 SD add LastScan*)STATION^.ScannerInput.szLastScanBarcodeMat 		:= '';(*11.10.2018 SD add LastScan*)STATION^.ScannerInput.bDoneMaterial 			:= FALSE;STATION^.ScannerInput.bDoneFeeder 				:= FALSE;actPrepareOrder();6: (* wait for answer *)IF STATION^.ITAC.MMC_Comm.SET_OBC.bRecACK THENIF STATION^.ITAC.MMC_Comm.SET_OBC.sOrderBarCodeREC <> STATION^.ITAC.MMC_Comm.SET_OBC.sOrderBarCode THENsArg1 := STATION^.ITAC.MMC_Comm.SET_OBC.sOrderBarCodeREC;sArg2 := STATION^.ITAC.MMC_Comm.SET_OBC.sOrderBarCode;FormatString(	sFormat	:= '06| SCAN_ORDER: Recieved WTRCode  [%s] is not matching with sent WTRCode [%s]',arg1 	:= F_STRING (sArg1),arg2 	:= F_STRING (sArg2),sOut	=> STATION^.ScannerInput.sErrText);iStep := cErrStep;END_IF;iStep := iStep+1;	(* Order = IO -> continue *)ELSIF	STATION^.ITAC.MMC_Comm.SET_OBC.bError THEN (* Set Error *)sArg1 := STATION^.ITAC.MMC_Comm.SET_OBC.sErrText;FormatString(	sFormat	:= '03| SCAN_ORDER: >> %s',arg1 	:= F_STRING (sArg1),sOut	=> STATION^.ScannerInput.sErrText);iStep := cErrStep;ELSIF tTimeInTheStep > cTimeoutMMC THEN (* Timeout *)STATION^.ScannerInput.sErrText	:= cTimeoutMessage;iStep := cErrStep;END_IF;7: (* check Order data *)actPrepareGetWBM();8: (* Wait for ACK WBM *)IF STATION^.ITAC.MMC_Comm.GET_WBM.bRecACKAND NOT STATION^.ITAC.MMC_Comm.GET_WBM.bError THEN (* Check GET WBM sucessfully done *)(******)	(*---------------------------------------------*)
(* BOM input completed now transfer to feeder  *)
(*---------------------------------------------*)
(* clear old BOB *)
(* Attention, 1. capcity is used for verification *)IF STATION^.ITAC.MMC_Comm.GET_WBM.starBOMItems[1].sCapacity = STATION^.ITAC.sCapacityNo THENFOR j := 1 TO cMaxFeederStation DOFOR k := 1 TO cMaxAltMaterial DOSTATION^.FEEDER_POS[j].BOM[k].sMatNo   	:= '';STATION^.FEEDER_POS[j].BOM[k].sMatText	:= '';STATION^.FEEDER_POS[j].BOM[k].sSupplierNumber	:= '';END_FOR;END_FOR;ELSEsArg1 := STATION^.ITAC.MMC_Comm.GET_WBM.starBOMItems[1].sCapacity;sArg2 := STATION^.ITAC.sCapacityNo;FormatString(sFormat := '08| GET_WBM decoder: Capacity in BOM [%s] <> machine [%s]',arg1 := F_STRING (sArg1),arg2 := F_STRING (sArg2),sOut => STATION^.ITAC.MMC_Comm.GET_WBM.sErrText);STATION^.ITAC.MMC_Comm.GET_WBM.bError	:= TRUE;RETURN;END_IF;(* now store material on feeder                *)FOR k := 1 TO cMAxMMC_BOM DO(* Check Capacity *)IF STATION^.ITAC.MMC_Comm.GET_WBM.starBOMItems[k].sCapacity = STATION^.ITAC.sCapacityNo THENCASE STATION^.ITAC.MMC_Comm.GET_WBM.starBOMItems[k].uiFeeder OF1..cMaxFeederStation:(* BOM idx!!! *)arFeederBomIdx[STATION^.ITAC.MMC_Comm.GET_WBM.starBOMItems[k].uiFeeder] := arFeederBomIdx[STATION^.ITAC.MMC_Comm.GET_WBM.starBOMItems[k].uiFeeder] + 1; (* increase BOM index *)IF arFeederBomIdx[STATION^.ITAC.MMC_Comm.GET_WBM.starBOMItems[k].uiFeeder] <= cMaxAltMaterial THENj := arFeederBomIdx[STATION^.ITAC.MMC_Comm.GET_WBM.starBOMItems[k].uiFeeder];STATION^.FEEDER_POS[STATION^.ITAC.MMC_Comm.GET_WBM.starBOMItems[k].uiFeeder].BOM[j].sMatNo   := STATION^.ITAC.MMC_Comm.GET_WBM.starBOMItems[k].sMatSNR;STATION^.FEEDER_POS[STATION^.ITAC.MMC_Comm.GET_WBM.starBOMItems[k].uiFeeder].BOM[j].sMatText := STATION^.ITAC.MMC_Comm.GET_WBM.starBOMItems[k].sMatText;(* Take over actual Order *)STATION^.FEEDER_POS[STATION^.ITAC.MMC_Comm.GET_WBM.starBOMItems[k].uiFeeder].HandShake.bBOMCheckReady	:= TRUE;STATION^.ITAC.sOrder := STATION^.ITAC.MMC_Comm.GET_WBM.sOrderBarCodeRecv;ELSE(* Error Message *)rCode:= cMaxAltMaterial;FormatString(sFormat := '09| GET_WBM decoder: Feeder [%d] too many materials found [%d] max [%d]',arg1 := F_UINT (STATION^.ITAC.MMC_Comm.GET_WBM.starBOMItems[k].uiFeeder),arg2 := F_UINT (arFeederBomIdx[STATION^.ITAC.MMC_Comm.GET_WBM.starBOMItems[k].uiFeeder]),arg3 := F_INT (rCode),sOut => STATION^.ITAC.MMC_Comm.GET_WBM.sErrText);STATION^.ITAC.MMC_Comm.GET_WBM.bError	:= TRUE;RETURN;END_IF;END_CASE;ELSIF STATION^.ITAC.MMC_Comm.GET_WBM.starBOMItems[k].sCapacity <>'' THEN(* Error Message *)sArg1 := STATION^.ITAC.MMC_Comm.GET_WBM.starBOMItems[k].sCapacity;sArg2 := STATION^.ITAC.sCapacityNo;FormatString(sFormat := '10| GET_WBM decoder: Capacity in BOM [%s] <> machine [%s]',arg1 := F_STRING (sArg1),arg2 := F_STRING (sArg2),sOut => STATION^.ITAC.MMC_Comm.GET_WBM.sErrText);STATION^.ITAC.MMC_Comm.GET_WBM.bError	:= TRUE;RETURN;END_IF;(* capacity check *)END_FOR; (* k *)(******)STATION^.ScannerInput.bDoneOrder := TRUE;iStep := iStep + 1;ELSIF	STATION^.ITAC.MMC_Comm.GET_WBM.bError THENsArg1 := STATION^.ITAC.MMC_Comm.GET_WBM.sErrText;FormatString(	sFormat	:= '06| SCAN_ORDER: %s',arg1 	:= F_STRING (sArg1),sOut	=> STATION^.ScannerInput.sErrText);iStep := cErrStep;ELSIF tTimeInTheStep > cTimeoutMMC THEN (* Timeout *)STATION^.ScannerInput.sErrText	:= cTimeoutMessage;iStep := cErrStep;END_IF;9: (* Check actual feeder setup *)actVerifyFeederSetup();iStep := iStep+1;10: (* Check Setup Complete       *)(*actCheckSetupComplete;*)IF STATION^.bSetupComplete THEN(* Set ACT *)STATION^.ITAC.MMC_Comm.SET_ACT.bSendRequest := TRUE; (*11.10.2018 SD add SET_ACT*)iStep := iStep+1;END_IF;iStep := 0 ; (* ReLoop *)11: (* Wait for answer from ACK ACT *)(*11.10.2018 SD add SET_ACT*)IF STATION^.ITAC.MMC_Comm.SET_ACT.bRecACK THENiStep := iStep+1;ELSIF	STATION^.ITAC.MMC_Comm.SET_ACT.bError THEN (* Set Error *)STATION^.ScannerInput.bError	:= TRUE;sArg1 := STATION^.ITAC.MMC_Comm.SET_ACT.sErrText;FormatString(	sFormat	:= '11| SCAN_ORDER: >> %s',arg1 		:= F_STRING (sArg1),sOut		=> STATION^.ScannerInput.sErrText);iStep := cErrStep;ELSIF tTimeInTheStep > cTimeoutMMC THEN (* Timeout *)STATION^.ScannerInput.sErrText	:= cTimeoutMessage;iStep := cErrStep;END_IF;12:iStep := 0 ; (* ReLoop *)(*---------------------------------------------*)
(* SUB Scan Material                           *)
(*---------------------------------------------*)100: (* Scan MatCode    		*)STATION^.ScannerInput.bDoneMaterial 			:= FALSE;STATION^.ScannerInput.szLastScanBarcodeFeeder 	:= '';STATION^.ScannerInput.bDoneFeeder 				:= FALSE;actPrepareMaterial();101:	(* wait for answer 		*)IF STATION^.ITAC.MMC_Comm.GET_MB.bRecACK THENiStep := iStep+1;ELSIF	STATION^.ITAC.MMC_Comm.GET_MB.bError THEN (* Set Error *)STATION^.ScannerInput.bError	:= TRUE;sArg1 := STATION^.ITAC.MMC_Comm.GET_MB.sErrText;FormatString(	sFormat	:= '03| SCAN_MAT: >> %s',arg1 	:= F_STRING (sArg1),sOut	=> STATION^.ScannerInput.sErrText);iStep := cErrStep;ELSIF tTimeInTheStep > cTimeoutMMC THEN (* Timeout *)STATION^.ScannerInput.sErrText	:= cTimeoutMessage;iStep := cErrStep;END_IF;102:STATION^.ScannerInput.bDoneMaterial := TRUE;STATION^.ScannerInput.uiCodeSelect	:= 0; 		(* unlock Scanner *)iStep := 200 ;(*---------------------------------------------*)
(* SUB Scan Feeder                             *)
(*---------------------------------------------*)200:(* wait feeder  *)(*----------------------------------------------*)(* standard feeder 								*)(*----------------------------------------------*)IF STATION^.ScannerInput.uiCodeSelect = 1 AND NOT STATION^.ScannerInput.bPreSetup THEN(* Save feeder number *)STATION^.ScannerInput.uiMaterialFeeder	:= STRING_TO_UINT(RIGHT(STATION^.ScannerInput.szBarcodeFeeder,3));iStep := iStep+1;END_IF;(*----------------------------------------------*)(*  pre-feeder 									*)(*----------------------------------------------*)IF STATION^.ScannerInput.uiCodeSelect = 1 AND STATION^.ScannerInput.bPreSetup THEN(* Save feeder number *)STATION^.ScannerInput.uiMaterialFeeder	:= STRING_TO_UINT(RIGHT(STATION^.ScannerInput.szBarcodeFeeder,3));iStep := 300;END_IF;STATION^.ScannerInput.uiCodeSelect	:= 0;IF tTimeInTheStep >  cTimeoutUser THENSTATION^.ScannerInput.sErrText	:= cMessageUser1;iStep							:= cErrStep;END_IF;201:actCheckMaterial();202:	(* check feeder assigmnment, right NO *)actFeederAssignment();203: (* Material & Feeder IO *) (*21.11.2019 SD CheckFamiliy and Feeder not possible until now*)actCheckFamilyAndVendor();204: (* prepare request message *)  (*16.11.2018 SD add act PrepareFeeder - Set MB)*)actPrepareFeeder();205:	(* wait answer *)IF STATION^.ITAC.MMC_Comm.SET_MB.bRecACK THENiStep := iStep+1;ELSIF	STATION^.ITAC.MMC_Comm.SET_MB.bError THENsArg1 := STATION^.ITAC.MMC_Comm.SET_MB.sErrText;FormatString(	sFormat	:= '03| SCAN_FEEDER: >> %s',arg1 	:= F_STRING (sArg1),sOut	=> STATION^.ScannerInput.sErrText);iStep					:= cErrStep;ELSIF tTimeInTheStep > cTimeoutMMC THEN (* Timeout *)STATION^.ScannerInput.sErrText	:= cTimeoutMessage;iStep							:= cErrStep;END_IF;206: actCheckFeeder();207:(*---------------------------------------------*)(* all prechecks passed, now accept material   *)(*---------------------------------------------*)STATION^.FEEDER_POS[STATION^.ScannerInput.uiMaterialFeeder].ACT_SETUP					:= STATION^.FEEDER_POS[STATION^.ScannerInput.uiMaterialFeeder].INPUT.Material;STATION^.ScannerInput.bDoneFeeder														:= TRUE;STATION^.FEEDER_POS[STATION^.ScannerInput.uiMaterialFeeder].HandShake.bFeederSetupIO 	:= TRUE;STATION^.FEEDER_POS[STATION^.ScannerInput.uiMaterialFeeder].HandShake.bFeederSetupNIO 	:= FALSE;iStep := iStep+1;208:(* Check Setup Complete       *)(*actCheckSetupComplete;*)IF STATION^.bSetupComplete THEN(* Set ACT *)STATION^.ITAC.MMC_Comm.SET_ACT.bSendRequest := TRUE;iStep := iStep+1;END_IF;iStep := 0 ; (* ReLoop *)209: (* Wait for answer from ACK ACT *)IF STATION^.ITAC.MMC_Comm.SET_ACT.bRecACK THENiStep := iStep+1;ELSIF	STATION^.ITAC.MMC_Comm.SET_ACT.bError THEN (* Set Error *)STATION^.ScannerInput.bError	:= TRUE;sArg1 := STATION^.ITAC.MMC_Comm.SET_ACT.sErrText;FormatString(	sFormat	:= '207| SCAN_FEEDER: >> %s',arg1 		:= F_STRING (sArg1),sOut		=> STATION^.ScannerInput.sErrText);iStep := cErrStep;ELSIF tTimeInTheStep > cTimeoutMMC THEN (* Timeout *)STATION^.ScannerInput.sErrText	:= cTimeoutMessage;iStep := cErrStep;END_IF;210:iStep := 0 ; (* ReLoop *)RETURN;
(* -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *)(*----------------------------------------------*)
(* Entry Point: PreFeeder 						*)
(*----------------------------------------------*)300:iStep := iStep + 1;301:(* Verify witch Feeder PreSetup aktiv *)actVerifyPreSetupAktiv();iStep := iStep+1;302:(* Assign the Material from PreSetup *)actPreSetupAssignmentMaterial();303: (* no further checks, move material to presetup STRUCT *)STATION^.ScannerInput.bDoneFeeder														:= TRUE;iStep := 0 ; (* ReLoop *)RETURN;(* -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *)(*----------------------------------------------*)
(* Entry Point: Move PRE_Setup to ACT_Setup		*)
(*----------------------------------------------*)400:iStep := iStep + 1;401:(* Material & Feeder IO *) (*21.11.2019 SD CheckFamiliy and Feeder not possible until now*)actCheckFamilyAndVendorPRE();402: (* prepare request message *)  (*16.11.2018 SD add act PrepareFeeder - Set MB)*)actPrepareFeederPreSetup();403:	(* wait answer *)IF STATION^.ITAC.MMC_Comm.SET_MB.bRecACK THENiStep := iStep+1;ELSIF	STATION^.ITAC.MMC_Comm.SET_MB.bError THENsArg1 := STATION^.ITAC.MMC_Comm.SET_MB.sErrText;FormatString(	sFormat	:= '03| SCAN_FEEDER: >> %s',arg1 	:= F_STRING (sArg1),sOut	=> STATION^.ScannerInput.sErrText);iStep					:= cErrStep;ELSIF tTimeInTheStep > cTimeoutMMC THEN (* Timeout *)STATION^.ScannerInput.sErrText	:= cTimeoutMessage;iStep							:= cErrStep;END_IF;404: actCheckFeederPreSetup();405:(*---------------------------------------------*)(* all prechecks passed, now accept material   *)(*---------------------------------------------*)STATION^.FEEDER_POS[STATION^.uiFeederMoveSetupActive].ACT_SETUP					:= STATION^.FEEDER_POS[STATION^.uiFeederMoveSetupActive].INPUT.Material;STATION^.ScannerInput.bDoneFeeder													:= TRUE;STATION^.FEEDER_POS[STATION^.uiFeederMoveSetupActive].HandShake.bFeederSetupIO 		:= TRUE;STATION^.FEEDER_POS[STATION^.uiFeederMoveSetupActive].HandShake.bFeederSetupNIO 	:= FALSE;STATION^.FEEDER_POS[STATION^.uiFeederMoveSetupActive].HandShake.bFeederPreSetup		:= FALSE;STATION^.bMoveSetupActive 			:= FALSE;STATION^.uiFeederMoveSetupActive	:= 0;iStep := 208 ;RETURN;(*IF STATION^.sOrder = '' THENiStep := 0;	(* done and out *)ELSE	(* simulate order scan *)STATION^.ScannerInput.szBarcodeOrder	:= STATION^.sOrder;iStep := 5;	(* check order again *)END_IF;*)(*---------------------------------------------*)
(* SUB Error STEP = Delay for Display          *)
(*---------------------------------------------*)cErrStep: (* 499 *)STATION^.ScannerInput.bError	:= TRUE;LogMessage01 (title := 'Error', text := STATION^.ScannerInput.sErrText);iStep := iStep +1;500:IF tTimeInTheStep > cTimeoutError THENiStep := 0 ;END_IF;(*---------------------------------------------*)
(* totally wrong                               *)
(*---------------------------------------------*)ELSESTATION^.ScannerInput.sErrText := 'PROGRAM ERROR: undefined iSTEP no!!!!!!';iStep := cErrStep;END_CASE;

3、Station_INPUT 代码分析 

3.1、系统初始化与状态检查
actTimingSystem();          // 时间系统管理(计时、超时检测)
actBarcodeSwitch();         // 条形码扫描设备切换控制
actCheckSetupComplete();    // 检查生产线设置是否完成IF NOT STATION^.bMoveSetupActive THENactCheckMoveSetupActive();  // 激活移动设置状态检查
END_IFFOR i := 1 TO cMaxFeederStation DO arFeederBomIdx[i] := 0; END_FOR;  // 初始化供料器BOM索引
  • 功能
    1. 启动时间管理系统,为后续超时检测提供基准。
    2. 检测扫描设备状态,确保条形码输入有效。
    3. 初始化供料器相关索引数组,为物料分配做准备。
3.2、状态机核心逻辑(CASE 结构)
1. 初始化状态(iStep=0)
0: (* INIT *)STATION^.ScannerInput.uiCodeSelect := 0;        // 重置扫描类型选择STATION^.ScannerInput.bError := FALSE;         // 清除错误标志STATION^.ScannerInput.sErrText := '';          // 清空错误信息STATION^.ScannerInput.sBarcodeRead := '';      // 清空扫描缓存iStep := iStep+1;                               // 切换到下一个状态
  • 功能:系统启动时的初始化,重置扫描模块状态。
2. 主等待状态(iStep=1)
1: (* wait for something *)actCheckSetupComplete();  // 检查设置完成状态IF NOT STATION^.bMoveSetupActive THENactCheckMoveSetupActive();  // 激活移动设置检查END_IFCASE STATION^.ScannerInput.uiCodeSelect OF0: (* 等待扫描输入,超时则重置预设置 *)1: (* 扫描供料器条码:错误,需先扫描物料 *)2: (* 扫描订单条码:进入订单处理流程 *)3: (* 扫描物料条码:进入物料处理流程 *)4: (* 扫描预设置条码:激活预设置模式 *)ELSE: (* 未知扫描类型:错误处理 *)END_CASE;
  • 功能
    根据扫描输入的类型(订单、物料、供料器)切换不同处理流程,确保扫描顺序正确(如必须先扫物料再扫供料器)。
3.3、订单扫描处理流程(iStep=5~12)
1. 订单扫描初始化(iStep=5)
5:STATION^.ScannerInput.bDoneOrder := FALSE;      // 重置订单完成标志actPrepareOrder();                              // 准备订单数据
6: (* 等待MMC系统响应订单数据 *)IF 收到ACK:验证订单条码一致性ELSIF 收到错误:记录错误信息ELSIF 超时:触发超时错误
  • 功能
    扫描订单条码后,向 MMC 系统发送订单请求,验证返回的条码与扫描值是否一致,确保订单信息正确。
2. 物料清单(BOM)解析(iStep=7~8)
7: actPrepareGetWBM();  // 准备获取物料清单
8: (* 等待MMC返回BOM数据 *)IF 成功获取BOM:// 验证BOM中的产能编号与设备一致FOR k := 1 TO cMAxMMC_BOM DO// 按供料器位置存储物料信息到FEEDER_POS数组END_FOR;STATION^.ScannerInput.bDoneOrder := TRUE;  // 标记订单处理完成END_IF;
  • 功能
    从 MMC 系统获取订单对应的物料清单(BOM),验证产能信息后,将物料分配到对应的供料器位置。
3.4、物料扫描处理流程(iStep=100~102)
100: (* 扫描物料条码 *)STATION^.ScannerInput.bDoneMaterial := FALSE;  // 重置物料完成标志actPrepareMaterial();                          // 准备物料数据
101: (* 等待MMC响应物料信息 *)
102:STATION^.ScannerInput.bDoneMaterial := TRUE;   // 标记物料处理完成
  • 功能:扫描物料条码后,与 MMC 系统交互验证物料信息,确保物料与订单匹配。
3.5、供料器扫描处理流程(iStep=200~210)
1. 供料器扫描与分配(iStep=200~207)
200: (* 解析供料器条码,获取供料器编号 *)
201: actCheckMaterial();          // 检查物料与供料器匹配性
202: actFeederAssignment();       // 分配供料器位置
203: actCheckFamilyAndVendor();   // 验证物料族与供应商信息
204: actPrepareFeeder();          // 准备供料器数据
205: (* 等待MMC确认供料器设置 *)
206: actCheckFeeder();            // 检查供料器状态
207:// 保存供料器设置,标记供料器处理完成STATION^.FEEDER_POS[...].ACT_SETUP := 物料信息;STATION^.ScannerInput.bDoneFeeder := TRUE;
  • 功能
    扫描供料器条码后,验证物料与供料器的匹配性,将物料信息绑定到具体供料器,并同步到 MMC 系统。
3.6、预设置与移动设置流程(iStep=300~405)
1. 预设置模式(iStep=300~303)
300: (* 预设置入口 *)
301: actVerifyPreSetupAktiv();    // 验证预设置激活状态
302: actPreSetupAssignmentMaterial();  // 分配预设置物料
303: STATION^.ScannerInput.bDoneFeeder := TRUE;  // 标记预设置完成
  • 功能:用于提前配置供料器物料,支持快速切换生产任务。
2. 移动预设置到实际设置(iStep=400~405)
400: (* 移动预设置入口 *)
401: actCheckFamilyAndVendorPRE();  // 验证预设置物料信息
402: actPrepareFeederPreSetup();    // 准备预设置供料器数据
405:// 将预设置物料应用到实际供料器STATION^.FEEDER_POS[...].ACT_SETUP := 预设置物料;STATION^.bMoveSetupActive := FALSE;  // 完成移动设置
  • 功能:将预配置的物料信息快速应用到生产线,减少换产时间。
3.7、错误处理流程(iStep=cErrStep~500)
cErrStep: (* 错误状态 *)STATION^.ScannerInput.bError := TRUE;LogMessage01('Error', STATION^.ScannerInput.sErrText);  // 记录错误日志
500:IF 超时时间到达 THENiStep := 0;  // 错误清除后返回初始化状态END_IF;
  • 功能:处理各类异常(如数据不匹配、超时、未知状态),记录错误信息并等待用户确认后重置系统。
3.8、核心交互与数据同步
MMC_COM(...);  // 与制造执行系统通信,获取订单和物料数据
FormatString(...);  // 格式化错误信息,便于HMI显示
actTimingSystem();  // 管理超时逻辑,确保流程时效性
  • 功能
    通过 MMC_COM 功能块与上位机系统交互,同步生产数据;使用 FormatString 生成标准化错误信息,通过 HMI 反馈给操作员。
3.9、整体流程总结
  1. 扫描优先级控制:必须按 “订单→物料→供料器” 的顺序扫描,确保数据一致性。
  2. 数据验证机制:通过与 MMC 系统交互,验证订单条码、物料清单、供料器分配的合法性。
  3. 预设置优化:支持预配置物料,通过 “预设置→实际应用” 流程快速切换生产任务。
  4. 异常处理:全流程超时检测和错误日志记录,确保系统故障可追溯。

四、MMC_COM  通讯实例

1、MMC_COM变量声明

VAR_INPUTptIN_STATION_ITAC		:POINTER TO ST_ITAC_V2_0;END_VARVARFbTCP_CLIENT		:TCP_CLIENT;RECEIVE_MMC			:FB_RECEIVE_MMC_V2_5_0;SEND_MMC			:FB_SEND_MMC_V2_5_0;// SPLIT_BomString 		:FB_SPLIT_BomString_V1_0;fConnectionEstablished 	:R_TRIG;fConnectionLost 	   	:R_TRIG;END_VAR

2、MMC_COM代码实例

(*              Interface                      *)
(*---------------------------------------------*)
FbTCP_CLIENT (    bEnable             := ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.bEnable,Reset                := ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.bReset,nPartnerPort        := ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.uiPort,sPartnerHost        := ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.sAddress,tFireDelay            := ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.tFireDelay,bConnected          => ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.bConnected);fConnectionEstablished    (CLK:= ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.bConnected);fConnectionLost            (CLK:= NOT ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.bConnected);IF fConnectionEstablished.Q THENptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.dtConnected := GetDateTimStamp_AS_STRING();END_IF;IF fConnectionLost.Q THENptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.dtdisConnected:= GetDateTimStamp_AS_STRING();END_IF;(*---------------------------------------------*)
(* OFFLINE !!??                                *)
(*---------------------------------------------*)
IF NOT ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.bConnected THENptIN_STATION_ITAC^.MMC_Comm.SET_OBC.bSendRequest         := FALSE;ptIN_STATION_ITAC^.MMC_Comm.GET_OBC.bSendRequest         := FALSE;ptIN_STATION_ITAC^.MMC_Comm.GET_WBM.bSendRequest         := FALSE;ptIN_STATION_ITAC^.MMC_Comm.GET_MB.bSendRequest            := FALSE;ptIN_STATION_ITAC^.MMC_Comm.SET_MB.bSendRequest            := FALSE;ptIN_STATION_ITAC^.MMC_Comm.SET_ACT.bSendRequest        := FALSE;ptIN_STATION_ITAC^.MMC_Comm.SET_MD.bSendRequest            := FALSE;ptIN_STATION_ITAC^.MMC_Comm.GET_SNC.bSendRequest        := FALSE;ptIN_STATION_ITAC^.MMC_Comm.SET_OAT.bSendRequest        := FALSE;ptIN_STATION_ITAC^.MMC_Comm.SET_SNB.bSendRequest        := FALSE;ptIN_STATION_ITAC^.MMC_Comm.GET_AFO.bSendRequest        := FALSE;ptIN_STATION_ITAC^.MMC_Comm.GET_SCM.bSendRequest        := FALSE;ptIN_STATION_ITAC^.MMC_Comm.SET_ASN.bSendRequest        := FALSE;ptIN_STATION_ITAC^.MMC_Comm.SET_EXS.bSendRequest        := FALSE;ptIN_STATION_ITAC^.MMC_Comm.SET_SNR.bSendRequest        := FALSE;ptIN_STATION_ITAC^.MMC_Comm.SET_STS.bSendRequest        := FALSE;RETURN;
END_IF;(*---------------------------------------------*)
(*              Receive Routines               *)
(*---------------------------------------------*)
RECEIVE_MMC(    ptIN_STATION_ITAC        := ptIN_STATION_ITAC,    (* !!! POINTER !!! *)rxBuffer    := FbTCP_CLIENT.strReceiveBuffer);(*---------------------------------------------*)
(*              Send Routines                  *)
(*---------------------------------------------*)
SEND_MMC(           ptIN_STATION_ITAC        := ptIN_STATION_ITAC,                         (* !!! POINTER !!!  *)SEND_QUEUE    := ADR(FbTCP_CLIENT.strSendQueue)); (* Pointer required *)

3、MMC_COM代码解读

3.1、TCP 客户端连接管理
FbTCP_CLIENT (bEnable := ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.bEnable,Reset := ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.bReset,nPartnerPort := ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.uiPort,sPartnerHost := ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.sAddress,tFireDelay := ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.tFireDelay,bConnected => ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.bConnected
);

  • 功能
    实例化 TCP 客户端功能块,配置与 MMC 系统通信的参数(IP 地址、端口号),并通过bConnected输出连接状态。

  • 参数说明

    • bEnable:启用 TCP 连接(由系统控制)。
    • Reset:重置连接。
    • nPartnerPort/sPartnerHost:目标服务器的端口和 IP 地址。
    • tFireDelay:发送数据的延迟时间。
    • bConnected:连接状态反馈(TRUE 表示已连接)。
3.2、连接状态监控
fConnectionEstablished (CLK:= ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.bConnected);
fConnectionLost (CLK:= NOT ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.bConnected);IF fConnectionEstablished.Q THENptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.dtConnected := GetDateTimStamp_AS_STRING();
END_IF;IF fConnectionLost.Q THENptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.dtdisConnected := GetDateTimStamp_AS_STRING();
END_IF;
  • 功能
    1. 使用上升沿触发 (fConnectionEstablished) 和下降沿触发 (fConnectionLost) 检测连接状态变化。
    2. 记录连接建立和断开的时间戳,用于日志追踪。
3.3、离线处理机制
IF NOT ptIN_STATION_ITAC^.MMC_Comm.CONVERSION_INTERFACE.bConnected THENptIN_STATION_ITAC^.MMC_Comm.SET_OBC.bSendRequest := FALSE;// 禁用所有MMC通信请求...RETURN;
END_IF;
  • 功能
    当 TCP 连接断开时,立即禁用所有 MMC 通信请求(如订单设置、物料查询等),防止数据丢失或通信异常,确保系统安全。
3.4、数据接收处理
RECEIVE_MMC (ptIN_STATION_ITAC := ptIN_STATION_ITAC,rxBuffer := FbTCP_CLIENT.strReceiveBuffer
);
  • 功能
    调用RECEIVE_MMC功能块,从 TCP 接收缓冲区 (strReceiveBuffer) 读取 MMC 系统发送的数据,并解析为系统可识别的格式(如订单信息、物料清单)。
3.5、数据发送处理
SEND_MMC (ptIN_STATION_ITAC := ptIN_STATION_ITAC,SEND_QUEUE := ADR(FbTCP_CLIENT.strSendQueue)
);
  • 功能
    调用SEND_MMC功能块,将系统需要发送的数据(如物料请求、设备状态)封装到 TCP 发送队列 (strSendQueue),由 TCP 客户端发送给 MMC 系统。

五、ACTFEEDER 程序代码

1、ActFeeder 变量声明

VAR CONSTANTcUnblockTime		:TIME 	:= t#5s;cFeederEmptyTime	:TIME 	:= t#1s;cStepTime			:TIME 	:= t#60m;
END_VARVAR_INPUTSTATION		:POINTER TO ST_SetupControl_ITAC_V2_0;uiFEEDER	:UINT;bACK_Operator	:BOOL;bNACK_Operator	:BOOL;bFeederFull		:BOOL;bFeederON		:BOOL;bMoveSetupFromPreToAct		:BOOL;bShelfSystem		:BOOL;
END_VARVAR_OUTPUTbRequest_HMI			:BOOL;bUnblockFeeder		:BOOL;bDischargeMaterial	:BOOL;bFeederSetupIO		:BOOL;bPreSetupActive		:BOOL;
END_VARVARRemoveBin		:FB_RemoveBIN_V1_0;iStep,iOldStep			:INT;TimerLockFeeder				:TON;TimerFeederEmpty		:TON;FB_TON_StepTime			:TON;tTimeInTheStep			:TIME;END_VAR

2、ActFeeder 程序代码

actTimingSystem();
bFeederSetupIO	:= STATION^.FEEDER_POS[uiFEEDER].HandShake.bFeederSetupIO;
bPreSetupActive := STATION^.FEEDER_POS[uiFEEDER].HandShake.bFeederPreSetup;
STATION^.FEEDER_POS[uiFEEDER].HandShake.bMoveSetupFromPreToAct := bMoveSetupFromPreToAct;(*---------------------------------------------*)
(* Feeder OFF/ON *)
(*---------------------------------------------*)IF bFeederON  THENSTATION^.FEEDER_POS[uiFEEDER].HandShake.bFeederON := TRUE;END_IF;IF NOT bFeederON  THENSTATION^.FEEDER_POS[uiFEEDER].HandShake.bFeederON := FALSE;IF NOT bPreSetupActive THENRETURN;END_IFEND_IF;(*---------------------------------------------*)
(* Check Fedder SetupNIO *)
(*---------------------------------------------*)CASE iStep OF0: (* init *)(*IF bShelfSystem THENbRequest_HMI 		:= FALSE;bDischargeMaterial := FALSE;END_IF*)iStep := iStep + 1;1:IF STATION^.FEEDER_POS[uiFEEDER].Handshake.bFeederSetupNIO AND bFeederFull AND NOT bDischargeMaterial AND NOT bPreSetupActive THENiStep := iStep + 1;END_IF;2: (* send Request to HMI *)bRequest_HMI := TRUE;iStep := iStep + 1;3: (*Wait for Answer Operator*)IF bACK_Operator  THENbRequest_HMI := FALSE;bDischargeMaterial := TRUE;iStep := 0; (* ReLoop *)END_IFIF bNACK_Operator  THENbRequest_HMI := FALSE;bDischargeMaterial := FALSE;iStep := 0; (* ReLoop *)END_IFIF  tTimeInTheStep > T#30S THENbRequest_HMI := FALSE;iStep := 0; (* ReLoop *)END_IFEND_CASE;(*---------------------------------------------*)
(* Feeder Empty *)
(*---------------------------------------------*)TimerFeederEmpty(IN:= NOT bFeederFull ,PT:=cFeederEmptyTime);IF TimerFeederEmpty.Q  THENbDischargeMaterial 										:= FALSE;STATION^.FEEDER_POS[uiFEEDER].HandShake.bFeederSetupNIO := TRUE;STATION^.FEEDER_POS[uiFEEDER].HandShake.bFeederSetupIO 	:= FALSE;STATION^.bSetupComplete 								:= FALSE;END_IF;IF bShelfSystem AND TimerFeederEmpty.Q AND  STATION^.FEEDER_POS[uiFEEDER].ACT_SETUP.sMatNo <> '' THENSTATION^.FEEDER_POS[uiFEEDER].Handshake.bRemoveBin := TRUE;END_IF;(*---------------------------------------------*)
(* Unblock Feeder*)
(*---------------------------------------------*)IF STATION^.ScannerInput.bDoneFeeder AND STATION^.ScannerInput.uiMaterialFeeder=uiFEEDER THENbUnblockFeeder :=TRUE;END_IFTimerLockFeeder(IN:=bUnblockFeeder,PT:=cUnblockTime);IF TimerLockFeeder.Q THENbUnblockFeeder :=FALSE;END_IFRemoveBin(uiFEEDER := uiFEEDER,Station	:= STATION,bRemove:=STATION^.FEEDER_POS[uiFEEDER].Handshake.bRemoveBin);

3、ActFeeder 代码解释

3.1、基础状态初始化
actTimingSystem();  // 时间系统管理(计时、超时检测)
bFeederSetupIO := STATION^.FEEDER_POS[uiFEEDER].HandShake.bFeederSetupIO;  // 获取供料器IO设置状态
bPreSetupActive := STATION^.FEEDER_POS[uiFEEDER].HandShake.bFeederPreSetup;  // 获取预设置状态
STATION^.FEEDER_POS[uiFEEDER].HandShake.bMoveSetupFromPreToAct := bMoveSetupFromPreToAct;  // 设置预设置转实际设置标志
  • 功能
    初始化供料器状态变量,为后续逻辑判断提供基础数据。
3.2、供料器开关控制

iecst

IF bFeederON THENSTATION^.FEEDER_POS[uiFEEDER].HandShake.bFeederON := TRUE;  // 开启供料器
END_IF;IF NOT bFeederON THENSTATION^.FEEDER_POS[uiFEEDER].HandShake.bFeederON := FALSE;  // 关闭供料器IF NOT bPreSetupActive THENRETURN;  // 非预设置模式下直接退出END_IF
END_IF;
  • 功能
    通过bFeederON信号控制供料器的开启 / 关闭。若关闭且非预设置模式,直接退出当前逻辑。
3.3、物料卸载请求处理(状态机)

iecst

CASE iStep OF0: iStep := iStep + 1;  // 初始化1:  // 检测是否需要卸载物料IF 供料器已设置且满料且未请求卸载且非预设置模式 THENiStep := iStep + 1;END_IF;2:  // 向HMI发送卸载请求bRequest_HMI := TRUE;iStep := iStep + 1;3:  // 等待操作员响应IF 操作员确认 THENbDischargeMaterial := TRUE;  // 执行卸载iStep := 0;  // 重置状态机END_IF;IF 操作员取消 OR 超时(30秒) THEN取消请求;iStep := 0;END_IF;
END_CASE;
  • 功能
    当供料器满料且需要卸载时,通过 HMI 向操作员发送请求,并根据响应执行卸载或取消操作。设置超时机制防止长时间等待。
3.4、空料检测与处理
TimerFeederEmpty(IN:= NOT bFeederFull ,PT:=cFeederEmptyTime);  // 空料计时器(非满料时开始计时)IF TimerFeederEmpty.Q THEN  // 空料超时bDischargeMaterial := FALSE;  // 停止卸载STATION^.FEEDER_POS[uiFEEDER].HandShake.bFeederSetupNIO := TRUE;  // 设置供料器为未就绪状态STATION^.FEEDER_POS[uiFEEDER].HandShake.bFeederSetupIO := FALSE;  // 清除供料器就绪标志STATION^.bSetupComplete := FALSE;  // 标记系统设置未完成
END_IF;IF bShelfSystem AND TimerFeederEmpty.Q AND 供料器有物料 THENSTATION^.FEEDER_POS[uiFEEDER].Handshake.bRemoveBin := TRUE;  // 触发货架系统移除料箱
END_IF;
  • 功能
    1. 通过计时器检测供料器空料状态,超时后重置供料器设置。
    2. 在货架系统中,自动触发料箱移除操作。
3.5、供料器锁定与解锁
IF STATION^.ScannerInput.bDoneFeeder AND STATION^.ScannerInput.uiMaterialFeeder=uiFEEDER THENbUnblockFeeder := TRUE;  // 供料器扫描完成后解锁
END_IFTimerLockFeeder(IN:=bUnblockFeeder,PT:=cUnblockTime);  // 解锁计时器IF TimerLockFeeder.Q THENbUnblockFeeder := FALSE;  // 超时后重新锁定
END_IFRemoveBin(uiFEEDER := uiFEEDER,  // 调用移除料箱功能块Station := STATION,bRemove := STATION^.FEEDER_POS[uiFEEDER].Handshake.bRemoveBin);
  • 功能
    1. 当供料器扫描完成后,短暂解锁供料器(防止误操作)。
    2. 通过RemoveBin功能块执行料箱移除操作,实现自动化物料管理。
3.6 整体流程总结
  1. 供料器控制

    • 支持远程开启 / 关闭供料器,非预设置模式下关闭后直接退出。
  2. 物料卸载机制

    • 自动检测需要卸载的场景,通过 HMI 与操作员交互,确保操作安全。
    • 设置超时保护,避免长时间等待导致流程停滞。
  3. 空料处理

    • 通过计时器检测空料状态,自动重置供料器设置。
    • 与货架系统集成,实现料箱自动移除。
  4. 安全锁定

    • 扫描完成后短暂解锁供料器,防止误操作,提高系统安全性。

相关文章:

  • Wise Disk Cleaner:免费高效的系统清理专家
  • C++课设:从零开始打造影院订票系统
  • Java中的抽象类
  • 2.1.3_2 编码和调制(下)
  • 用 DeepSeek 创作一首属于自己的歌
  • 图的邻接表存储及求邻接点操作
  • 【QT】QT多语言切换
  • 极客时间:在 Google Colab 上尝试 Prefix Tuning
  • 01.SQL语言概述
  • 算法-构造题
  • CSS悬停闪现与a标签嵌套的问题
  • vue3:十六、个人中心-修改密码
  • 《前端面试题:JavaScript 作用域深度解析》
  • leetcode Top100 189.轮转数组
  • Python Cookbook-7.13 生成一个字典将字段名映射为列号
  • 【学习笔记】TLS
  • 【threejs】每天一个小案例讲解:题外话篇
  • JDK 17 新特性
  • Java常见异常处理指南:IndexOutOfBoundsException与ClassCastException深度解析
  • Linux系统防火墙之iptables
  • wordpress怎么弄/南昌seo方案
  • 展馆展示设计公司排名推荐/seo快速排名点击
  • 该网站的域名已经被其他人绑定/网络快速排名优化方法
  • 网站权重最高是多少/网站建设开发简介
  • 崇信县人民政府网站/市场营销的八个理论
  • 网上做石材去哪个网站/做电商如何起步