当前位置: 首页 > backend >正文

博图 SCL 编程技巧:灵活实现上升沿与下降沿检测案例分享(下)

应用案例分享:电机启停与状态记录

假设我们有一个电机控制场景:

  1. 按下启动按钮 (StartButton) 的上升沿启动电机 (MotorRun)。

  2. 按下停止按钮 (StopButton) 的上升沿停止电机。

  3. 记录电机启动成功的时刻(启动命令发出后,当运行反馈 MotorFeedback 变为 TRUE 的上升沿)。

  4. 记录电机停止完成的时刻(停止命令发出后,当运行反馈 MotorFeedback 变为 FALSE 的下降沿)。

SCL 实现代码示例


VAR_INPUTStartButton: BOOL; // 瞬动按钮 (上升沿有效)StopButton: BOOL; // 瞬动按钮 (上升沿有效)MotorFeedback: BOOL; // 电机运行反馈信号ResetLog: BOOL; // 复位记录的时间戳
END_VAR

VAR_OUTPUTMotorRun: BOOL; // 电机运行命令输出StartTime: DTL; // 电机启动成功时间StopTime: DTL; // 电机停止完成时间
END_VAR
VAR// 边沿检测实例StartEdge: R_TRIG; // 启动按钮上升沿StopEdge: R_TRIG; // 停止按钮上升沿FeedbackRising: R_TRIG; // 反馈信号上升沿 (用于启动完成)FeedbackFalling: F_TRIG; // 反馈信号下降沿 (用于停止完成)
END_VAR

// 主执行逻辑
// 1. 检测按钮边沿
#StartEdge(CLK := #StartButton);
#StopEdge(CLK := #StopButton);// 2. 控制电机启停 (启保停逻辑)
#MotorRun := (#MotorRun OR #StartEdge.Q) AND NOT #StopEdge.Q;// 3. 检测电机反馈边沿
#FeedbackRising(CLK := #MotorFeedback);
#FeedbackFalling(CLK := #MotorFeedback);// 4. 记录启动/停止完成时间 (使用DTL类型)
IF #FeedbackRising.Q THEN#TempTime[0]:= "Date_And_Time_Long".StartTime[0];  // 读取当前本地时间#StartTime := #TempTime[0];      // 直接存储DTL类型
END_IF;IF #FeedbackFalling.Q THEN#TempTime[1] := "Date_And_Time_Long".StartTime[0];;  // 读取当前本地时间#StopTime := #TempTime[1];       // 直接存储DTL类型
END_IF;// 5. 复位记录
IF #ResetLog THEN// 使用DTL类型默认值#StartTime := DTL#1970-01-01-00:00:00.000;#StopTime := DTL#1970-01-01-00:00:00.000;
END_IF;
OB1




启动调试
停止调试

复位调试

代码关键点解析

  1. 边沿检测: 使用了四个 R_TRIG 和 F_TRIG 实例分别检测启动按钮、停止按钮的上升沿以及电机反馈信号的上升沿和下降沿。这清晰地分离了不同信号的检测逻辑。

  2. 电机控制: 使用标准的启保停逻辑 (MotorRun := (MotorRun OR StartEdge.Q) AND NOT StopEdge.Q;)。StartEdge.Q 和 StopEdge.Q 只在对应按钮按下时的一个扫描周期内为 TRUE,确保了单次触发。

  3. 时间记录:

    • 当检测到电机反馈信号的上升沿 (FeedbackRising.Q = TRUE),意味着电机实际启动成功,此时记录 StartTime

    • 当检测到电机反馈信号的下降沿 (FeedbackFalling.Q = TRUE),意味着电机实际停止完成,此时记录 StopTime

    • 使用 LOCAL_TIME (返回 DTL 类型) 配合 DTL_TO_DT 函数获取当前时间戳 (转换为 DT 类型存储)。DT 类型在 TIA Portal 中常用于时间戳记录。

  4. 复位: ResetLog 输入允许外部复位记录的时间戳。

