西门子S7-1200 OB1主程序构架-填料天车1

西门子S7-1200 OB1主程序全套完整资料

一、程序

1.1 程序概述

对应西门子S7-1200 PLC(CPU型号:S7-1215C)OB1主循环组织块,采用SCL(结构化控制语言)编写,适用于大车行走机构、行车、堆取料机、布料机等移动机械设备的自动控制系统。

OB1共分为14个程序段(Network),采用模块化结构化编程思想,将高速计数、位置计算、输出控制、通信交互、报警处理、HMI动画、数据上传等功能封装为FB/FC功能块,主程序仅做调用与调度,结构清晰、易于维护、可扩展性强。

核心功能覆盖:编码器脉冲采集、物理位移换算、实时速度计算、数字量输出集中控制、Modbus RTU通信、全设备报警管理、系统时间读写、HMI动画同步、SQL数据上传、变频器数据解析、从站状态检测,满足移动设备的自动化控制与数据追溯需求。

1.2 硬件配置说明

|---------|---------------------|----|-----------------------|
| 硬件名称 | 型号/规格 | 数量 | 用途 |
| PLC CPU | S7-1215C DC/DC/DC | 1台 | 主控制器,执行OB1主程序 |
| 编码器 | 增量式编码器(500脉冲/转) | 2台 | 采集大车左右行走脉冲,接入HSC通道 |
| 变频器 | 支持Modbus RTU通信 | 1台 | 控制大车行走电机,与PLC通信交互参数 |
| 激光测距仪 | 模拟量/数字量输出(DINT类型) | 1台 | 校准大车位置,提供精准坐标 |
| 远程IO/仪表 | 支持Profinet/Modbus从站 | 若干 | 采集限位、急停、气缸等信号,扩展IO |
| HMI触摸屏 | 任意支持S7-1200通信的型号 | 1台 | 显示设备状态、参数,提供手动操作与时间校准 |

1.3 程序结构总览

|--------------|----------------|---------------------|------------------------------|
| 程序段(Network) | 核心功能 | 调用指令/FB | 核心作用 |
| 1 | 高速计数器HSC控制 | CTRL_HSC | 采集编码器脉冲,为位置计算提供原始数据 |
| 2 | 脉冲→实际位移换算 | FB4 "GearRatio" | 消除机械传动影响,得到大车实际行走距离 |
| 3 | 数字量输出集中控制 | FB1 "OutputControl" | 统一管理电机、电磁阀、指示灯等输出,含联锁逻辑 |
| 4 | Modbus RTU主站通信 | FB6 "ModbusMaster" | 与变频器、仪表通信,读写参数与控制指令 |
| 5 | 报警与故障处理 | FB8 "AlarmHandler" | 集中采集故障信号,生成报警代码与文本,实现联锁 |
| 6 | 大车实时速度计算 | TON定时器、数学指令 | 基于位置差计算实时速度,用于超速保护与HMI显示 |
| 7 | 数据转换与坐标校准 | 数据类型转换指令 | 统一数据格式,校准大车坐标,便于后续调用 |
| 8 | 信号汇总与逻辑判断 | 逻辑运算指令 | 汇总安全信号、判断运行条件与位置区间,生成系统状态字 |
| 9 | PLC系统时间写入 | WR_LOC_T | 通过HMI校准PLC时间,保证数据时间戳准确 |
| 10 | PLC系统时间读取 | RD_LOC_T | 实时读取系统时间,用于HMI显示与SQL上传 |
| 11 | HMI动画坐标计算 | 数学转换指令 | 将物理位置转为HMI像素坐标,实现画面与设备同步 |
| 12 | SQL数据上传 | FB7 "SQL_Data" | 将运行数据上传数据库,实现生产追溯与统计 |
| 13 | 变频器数据解析 | 数据类型转换指令 | 将Modbus读取的原始值转为实际工程值(频率、电流等) |
| 14 | 从站状态检测 | DeviceStates | 监测变频器、远程IO等从站状态,触发通信故障报警 |

1.4 调试与维护说明

