美文网首页
树莓派安装modbus tk库

树莓派安装modbus tk库

作者: 後輪追前輪 | 来源:发表于2021-04-20 23:28 被阅读0次

    一、安装modbus-tk

    1.安装modbus-tk并卸载重装 pyserial(需要安装python2.5以上)
    sudo pip3 install modbus-tk
    
    //卸载
    sudo pip3 uninstall pyserial
    sudo pip3 uninstall serial
    //重装
    sudo pip3 install pyserial
    
    2.从机测试代码:
    #!/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/ttyUSB0", 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()
    
    
    2.1查看 USB 设备 使用的是哪个串口
    ls -l /dev/ttyUSB*
    //crw-rw---- 1 root dialout 188, 0 4月  20 21:24 /dev/ttyUSB0
    
    2.2运行测试,代码报错
    pi@raspberrypi:~/Desktop $ sudo python modbus_slave.py 
    Traceback (most recent call last):
      File "modbus_slave.py", line 12, in <module>
        import RPi.GPIO as GPIO
    ModuleNotFoundError: No module named 'RPi'
    
    //原因没安装RPi.GPIO库
    //安装 RPi.GPIO
    sudo pip3 install RPi.GPIO
    

    再次运行测试代码,使用modbus poll通讯正常




    3.1主机测试程序:

    由于tk库历程是安全线程的(即超时就会退出程序 )不适合我用,所以写了测试的代码

    import serial #导入模块
    import time
    
    import binascii
    
    try:
    
        #端口,GNU / Linux上的/ dev / ttyUSB0 等 或 Windows上的 COM3 等
        portx="/dev/ttyUSB2"
        #波特率,标准值之一:50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,19200,38400,57600,115200
        bps=9600
        #超时设置,None:永远等待操作,0为立即返回请求结果,其他值为等待超时时间(单位为秒)
        timex=5
        # 打开串口,并得到串口对象
        ser=serial.Serial(portx,bps,timeout=timex)
        print("串口详情参数:", ser)
    
        print(ser.port)#获取到当前打开的串口名
        print(ser.baudrate)#获取波特率
        #Tx:004-01 01 00 00 00 08 3D CC
        red_all='0101000000083DCC'#modbus读取线圈指令01H的报文
        data = bytes.fromhex(red_all)
        result=ser.write(data)
        print("写总字节数:",result)
    
    
        #print(ser.read())#读一个字节
        # print(ser.read(10).decode("gbk"))#读十个字节
        #print(ser.readline().decode("gbk"))#读一行
        #print(ser.readlines())#读取多行,返回列表,必须匹配超时(timeout)使用
        #print(ser.in_waiting)#获取输入缓冲区的剩余字节数
        #print(ser.out_waiting)#获取输出缓冲区的字节数
    
        #循环接收数据,此为死循环,可用线程实现
        while True:
            result=ser.write(data)#读取线圈
            time.sleep(1)
            
            if ser.in_waiting:
                read_data=ser.read(ser.in_waiting )#读取缓存区数据
                r_data= str(binascii.b2a_hex(read_data))[2:-1]#把数据转为HEX格式
                print("收到数据:",r_data.upper() )#转为大写并打印数据
        print("---------------")
        ser.close()#关闭串口
    
    
    except Exception as e:
        print("---异常---:",e)
    

    再打开一个终端,两个终端分别运行两个测试程序
    若主机程序的终端显示收到数据: 01010142D1B9
    PS:
    42是因为我把第1和第6个线圈置一了,
    若直接运行应为收到数据:01010100CRC,CRC的值就不算了(太懒..)

    即为主从通讯正常

    注意:当结束串口程序时务必使用ctrl+C 终止程序,不要使用ctrl + Z,ctrl+z这样会导致串口无法正常关闭,从而导致串口号被占用,导致出现每次的串口号不同这个问题。

    相关文章

      网友评论

          本文标题:树莓派安装modbus tk库

          本文链接:https://www.haomeiwen.com/subject/selolltx.html