1.ASCII模式
当控制器设为在Modbus网络上以ASCII(美国标准信息交换代码)模式通信,在消息中的每个8Bit字节都作为一个ASCII码(两个十六进制字符)发送。这种方式的主要优点是字符发送的时间间隔可达到1秒而不产生错误。
2、RTU模式
当控制器设为在Modbus网络上以RTU(远程终端单元)模式通信,在消息中的每个8Bit字节包含两个4Bit的 十六进制字符。这种方式的主要优点是:在同样的波特率下,可比ASCII方式传送更多的数据。
回去以后上网查了不少PLC、modbus相关的资料,也看了西门子BW500的手册,有了些许眉目.
关于slave和master:
皮带秤(对我们来说就是显示的仪表)是作为slave,计算机作为master。
这种划分是因为对于同一个串口可能连接多个modbus设备,这样就需要用slaveid来区分。
而从一个java程序员的理解来看,modbus
slave(仪表)就像一个server,我们(计算机程序--master)通过串口(功能相当于网线)连接仪表(这里是西门子BW500)发送请求(request),仪表会返回一个bit数组(respose)。
这样看来,slave相当于server,master相当于client。
请求格式:
发送的请求信息中包括串口名(COM1,2,3等)slaveId(范围是1-247,仪表可以设置),开始位置,需要返回的个数。
由于仪表的保持寄存器(你可以当成内存来理解),每位是16字节,BW500仪表可以存放9999位。
比如我需要1000-1020位的数据,开始位置就是1000,需要返回的个数就是21。
返回格式:
如上所述。返回一个16位(对应java中short)数组,在java中看就是short[需要返回的个数]
拿到以后还不算完,因为每位是short类型,而大多数的数据时int甚至long型的,另外还带有小数。所以需要用返回的short数组进行运算才能得到想要的值,
皮带秤1的算法如下:
数据结构:第1016位和1017位共同表示表示仪表累积量。
用1017位的short值的二进制作为高16位。
用1016位的short值的二进制作为低16位。
组成一个新的32位int型数据,
转为10进制
除以1000。
得到一个带有3位小数的值,这就是最终的仪表上的累积量。
具体例子:
1016:-6149
二进制:1110011111111011(注意,如果不足16位,前面要补零)
1017:250 二进制:11111010
最终二进制111110101110011111111011
转为十进制16443387
以上几步在java可以这样:
public int joinBinary(short low, short high) {
int intLow = (int) low & 0xFFFF;
int intHigh = ((int) high << 16) & 0xFFFF0000;
return intHigh | intLow;
}
除1000=16443.387(仪表上显示的是16443.38
看起来是舍弃了最后一位)
当然这只是西门子BW500仪表的算法,如果是其他仪表,就要根据其技术手册上的描述进行计算。
另外想说的一点就是技术手册上的内容感觉就是针对熟悉硬件的人员的,比如BW500上关于累积量的取值就一句话:4016和4017代表累积量。
当时猜了好久,各种试,在快绝望的最后一刻给弄出来了。。。。。
上网搜基本全是卖设备的,偶尔有一个文档,兴冲冲的打开,发现和手里的一样。。。。
找到一个英文的打开---就是手里技术手册的英文原版。。。。。
关于modbus,我的理解也仅限于这些。有问题可以交流。
后记:
其实不用modbus4j也是可以的,只要能连上串口就可以了,向串口写符合modbus格式的数据,仪表就会返回数据了