1.4.1 调试步骤

  1. 硬件接线检查:确认编码器、变频器、限位开关等设备接线正确,HSC通道、通信端口接线无误。
  2. 变量初始化:在DB块中设置编码器分辨率、齿轮比、车轮直径、位置偏移量等参数,确保与现场设备一致。
  3. 分段调试:依次调试各程序段,先调试HSC脉冲采集与位移换算,再调试通信、报警、输出等功能,避免连锁故障。
  4. 联机调试:所有分段调试完成后,联机运行,验证设备联动逻辑、HMI同步、数据上传等功能是否正常。
  5. 故障排查:若出现异常,查看DB块中变量值、报警代码,结合程序逻辑定位故障点(如通信故障、编码器故障、限位触发等)。

1.4.2 维护要点

  1. 定期检查编码器接线,避免松动导致脉冲丢失;定期校准激光测距仪,确保位置精度。
  2. 检查Modbus通信线路,避免干扰导致通信异常;定期备份PLC程序与DB块数据。
  3. 根据现场设备参数变化(如齿轮比、车轮直径),及时修改DB块中对应参数,确保计算准确。
  4. 定期清理报警记录,检查报警逻辑是否正常,避免误报警或漏报警。

二、逐段

TIA Portal的OB1中,需提前创建对应DB块、FB块(FB1、FB4、FB6、FB7、FB8),变量名称与DB块名称需与代码一致。

Network 1:高速计数器HSC控制(采集编码器脉冲)

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| // 功能:初始化并启动2路高速计数器,采集大车左右编码器脉冲 // 通道说明:HSC1(编号257)对应左侧编码器,HSC2(编号258)对应右侧编码器 // 工作模式:连续计数,不写入新当前值/参考值,仅启动计数并读取状态 // 高速计数器1(HSC1,通道257)控制 "CTRL_HSC"( HSC := 257, // HSC通道编号(S7-1215C默认HSC1对应257) NEW_CV := FALSE, // 不写入新的当前值 CV := 0, // 未使用(NEW_CV为FALSE时无效) NEW_RV := FALSE, // 不写入新的参考值 RV := 0, // 未使用(NEW_RV为FALSE时无效) START := TRUE, // 持续启动计数器 STOP := FALSE, // 不停止计数器 STATUS => "DB_HSC".HSC1_Status, // 计数器运行状态字(16#0为正常) CV_OUT => "DB_HSC".HSC1_CV // 计数器当前脉冲值(左侧编码器) ); // 高速计数器2(HSC2,通道258)控制 "CTRL_HSC"( HSC := 258, // HSC通道编号(S7-1215C默认HSC2对应258) NEW_CV := FALSE, // 不写入新的当前值 CV := 0, // 未使用 NEW_RV := FALSE, // 不写入新的参考值 RV := 0, // 未使用 START := TRUE, // 持续启动计数器 STOP := FALSE, // 不停止计数器 STATUS => "DB_HSC".HSC2_Status, // 计数器运行状态字 CV_OUT => "DB_HSC".HSC2_CV // 计数器当前脉冲值(右侧编码器) ); |

