树莓派以强大的性能与低廉的价格,非常适合作为物联网终端设备,树莓派将现场传感器采集到的设备传输到监控中心时,可以采用不同的语言与通讯协议。在工业现场中,Modbus是非常常见的一种通讯方式,本文以python语言Modbus_tk库为例,使用电脑作为ModbusTCP通讯主站,与树莓派实现ModbusTCP通讯(树莓派作为通讯从站)。本文以CSDN博客文章为基础,将python版本从2.7更新到了3.6,同时将开发平台迁移到了树莓派下。

1. 系统与环境

台式机安装windows10专业版,安装Anaconda发行版的python(3.6版本),树莓派安装官方Rapbian系统,安装python3.7发行版。首先需要安装modbus_tk库。
pip install modbus_tk 。由于树莓派下同时安装有python2.7和3.7,因此使用pip3代替pip来确定modbus_tk安装在python3.7下。
树莓派与台式机在同一局域网下,树莓派ip地址为192.168.1.20,开放端口11100(仅做示例).
在树莓派下,通过命令行安装ufw防火墙管理软件并且打开11100端口。对ssh方式连接树莓派等基础操作从略。

  1. sudo ufw enable
  2. sudo ufw allow 11100
  3. sudo ufw enable

2. 从机程序示例

  1. '''
  2. !/usr/bin/env python
  3. -- coding: utf_8 --
  4. 作者:weizy
  5. 时间:2019/7/23
  6. 简介:modbus协议从机测试脚本
  7. '''
  8. import sys
  9. import logging
  10. import threading
  11. import modbus_tk
  12. import modbus_tk.defines as cst
  13. import modbus_tk.modbus as modbus
  14. import modbus_tk.modbus_tcp as modbus_tcp
  15. LOGGER = modbus_tk.utils.create_logger(name="console", record_format="%(message)s")
  16. if name == "main":
  17. try:
  18. # server里的address需要写的树莓派的IP和需要开放的端口,注意开放相应的端口
  19. SERVER = modbus_tcp.TcpServer(address="", port=11100)
  20. LOGGER.info("running…")
  21. LOGGER.info("enter 'quit' for closing the server")
  22. # 服务启动
  23. SERVER.start()
  24. # 建立第一个从机
  25. SLAVE1 = SERVER.add_slave(1)
  26. SLAVE1.add_block('A', cst.HOLDING_REGISTERS, 0, 4)#地址0,长度4
  27. SLAVE1.add_block('B', cst.HOLDING_REGISTERS, 4, 14)
  28. #建立另一个从机2
  29. SLAVE2 = SERVER.add_slave(2)
  30. SLAVE2.add_block('C', cst.COILS, 0, 10) #地址0,长度10
  31. SLAVE2.add_block('D', cst.HOLDING_REGISTERS, 0, 10)#地址0,长度10
  32. SLAVE1.set_values('A', 0, 4) #改变在地址0处的寄存器的值
  33. SLAVE1.set_values('B', 4, [1, 2, 3, 4, 5, 5, 12, 1232]) #改变在地址4处的寄存器的值
  34. SLAVE2.set_values('C', 0, [1, 1, 1, 1, 1, 1])
  35. SLAVE2.set_values('D', 0, 10)
  36. while True:
  37. CMD = sys.stdin.readline()
  38. if CMD.find('quit') == 0:
  39. sys.stdout.write('bye-bye\r\n')
  40. break
  41. else:
  42. sys.stdout.write("unknown command %s\r\n" % (args[0]))
  43. finally:
  44. SERVER.stop()

<br />

3. 主机程序示例

<br />

  1. !/usr/bin/env python-- coding: utf_8 --
  2. 作者:weizy
  3. 时间:2017/3/10
  4. 简介:modbus协议主机测试脚本
  5. import sys
  6. import logging
  7. import modbus_tk
  8. import modbus_tk.defines as cst
  9. import modbus_tk.modbus_tcp as modbus_tcp
  10. LOGGER = modbus_tk.utils.create_logger("console")
  11. if name == "main":
  12. try:
  13. #连接从机地址,这里要注意端口号和IP与从机一致
  14. MASTER = modbus_tcp.TcpMaster(host="192.168.1.20", port=11100)
  15. MASTER.set_timeout(5.0)
  16. LOGGER.info("connected")
  17. #读取从机1的0-4保持寄存器
  18. LOGGER.info(MASTER.execute(1, cst.READ_HOLDING_REGISTERS, 0, 4))
  19. #读取从机1的4-14保持寄存器,因为寄存器独立分块了,所以不能直接连通读取,强行结果是会出现数据越界
  20. LOGGER.info(MASTER.execute(1, cst.READ_HOLDING_REGISTERS, 4, 14))
  21. # 需要按照execute格式
  22. LOGGER.info(MASTER.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 0, output_value=[0, 1, 2]))
  23. LOGGER.info(MASTER.execute(1, cst.READ_HOLDING_REGISTERS, 0, 4))
  24. LOGGER.info(MASTER.execute(2, cst.READ_COILS, 0, 8))
  25. LOGGER.info(MASTER.execute(2, cst.WRITE_MULTIPLE_COILS, 0, output_value=[1, 0, 0, 0, 1]))
  26. LOGGER.info(MASTER.execute(2, cst.READ_COILS, 0, 8))
  27. LOGGER.info(MASTER.execute(2, cst.READ_HOLDING_REGISTERS, 0, 4))
  28. # 线圈和寄存器地址不是同一区块的
  29. except modbus_tk.modbus.ModbusError as err:
  30. LOGGER.error("%s- Code=%d" % (err, err.get_exception_code()))

<br />
使用树莓派和Python实现ModbusTCP通讯 - 图1

4.modbus 功能代码: defines.py

  1. modbus 异常代码
  2. ILLEGAL_FUNCTION = 1 功能代码不合法
  3. ILLEGAL_DATA_ADDRESS = 2 数据地址不合法
  4. ILLEGAL_DATA_VALUE = 3 数据值不合法
  5. SLAVE_DEVICE_FAILURE = 4 slave设备失败
  6. COMMAND_ACKNOWLEDGE = 5 命令已收到
  7. SLAVE_DEVICE_BUSY = 6 slave设备忙
  8. MEMORY_PARITY_ERROR = 8 内存奇偶误差
  9. supported modbus 功能代码
  10. READ_COILS = 1 读线圈
  11. READ_DISCRETE_INPUTS = 2 读离散输入
  12. READ_HOLDING_REGISTERS = 3 【读乘法寄存器】
  13. READ_INPUT_REGISTERS = 4 读输入寄存器
  14. WRITE_SINGLE_COIL = 5 写单一线圈
  15. WRITE_SINGLE_REGISTER = 6 写单一寄存器
  16. WRITE_MULTIPLE_COILS = 15 写多个线圈 【强制多点线圈】
  17. WRITE_MULTIPLE_REGISTERS = 16 写多寄存器 【写乘法寄存器】
  18. supported block types 支持的块类型
  19. COILS = 1 线圈
  20. DISCRETE_INPUTS = 2 离散输入(数字量输入)
  21. HOLDING_REGISTERS = 3 乘法寄存器
  22. ANALOG_INPUTS = 4 模拟量输入

<br />
使用树莓派和Python实现ModbusTCP通讯 - 图2
案例源码下载地址:
链接:https://pan.baidu.com/s/13ke9X17YpCd_4KN-IMB7Ag
提取码:fv6q