当前位置: 首页 > 知识库问答 >
问题:

Raspberry Pi RS485/UART Modbus

邢承弼
2023-03-14

[Modbus-设备]<===>[RS485芯片<==>Raspberry PI GPIO]引脚。RS485有三根线(发射、接收、方向),它们的连接方式如下

RaspiPi<=>适配器

GPIO 14(8)-Tx<=>数据+

我被困在让modbus在GPIO适配器上工作。我尝试过使用minimalmodbus,它在USB-RS485适配器上工作得很好,但在GPIO适配器上失败了。我怀疑这是因为方向针没有设置。

理想的解决方案是在pi上为GPIO找到一个RS485驱动程序,但除此之外,我看到了三种选择

1-制作我自己的驱动程序(我完全不熟悉)2-以某种方式获得一个modbus库来翻转内核空间中的GPIO pin 3-手动通过串行发送modbus消息并调整用户空间中的GPIO pin。就速度和可靠性而言,这似乎是最容易的,但也是最糟糕的。我的代码尝试低于[2]

对此问题的任何建议都将不胜感激。如果有人以前做过类似的事情,可以权衡我的选择,这将是有帮助的。我从来没有在这个级别上工作过软件,所以如果有一些明显的答案我完全忽略了,我不会觉得奇怪。

[1]此代码与raspberry pi上连接USB的另一个RS485适配器通信。这是写来证明GPIO适配器是工作的,我可以控制方向与12针在覆盆子pi

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()

[2]此代码正试图与另一个modbus设备通信。我的信息正在发送,但回应是garabge。我的假设是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
#1/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)

编辑:澄清方案。Edit2:进一步澄清方案和增加/编辑代码

共有1个答案

金泉
2023-03-14

示例2中的代码实际上工作正常。我只需要格式化回应。

print RecievedData.encode('hex')

这将以modbus响应格式给出十六进制字符串。正如Andrej Debenjak所暗示的那样,time.sleep(x)将取决于波特率和消息大小。

附注:我发现这个页面有助于破译modbus传输。

 类似资料:

相关问答

相关文章

相关阅读