Network 2:编码器脉冲→实际位移换算

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| scl // 功能:调用FB4"GearRatio",将编码器脉冲值转换为大车实际行走距离 // 计算公式:实际距离 = 脉冲数 ÷ 分辨率 × 车轮周长 ÷ 减速比 // FB4说明:封装齿轮比换算逻辑,输入脉冲值、分辨率等,输出实际距离 // 左侧编码器位移计算(调用FB4实例) "GearRatio"( EncoderValue := "DB_HSC".HSC1_CV, // 输入:左侧编码器脉冲值(HSC1采集) Resolution := 500.0, // 输入:编码器分辨率(500脉冲/转,可修改) GearRatio := 20.0, // 输入:机械减速比(可根据现场修改) WheelDiameter := 1.2, // 输入:车轮直径(单位:m,可修改) Distance => "DB_Position".Left_Distance // 输出:左侧实际行走距离(单位:m) ); // 右侧编码器位移计算(调用FB4实例) "GearRatio"( EncoderValue := "DB_HSC".HSC2_CV, // 输入:右侧编码器脉冲值(HSC2采集) Resolution := 500.0, // 输入:与左侧编码器分辨率一致 GearRatio := 20.0, // 输入:与左侧机械减速比一致 WheelDiameter := 1.2, // 输入:与左侧车轮直径一致 Distance => "DB_Position".Right_Distance // 输出:右侧实际行走距离(单位:m) ); // FB4 "GearRatio" 内部SCL代码(封装于FB4中,可直接复制创建FB) FUNCTION_BLOCK "GearRatio" VAR_INPUT EncoderValue: DINT; // 编码器脉冲值(输入,来自HSC) Resolution: REAL; // 编码器分辨率(脉冲/转,输入) GearRatio: REAL; // 机械减速比(输入) WheelDiameter: REAL; // 车轮直径(单位:m,输入) END_VAR VAR_OUTPUT Distance: REAL; // 实际行走距离(单位:m,输出) END_VAR VAR_TEMP WheelCircumference: REAL; // 临时变量:车轮周长 END_VAR // 计算车轮周长(周长=π×直径,π取3.1416) WheelCircumference := 3.1416 * WheelDiameter; // 换算实际距离:脉冲数→转数→距离,消除减速比影响 Distance := REAL(EncoderValue) / Resolution * WheelCircumference / GearRatio; |

Network 3:数字量输出集中控制

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| // 功能:调用FB1"OutputControl",统一管理所有数字量输出,包含急停、故障联锁 // 输出对象:电机接触器、电磁阀、指示灯、蜂鸣器等,逻辑封装于FB1,主程序仅调用 "OutputControl"( EmergencyStop := "DB_Safety".EmergencyStop, // 输入:急停信号(TRUE=急停触发) FaultSignal := "DB_Alarm".FaultTotal, // 输入:总故障信号(TRUE=存在故障) AutoMode := "DB_Mode".AutoMode, // 输入:自动模式信号(TRUE=自动) ManualMode := "DB_Mode".ManualMode, // 输入:手动模式信号(TRUE=手动) DO_Motor1 => "DB_Output".DO_Motor1, // 输出:电机1控制信号(对应PLC DO点) DO_Motor2 => "DB_Output".DO_Motor2, // 输出:电机2控制信号 DO_Solenoid1 => "DB_Output".DO_Solenoid1, // 输出:电磁阀1控制信号 DO_Indicator1 => "DB_Output".DO_Indicator1, // 输出:状态指示灯控制信号 DO_Buzzer => "DB_Output".DO_Buzzer // 输出:蜂鸣器控制信号(故障时报警) ); // FB1 "OutputControl" 内部SCL代码(封装于FB1中) FUNCTION_BLOCK "OutputControl" VAR_INPUT EmergencyStop: BOOL; // 急停信号(TRUE=急停触发,强制切断输出) FaultSignal: BOOL; // 总故障信号(TRUE=存在故障,强制切断输出) AutoMode: BOOL; // 自动模式(TRUE=自动控制输出) ManualMode: BOOL; // 手动模式(TRUE=手动控制输出) END_VAR VAR_OUTPUT DO_Motor1: BOOL; // 电机1输出(DO点) DO_Motor2: BOOL; // 电机2输出(DO点) DO_Solenoid1: BOOL; // 电磁阀1输出(DO点) DO_Indicator1: BOOL; // 指示灯输出(DO点) DO_Buzzer: BOOL; // 蜂鸣器输出(DO点) END_VAR // 联锁逻辑:急停或故障时,切断所有危险输出(电机、电磁阀) IF EmergencyStop OR FaultSignal THEN DO_Motor1 := FALSE; DO_Motor2 := FALSE; DO_Solenoid1 := FALSE; ELSE // 自动/手动模式切换,控制输出 IF AutoMode THEN // 自动模式:由自动控制逻辑(DB_Auto)决定输出 DO_Motor1 := "DB_Auto".Motor1_Auto; DO_Motor2 := "DB_Auto".Motor2_Auto; DO_Solenoid1 := "DB_Auto".Solenoid1_Auto; ELSIF ManualMode THEN // 手动模式:由手动操作(DB_Manual)决定输出 DO_Motor1 := "DB_Manual".Motor1_Manual; DO_Motor2 := "DB_Manual".Motor2_Manual; DO_Solenoid1 := "DB_Manual".Solenoid1_Manual; END_IF; END_IF; // 指示灯控制:正常状态(无急停、无故障)亮,异常状态灭 DO_Indicator1 := NOT EmergencyStop AND NOT FaultSignal; // 蜂鸣器控制:故障时报警(常响) DO_Buzzer := FaultSignal; |

