首页 文章

Raspberry Pi RS485 / Uart Modbus

提问于
浏览
2

我试图在UART连接一个RS485适配器,通过Raspberry Pi上的modbus进行通信 . 我的最终目标是让所有这些都与Node应用程序一起工作,但到目前为止我的开发人员一直使用Python .

我的硬件连接如下:

[Modbus-Device] <===> [RS485芯片<==> Raspberry PI GPIO]引脚 . RS485有三条线(发送,接收,方向),它们按如下方式连接

RaspiPi <=> Adapter

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

GPIO 15(10) - Rx <=> - 数据 -

GPIO 18(12) - 方向

RS485不是典型的9针适配器 . 我有三根电线在芯片上运行 . 双绞线,用作差动装置和地线 .

我已经能够通过手动翻转GPIO18进行发送/接收,在此adpater和USB-RS485适配器之间发送串行通信 . (以下代码)[1] . 此代码纯粹用于证明适配器的工作原理

我坚持让modbus在GPIO适配器上工作 . 我尝试过使用minimalmodbus,它适用于USB-RS485适配器,但是使用GPIO适配器失败了 . 我怀疑这是因为没有设置方向引脚 .

理想的解决方案是在pi上为GPIO找到一个RS485驱动程序,但我没看到三个选项

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

任何关于这个主题的建议都将非常感激 . 如果有人之前做过类似的事情并且可以权衡我的选择,这会有所帮助 . 我从来没有在这个级别的软件上工作,所以如果有一些明显的答案我完全忽视,我就不会感到惊讶 .

[1]此代码与连接USB的树莓派上的另一个RS485适配器通信 . 这是为了证明GPIO适配器正在工作,我可以用Raspberry pi上的Pin 12控制方向

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设备通信 . 我的消息正在发送,但响应是嘎嘎嘎嘎 . 我的假设是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

[3]工作USB-RS-485代码 . Pi上的USB适配器连接到Modbus设备此代码每秒读取寄存器440 .

#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 回答

  • 1

    示例-2中的代码实际上可以正常工作 . 我只需要格式化响应 .

    print RecievedData.encode('hex')
    

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

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

    http://www.modbustools.com/modbus.html

    Edit: 我发送的ByteString不适用于正确的modbus设置 . 第一个字节x00是广播字节,不应该请求响应 . 似乎硬件我正在尝试与之通信 . 感谢Marker指出这一点 .

相关问题