西门子PLC精确计算设备运行时间程序(1200PLC与1500PLC通用)——改良版实时时间比较法
西门子PLC精确计算设备运行时间程序,1200PLC和1500PLC通用,两次读取PLC的实时时间做比较,这样就可以不算入PLC每次扫描时间,非常准确的记录设备运行时间。 虽然西门子官方有案例,但是不好用,我进行了改良,可以非常合适的应用到项目里。
搞工控的兄弟应该都遇到过这种需求——得精确统计设备运行时间。西门子PLC自带的时间记录功能用过的都知道,那玩意儿就跟闹着玩似的,扫描周期造成的误差能气死人。今天分享个野路子,直接读取两次PLC系统时间做对比,误差控制在毫秒级。
先上核心代码:
VAR FirstScanTime: DT; //第一次读取时间戳 LastScanTime: DT; //第二次读取时间戳 RunTimeAccumulator: TIME; //运行时间累加器 END_VAR IF "设备运行信号" THEN FirstScanTime := RD_SYS_T(); //首次抓取系统时间 //...中间可能有其他逻辑 LastScanTime := RD_SYS_T(); //再次抓取系统时间 RunTimeAccumulator := RunTimeAccumulator + (LastScanTime - FirstScanTime); END_IF;这代码的精髓在于两次读取系统时间。PLC的扫描周期虽然不稳定,但两次读取动作发生在同一个扫描周期内,系统时间的差值刚好就是程序处理实际业务逻辑的时间。注意这里用DT数据类型(DATEANDTIME)直接相减会自动转成TIME类型,省去了类型转换的麻烦。
西门子PLC精确计算设备运行时间程序,1200PLC和1500PLC通用,两次读取PLC的实时时间做比较,这样就可以不算入PLC每次扫描时间,非常准确的记录设备运行时间。 虽然西门子官方有案例,但是不好用,我进行了改良,可以非常合适的应用到项目里。
实际项目里我习惯在OB1开头和结尾各放一个RDSYST:
//OB1开头 #StartTime := RD_SYS_T(); //...主程序逻辑 //OB1结尾 #EndTime := RD_SYS_T(); #RunTimeAccumulator += (#EndTime - #StartTime);这种写法有个隐藏福利——就算PLC突然断电,累加器数值也不会清零。当然记得要在DB块里设置保持属性,不然重启后数据就飞了。
遇到过最坑爹的情况是跨午夜时间计算,这时候得处理日期变更:
IF DATE_TO_DINT(#EndTime.DATE) > DATE_TO_DINT(#StartTime.DATE) THEN //处理跨天的情况 #TempTime := DINT_TO_TIME(86400000) - #StartTime.TOD; //计算当天剩余时间 #RunTimeAccumulator := #RunTimeAccumulator + #TempTime + #EndTime.TOD; ELSE //正常时间差计算 #RunTimeAccumulator := #RunTimeAccumulator + (#EndTime - #StartTime); END_IF;这段处理跨天的逻辑建议封装成FC块,调用起来方便。实测误差可以控制在PLC系统时钟精度范围内(约±2秒/天),比用计数器统计靠谱多了。
最后提醒下,别在中断OB里用这招,中断程序的执行时间会被算到主程序头上。要是项目对时间精度要求变态级,可以挂个硬件时钟模块,不过那又是另一个故事了...
