跳到正文
Learn-LAD
示例库/分拣箱(Factory IO)

分拣箱(Factory IO)

Factory IO 分拣箱产线:18 个网络的启停、进料、左右分拣、计数与出料控制,外加 Factory IO 通信配置 SCL。

综合 多块 S7-1200 Factory IO 分拣 SCL 综合

导入到我的 TIA 项目

通过 TiaLink 把本示例的 8 个对象导入你当前打开的 TIA Portal 项目。导入前会先预检,默认不覆盖同名对象,导入后不会自动保存。

TiaLink 设置

默认 http://localhost:8080。也可以在本页地址后加 ?tialink= 临时指定。

TiaLink 启动时若设置了 --api-token,这里要填相同的值;只保存在本机浏览器 localStorage,不会上传。

概述

这是一个 Factory IO 分拣箱产线:启动后进料输送机送箱,高度传感器判断箱子类型,左右链条/输送机把箱子分流,入口传感器计数,最后出料器动作。

程序由 18 个网络组成:1 个 Factory IO 通信 SCL 调用、启停与指示灯、进料控制、左右分拣、计数和出料。它比前面的单功能示例更接近真实产线,也暴露了原工程里右分拣分支不完整的问题(见 Network 11/12)。

信号表

信号 类型 含义 作用
Start_Button_1 / Reset_Button_1 I 启动/复位 控制运行标志 Tag_1
Height_sensor_1 I 进料高度检测 允许进料
Height_sensor_2 / _3 I 分拣高度检测 组合判断箱子类型
Load I 负载/到位检测 停止进料、触发分拣
Left Entry / Right Entry I 左/右入口 分拣完成、复位分支、计数
Tag_1 M 运行标志 总使能
Tag_2 M 左分支标志 左分拣保持
Tag_5 M 右分支标志 右分拣保持(程序中没有置位它)
Tag_9 M 出料节拍 10 秒周期的短脉冲
Feed Conveyor Q 进料输送机 送箱/停止
Chain_Transfer_Left/Right Q 左右链条 分流
Left_Conveyor / Right_Conveyor Q 左右输送机 分流后输送 8 秒
Remover 1/2 Q 推料器 运行时动作
Emitter Q 出料器 由 Tag_9 触发
right counter / Left counter QW 左右计数 CTU 的 CV
Start Light / Reset Light Q 状态灯 运行/停止指示

工作流程

  1. 按 Start_Button_1 → Tag_1 置位;按 Reset_Button_1 → 复位;
  2. 运行时进料输送机、启动灯、两个推料器输出;
  3. Height_sensor_1 检测到箱子且 Load=0 → 启动进料;
  4. Load=1 或复位 → 停止进料;
  5. 高度传感器 2+3 同时动作 → 置位左分支 Tag_2;
  6. Tag_2 且 Load=1 → 左链条动作,左输送机运行 8 秒;
  7. Left Entry 下降沿 → 复位左分支;右分支结构类似(但 Tag_5 从未被置位,见下);
  8. 左右入口上升沿分别计数;Reset_Button_1 复位计数器;
  9. Tag_9 每 10 秒产生一个短脉冲,驱动 Emitter;
  10. 周期调用 Factory IO 通信 SCL。

MainOB · 主程序

Network 1 — Factory IO 通信配置

Network 1

目的:调用 SCL 函数完成 Factory IO 的通信/同步配置。

条件 → 动作:无条件调用 MHJ-PLC-Lab-Function-S71200。

注意:这段 SCL 是仿真环境的底层握手(PEEK/POKE、固定内存地址、系统时间读写),不是分拣逻辑;导出代码里还有 511Ret_Val、空 GOTO ; 等疑似语法问题。

Network 2 — 复位系统

Network 2:Reset_Button_1、Tag_1

条件 → 动作:按 Reset_Button_1 → 复位 Tag_1。

逻辑:Tag_1 = Reset_Button_1(复位线圈)

Network 3 — 启动系统

