4、定时中断:定时中断原理、定时中断设置、定时中断应用场景、定时中断实例
定时中断,说白了就是让PLC每隔一段固定的时间,自动去执行一段程序。你不需要一直盯着它,它自己会按时干活。这个功能在工业现场非常实用,我几乎每个项目都会用到。
4.1 定时中断原理
定时中断的核心思想很简单:PLC内部有一个高精度的定时器,这个定时器一直在跑。当它计数到我们设定的值时,就会触发一个中断信号。CPU收到这个信号后,会暂停当前正在执行的主程序,转而去执行中断服务程序。执行完再回来接着干主程序。
为什么会这样设计?你想想看,主程序扫描周期是不固定的。有时候程序长,扫描慢;有时候程序短,扫描快。但有些任务,比如PID调节、高速数据采集,必须严格按固定时间间隔执行。这时候定时中断就派上用场了。
核心要点:定时中断的优先级高于主程序扫描周期。它不受主程序长短的影响,严格按设定的时间间隔触发。
我在项目中遇到过这样的情况:一个包装机需要每10ms采集一次称重传感器的数据。如果用主程序轮询,扫描周期一波动,数据采集就不准了。后来改用定时中断,问题立马解决。
4.2 定时中断设置
不同品牌的PLC,定时中断的设置方法略有差异。但核心参数就三个:中断号、时间间隔、中断服务程序。
以西门子S7-1200为例,我习惯这样设置:
// 在OB块中配置定时中断
// OB30:循环中断,默认时间间隔100ms
// 可设置范围:1ms - 60000ms
// 第一步:添加循环中断组织块
// 在项目树中双击"添加新块"
// 选择"组织块(OB)" -> "循环中断(OB30)"
// 第二步:设置时间间隔
// 在OB30的属性中,设置"循环时间"为10ms
// 第三步:编写中断服务程序
// 在OB30中写入需要定时执行的代码
个人经验:时间间隔不要设得太短。我曾经为了追求极致响应,把中断间隔设为1ms。结果CPU大部分时间都在处理中断,主程序反而跑不动了。一般建议:普通应用10-50ms,高速应用5-10ms,极限情况不要低于2ms。
三菱FX系列的做法不太一样:
// 三菱FX3U定时中断设置
// 使用M8028特殊继电器启用定时中断
// 通过D8028设置中断时间间隔(单位:ms)
// 示例:设置10ms定时中断
LD M8000
MOV K10 D8028 // 设置中断间隔为10ms
SET M8028 // 启用定时中断
// 中断服务程序写在指针P0处
P0
// 这里写需要定时执行的代码
IRET // 中断返回
| 品牌 | 中断组织块 | 时间设置范围 | 精度 |
|---|---|---|---|
| 西门子S7-1200 | OB30-OB38 | 1ms - 60000ms | ±0.1ms |
| 三菱FX3U | 指针P0-P15 | 1ms - 1000ms | ±0.5ms |
| 欧姆龙CP1H | 定时中断任务 | 0.5ms - 9999ms | ±0.1ms |
4.3 定时中断应用场景
定时中断的应用场景其实挺多的。我挑几个典型的说说:
- PID闭环控制:温度、压力、流量等模拟量控制,需要固定采样周期。比如温度控制,每100ms采集一次温度值,计算PID输出。用定时中断最合适。
- 高速计数与测速:配合编码器测转速,需要固定时间窗口内统计脉冲数。比如每50ms统计一次脉冲数,换算成转速。
- 数据采集与记录:需要按固定间隔采集传感器数据,存入数据缓冲区或上传到上位机。
- 脉冲输出控制:步进电机或伺服电机的脉冲频率控制,需要精确的时间基准。
- 通信心跳检测:定时检查与上位机或其他设备的通信状态,超时则报警。
注意:定时中断服务程序要尽量短小精悍。我曾经见过有人把整个PID运算都放在中断里,结果中断执行时间太长,影响了下一个中断的触发。记住:中断里只做必要的事,复杂的计算放到主程序里做。
4.4 定时中断实例
下面我以一个实际项目为例,展示定时中断的完整应用。这是一个恒温控制系统的核心代码:
// 项目:恒温箱温度控制
// 要求:温度控制在50±0.5℃,每100ms执行一次PID运算
// 主程序(OB1)
Network 1: 初始化
"Init_Done" := FALSE;
IF "First_Scan" THEN
"Setpoint" := 50.0; // 设定温度50℃
"Kp" := 2.5; // 比例系数
"Ki" := 0.1; // 积分系数
"Kd" := 0.05; // 微分系数
"Init_Done" := TRUE;
END_IF;
// 定时中断程序(OB30,间隔100ms)
Network 1: 读取当前温度
"Current_Temp" := "Temp_Sensor"; // 读取温度传感器
Network 2: 计算偏差
"Error" := "Setpoint" - "Current_Temp";
Network 3: PID运算
// 比例项
"P_Out" := "Kp" * "Error";
// 积分项(带限幅)
"I_Out" := "I_Out" + "Ki" * "Error" * 0.1;
IF "I_Out" > 100.0 THEN "I_Out" := 100.0; END_IF;
IF "I_Out" < -100.0 THEN "I_Out" := -100.0; END_IF;
// 微分项
"D_Out" := "Kd" * ("Error" - "Last_Error") / 0.1;
"Last_Error" := "Error";
// 总输出
"PID_Out" := "P_Out" + "I_Out" + "D_Out";
// 输出限幅
IF "PID_Out" > 100.0 THEN "PID_Out" := 100.0; END_IF;
IF "PID_Out" < 0.0 THEN "PID_Out" := 0.0; END_IF;
Network 4: 输出到加热器
"Heater_Output" := "PID_Out"; // 控制加热器功率
避坑指南:我曾经在积分项上吃过亏。积分项如果不加限幅,当温度偏差持续存在时,积分值会一直累加,导致输出饱和。等温度达到设定值时,积分值已经很大了,需要很长时间才能退出来,造成超调。所以一定要加积分限幅。
这个实例中,定时中断每100ms执行一次PID运算。主程序负责初始化和其他非实时任务。两者分工明确,互不干扰。实际运行效果很好,温度控制精度达到了±0.3℃。
嗯,这里要注意一点:定时中断的时间间隔要跟被控对象的响应速度匹配。温度控制这种大惯性系统,100ms的采样周期足够了。如果是电机转速控制,可能需要10ms甚至更短。
以上就是定时中断的核心内容。从原理到设置,再到实际应用,希望能帮你建立起完整的知识框架。记住一句话:定时中断是PLC实现精确时间控制的关键手段,用好它,你的程序会上一个台阶。