LabVIEW使用硬件抽象层适应不同的接口
在实验室工作时,拥有不同品牌/型号的各种设备,有时(或多或少)具有相同的目的。为了缩短开发时间,想创建一个硬件抽象层,允许使用所有相同类型的仪器,并具有高级驱动程序(抽象)。我认为最好的“架构”是OOP,但我面临一个问题。
作为一个例子,让以父类(抽象层)PowerSupply.lvclass为例。子类为PS_ModelA.lvclass,PS_ModelB.lvclass等。
父类定义方法 Initialize.vi、SetVoltage.vi 和 Close.vi
现在,问题是:如果PS_ModelA使用USB接口(VISA/COM端口),而PS_ModelB使用GPIB/IVI,则选择与仪器通信的端口的控件不属于同一类型。
因此,我不能使用“端口”控件(VISA 或 IVI)作为父方法“初始化”的输入,因为一个或另一个子项的类型不匹配。
目前的“技巧”是定义一个多态VI初始化,它调用静态VI“初始化PS_A”或“初始化PS_B”。但是,失去了 OOP的动态部分,我已经可以看到这种方法带来的可扩展性问题,所以感觉不对。
解答:
这里的简单解决方案是让 Initialize 成为动态调度(可能已经走到了这一步),然后在子类中使用私有数据。
为每个类中的必要详细信息(A 的 VISA 资源、B 的 GPIB 等)提供一个写入访问器,并在程序开始之前在类常量上调用它们。可以创建接受这些输入并生成类对象的子VI(作为类成员,或在子类外部,但可能在库中)。(这基本上类似于在初始化PS_A和初始化PS_B VI中描述的内容)。
如果有很多类似的情况,另一种解决方案是定义仅执行通信的类,例如“VISA Communicator”,“GPIB Communicator”,并让它们继承“GeneralCommunicator”类,包括“Read”,“Write”,“Init”等。然后,你给一个“通信器”作为初始化的输入(对于 PS),并且可以在那里保留某种通用性。但是,仍然需要设置 Communicator 子项,这将需要与当前关注的有关PS_A、PS_B初始化相同类型的代码。
代码这样做,它还有一个额外的好处:你可以通过给它一个“假通信器”来更轻松地测试电源代码,它存储例如传递给“写入”的字符串数组,或者允许您设置一个固定字符串在调用“读取”时提供, 检查电源在各种条件下的行为。如果要执行一些单元测试,则很有用。
其余选项包括使用变体或字符串(在这种情况下,我相信可以携带两个必要的名称来初始化您的电源),但这会失去一些类型安全性,并阻止例如单击下拉列表控件以检查可用的 VISA 端口。该变体可能允许使用 VISA 资源名称控件,然后使用 VISA 资源子类中的数据变体,但这是一个相当模糊的解决方案,需要您知道子级所需的数据类型,在这种情况下,您不会从连接器窗格中获取该信息。可能最好避免此选项,但您可以考虑它...
从左上角开始,逆时针移动,我有
初始化子序列类(VISA 串行)。与你想做的事情不完全相同,但非常相似。
设置主 Power.vi(我想为电源实现的几个命令之一)。这知道此特定 PS 的命令,但不处理特定的消息格式
发送消息并获取 Acknowledgement.vi:格式化消息(所有命令都调用此子VI),然后尝试发送消息并接收响应。仍然是PS类的一部分,但是如果您有许多更通用的电源(或动态调度等),则可以对其进行修改
向 Serial.vi 发送消息:PS 类的成员,使用 Write.vi 然后调用嵌套对象“串行”,然后 Read.vi。对端口等的这一级别一无所知(这些是在 Init VI 中设置的)。
Write.vi(在单独的库文件,通过PPL):实际执行VISA Write。在后台,您会看到此类的类层次结构:它有一个同级,其中包含用于读取和写入固定响应的内部字符串数组。使用自己的私有数据在初始化VI中打开串口。
需要说明的是,上述的例程和文档,都是可以下载的,双击即可打开,其中压缩文件是可以采用粘贴复制的方式,拷贝到硬盘上。这不是图片,各位小伙伴看到后尝试一下,这个问题就不用加微信咨询了。有关LabVIEW编程、LabVIEW开发等相关项目,可联系们。附件中的资料这里无法上传,可去公司网站搜索下载。