使用串口IO采集模块的情况

有时候,我们会使用IO采集模块,这种采集模块通过485和FSU相连接,然后提供多路的DI,AI,DO的接口。

通常情况下,使用这种模块有以下原因:

  1. 扩展DI,AI,DO的接口数量
  2. AI可以提高更宽的输入电压检测范围,比如板载AI支持0-10V,扩展AI支持0-400V
  3. DO可以支持更高的负载电流通过,比如板载DO可以通过20A的电流,扩展DO可以通过100A的电流

通常,我们将此类设备当作智能设备接入,然后将各个通道数据显示为正常的读数,但是,这样的显示方式对用户很不友好。尤其涉及到更复杂的应用场景:

  1. 每个DI实际是一个水浸,用户希望配置为水浸设备,并使用系统的告警规则,并支持B接口的数据上送。
  2. 每个AI实际一个温度,或者电压,用户希望表现为正常AI的设备。
  3. DO用户希望使用正常的方式进行控制。

我们如何解决上述问题?

  1. 通常,如果只是用户显示问题,可以通过一个虚拟驱动来映射信号并显示并上送B接口,但是无法支持告警判断。
  2. 如果将此设备作为扩展板设备,将协议作为SMDDevice的一部分,并将DI,AI,DO映射为正常DI,AI,DO数据,则各种型号的扩展板会把SMDDevice搞乱。
  3. 如果将此设备作为正常的智能设备进行数据采集,但是要解决2个方向的问题,DI,AI,DO映射为正常的DI,AI,DO,并且DO的操作还要调用这个设备去执行。

由于我们不想修改SDK的头文件,导致驱动没有办法去更新SMDDevice的DI,AI,DO的数据,因此我们需要特殊处理。

约定: 当RT_ID 为 2020 时,我们认为此设备是一个IO扩展板设备。 此设备的cData结构为:
struct IO_Data_t{
uint32_t data_id;
uint16_t di_number;//共有几个DI数据
uint16_t di_offset;//要更新SMDDevice的DI偏移量是多少
uint8_t di_values[di_number];
uint16_t ai_number;
uint16_t ai_offset;
float ai_values[ai_number];
uint16_t do_number;
uint16_t do_offset;
uint8_t do_values[do_number];
};

当SMDDevice收到驱动发出的RT_Data时,如果发现RT_ID == 2020,会自动按上述结构对数据进行解析,并自动更新自己的DI,AI,DO数据。
例如:
如果解析出 di_number = 16, di_offset = 50 则会从 di_values 读取16个值,并更新自己的di[50] = di_values[0]

AI,DO 同理。

并且,第一次读到这个data_id的数据时,如果do_number不为0,会自动建立关联: SMDDevice的设置do[do_offset] => 自动调用 DeviceIoControl(data_id, SET_DO_H, 要设置的do-do_offset)
例如:
do_offset = 50, 则如果程序对SMDDevice的do 50进行设置1的动作,会自动调用
DeviceIoControl(data_id, SET_DO_H, 0)
如果对do 51进行设置0的动作,会自动调用
DeviceIoControl(data_id, SET_DO_L, 1)
SET_DO_H代表设置1,SET_DO_L代表设置0. 第3个参数0 是因为50-50=0, 第3个参数1是因为 51-50 = 1, 50和51是SMDDevice的do序号,驱动内部是0开始的。

如果有多个扩展板,则需要用户使用逻辑参数,将要映射的通道区分开,避免重叠引起麻烦。