博图SCL灵活运用加减计数指令案例:智能物料分拣站
1. 应用场景与解决方案
在自动化分拣站中,需要根据不同类型的物料箱动态调整产品装入数量:
- A类箱:10个产品
- B类箱:15个产品
- C类箱:8个产品
传统计数器只能处理固定目标值,我们通过SCL语言灵活运用CTU计数器,实现了:
- 动态目标值设置
- 运行时目标值调整
- 安全保护机制
- 状态实时同步
2. 系统流程图
3. SCL程序实现
FUNCTION_BLOCK FB_SmartCounter
VAR
// 输入输出定义
ProductSensor: BOOL; // 产品检测传感器
Button_A, Button_B, Button_C: BOOL; // 箱子类型选择
ResetButton, EStop: BOOL; // 复位和急停
UpButton, DownButton: BOOL; // 目标值调整
BoxFull: BOOL; // 装箱完成信号
CurrentCount: INT; // 当前计数值
CurrentTarget: INT; // 当前目标值
StatusMessage: STRING(80); // 状态信息
// 内部变量
PrevProductSensor, PrevUpButton, PrevDownButton: BOOL;
Counter: CTU; // 加计数器实例
Mode: INT := 0; // 0:未选, 1:A, 2:B, 3:C
DefaultTargets: ARRAY[1..3] OF INT := [10, 15, 8]; // 默认目标值
bInitialized: BOOL := FALSE;
END_VAR
#CurrentTarget_1 := #CurrentTarget;
#CurrentCount_1:= #CurrentCount;
#StatusMessage_1 := #StatusMessage;
#BoxFull_1:= #BoxFull;
//===== 初始化部分 =====//
IF NOT #bInitialized THEN
"IEC_Counter_0_DB".CTUD(CU:=FALSE,
CD:=FALSE,
R:=TRUE,
PV:=0);
#CurrentTarget := 0;
#CurrentCount := 0;
#BoxFull := FALSE;
#StatusMessage := 0;
#bInitialized := TRUE;
RETURN;
END_IF;
//===== 急停/复位处理 =====//
IF #EStop OR #ResetButton THEN
"IEC_Counter_0_DB".R := TRUE;
#CurrentCount := 0;
#BoxFull := FALSE;
#Mode := 0;
#StatusMessage := 9;
RETURN;
END_IF;
//===== 模式选择 =====//
IF #Button_A AND NOT #PrevProductSensor THEN
#Mode := 1;
#CurrentTarget := #DefaultTargets[1];
"IEC_Counter_0_DB".R := TRUE;
#CurrentCount := 0;
#BoxFull := FALSE;
#StatusMessage := 1;
ELSIF #Button_B AND NOT #PrevProductSensor THEN
#Mode := 2;
#CurrentTarget := #DefaultTargets[2];
"IEC_Counter_0_DB".R := TRUE;
#StatusMessage := 2;
ELSIF #Button_C AND NOT #PrevProductSensor THEN
#Mode := 3;
#CurrentTarget := #DefaultTargets[3];
"IEC_Counter_0_DB".R := TRUE;
#StatusMessage := 3;
END_IF;
IF #CurrentCount_1<>0 THEN
#PrevProductSensor := #CurrentCount_1 >= #CurrentTarget_1;
ELSE
#PrevProductSensor :=FALSE;
END_IF;
//===== 状态保存 =====//
"R_TRIG_DB"(CLK:= #UpButton,
Q=> #PrevUpButton);
"R_TRIG_DB_1"(CLK:= #DownButton,
Q=>#PrevDownButton);
//===== 模式检测 =====//
IF #Mode = 0 THEN
RETURN;
END_IF;
//===== 核心计数逻辑 =====//
#CurrentCount := "IEC_Counter_0_DB".CV;
"IEC_Counter_0_DB".CTUD(CU := #ProductSensor AND NOT #PrevProductSensor,
CD := FALSE,
R := FALSE,
PV := #CurrentTarget);
// 目标值检测
IF "IEC_Counter_0_DB".QU THEN
#BoxFull := TRUE;
#StatusMessage := 4;
ELSE
#BoxFull := FALSE;
END_IF;
//===== 动态目标值调整 =====//
// 增加目标值
IF #UpButton AND NOT #PrevUpButton THEN
#CurrentTarget := LIMIT(MN := #DefaultTargets[#Mode], IN := #CurrentTarget , MX := #DefaultTargets[#Mode] + 5);
"IEC_Counter_0_DB".PV := #CurrentTarget + 1;
#StatusMessage := 5;
#CurrentTarget := "IEC_Counter_0_DB".PV;
END_IF;
// 减少目标值
IF #DownButton AND NOT #PrevDownButton THEN
#CurrentTarget := LIMIT(MN := #DefaultTargets[#Mode], IN := #CurrentTarget , MX := #DefaultTargets[#Mode] + 5);
"IEC_Counter_0_DB".PV := #CurrentTarget - 1;
#StatusMessage := 5;
END_IF;
//===== 安全保护机制 =====//
// 强制完成检测
IF #CurrentCount >= #CurrentTarget AND NOT #BoxFull THEN
#BoxFull := TRUE;
#StatusMessage := 7;
END_IF;
// 状态同步
IF #BoxFull AND #CurrentCount < #CurrentTarget THEN
#BoxFull := FALSE;
#StatusMessage := 8;
END_IF;