Network 4:Modbus RTU主站通信

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| // 功能:调用FB6"ModbusMaster",作为Modbus主站与变频器通信,读取参数、写入控制指令 // 通信参数:波特率9600、无校验、1位停止位,从站地址1(可根据现场修改) // 读取变频器参数(频率、电流、电压、温度、状态) "ModbusMaster"( EN_R := TRUE, // 使能Modbus通信(持续使能) PORT := 0, // 通信端口(根据PLC硬件组态设置,默认0) BAUDRATE := 9600, // 波特率(与变频器一致) PARITY := 0, // 校验位:0=无校验,1=奇校验,2=偶校验 STOPBITS := 1, // 停止位:1位 SLAVE := 1, // 变频器从站地址(可修改) RW := 0, // 读写标识:0=读取,1=写入 ADDRESS := 40001, // 读取寄存器地址(变频器频率寄存器,可修改) LENGTH := 5, // 读取寄存器长度(5个寄存器,对应5个参数) DATA => "DB_Modbus".Inverter_ReadData, // 读取数据存储区(数组,保存原始WORD值) ERROR => "DB_Modbus".Inverter_Error, // 通信错误代码(0=正常,非0=异常) DONE => "DB_Modbus".Inverter_Done // 通信完成标志(TRUE=读取完成) ); // 写入变频器控制指令(示例:设定运行频率) "ModbusMaster"( EN_R := "DB_Control".SetFreq_Trigger, // 频率设定触发信号(HMI手动触发) PORT := 0, // 与读取端口一致 BAUDRATE := 9600, PARITY := 0, STOPBITS := 1, SLAVE := 1, // 与读取从站地址一致 RW := 1, // 读写标识:1=写入 ADDRESS := 40100, // 变频器频率设定寄存器地址(可修改) LENGTH := 1, // 写入寄存器长度(1个寄存器) DATA[0] := REAL_TO_INT("DB_Control".SetFreq * 10), // 频率放大10倍(适配变频器寄存器) ERROR => "DB_Modbus".Write_Error, // 写入错误代码 DONE => "DB_Modbus".Write_Done // 写入完成标志 ); |

