最灵活的Modbus网关

BACRouter内置了一个强大的Modbus主站模块,但是基于现场的复杂性,它仍然不能很好的应对某些场景,比如:

  1. 点的值从寄存器3X0001读取,但是写时需要写到寄存器4X0001
  2. Modbus值1读入时,映射到BACnet值1,  但是写BACnet值1时,需要写10到Modbus。(Modbus主站模块的Lua脚本可以处理非对称的自定义类型的模拟对象的换算)
  3. 模拟对象或多状态对象映射到线圈或离散输入点的多个位。
  4. 只写的Modbus数据地址,读取时报错或无响应。

幸运的是,从固件版本v5.00起,我们引入了自由协议模块,可以用Lua脚本实现一个非常灵活的Modbus网关, 我们把modbus.lua 脚本托管于 github.com

modbus.lua定义的总线上所有设备采用相同的波特率/校验/超时参数。而对于Modbus主站模块,每个设备可以采用不同的设定。

用户应该首选尝试Modbus主站模块,因为Modbus主站模块内置的测试功能,可以方便用户在编辑映射时快速地验证。

当所有的常规点编辑完毕,可能留下几个古怪的点无法处理,但是请先对读操作进行验证。

接下来,请验证“编组读取”。

然后将Modbus设备的配置导出。

在github仓库中有一个 fcmbconv.py python程序, 请先安装 python 再运行它。它将提示你选择modbus.lua文件,再选择导出的Modbus设备配置文件,它会将其转换为自由协议总线配置文件。

然后在BACRouter的自由协议模块下导入上述配置文件。

最后编辑配置,处理那些古怪的点。

示例:

我们假设有一个这样的Modbus设备,除了几个常规点,还有:

  1. 模拟输出对象”lamp1″与”lamp2″从寄存器4X00032的位0与位1读取开关值,对应位为1值代表开,0值代表关。但是输出开关值,必须写到寄存器4X00031中,且对应位的1值代表关,0值代表开。
  2. 离散输入1X00008开始的8个位映射成模拟输入对象“temperature3″
  3. 4X00100是一个只写寄存器,读将无响应或报错。该寄存器的低字节映射为模拟输出对象”load1“,寄存器的高字节映射为模拟输出对象”load2″

首先我们配置一个Modbus主站模块的Modbus设置,配置文件: ExampleModbusDevice,  用“编组读取”测试验证
使用上述的 fcmbconv.py将其转为自由协议的总线配置文件:  FCModbus

将其导入到BACRouter的自由协议模块:

修改那些古怪的点配置。

如 lamp1:

如 temperature3:

如 load1 与 load2:

修改完毕后,使用Yabe 进行验证。假如脚本运行失败,请检查日志。

修改完毕的自由协议总线配置文件见:FCModbusFinal

为BACRouter增加新IP

我们经常在现场面对IP无法修改的第三方设备,而且其IP与BACRouter或其它BIP设备不在同一个子段内。
已有的解决方案是增加一个IP路由器,这样将导致成本与复杂度增加。
通常我们只需要BACRouter与这种第三方设备采用Modbus TCP或BACnet IP协议进行通讯,因此最简单的办法是为BACRouter增加一个专用于与此设备通讯的IP

例如,当前IP子网是192.168.100.0/24,  BACRouter的IP是192.168.100.1, 第三方设备的IP是172.16.1.20, 子网掩码为255.255.255.0

我们将为BACRouter添加一个新IP:172.16.1.1
初始的/etc/rc.local:

root@OpenWrt:~# cat /etc/rc.local
# Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.

cd /root
./webui&
exit 0

修改/etc/rc.local: (也可以用vi编辑)

root@OpenWrt:~# cat>/etc/rc.local
# Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.

ifconfig br-lan:1 172.16.1.1 netmask 255.255.255.0
cd /root
./webui&
exit 0
CTRL+D

这里的ifconfig指令将添加br-lan:1 新接口,其IP为172.16.1.1。如果我们需要以BIP协议连接第三方设备,我们还需要将新接口添加到BACRouter的配置文件中:

初始的/root/resource.conf:

~#cat /root/resource.conf
{ “eth0”: { “type”: “ETH”, “ifname”: “br-lan” }, “RS485-1”: { “type”: “USB”, “ifname”: “0:0” }, “RS485-2”: { “type”: “USB”, “ifname”: “0:1” } }

修改/root/resource.conf: (也可以用vi编辑)

~#cat >/root/resource.conf
{ “eth0”: { “type”: “ETH”, “ifname”: “br-lan” }, “eth1”:{“type”:”ETH”, “ifname”:”br-lan:1″}, “RS485-1”: { “type”: “USB”, “ifname”: “0:0” }, “RS485-2”: { “type”: “USB”, “ifname”: “0:1” } }
CTRL+D

现在断电重启BACRouter!

转换BASgatewayLX的CSV格式配置文件

BASgatewayLX(以下简单LX)的从站配置采用CSV格式,有较详细的文档说明,并且有一个可下载的配置列表。 我们提供了从其CSV配置文件转换到BACRouter的从站json配置文件的迁移工具。

在我们网站上直接转换

下载转换工具解压缩后用浏览器打开index.html

几点注意事项:

虽然LX的CSV文档说明中,对象名是唯一的,但配套的Profile Checker并不检查重复,且我们在测试中发现不少的重复对象名。遇到这种情况,我们将把冲突对象置为停用。

有的CSV配置文件的字符集不是常用的UTF8,可能是ISO-8859-1。我们尽量在转换时进行探测,最后回退到ISO-8859-1

LX支持的最长对象名与描述是64个字符,采用的是ISO-8859-1编码。BACRouter也支持最长64个字符,但采用utf8编码,存在一种可能即满足LX的64个ISO-8859-1个字符,又超过BACRouter的64个utf8编码长度,虽然我们测试中没有发生这种情况。如果转换中发现对象名或描述长度超出限制,我们将进行尾部裁断,并进行提示。

BACRouter不允许输出类型的对象所映射的Modbus地址重叠,但LX似乎允许。遇到这种情况,我们将把冲突对象置为停用。

LX允许对每一个32位数据单独设置字顺序,BACRouter必须在从站参数中统一设置。如果在转换中发现字顺序定义互相矛盾,我们将采用在先的定义,并提示冲突。

BACRouter每个从站的对象实例空间只有0~999,LX似乎没有限制,如果遇到定义的实例号超出999,我们将采用自动分配实例号。