重要注意事项

  1. 存储位置:

    • 对于方法 1 (R_TRIG/F_TRIG),函数块的内部状态(相当于 LastState)存储在实例 DB 中。确保实例 DB 被正确分配和保持。

    • 对于方法 2 (纯 SCL),LastState 必须声明为 STATIC 或位于 FB 的非保持性 VAR 区域(但需要确保 FB 实例 DB 保持),或者在 FC 中声明为 STATIC关键是其值必须在扫描周期之间保持。

  2. 扫描周期: 边沿检测依赖于比较当前值上一扫描周期的值。务必在同一个块内、按正确的顺序(先比较,再更新 LastState)执行逻辑。

  3. 单周期脉冲: 所有方法产生的边沿检测输出 (Q 或 Out) 都只在一个 PLC 扫描周期内为 TRUE。如果你的动作需要维持更长的时间(如点亮一个指示灯表示“检测到过边沿”),你需要自行添加锁存逻辑(例如使用 SET 指令或简单的自锁)。

  4. 初始化:

    • R_TRIG/F_TRIG 块在第一次扫描或冷启动时,其内部状态通常初始化为 0

    • 在纯 SCL 方法中,务必初始化 LastState (如 LastState: BOOL := FALSE;)。未初始化的静态变量值是不确定的!

  5. 输入信号抖动: 对于物理按钮或传感器,可能存在抖动(短时间内多次跳变)。边沿检测块会对每次跳变都产生一个脉冲。如果业务逻辑要求忽略抖动,需要在边沿检测之前添加去抖动逻辑(例如使用定时器)。

  6. 多任务环境: 如果边沿检测的输入信号在一个扫描周期内被多个任务或中断访问并修改,可能导致边沿检测逻辑失效或产生意外脉冲。确保信号状态在单个任务周期内是稳定的。

总结

在 TIA Portal SCL 中实现上升沿和下降沿检测,推荐优先使用系统函数块 R_TRIG 和 F_TRIG。它们标准化、易用、封装性好,是多信号检测场景的首选。理解其背后的原理(比较当前值和上一周期值)对于调试和理解 PLC 扫描机制至关重要。

纯 SCL 代码实现适用于简单、临时的检测需求,或者作为理解底层机制的学习工具。务必注意静态变量的初始化和生命周期管理。

选择哪种方法取决于项目的复杂度、可读性要求、个人习惯以及对资源管理的考量。希望本文的案例和解释能帮助你在实际博图 SCL 项目中更得心应手地处理边沿检测问题!


进阶思考:

  • 如何用 SCL 实现一个既能检测上升沿也能检测下降沿的通用边沿检测块 (ANY_EDGE)?

  • 如何在 FC (函数) 中安全地实现边沿检测(注意 FC 无状态,需通过 INOUT 参数传递 LastState)?

  • 如何处理边沿检测与 PLC 任务扫描时间的关系,特别是在高速应用中?

http://www.xdnf.cn/news/13152.html

相关文章:

  • 交通自动气象站的作用
  • [Linux] 命令行管理文件
  • 国产三维CAD皇冠CAD(CrownCAD)建模教程:压力变送器
  • 如何开发ONLYOFFICE协作空间插件:完整教程
  • AI高考志愿助手应用架构设计并上线实施运行
  • 使用python进行图像处理—图像变换(6)
  • 前端开发面试题总结-vue2框架篇(一)
  • MES系统如何解决电机制造业自动化生产管理?
  • 回溯算法学习
  • PCIe-8622工业级网卡特性解析
  • Linux中《基础IO》详细介绍
  • leetcode刷题经验
  • 云安全与网络安全:核心区别与协同作用解析
  • 统计学(第8版)——统计抽样学习笔记(考试用)
  • 使用 Python 正则表达式实现文本替换与电话号码规范化
  • 位运算求最大值的子集数目问题
  • Ace网络验证软件卡密系统-免费免搭建 记录整理
  • 如何让非 TCP/IP 协议驱动屏蔽 IPv4/IPv6 和 ARP 报文?
  • 搭建仿真yolo环境
  • Docker安装、基础知识、项目部署笔记
  • Ubuntu里面单独编译某一个模块
  • iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享
  • nacos开启鉴权密码登录
  • FFmpeg:Windows系统小白安装及其使用
  • R语言速释制剂QBD解决方案之三
  • 曼昆《经济学原理》第九版 第十一章公共物品与公共资源
  • WDK 10.0.19041.685,可在32位win7 sp1系统下搭配vs2019使用,可以编译出xp驱动。
  • 深度剖析OpenSSL心脏滴血漏洞与Struts2远程命令执行漏洞
  • DAP-seq测序(DNA亲和纯化测序)!
  • Python爬虫实战:研究Restkit库相关技术