添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

一个ModBus命令包含了打算执行的设备的Modbus地址。所有设备都会收到命令,但只有指定位置的设备会执行及回应指令 (地址0例外,指定地址0的指令是广播指令,所有收到指令的设备都会运行,不过不回应指令)。 所有的Modbus命令包含了检查码,以确定到达的命令没有被破坏。

基本的ModBus命令能指令一个RTU改变它的寄存器的某个值,控制或者读取一个I/O端口,以及指挥设备回送一个或者多个其寄存器中的数据。

有许多modems和网关支持Modbus协议,因为Modbus协议很简单而且容易复制。它们当中一些为这个协议特别设计的。 有使用有线、无线通信甚至短消息和GPRS的不同实现。不过设计者需要克服一些包括高延迟和时序的问题。

目前多个HaaS设备( HaaS100, HaaS506,HaaS600 )均支持485接口,下面我们以两个 HaaS100 为例来演示如何基于 Modbus 协议实现设备间通信。

案例中我们以左边的板子为主机,右边的板子为从机,实现两个设备的命令发送及响应。更多的设备均可以通过 Modbus 总线连接,这里我们不做更多扩展。

Python轻应用支持的 Modbus 接口可以参考 modbus — Modbus协议

示例演示

示例代码:

86
# -*- encoding: utf-8 -*-
import time
import usys as sys
import modbus as mb
serial_port = 1         # 485端口号,haas100使用的端口为1
serial_baudrate = 9600  # 波特率
slave_addr = 1          # 从机设备地址
reg_addr = 1            # 寄存器地址
reg_value = 2           # 寄存器数据
req_reg_cnt = 10        # 寄存器数目
resp_timeout = 200      # 响应等待时间,单位为毫秒(ms
rw_timeout = 500        # 串口读写超时时间,单位为毫秒(ms
loop_cnt = 5
def mb_master():
   mb.init(serial_port, serial_baudrate, mb.PARITY_NONE, resp_timeout)
   loop = 0
   while(loop < loop_cnt):
      res = mb.writeHoldingRegister(
            slave_addr, reg_addr, reg_value, rw_timeout)
      print('modbus master write Holding Reg result:', res)
      data = bytearray(req_reg_cnt * 2)
      res = mb.readHoldingRegisters(
            slave_addr, reg_addr, req_reg_cnt, data, -1)
      print('modbus master read Holding Regs result:', res)
      loop = loop + 1
      time.sleep(1)
   mb.deinit()
def mb_slave():
   mb.init(serial_port, serial_baudrate, mb.PARITY_NONE, 100)
   while True:
      data = mb.recv()
      status  = data[0]
      rx      = data[1]
      # 收到有效数据,处理并响应请求
      if(status == 0):
            # 提取数据并判断是否为发送给自己
            if(rx[0] == slave_addr):
               if rx[1] == 0x06:
                  resp = bytearray(5)
                  resp[0] = rx[1]
                  resp[1] = rx[2]
                  resp[2] = rx[3]
                  resp[3] = rx[4]
                  resp[4] = rx[5]
               elif rx[1] == 0x03:
                  # 填充假数据作为响应数据
                  resp = bytearray(req_reg_cnt * 2 + 2)
                  resp[0] = rx[1]
                  resp[1] = req_reg_cnt * 2
                  for i in range(req_reg_cnt):
                        resp[i*2+2] = 0
                        resp[i*2+3] = i
               else:
                  print('unsupported cmd for demo')
               print('resp data:', resp)
               mb.send(slave_addr, resp, 100)
   mb.deinit()
if __name__ == '__main__':
   if(len(sys.argv) == 2):
      config = sys.argv[1]
      if(config == 'master'):
            mb_master()
      elif(config == 'slave'):
            mb_slave()
   else:
      print('Should specifiy master or slave')

在主机设备上运行命令:

python /data/pyamp/main.py master

在从机设备上运行命令:

python /data/pyamp/main.py slave

最终可以从主机从机上得到不同的输出:

主机输出:

(ash:/data)# python /data/pyamp/main.py master
Welcome to MicroPython
modbus master write Holding Reg result: (0, 1, 2, 0)
modbus master read Holding Regs result: (0, 20)
modbus master write Holding Reg result: (0, 1, 2, 0)
modbus master read Holding Regs result: (0, 20)
modbus master write Holding Reg result: (0, 1, 2, 0)
modbus master read Holding Regs result: (0, 20)
modbus master write Holding Reg result: (0, 1, 2, 0)
modbus master read Holding Regs result: (0, 20)
modbus master write Holding Reg result: (0, 1, 2, 0)
modbus master read Holding Regs result: (0, 20)
(ash:/data)# python /data/pyamp/main.py slave
Welcome to MicroPython
[ 108.558]<E>modbusm frame is too short or CRC error
[ 108.558]<E>modbus Failed to disassemble frame
resp data: bytearray(b'\x06\x00\x01\x00\x02')
resp data: bytearray(b'\x03\x14\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\t')
resp data: bytearray(b'\x06\x00\x01\x00\x02')
resp data: bytearray(b'\x03\x14\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\t')
resp data: bytearray(b'\x06\x00\x01\x00\x02')
resp data: bytearray(b'\x03\x14\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\t')
resp data: bytearray(b'\x06\x00\x01\x00\x02')
resp data: bytearray(b'\x03\x14\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\t')
resp data: bytearray(b'\x06\x00\x01\x00\x02')
resp data: bytearray(b'\x03\x14\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\t')