Image by xresch from Pixabay

LabView-03

变量与模板

Posted by Yvan on October 15, 2021

LabView

一 [L1/2] 数据传递

A Variable

用一个开关同时停止两个Loop循环

image-20211016000415177

使用场景

  1. 初始化
  2. 重写Controls数据
  3. 同步控制平行loop

缺点:

  1. 失去Data Flow先后顺序的可读性
  2. 布尔原件只能试用switch类
  3. Race Condition
  4. Data Loss 如果两个循环以不同速率运行/因为循环内算法原因产生不同时间的延时。
  5. 慢, 每一个变量都是一个副本,同时占用内存空间 (但是比 Property Node - Value 要快

* Race Condition

同时运行的Data Flow:

image-20211016001902951

防止方法:

  1. 减少使用变量
  2. 合理使用sequence结构,安排先后顺序
  3. 一写一读/一写多读 

单线程应用程序中,使用子程序级VI读出或者写入全局变量不会造成竞争状态,因为子程序级VI不与其它VI共享执行线程。在多线程应用程序中,子程序级不保证对全局变量的唯一访问,因为当另一个VI在另一个线程上运行时,它能够同时访问全局变量。

 

B Queue

平行的loop可以分为同步与异步。传递值也可以分为传递最终值和传递每一个值。如果只需要传递最终值,可以使用局部变量,比如开关。但如果需要传递每一个值,局部变量可能会导致数据丢失/重复

image-20211016005123322

使用Queue能很好的同步两个循环,并且避免数据丢失或重复。FIFO,允许在队尾队首进行插入操作。

优点:

1. 多个循环能很好的同步 2. 避免了数据丢失的可能 3. 不使用轮询机制,减少资源消耗

C Notifier

队列列无法实现一写多读,一个值入列后,只能被一次出列获取。Notifier可以广播一个变量,但是不能缓存值,只能传递最终值,即如果在第一次广播时刻,收听广播的循环挂起,第二次广播时才回来,那么第一次的值就会丢失。

image-20211016010451217

二 [L3] 样式

代码结构样式

样式由大量开发者努力提升而来,有点是简单明确,可读性高,可维护性高。用状态机和producer-consumer的样式基本能解决大多数简单问题了。

Simple Design Pattern

单次运行的程序,多用于SubVI。操作快捷,结构简单,只需要点击开始运行程序即可。

General VI Pattern

开始 - 主程序 - 结束

开始负责初始化硬件,变量等。主程序使用循环,直到用户选择退出程序。结束负责关闭文件,删除任务等。

State Machine Pattern

开始 - 状态机- 结束

  1. Polling State Machine Framework

image-20211016011249879

  1. Event-Based State Machine

    image-20211016011316776

Multiple Loop Design Patterns

注意一写多读/一写一读

  1. Producer/Consumer Design Pattern

    image-20211016011517029

  2. Event based Producer/Consumer Design Pattern with Error Handling

    1. Producer使用event机制向队列中增加元素,consumer使用dequeue获取元素。

    2. 如果producer出现error:

      1. guard进入error-case,在队列最前端插入stop-state
      2. consumer得到stop-state,进入stop-state,停止自身,并激活虚拟stop按钮(property node - value signal)
      3. producer激活stop-event,停止自身
    3. 如果在consumer中出现error:

      1. 通过shift register将error传递给下一个loop
      2. guard进入error-case,将状态机带入stop-state,停止自身,激活stop按钮
      3. producer激活stop-event,停止自身
    4. 下图是比较经典的结构,但有一个错误点

      producer的error-guard的enque不应该连结error-in,如果连接,在error状态下enqueue不会触发。应该断开连结,并在出口处用merge error整合原始error和enqueue的error-out。

    LabVIEW PC block diagram: producer-loop contains event structure and guard clause; consumer-loop contains guard clause and case structure; both loops share the same queue reference

比较

image-20211016012843397

image-20211016012906935

功能全局变量样式

这一整个代码部分被叫做功能全局变量,而不仅仅只是一个“变量”。

img

  1. 功能全局变量多为VI,常用的例子是Timer,可以作为SubVI供其他使用
  2. 功能全局变量是不可重进入的,使用不初始化的位移寄存器。
  3. 通常有一个动作(上图中:操作) 输入参数,用于指定VI执行的任务,即改变状态/Case。
  4. 可以保护访问变量操作的关键代码,避免全局变量引起的竞态。相当于文本代码编程中只留下set方法来改变变量,需要改变变量时必须调用这个方法,这里时必须调用这个SubVI。LabVIEW的单线程SubVI无法同时被调用(确保一次只有一个调用者修改数据内容),所以避免了竞态。
  5. 缺点是如果需要对变量进行新的操作,则需要增加状态/case。

错误处理样式

  1. 错误处理

    用于显示错误弹窗,调整状态机代码至错误/关机状态

image-20211016014617436

  1. 错误生成

    使用 Error Ring / Errr Cluster

时间样式

  1. Execution Timing:暂停这个循环的时间,使处理器处理其他事件
    1. wait ms
    2. wait unit next ms multiple
    3. Event based Producer without timeout
  2. Software Control Timing:告知时间,不改变运行速度
    1. Elapsed Time
    2. Fuctional Timeout
    3. obtaining timestamp
      1. Tick Count ms
      2. High Resolution Relative Seconds
      3. Get Date/Time in Seconds

三 [L4] 用户界面

1 VI Server 面向对象/类

不是服务器的意思,是指提供了针对VI的服务。提供了允许用户动态控制前面板控件、VI和LabVIEW环境的一系列函数,也包括通过网络动态加载VI等(真·服务器)功能。

功能:

  • 编程地控制前面板控件和VI (LabVIEW的编程指Block Diagram程序框图的图像编程)
  • 动态加载和调用VI
  • 本地运行/网络运行VI
  • 编程地进入VI环境和编辑器

VI前面板控件具有面向对象架构。所有VI都具有可以通过VI服务器函数来读写的属性,也有可以被VI服务器函数调用的方法

image-20211016112314825

比如 布尔控件(开关) 是 图形对象类 - 控件类 - 布尔控件类 的成员。那么和文本编程一样,高级别的大类的属性和方法被子类继承,低级别的子类具有自己独特的属性和方法。

img

2 属性 Property Nodes

功能:

  • 读写属性
  • 在程序中自定义(如:当x大于50时显示按钮为红色)

Reference的Implicitly连接和Explicitly连接

image-20211016115429274

img

如果需要传递一个值,那么有三种方法:

  1. Data Flow连线
  2. 局部变量:Local Variable
  3. 属性-值:Property Node - Value

能用Data Flow尽量用,最差的选择就是Property Node - Value。

详细比较见:输入控件/显示控件、局部变量和值属性节点之间的区别

3 方法 Invoke Nodes

功能:

  • 调用方法 (比如导出图表图片)

也分为Implicitly连接和Explicitly连接,输入有必须和可选

image-20211016120037017

4 Reference

1 连接属性/方法Node

Implicitly连接

  • 属性/方法Node被直接关联到对应的控件,只能在同一个VI中使用。
  • 由于没有连线,所以叫Implicitly。节点有颜色显示连接状态。

Explicitly连接

  • explicitly的连接方式是可以到到SubVI中调用的, 当然也可以在同一个VI中使用。
  • 有连线所以叫Explicitly。节点有小扳手/箭头。

image-20211016120706399

建立用于Explicitly连接的Reference Terminal

  • 和其他控件类似,Reference也有 ConstantControl/Indicator
    • Constante会输出固定的refnum,并且只显示在程序框图界面中,连接的属性/方法节点的类Class和类型Type会被限制住。

      image-20211016123655886

    • Control/Indicator需要在前面板中添加,可以连接connector pannel,也就是说,可以传入/传出SubVI。

      image-20211016122802194

      image-20211016130523506

      • :低级或者高级 VI Server Class:可以限制/拓展接口输入的接纳程度,比如选择控件类还是布尔控件类。

        image-20211016135027783

      • 类型Weakly typed或者Strictly typed

        • weakly不关心输入ref的data type,

        • strickly限制data type,接受程度取决于能否coercion。

        • 例:如果控件refnum选择为滑块,

          • 那么weakly的可以连结 any data type
          • 而stricly只接受具体连接到的那一种,在这里是numeric的。stricly的图标上有红色五角星。

          image-20211016132525353

2 连接Reference Terminal

image-20211016142534989

image-20211016142718833