#03 SimpleStateMachine应该如何处理

我们在软件开发过程中,常常会遇到将机器设计成按一定的逻辑执行某些步骤,我们常管这个叫简单状态机Simple State Machine , 熟悉NI Core教程的小伙伴都知道学的第一款框架就是QMH(Queue Message Handler)。 在MHL(Message Handler Loop)中不同case间的来回切换很容易让我们觉得这就是个状态机。

State machine 中的case为何不能直接放入MHL,用MHL的case结构来控制不同状态的切换?

有些工程师会将这些步骤打包成数组放在MHL中,然而在实际中,当程序运行至Sequence中,如果有异常中断,比如说用户退出,则需要将队列中所有步骤运行完才会停止,因此如此操作并非明智之举。

还有些工程师可能会采用Flush Queue来解决这个问题,每次有异常中断时,先将队列中元素移除,以方便处理无法预料的中断。然而,这样做法依然不妥,因为我们只是简单的移除队列中剩余步骤,试想一下,当中断完成之后,仍然需要接着中断之前的顺序来执行改如何处理?

还有一个点子就是设计成高优先级(High Priority),当有事件传进来之后,将这个队列元素插入到其他元素之前,如果中断的种类增多,应该优先执行哪一个?

在执行Step1 到Step2的过程中,我们理想的情况是中间不会产生其他的步骤,但是我们始终无法避免哪天会不会有一个Step1.1冒出来,因此,开发的时候就应该将QMH中的case看成一个有机的个体,QMH并非一个StateMachine,为了减少case中间的相互依赖,每个case中不应该通过Enqueue Message联系。

如何实现Process中途停止?

做好State Machine并非使用一个While + Case如此简单。一种比较好的方式是将StateMachine做成子vi,而这个子vi可以采用Event来响应外部的中断信息,在Timeout分支中创建需要执行的控制步骤,当有外部中断产生时,触发事件跳出循环。

在实际应用中,用Sequence 模块来管理控制流程,如Noload→Load→…→Poweroff,考虑到后续动作需求的变化,
我将硬件DIO以及AIO的基本控制单独封装于DAQ模块,而时间控制则采用Timer模块。在Sequence模块中,可以调用DAQ,和Timer的方法来管理控制流程,当每次需要增加步骤时,只需要改动Sequence模块中代码,而无需改变DAQ,和Timer模块代码。

总结

  1. StateMahine是学习Labview的必经之路,如何在实际项目中找成出更好的解决之道才是关键。
  2. 搭配通知器Notifier与队列Queue的使用会使得Labview编程更加愉快。
  3. 可以做一个Controller Module 来更好的实现步骤的管理,而无需依赖MHL中case的切换。

参考

NI Simple State Machine http://www.ni.com/video/2727/en/
NI QMH https://delacor.com/ni-qmh-template/

发表评论