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

博图 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 任务扫描时间的关系,特别是在高速应用中?

相关文章:

  • LangChain4j(18)——通过Xinference调用Rerank模型
  • 【前端实战】如何让用户回到上次阅读的位置?
  • 【C++】IO库 IO流
  • 禁用思科锐捷设备分页功能
  • redis--黑马点评--Redisson快速入门
  • pytorch卷积层权重之 二维互相关运算(corr2d) (亲测,已解决)
  • 神经网络学习-神经网络简介【Transformer、pytorch、Attention介绍与区别】
  • pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
  • 网页后端开发(基础1--maven)
  • 初探用uniapp写微信小程序遇到的问题及解决(vue3+ts)
  • 如何在 PyTorch 中自定义卷积核参数(亲测,已解决)
  • [免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
  • 设计模式-抽象工厂模式
  • C/Python/Go示例 | Socket Programing与RPC
  • 云原生时代的系统设计:架构转型的战略支点
  • GO语言---init函数
  • Go 语言底层(四) : 深入 Context 上下文
  • 鸿蒙 Stege模型 多模块应用
  • GO 基础语法和数据类型面试题及参考答案(下)
  • 解密鸿蒙系统的隐私护城河:从权限动态管控到生物数据加密的全链路防护
  • 有没有接单做加工的网站/衡阳网站建设公司
  • 山西做网站多少钱/seo需要付费吗
  • 中国建设银行网站首/宁德市安全教育平台
  • 濮阳网站建设 公司名字/没广告的视频播放器app
  • 做网站卖机器怎么弄/广州网站关键词推广
  • 小猫mip网站建设/石家庄seo关键词排名