我经常使用Trace来验证通信的数据结构,这类数据快速变化的逻辑场景,已经习惯了。这个话题比较泛泛,不似某个具体功能或设备FB,只能说点体会。
论坛中的绝大部分人似乎很少或几乎从来不用博图中的Trace功能,这应该是经典PLC编程习俗给塑造出来的,就靠脑袋。
但现实中我们都明白,做事想要有效率,必须要有专用工具。程序中所有的关键数据,在每个扫描周期是如何变化的,如果干靠脑袋,随着事情越来越复杂,能把程序员搞蒙或耗时费力累惨。
博图和smart平台的一个重要区别,就是这Trace功能。它提供给程序员一种可以实时动态观察数据结构变化的精确手段。
如果用熟了,Trace在直觉效果上等于是一种图形语言,这句话是我的总结,它和构画一篇文章是类似的。
如果想要在Trace中非常容易和直觉化的看出数据结构的演化过程,用到的变量,在PLC程序设计的时候,就要考虑到这个变量在诊断中的使用方式和效率,也就是让它在Trace画面中的呈现方式要更易于理解。
功能异常、诊断和调试才是编程的常态,数据结构设计主要为此而存在。正常和满意是小概率事件。技术人员是为异常而活的,大部分人生都是耗费在出问题和解决问题上。所以解决问题的工具要锋利才好。
以下面这幅Trace图来解释一下。
这个图的物理场景是:我有3个温控器连接到1200的CB1241的485口,进行按设备的Modbus轮询。它们的真实波特率都是9600。
我在HMI界面上故意把第1个温控器的波特率设置为19200,它就被报警淘汰踢掉线了,不再进行通信。所以在图中的第2行,在开始的部分,你会看到iJob的数值一直是-1。
每个温控器FB实例,都有自己的一个任务数组,这个iJob就是当前正在执行读写任务的下标。因为0这个数字对于任务数组而言,它代表了一个真实的读写任务,而不是什么都没有,所以我让iJob的数值,在不执行任何任务的时候,默认值就是-1。这样每个任务之间就会被一个宽度为1个扫描周期的缝隙分割开,就可以清晰看到这些任务哪个是哪一个,一眼掌握进度和次序。
如果不是为了Trace,单纯从PLC算法而言,没必要每次都回到-1。或者说你也许根本不会意识到这种需求。
这和第1行中IndexActive的道理是一样的。IndexActive是目前正在占用485通道的从站,它在端口调度结构中的数组下标(注意:不是Modbus协议中的从站号)。所有的站点轮询一遍回来之后,它都会回到-1这个数值保持一个周期,这样我就知道它们到底转了多少圈了,每圈之间有一个扫描周期的视觉裂隙分割。
其实我在每个从站结束485通道占用的时候,都会让它为-1,但它马上就被扫描中的下一个从站给另外赋值了,所以只有在扫描中位于最后位置的那个从站,它释放485通道后的这个周期可以看到-1这个默认值缝隙。
你应该能看出来,程序中应该不止有3个温控器,因为IndexActive为2这个状态一直被跳跃过去了。事实上总共有5个从站(调度数组从0到4),2和4已经被淘汰了。我把它们设为不可见,减少两行的视觉占用和页面拥挤。
在时间轴上大约4000毫秒的地方,我在HMI上的第1个温控器的通信监控页面,按下了自动匹配485波特率的按钮。在这个画面中,你会看到我先后进行了2次波特率的自动匹配。这个功能完成后会自动复位(也可以人为在HMI上在执行过程中强行终止)。图中第6行的波特率检查这个Bool变量被置位和复位,先后两遍。
在波特率检查被置位期间(大约2秒钟),会看到第1个温控器,总共执行了11个任务。每个任务的宽度时长,和第5行的当前端口波特率(ActiveBaudRate)的每种波特率的宽度是上下一致对应的。
正确波特率的任务会更快执行完毕,所以这11个任务中会有一个相对更窄,也就是第6个任务(从300到115200,这11种西门子波特率中,9600排在第六位)。
你也会看出来,这11个任务,并不是每次都派发同一个任务。依然是按照任务自身的正常轮询次序,赶上那个算哪个,也就是自动匹配波特率这项功能,不会根本上影响任务的调度。这是通过Trace来验证调度算法的作用。
变量的设计和Trace的设计,都是为了让视觉更直观。
我们常说程序的易读性,一般是指在LAD、SCL等语言的视觉排版布局。这种可读性,顶多只能给程序员提供代码的静态结构效率。而Trace画面的易读性,提供的是程序员最需要掌握的动态数据变化描述,尤为重要。
Trace提供一种有效的手段,让程序员可以精雕细琢自己的数据结构和逻辑设计,让代码迭代更扎实。提高水平没啥绝招,就是持续学习新事物,不断实践,熟能生巧。