LabView
一 [L1/2] 数据传递
A Variable
用一个开关同时停止两个Loop循环
使用场景:
- 初始化
- 重写Controls数据
- 同步控制平行loop
缺点:
- 失去Data Flow先后顺序的可读性
- 布尔原件只能试用switch类
- Race Condition
- Data Loss 如果两个循环以不同速率运行/因为循环内算法原因产生不同时间的延时。
- 慢, 每一个变量都是一个副本,同时占用内存空间 (但是比 Property Node - Value 要快)
* Race Condition
同时运行的Data Flow:
防止方法:
- 减少使用变量
- 合理使用sequence结构,安排先后顺序
- 一写一读/一写多读
在单线程应用程序中,使用子程序级VI读出或者写入全局变量不会造成竞争状态,因为子程序级VI不与其它VI共享执行线程。在多线程应用程序中,子程序级不保证对全局变量的唯一访问,因为当另一个VI在另一个线程上运行时,它能够同时访问全局变量。
B Queue
平行的loop可以分为同步与异步。传递值也可以分为传递最终值和传递每一个值。如果只需要传递最终值,可以使用局部变量,比如开关。但如果需要传递每一个值,局部变量可能会导致数据丢失/重复。
使用Queue能很好的同步两个循环,并且避免数据丢失或重复。FIFO,允许在队尾队首进行插入操作。
优点:
1. 多个循环能很好的同步 2. 避免了数据丢失的可能 3. 不使用轮询机制,减少资源消耗
C Notifier
队列列无法实现一写多读,一个值入列后,只能被一次出列获取。Notifier可以广播一个变量,但是不能缓存值,只能传递最终值,即如果在第一次广播时刻,收听广播的循环挂起,第二次广播时才回来,那么第一次的值就会丢失。
二 [L3] 样式
代码结构样式
样式由大量开发者努力提升而来,有点是简单明确,可读性高,可维护性高。用状态机和producer-consumer的样式基本能解决大多数简单问题了。
Simple Design Pattern
单次运行的程序,多用于SubVI。操作快捷,结构简单,只需要点击开始运行程序即可。
General VI Pattern
开始 - 主程序 - 结束
开始负责初始化硬件,变量等。主程序使用循环,直到用户选择退出程序。结束负责关闭文件,删除任务等。
State Machine Pattern
开始 - 状态机- 结束
- Polling State Machine Framework
-
Event-Based State Machine
Multiple Loop Design Patterns
注意一写多读/一写一读
-
Producer/Consumer Design Pattern
-
Event based Producer/Consumer Design Pattern with Error Handling
-
Producer使用event机制向队列中增加元素,consumer使用dequeue获取元素。
-
如果producer出现error:
- guard进入error-case,在队列最前端插入stop-state
- consumer得到stop-state,进入stop-state,停止自身,并激活虚拟stop按钮(property node - value signal)
- producer激活stop-event,停止自身
-
如果在consumer中出现error:
- 通过shift register将error传递给下一个loop
- guard进入error-case,将状态机带入stop-state,停止自身,激活stop按钮
- producer激活stop-event,停止自身
-
下图是比较经典的结构,但有一个错误点:
producer的error-guard的enque不应该连结error-in,如果连接,在error状态下enqueue不会触发。应该断开连结,并在出口处用merge error整合原始error和enqueue的error-out。
-
比较
功能全局变量样式
这一整个代码部分被叫做功能全局变量,而不仅仅只是一个“变量”。
- 功能全局变量多为VI,常用的例子是Timer,可以作为SubVI供其他使用
- 功能全局变量是不可重进入的,使用不初始化的位移寄存器。
- 通常有一个动作(上图中:操作) 输入参数,用于指定VI执行的任务,即改变状态/Case。
- 可以保护访问变量操作的关键代码,避免全局变量引起的竞态。相当于文本代码编程中只留下set方法来改变变量,需要改变变量时必须调用这个方法,这里时必须调用这个SubVI。LabVIEW的单线程SubVI无法同时被调用(确保一次只有一个调用者修改数据内容),所以避免了竞态。
- 缺点是如果需要对变量进行新的操作,则需要增加状态/case。
错误处理样式
-
错误处理
用于显示错误弹窗,调整状态机代码至错误/关机状态
-
错误生成
使用 Error Ring / Errr Cluster
时间样式
- Execution Timing:暂停这个循环的时间,使处理器处理其他事件
- wait ms
- wait unit next ms multiple
- Event based Producer without timeout
- Software Control Timing:告知时间,不改变运行速度
- Elapsed Time
- Fuctional Timeout
- obtaining timestamp
- Tick Count ms
- High Resolution Relative Seconds
- Get Date/Time in Seconds
三 [L4] 用户界面
1 VI Server 面向对象/类
不是服务器的意思,是指提供了针对VI的服务。提供了允许用户动态控制前面板控件、VI和LabVIEW环境的一系列函数,也包括通过网络动态加载VI等(真·服务器)功能。
功能:
- 编程地控制前面板控件和VI (LabVIEW的编程指Block Diagram程序框图的图像编程)
- 动态加载和调用VI
- 本地运行/网络运行VI
- 编程地进入VI环境和编辑器
VI前面板控件具有面向对象的类架构。所有VI都具有可以通过VI服务器函数来读写的属性,也有可以被VI服务器函数调用的方法。
比如 布尔控件(开关) 是 图形对象类 - 控件类 - 布尔控件类 的成员。那么和文本编程一样,高级别的大类的属性和方法被子类继承,低级别的子类具有自己独特的属性和方法。
2 属性 Property Nodes
功能:
- 读写属性
- 在程序中自定义(如:当x大于50时显示按钮为红色)
Reference的Implicitly连接和Explicitly连接
如果需要传递一个值,那么有三种方法:
- Data Flow连线
- 局部变量:Local Variable
- 属性-值:Property Node - Value
能用Data Flow尽量用,最差的选择就是Property Node - Value。
3 方法 Invoke Nodes
功能:
- 调用方法 (比如导出图表图片)
也分为Implicitly连接和Explicitly连接,输入有必须和可选。
4 Reference
1 连接属性/方法Node
Implicitly连接
- 属性/方法Node被直接关联到对应的控件,只能在同一个VI中使用。
- 由于没有连线,所以叫Implicitly。节点有颜色显示连接状态。
Explicitly连接
- explicitly的连接方式是可以到到SubVI中调用的, 当然也可以在同一个VI中使用。
- 有连线所以叫Explicitly。节点有小扳手/箭头。
建立用于Explicitly连接的Reference Terminal
- 和其他控件类似,Reference也有 Constant 和 Control/Indicator:
-
Constante会输出固定的refnum,并且只显示在程序框图界面中,连接的属性/方法节点的类Class和类型Type会被限制住。
-
Control/Indicator需要在前面板中添加,可以连接connector pannel,也就是说,可以传入/传出SubVI。
-
类:低级或者高级 VI Server Class:可以限制/拓展接口输入的接纳程度,比如选择控件类还是布尔控件类。
-
类型:Weakly typed或者Strictly typed
-
weakly不关心输入ref的data type,
-
strickly限制data type,接受程度取决于能否coercion。
-
例:如果控件refnum选择为滑块,
- 那么weakly的可以连结 any data type;
- 而stricly只接受具体连接到的那一种,在这里是numeric的。stricly的图标上有红色五角星。
-
-
-