Network 5:报警与故障处理

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| // 功能:调用FB8"AlarmHandler",集中采集所有故障信号,实现报警锁存、复位、代码生成 // 处理信号:急停、限位、电机过载、通信故障、编码器故障等 "AlarmHandler"( EmergencyStop_Alarm := "DB_Safety".EmergencyStop, // 输入:急停报警信号 LimitLeft_Alarm := "DB_IO".LimitLeft, // 输入:左限位报警信号 LimitRight_Alarm := "DB_IO".LimitRight, // 输入:右限位报警信号 Motor1_Overload := "DB_IO".Motor1_Overload, // 输入:电机1过载报警信号 Modbus_Error := "DB_Modbus".Inverter_Error <> 0, // 输入:Modbus通信报警(错误代码非0) Encoder1_Fault := "DB_HSC".HSC1_Status <> 16#00, // 输入:左侧编码器故障(状态字非16#0) Encoder2_Fault := "DB_HSC".HSC2_Status <> 16#00, // 输入:右侧编码器故障 Alarm_Reset := "DB_Control".AlarmReset, // 输入:报警复位信号(HMI触发) Alarm_Code => "DB_Alarm".AlarmCode, // 输出:报警代码(区分不同故障) Alarm_Text => "DB_Alarm".AlarmText, // 输出:报警文本(描述故障内容) Alarm_Latch => "DB_Alarm".AlarmLatch, // 输出:报警锁存(故障消除后需复位) FaultTotal => "DB_Alarm".FaultTotal // 输出:总故障信号(任意报警触发为TRUE) ); // FB8 "AlarmHandler" 内部SCL代码(封装于FB8中) FUNCTION_BLOCK "AlarmHandler" VAR_INPUT EmergencyStop_Alarm: BOOL; // 急停报警 LimitLeft_Alarm: BOOL; // 左限位报警 LimitRight_Alarm: BOOL; // 右限位报警 Motor1_Overload: BOOL; // 电机1过载报警 Modbus_Error: BOOL; // Modbus通信报警 Encoder1_Fault: BOOL; // 编码器1故障 Encoder2_Fault: BOOL; // 编码器2故障 Alarm_Reset: BOOL; // 报警复位信号 END_VAR VAR_OUTPUT Alarm_Code: INT; // 报警代码(1001-1007,区分故障类型) Alarm_Text: STRING[50]; // 报警文本(描述故障内容) Alarm_Latch: BOOL; // 报警锁存(TRUE=存在未复位报警) FaultTotal: BOOL; // 总故障信号(TRUE=任意报警触发) END_VAR // 总故障判断:任意报警触发,总故障为TRUE FaultTotal := EmergencyStop_Alarm OR LimitLeft_Alarm OR LimitRight_Alarm OR Motor1_Overload OR Modbus_Error OR Encoder1_Fault OR Encoder2_Fault; // 报警锁存与复位逻辑 IF Alarm_Reset THEN // 复位时,清除报警锁存、代码、文本 Alarm_Latch := FALSE; Alarm_Code := 0; Alarm_Text := ""; ELSIF FaultTotal AND NOT Alarm_Latch THEN // 故障触发且未锁存时,锁存报警并赋值代码、文本(按优先级排序) Alarm_Latch := TRUE; IF EmergencyStop_Alarm THEN Alarm_Code := 1001; Alarm_Text := "急停触发,设备停机,请复位急停"; ELSIF LimitLeft_Alarm THEN Alarm_Code := 1002; Alarm_Text := "左限位触发,禁止向左运行"; ELSIF LimitRight_Alarm THEN Alarm_Code := 1003; Alarm_Text := "右限位触发,禁止向右运行"; ELSIF Motor1_Overload THEN Alarm_Code := 1004; Alarm_Text := "电机1过载,需手动复位"; ELSIF Modbus_Error THEN Alarm_Code := 1005; Alarm_Text := "Modbus通信异常,检查变频器接线"; ELSIF Encoder1_Fault THEN Alarm_Code := 1006; Alarm_Text := "左侧编码器故障,检查接线或设备"; ELSIF Encoder2_Fault THEN Alarm_Code := 1007; Alarm_Text := "右侧编码器故障,检查接线或设备"; END_IF; END_IF; |

|---|
| |

相关推荐
wanhengidc2 小时前
服务器该如何防范网络攻击?
运维·服务器·网络·网络协议·安全·web安全·智能手机
源远流长jerry2 小时前
LVS 负载均衡完全指南:从入门到精通
运维·负载均衡·lvs
是垚不是土2 小时前
Kafka 故障排查周期长?试试 Kdoctor
linux·运维·分布式·ai·kafka·运维开发
ZC跨境爬虫2 小时前
3D 地球卫星轨道可视化平台开发 Day10(交互升级与接口溯源)
前端·javascript·3d·自动化·交互
学术小白人2 小时前
广州高博科技|以科技赋能科研,做学术文明的摆渡人与科研加速器
运维·人工智能·科技·制造·rdlink研发家·数字能源
王莎莎-MinerU2 小时前
IP Publisher × Hermes:个人IP内容自动化完全指南
人工智能·tcp/ip·chatgpt·自动化·创业创新·个人开发
野木香2 小时前
linux安装常用服务(不含jenkins)
linux·运维·jenkins
计算机安禾2 小时前
【Linux从入门到精通】第8篇:用户与权限管理(上)——谁动了我的文件?
linux·运维·服务器
艾莉丝努力练剑2 小时前
【Linux线程】Linux系统多线程(九):线程池实现(附代码示例)
linux·运维·服务器·c++·学习·架构