Network 3:Start_Button_1、Tag_1

条件 → 动作:按 Start_Button_1 → 置位 Tag_1。

逻辑:Tag_1 = Start_Button_1(置位线圈)

Network 4 — 启动进料输送机、指示灯与推料器

Network 4:Tag_1、Feed Conveyor、Start Light、Remover 1、Remover 2

条件 → 动作:Tag_1=1 → Feed Conveyor、Start Light、Remover 1、Remover 2 输出。

为什么:四个输出共用运行标志,保证启停一致。

逻辑:Feed Conveyor = Tag_1(其余同理)

Network 5 — 复位指示灯

Network 5:Tag_1、Reset Light

条件 → 动作:Tag_1=0 → Reset Light=1。

逻辑:Reset Light = NOT Tag_1

Network 6 — 启动进料(有箱且无负载)

Network 6:Tag_1、Height_sensor_1、Load、Feed Conveyor

条件 → 动作:Tag_1=1 且 Height_sensor_1=1 且 Load=0 → 置位 Feed Conveyor。

为什么:只有检测到箱子、且当前没有负载时才继续进料,避免堆箱。

逻辑:Feed Conveyor = Tag_1 AND Height_sensor_1 AND NOT Load(置位)

Network 7 — 停止进料

Network 7:Load、Reset_Button_1、Feed Conveyor

条件 → 动作:Load=1(箱子到位)或 Reset_Button_1=1 → 复位 Feed Conveyor。

逻辑:Feed Conveyor = Load OR Reset_Button_1(复位)

Network 8 — 置位左分支标志

Network 8:Height_sensor_3、Height_sensor_2、Tag_2

条件 → 动作:Height_sensor_2=1 且 Height_sensor_3=1 → 置位 Tag_2。

为什么:两个高度传感器同时动作代表一种箱型,用 Tag_2 记住分拣方向。

逻辑:Tag_2 = Height_sensor_2 AND Height_sensor_3(置位)

Network 9 — 左链条与左输送机

Network 9:Tag_2、Load、Chain_Transfer_Left、Left_Conveyor

条件 → 动作:Tag_2=1 且 Load=1 → 置位 Chain_Transfer_Left;Left_Conveyor 由 TOF 保持 8 秒。

为什么:TOF 让左输送机在条件消失后继续运行 8 秒,保证箱子走完。

逻辑: Chain_Transfer_Left = Tag_2 AND Load(置位)

