labview操作者框架

http://blog.csdn.net/u011520129/article/details/51628175

    操作者框架适合于多并行任务的项目。在这样的项目中,多个并行任务之间往往需要相互通信,传统的解决办法是,每个任务一个队列,一个while循环,任务多的多个while在一个程序框图中,不好看,有木有。
NI说使用Actor Framework能够避免锁死,竞争,增大代码重用度。NI官方论坛上有一个例子,写的很好。


     如上图,这是一个反馈式蒸发器,通过不断向室内吹送水蒸气以达到降温目的。它主要由水位传感器,温度传感器,水箱,水阀,水泵,风扇,海绵组成。原理如下:读取水位,水位过低时,打开水阀向水箱中放水;水位过高时关闭水阀。同时,读取室内温度,温度过高时,打开水泵向海绵上抽水,等海绵吸满水后,打开风扇,向室内鼓风,干燥的风经过湿透的海绵,成为温度较低的湿润的风,以此来降低室内温度;温度过低时,关闭水泵。

    项目需求:

  1. 控制水位。过低打开水阀,过高时关闭水阀。
  2. 控制温度。过高时,打开水泵,等一会,再打开风扇。过低时,关闭水泵。
  3. 在界面上显示温度,水泵,风扇状态。
  4. 允许在界面上改动温度限制。
  5. 系统中总共使用两个风扇,一个坏另一个自动启用。
  6. 系统可以脱离界面运行。

    有点小复杂。

    解决方案:

    系统需要4个模块:UI(Cooler UI with Events.lvclass) ,冷却模块(Dual Fan.lvclass)),水位控制模块(Water Level.lvclass),风扇控制模块(Dual Fan.lvclass)。其中冷却模块是主模块,与风扇控制模块和水位控制模块组合关系,和UI模块是关联关系。(PS:Cooler需要负责Dual Fan和Water Level的启动和释放,Cool通过动态事件和Cooler Panel交互),每个模块为一个Actor。


有没有注意到,冷却模块(Cooler.lvclass)),水位控制模块(Water Level.lvclass),风扇控制模块(Dual Fan.lvclass)都需要轮询,Dual Fan轮询有没有风扇坏掉了,Water Level轮询水位,Cooler轮询温度。一个逻辑写三遍,烦。所以写个Timed Loop Controller.lvclass,哪个操作者需轮询要直接从它继承就可以了。继承使代码复用度提高了。

    同理,水位控制模块(Water Level.lvclass),风扇控制模块(Dual Fan.lvclass)还有相似的逻辑——超过限位就打开或关闭。写个Level Controller.lvclass作为这两个操作者的父类,因为labview中一个孩子只能有一个父亲,所以Level Controller.lvclass需要继承自Timed Loop Controller.lvclass。

    族谱如下:

1.创建Timed Loop Controller.class

这个类只需要一个属性:轮询频率。首先使其继承Actor.class。

1.1 Actor Core.vi


图中的Actor Core中有一个while, 当它收到停止消息时,就会退出,之后通过局部变量使stop为真,与Actor Core并行执行的循环结束。

1.2 Update.vi

什么都不写,留给子类重写。

2. 创建Level Controller

    Cooler actors 和Water Level actors的逻辑是一样的,都是超过限位就打开或者关闭。所以创建此类作为这两个类的父类,以增大代码重用度。
    这个类需要三个属性:高限位,低限位,这两个作为输入;另外还需要保存输出的值:高,低,不变。

    State Logic.vi是要复用的逻辑,Level Controller肯定要先从硬件读取输入,然后在进行逻辑操作,最后输出结果,输入和输出是和硬件有关系的,为了增大软件的灵活度,我们将输入和输出作为虚函数,留给子类去写,这样更换硬件时,我们只需从此类继承,并重写输入输出vi即可。太机智。
    另外,此类重写了Update.vi。
    因为父类中与状态机并行执行的while中,会一直发送update消息。

    这个消息会以轮询的速率往队列中添加。下图为上图的程序框图。
    图中为Message类的Do.vi。
Update Msg.lvclass重写了这个Do.vi。当Actor的任何子类作为输入时,就会调用自己的Update。
    这里用了很多技巧。
    重写的update会以固定间隔运行。所以在update中,读取输入,逻辑处理,最后设置输出。但是硬件不同,故读取功能的代码和输出功能的代码肯定不一样,为了使软件可扩展性更好,所以将读取输入和逻辑输出作为虚函数(就是明知程序中必须有,但是又不能写在此类中),留给子类自己完善。
    最后,为了让其他Actor修改高低限位,创建了Write Deadband.vi,然后为此vi生成一个消息类。

你可能感兴趣的:(Labview)