在西门子PLC(如S7-1200、S7-1500系列)编程中,配方(Recipe)功能常用于存储和管理生产过程中的参数集,例如不同产品类型(如A、B、C产品)的温度、压力、时间等设定值。这些参数可以视为一组相关数据的集合,使用结构体(STRUCT)来定义单个配方的结构(包含不同类型的数据),然后使用数组(ARRAY)来存储多个配方,实现批量管理和切换。
步骤:
打开TIA Portal项目,右键“类型”文件夹 → “添加新类型” → 选择“用户定义类型(UDT)”。
输入名称,如Recipe_Struct
。
在UDT编辑器中添加成员变量(不同类型):
示例UDT定义(SCL语法):
TYPE Recipe_Struct :
STRUCT
Temp_Set : REAL; // 温度设定值 (单位:℃)
Press_Set : INT; // 压力设定值 (单位:bar)
Time_Set : TIME; // 时间设定值 (单位:s)
END_STRUCT
END_TYPE
说明:
STRUCT
块内可嵌套基本类型(REAL、INT、TIME等)或其它STRUCT/ARRAY。
结构体大小固定,由成员类型决定(例如:REAL占4字节,INT占2字节,TIME占4字节,总计10字节)。
可添加更多成员,如字符串(STRING)用于配方名称:Recipe_Name : STRING[20];
。
数组用于容纳多个结构体实例,实现配方库。
步骤:
创建一个全局数据块(DB),如DB1
(配方库DB)。
在DB的静态变量区声明数组:
示例DB声明(SCL语法):
DATA_BLOCK "Recipe_DB"
TITLE = "配方库数据块"
VERSION : 0.1
BEGIN
Recipes : ARRAY[1..10] OF Recipe_Struct; // 10个配方,每个为Recipe_Struct类型
Current_Recipe_Index : INT := 1; // 当前选中的配方索引 (默认1)
END_DATA_BLOCK
说明:
ARRAY[1..10]
:一维数组,索引从1到10(S7系列默认从1开始,可自定义下限为0)。
数组元素类型为刚才定义的Recipe_Struct
,总大小=10 × 10字节=100字节。
支持多维数组,如ARRAY[1..5,1..2]
用于分组配方。
数组访问示例:Recipes[1].Temp_Set
(访问第1个配方的温度)。
在PLC启动(OB100)或专用功能块(FB)中初始化数组数据。使用赋值语句填充默认值。
示例SCL代码(在FB中):
FUNCTION_BLOCK "Init_Recipes"
VAR
i : INT;
END_VAR
BEGIN
FOR i := 1 TO 10 DO
CASE i OF
1: // 配方1:产品A
Recipes[i].Temp_Set := 150.5;
Recipes[i].Press_Set := 50;
Recipes[i].Time_Set := T#5S;
2: // 配方2:产品B
Recipes[i].Temp_Set := 200.0;
Recipes[i].Press_Set := 80;
Recipes[i].Time_Set := T#10S;
// ... 继续添加其他配方
ELSE
Recipes[i].Temp_Set := 0.0; // 默认值
Recipes[i].Press_Set := 0;
Recipes[i].Time_Set := T#0S;
END_CASE;
END_FOR;
END_FUNCTION_BLOCK
说明:
使用FOR
循环遍历数组,CASE
语句根据索引填充数据。
调用此FB:在主程序OB1中Init_Recipes();
。
数据可从HMI或CSV文件导入(使用SFC14/15块读写)。
在主程序中,根据输入(如HMI按钮)切换当前配方索引,并将参数应用到过程变量。
示例SCL代码(在OB1中):
ORGANIZATION_BLOCK "Main"
VAR
// 过程变量
Actual_Temp : REAL; // 实际温度
Actual_Press : INT; // 实际压力
Timer : TON; // 定时器
END_VAR
BEGIN
// 假设从HMI输入新配方索引到 Current_Recipe_Index
IF "New_Recipe_Select" THEN // 触发切换
Current_Recipe_Index := "HMI_Index_Input"; // 从输入获取索引 (1-10)
"New_Recipe_Select" := FALSE;
END_IF;
// 加载当前配方到过程变量
Actual_Temp := Recipes[Current_Recipe_Index].Temp_Set;
Actual_Press := Recipes[Current_Recipe_Index].Press_Set;
Timer(IN := TRUE, PT := Recipes[Current_Recipe_Index].Time_Set);
// 过程控制逻辑
IF Timer.Q THEN
// 配方执行完成
"Recipe_Done" := TRUE;
Timer(IN := FALSE);
END_IF;
END_ORGANIZATION_BLOCK
说明:
Current_Recipe_Index
控制数组访问,实现动态切换。
使用TON
定时器示例应用时间参数;类似地,可连接PID块处理温度/压力。
边界检查:添加IF Current_Recipe_Index < 1 OR Current_Recipe_Index > 10 THEN Current_Recipe_Index := 1; END_IF;
防止越界。