Left_Conveyor = TOF(IN = Tag_2 AND Load, PT = T#8s).Q

Network 10 — 左入口复位

Network 10:Left Entry、Chain_Transfer_Left、Tag_2

条件 → 动作:Left Entry 的下降沿(NBox,存储位 Tag_4)→ 复位 Chain_Transfer_Left 和 Tag_2。

为什么:箱子到达左入口后结束左分支,准备下一次分拣。

逻辑:Chain_Transfer_Left = FALLING(Left Entry)(复位);Tag_2 = FALLING(Left Entry)(复位)

Network 11 — 右链条条件(注意逻辑不完整)

Network 11:Tag_5、Load、Chain_Transfer_Right

条件 → 动作:Tag_5=0 且 Load=1 → Chain_Transfer_Right=1。

注意:Tag_5 在整个程序里没有置位逻辑(只有 Network 12/13 的置位/复位?实际只有复位),所以右分支通常不会按"箱型"触发;而且本网络用普通线圈、Network 12 又用置位线圈驱动同一个输出,容易互相覆盖。右分拣逻辑很可能漏了一个网络,使用前需要补上 Tag_5 的置位条件(例如"高度传感器另一种组合")。

逻辑:Chain_Transfer_Right = NOT Tag_5 AND Load

Network 12 — 右链条与右输送机

Network 12:Tag_5、Load、Chain_Transfer_Right、Right_Conveyor

条件 → 动作:Tag_5=1 且 Load=1 → 置位 Chain_Transfer_Right;Right_Conveyor 由 TOF 保持 8 秒。

注意:由于 Tag_5 从未置位,这一支路实际不会触发;保留它是为了对照 Network 9 的左分支结构。

逻辑: Chain_Transfer_Right = Tag_5 AND Load(置位)

Right_Conveyor = TOF(IN = Tag_5 AND Load, PT = T#8s).Q

Network 13 — 右入口复位

Network 13:Right Entry、Chain_Transfer_Right、Tag_5

条件 → 动作:Right Entry 的下降沿(NBox,存储位 Tag_6)→ 复位 Chain_Transfer_Right 和 Tag_5。

逻辑:Chain_Transfer_Right = FALLING(Right Entry)(复位);Tag_5 = FALLING(Right Entry)(复位)

Network 14 — 右侧计数

Network 14:Right Entry、Reset_Button_1

条件 → 动作:Right Entry 的上升沿(PBox,存储位 Tag_7)→ CTU 计数,PV=100,CV 写入 right counter;Reset_Button_1 复位。

逻辑:right counter = CTU(CU = RISING(Right Entry), PV = 100, R = Reset_Button_1).CV

Network 15 — 左侧计数

Network 15:Left Entry、Reset_Button_1

条件 → 动作:Left Entry 的上升沿(PBox,存储位 Tag_8)→ CTU 计数,PV=100,CV 写入 Left counter;Reset_Button_1 复位。

逻辑:Left counter = CTU(CU = RISING(Left Entry), PV = 100, R = Reset_Button_1).CV

Network 16 — 出料节拍

Network 16:Tag_1、Tag_9、Tag_9

条件 → 动作:Tag_1=1 且 Tag_9=0 → TON 计时 10 秒;到时 Tag_9=1,下一扫描条件断开,Tag_9 又复位,形成周期性短脉冲。

注意:这不是"保持 10 秒"的输出,而是每 10 秒一个扫描周期的脉冲;如果出料器需要持续动作,应改用 TP 或自锁。

逻辑:Tag_9 = TON(IN = Tag_1 AND NOT Tag_9, PT = T#10s).Q

Network 17 — 出料器输出

Network 17:Tag_9、Emitter

条件 → 动作:Tag_9=1 → Emitter=1。

逻辑:Emitter = Tag_9

MHJ-PLC-Lab-Function-S71200FC · 函数(SCL)

名称数据类型注释
Input
Output
InOut
Temp
rdTimeReturnInt
outputTimeDTL
SyncValByte
forValInt
forVal_2Int
ValueByte
Constant
CompValByte
Value_01Byte
Value_01_DWDWord
Value_02_DWDWord
Return
Ret_ValVoid

Network 1 — Factory IO 通信函数(SCL)

SCL
12#Value:=PEEK(area := 16#82,3     dbNumber := 0,4     byteOffset := 511Ret_Val);5#Value := #Value + 1;67POKE(area := 16#82,8     dbNumber := 0,9     byteOffset := 511,10     value := #Value);1112POKE(area:=16#81,13     dbNumber:=0,14     byteOffset:=1016,15     value:=#16#A165_D992);16POKE(area := 16#81,17     dbNumber := 0,18     byteOffset := 1020,19     value := #16#58BE_4401);2021POKE(area := 16#81,22     dbNumber := 0,23     byteOffset := 511,24     value := B#16#00);2526FOR #forVal := 0 TO 120 DO27    FOR #forVal_2:=0 TO 10 DO28        #rdTimeReturn:=RD_SYS_T(#outputTimeRET_VAL);29        #rdTimeReturn := WR_SYS_T(#outputTimeRET_VAL);30        #rdTimeReturn := RD_SYS_T(#outputTimeRET_VAL);31        #rdTimeReturn := WR_SYS_T(#outputTimeRET_VAL);32    END_FOR;33    #SyncVal:= PEEK(area := 16#81,34                   dbNumber := 0,35                   byteOffset := 511Ret_Val);36    IF #SyncVal = #16#34 THEN37       GOTO ;38    END_IF;39END_FOR;40RETURN;414243POKE(area := 16#81,44     dbNumber := 0,45     byteOffset := 511,46     value := B#16#0);474849    

目的:完成 Factory IO 仿真环境的通信/同步初始化。

条件 → 动作:函数用 PEEK/POKE 读写固定内存区域(area 16#81/16#82、DB 0、固定偏移),写入标识值,循环调用 RD_SYS_T/WR_SYS_T 并等待同步值,最后清理同步位。

为什么:这是仿真软件/厂商提供的底层连接例程,靠固定地址和标识值完成握手;主程序 Network 1 每个周期调用它一次。

注意:它与分拣逻辑无关,换项目时不能直接照搬;导出代码里的 511Ret_Val 和空 GOTO ; 看起来是语法问题,直接编译可能失败。

常见问题

  • 右侧不分拣:Tag_5 没有置位条件,且 Network 11/12 驱动同一个输出;需要补一个"右侧箱型判断"网络。
  • 计数器不清零:Reset_Button_1 同时用于复位系统和计数器;确认复位信号是否正常。
  • 出料器几乎不动作:Tag_9 是 10 秒一次的短脉冲,接触器可能来不及响应;改用 TP 保持一段时间。
  • SCL 编译失败:通信函数里的 511Ret_Val、GOTO ; 需要修正;它与分拣逻辑无关。

变体与扩展

  • 补全右分支:用另一组高度传感器组合置位 Tag_5,并让 Network 11/12 统一用一种线圈类型。
  • 出料定时:把 Tag_9 改成 TP,让出料器每次动作固定时间。
  • 计数显示:把 Left counter/right counter 接到 HMI,做产量统计。

变量与数据块

变量表:Default tag table

名称数据类型地址注释
Height_sensor_1Bool%I0.0
Height_sensor_2Bool%I0.1
Height_sensor_3Bool%I0.2
LoadBool%I0.3
Left EntryBool%I0.4
Right EntryBool%I0.5
Start_Button_1Bool%I1.0
Reset_Button_1Bool%I1.1
Feed ConveyorBool%Q0.0
Load SensorBool%Q0.1
UnloadBool%Q0.2
Chain_Transfer_LeftBool%Q0.3
Chain_Transfer_RightBool%Q0.4
Left_ConveyorBool%Q0.5
Right_ConveyorBool%Q0.6
Reset LightBool%Q0.7
Start LightBool%Q1.0
Remover 1Bool%Q1.1
Remover 2Bool%Q1.2
EmitterBool%Q1.3
Tag_1Bool%M0.0
Tag_2Bool%M0.1
Tag_3Time%MD1
Tag_4Bool%M0.5
Tag_5Bool%M0.2
Tag_6Bool%M0.7
Tag_7Bool%M2.0
right counterInt%QW34
Tag_8Bool%M2.1
Left counterInt%QW30
Tag_9Bool%M10.0
系统实例 DB(5 个)

TIA 自动生成的定时器/计数器实例 DB,导入示例时会一并导入。

IEC_Counter_0_DB 实例 DB(IEC_COUNTER)
名称数据类型起始值注释
Static
CUBool
CDBool
RBool
LDBool
QUBool
QDBool
PVInt
CVInt
IEC_Counter_0_DB_1 实例 DB(IEC_COUNTER)
名称数据类型起始值注释
Static
CUBool
CDBool
RBool
LDBool
QUBool
QDBool
PVInt
CVInt
IEC_Timer_0_DB 实例 DB(IEC_TIMER)
名称数据类型起始值注释
Static
PTTime
ETTime
INBool
QBool
IEC_Timer_0_DB_1 实例 DB(IEC_TIMER)
名称数据类型起始值注释
Static
PTTime
ETTime
INBool
QBool
IEC_Timer_0_DB_2 实例 DB(IEC_TIMER)
名称数据类型起始值注释
Static
PTTime
ETTime
INBool
QBool

下一步