树莓派学习笔记——实现modbus RTU从机

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 tk安装

2.简单的例子

    【说明】
    假设树莓派8个可用GPIO端口分别连接LED,在很多工控领域一个LED可称为控制点,在modbus协议中一个控制点被抽象为线圈寄存器,操作相应的线圈寄存器有05H和15H指令。若使用modbus-tk便不必关心modbus协议的具体内容。下面就通过modbus中协议实现树莓派扩展板上LED的控制。
    【代码】
[python] view plaincopy

  1. #!/usr/bin/env python  
  2. # -*- coding: utf_8 -*-  
  3. import sys  
  4. import logging  
  5. import threading  
  6. import modbus_tk  
  7. import modbus_tk.defines as cst  
  8. import modbus_tk.modbus as modbus  
  9. import modbus_tk.modbus_rtu as modbus_rtu  
  10. import serial  
  11. import time  
  12. import RPi.GPIO as GPIO  
  13. logger = modbus_tk.utils.create_logger(name=“console”, record_format=“%(message)s”)  
  14. # 创建server  
  15. server = modbus_rtu.RtuServer(serial.Serial(“/dev/ttyAMA0”9600))  
  16. slaver = server.add_slave(1)  
  17. # BCM GPIO编号  
  18. pins = [17,18,27,22,23,24,25,4]  
  19. def setup():  
  20.     # 采用BCM编号  
  21.     GPIO.setmode(GPIO.BCM)  
  22.     # 设置所有GPIO为输出状态,且输出低电平  
  23.     for pin in pins:  
  24.         GPIO.setup(pin, GPIO.OUT)  
  25.         GPIO.output(pin, GPIO.LOW)  
  26.      
  27.     slaver.add_block(“coil”, cst.COILS, 016)  
  28.     slaver.set_values(“coil”016*[0])  
  29.          
  30. def loop():  
  31.     logger.info(“running…”)  
  32.     # 启动从机  
  33.     server.start()  
  34.     while True:  
  35.         values = slaver.get_values(“coil”08)  
  36.         #print values[0]  
  37.         for i in range(08):  
  38.             if values[i] == 1:  
  39.                 GPIO.output(pins[i], GPIO.HIGH)  
  40.             else:  
  41.                 GPIO.output(pins[i], GPIO.LOW)  
  42.          
  43.         # 必要的延时  
  44.         time.sleep(0.5)  
  45. def destory():  
  46.     logger.info(“destory”)  
  47.     for pin in pins:  
  48.         GPIO.output(pin, GPIO.LOW)  
  49.         GPIO.setup(pin, GPIO.IN)  
  50.      
  51.     # 停止从机  
  52.     server.stop()  
  53.          
  54. if __name__ == “__main__”:  
  55.     setup()  
  56.     try:  
  57.         loop()  
  58.     except KeyboardInterrupt:  
  59.         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可以加入多个编号从机。

    【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扩展库,利用树莓派,原来觉得难以实现的东西现在做起来特别简单。

标签