You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

树莓派GPIO外接RS485芯片实现Modbus通信问题求助

树莓派GPIO RS485适配Modbus通信的问题求助

我最近在折腾树莓派通过GPIO连接RS485芯片实现Modbus通信,最终目标是适配Node应用,目前先用Python做前期开发,遇到了棘手的问题,想请教大家的建议:

硬件连接方式

整体链路是:[Modbus设备] <===> [RS485芯片 <==> 树莓派GPIO]
具体接线细节:

  • 树莓派GPIO14(引脚8,Tx)<=> RS485适配器Data+
  • 树莓派GPIO15(引脚10,Rx)<=> RS485适配器Data-
  • 树莓派GPIO18(引脚12)<=> RS485适配器方向控制引脚
    注:这个RS485是芯片引出的三线(差分对+地线),不是标准9针适配器

已完成的功能验证

我已经通过手动切换GPIO18的收发状态,实现了这个GPIO-RS485适配器和USB-RS485适配器之间的串口通信,验证代码如下:

import time
import serial
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT);
ser = serial.Serial(
    port= '/dev/ttyS0',
    baudrate= 57600,
    parity= serial.PARITY_NONE,
    stopbits= serial.STOPBITS_ONE,
    bytesize= serial.EIGHTBITS,
    timeout=1
)
def write_add():
    counter = 0;
    message = 0
    while (True):
        print "writing",
        GPIO.output(12,1) #set high/transmit
        ser.write('%d \n'%(message))
        time.sleep(0.005) #baud for 57600
        #time.sleep(0.5) #baud for 9600
        GPIO.output(12, 0) #pin set to low/receive
        loop_count = 0
        res =""
        while (res == ""):
            res =ser.readline();
            if(res != ""):
                print ""
                print "Read Cycles: "+str(loop_count)+" Total: "+str(counter)
                print res
                message = int(res) + 1
                counter = counter + 1
            elif(loop_count > 10):
                res = "start over"
            else:
                print ".",
                loop_count = loop_count + 1
write_add()

遇到的核心问题

现在卡在Modbus通信适配这块:

  1. minimalmodbus库时,USB-RS485适配器能正常和Modbus设备通信(工作代码如下),但换成GPIO-RS485适配器就完全不行,我推测是方向引脚没有被正确控制。
#!/usr/bin/env python
import minimalmodbus
import time
print minimalmodbus._getDiagnosticString()
minimalmodbus.BAUDRATE=57600
minimalmodbus.PARITY='N'
minimalmodbus.BYTESIZE=8
minimalmodbus.STOPBITS=1
minimalmodbus.TIMEOUT=0.1
instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 0) #port and slave
#instrument.debug = True
while True:
    batterVolt = instrument.read_register(440, 2) #register number, number decimals
    print batterVolt
    time.sleep(1)
  1. 我尝试过在用户态手动发送Modbus消息并切换GPIO引脚,但返回的都是乱码,估计是方向引脚的切换时机不对——要么过早切换导致发送的消息被截断,要么切换太晚错过了设备的响应。代码如下:
import serial
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
ser = serial.Serial(
    port='/dev/ttyS0',
    baudrate = 57600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS,
    timeout=1
)
GPIO.output(12,1) #set high/transmit
ByteStringToSend = "\x00\x03\x01\xb8\x00\x01\x04\x02"
ser.write(ByteStringToSend)
time.sleep(0.005) #baud for 57600
GPIO.output(12, 0) #pin set to low/receive
ReceivedData = ""
while (ReceivedData == ""):
    RecievedData = ser.readline();
    print RecievedData

目前想到的三种解决方案

  • 自行开发树莓派GPIO RS485驱动:但我完全不熟悉驱动开发,门槛太高
  • 让Modbus库在内核态切换GPIO引脚:不知道怎么实现,有没有现成的方法?
  • 用户态手动处理消息与GPIO切换:虽然容易实现,但速度和可靠性都差,担心长期运行出问题

希望有类似经验的朋友能给我一些建议,帮我选个靠谱的方案,或者有其他更优的解决办法也欢迎告诉我,非常感谢!

内容的提问来源于stack exchange,提问作者David Ryan

火山引擎 最新活动