0.前言
本文使用树莓派实现MODBUS RTU从机,借助python库——modbus-tk实现RTU从机。MODBUS是一种灵活可靠的工业通信协议,常用的MODBUS协议包括MODBUS RTU和MODBUS TCP。借助python强大的库函数,可以在树莓派平台上非常方便的实现MODBUS主机和从机,MODBUS RTU和TCP,甚至一个树莓派既可以跑MODBUS RTU主机也可以同时跑MODBUS TCP从机。相比于其他平台(例如STM32),在树莓派上实现modbus真的太简单了。
【有用的参考资料】
【1】MODBUS协议整理——汇总——如果您还不熟悉modbus,请你花点时间看看吧。
【2】 freemodbus modbus TCP 学习笔记——STM32平台,通过uIP实现modbus TCP从机
【3】MODBUS学习笔记——modbus tk modbus TCP主机实现——使用modbus tk实现modbus TCP主机。平台为PC,无需修改可移植到树莓派。
【4】树莓派学习笔记——UART使用——树莓派UART端口使用,本例中将会使用到该文提到的内容。
【5】树莓派学习笔记——RPi.GPIO 流水灯——GPIO相关操作,本例中将会使用到该文提到的内容。
【6】STM32 移植FreeModbus 详细过程——个人学习modbus的开始
1.modbus tk安装
详见以下博文
2.简单的例子
【说明】
假设树莓派8个可用GPIO端口分别连接LED,在很多工控领域一个LED可称为控制点,在modbus协议中一个控制点被抽象为线圈寄存器,操作相应的线圈寄存器有05H和15H指令。若使用modbus-tk便不必关心modbus协议的具体内容。下面就通过modbus中协议实现树莓派扩展板上LED的控制。
【代码】
#!/usr/bin/env python # -*- coding: utf_8 -*- import sys import logging import threading import modbus_tk import modbus_tk.defines as cst import modbus_tk.modbus as modbus import modbus_tk.modbus_rtu as modbus_rtu import serial import time import RPi.GPIO as GPIO logger = modbus_tk.utils.create_logger(name="console", record_format="%(message)s") # 创建server server = modbus_rtu.RtuServer(serial.Serial("/dev/ttyAMA0", 9600)) slaver = server.add_slave(1) # BCM GPIO编号 pins = [17,18,27,22,23,24,25,4] def setup(): # 采用BCM编号 GPIO.setmode(GPIO.BCM) # 设置所有GPIO为输出状态,且输出低电平 for pin in pins: GPIO.setup(pin, GPIO.OUT) GPIO.output(pin, GPIO.LOW) slaver.add_block("coil", cst.COILS, 0, 16) slaver.set_values("coil", 0, 16*[0]) def loop(): logger.info("running...") # 启动从机 server.start() while True: values = slaver.get_values("coil", 0, 8) #print values[0] for i in range(0, 8): if values[i] == 1: GPIO.output(pins[i], GPIO.HIGH) else: GPIO.output(pins[i], GPIO.LOW) # 必要的延时 time.sleep(0.5) def destory(): logger.info("destory") for pin in pins: GPIO.output(pin, GPIO.LOW) GPIO.setup(pin, GPIO.IN) # 停止从机 server.stop() if __name__ == "__main__": setup() try: loop() except KeyboardInterrupt: destory()
【分析】
【1】server = modbus_rtu.RtuServer(serial.Serial("/dev/ttyAMA0", 9600))
创建一个RTU从机,使用串口/dev/ttyAMA0。请注意server和主机并不是一个概念,这里可能胡产生概念的混淆,这里server可理解为一个设备,而这个设备可以具有多个身份(例如具有多个从机ID)
【2】slaver = server.add_slave(1)
从机编号为1。一个server可以加入多个编号从机。
【2】slaver = server.add_slave(1)
【3】slaver.add_block("coil", cst.COILS, 0, 16)
创建寄存器,寄存器的别名为coil,寄存器为线圈寄存器(COILS),寄存器起始地址为0,寄存器个数为16.
【4】slaver.set_values("coil", 0, 16*[0])
线圈寄存器的初始值全部为0
【5】values = slaver.get_values("coil", 0, 8)
读取线圈寄存器具体值,线圈寄存器地址从0到7,共8个。
3.测试
图1 modbus rtu测试
4.总结
使用python,借助python扩展库,利用树莓派,原来觉得难以实现的东西现在做起来特别简单。