西门子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个寄存器) DATA0 := 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: STRING50; // 报警文本(描述故障内容) 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; |

|---|
| |

相关推荐
荣--19 小时前
一键部署不是为了省时间 —— 它是把"买来的 PaaS"变成"自己的平台"的拐点
运维·zabbix·工程化·一键部署·平台化·边界设计
江华森20 小时前
动手实战学 Docker — 从零到集群编排完全指南
运维
Avan_菜菜1 天前
FRP 内网穿透完整实战:从 HTTP 映射到 HTTPS 自签代理
运维·nginx·https
SelectDB2 天前
Litefuse 开源并推出单进程轻量模式,25 秒就能跑起来的 Agent 可观测与评估平台
运维·后端·自动化运维
XIAOHEZIcode4 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220705 天前
如何搭建本地yum源(上)
运维
大树888 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠8 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质8 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
Inhand陈工8 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信