首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何用python读取RS485温度计数据

如何用python读取RS485温度计数据
EN

Stack Overflow用户
提问于 2021-09-30 13:56:51
回答 1查看 1.8K关注 0票数 1

该项目的想法是从RS485设备中获取数据,并编写出来供以后可视化。

我有覆盆子π4与4GB内存与帽子和传感器。

我不知道该如何从传感器发送和接收数据。从其文件中:

代码语言:javascript
运行
复制
THT-02 follows the RTU information frame protocol. In order to ensure the integrity of the information
frame, a pause time of 3.5 characters or more is required at the beginning and end of each information
frame, each byte of the information frame needs to be transmitted continuously. If there is a pause time greater than 1.5
characters, the sensor will treat it as invalid information and will not respond.

The sensor allows the host to use the function code 03 to read the temperature and humidity measurement
value of the sensor and other information. The information frame format of the 03 code is as follows:

Field Description Example

Slave address               01
Function code               03
Register address high byte  00
Register address low byte   00
High byte of query quantity 00
Low byte of query quantity  08
CRC check code low byte     44
CRC check code high byte    0C

Sensor response information frame

Slave address               01
Function code               03
Return the number of bytes  10
Temperature data high byte  00
Temperature data low byte   FA
Humidity data high byte     02
Low byte of humidity data   58
1 high byte reserved        00
1 low byte reserved         00
2 high byte reserved        00
2 low byte reserved         00
Address code high byte      00
Address code low byte       01
Baud rate high byte         25
Baud rate low byte          80
Hardware version high byte  06
Hardware version low byte   00
Software version high byte  00
Software version low byte   0A
CRC check code low byte     D4
CRC check code high byte    64

由于我没有真正了解modbus通信的概念,我认为这些值应该是我发送给设备以获得有效响应的请求。这是我试图在pyserial中使用的代码

代码语言:javascript
运行
复制
import time
import sys
import serial

ser = serial.Serial(
    port='/dev/ttyS0', baudrate=9600,
    parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS, xonxoff=False,
    rtscts=True, dsrdtr=True, timeout=3)

print(ser.name)
ser.write(br'\x01\x03\x00\x00\x00\x08\x44\x0C\r\n')
ret=str(ser.readlines())
print(ret)

这给了我一张空名单。在这里中,消息具有类似于11 03 006B 0003 7687的结构

如何构造发送到设备的消息以获得适当的响应?

更新,因此当我阅读pi上的gpio引脚时,不支持奇偶校验。出于这个原因,我设法控制了其中一个这些。这样,工作代码将使用pymodbus库:

代码语言:javascript
运行
复制
from pymodbus.client.sync import ModbusSerialClient as ModbusClient

client= ModbusClient(
    method = "RTU", 
    port = "/dev/ttyUSB0", 
    stopbits = 1, 
    bytesize = 8, 
    parity = 'N', 
    baudrate=9600)

client.strict = False
connection = client.connect()

FORMAT = ('%(asctime)-15s %(threadName)-15s'
' %(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)

rr = client.read_holding_registers(0, 2, unit=5)
log.debug(rr)
print(rr.registers)

client.close()

输出是一个包含温度计的所有数据的列表。

如注释中所述,更新2对于像我拥有的设备这样的快速响应速度很慢,因此我设法获得了以下响应:

代码语言:javascript
运行
复制
import time, serial
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)

s = serial.Serial(
    port = '/dev/ttyS0',
    baudrate = 9600,
    parity = serial.PARITY_NONE,
    stopbits = serial.STOPBITS_ONE,
    bytesize = serial.EIGHTBITS,
    xonxoff = False,
    rtscts = False, 
    dsrdtr =True,
    timeout = 1
)

temp = b'\x05\x03\x00\x00\x00\x01\x85\x8e' 
#temp response \x03\x02\x00\xea\xc8\x0b => \x00\xea = 234 => 23.4 C

humidity = b'\x05\x03\x00\x01\x00\x01\xd4\x4e' 
# humidity response  \x03\x02\x01\xda\xc9\x8f => \x01\xdd = 474 => 47.4 %

GPIO.output(12, 1)
time.sleep(0.01)
#s.write(temp)
s.write(humidity)
time.sleep(0.01)
GPIO.output(12, 0)
res = s.readlines()
print('reading')
print(res)

GPIO.cleanup()
s.close()

这不是最优雅的解决方案,但至少我得到了回应。但同样地,它并不总是对measurment有好处--有时响应不包含整个消息,而我最终得到的是不可用的字符串。

在与@MarcosG交谈后更新3,用于实现用于通信的pymodbuslibmodbus方法:

代码语言:javascript
运行
复制
from pylibmodbus import ModbusRtu


# For Python 3.x you have to explicitly indicate ASCII enconding
client=ModbusRtu(
    device="/dev/ttyS0".encode("ascii"), 
    baud=9600, 
    parity="N".encode("ascii"), 
    data_bit=8, 
    stop_bit=1
)

#Read and set timeout
timeout_sec = client.get_response_timeout()
print(timeout_sec)
client.set_response_timeout(timeout_sec+1)

#Connect
client.connect()

SERVER_ID=5
BCM_PIN_DE=18
BCM_PIN_RE=17

#Set Slave ID number
client.set_slave(SERVER_ID)

#Enable RPi GPIO Functions
client.enable_rpi(1)

#Define pin numbers to be used as Read Enable (RE) and Drive Enable (DE)
client.configure_rpi_bcm_pins(BCM_PIN_DE,BCM_PIN_RE)

#Export pin direction (set as outputs)
client.rpi_pin_export_direction()

#Write Modbus registers, 10 starting from 0
#client.write_registers(0, [0]*10)

#Read 10 input registers starting from number 0
result=(client.read_registers(0, 1))

#Show register values
print(result[0])

#Release pins and close connection
client.rpi_pin_unexport_direction()
client.close()

pylibmodbus无法工作的问题是新的libmodbus库与原始libmodbus库之间的冲突。该设备响应代码(眨眼),在终端中,我接收到我正在寻找的值- 247 => 24.7C

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-13 10:37:15

这是Modbus上软件与硬件信令的一个教科书示例。

您的USB- of 485提供自动硬件信令和它的工作在箱外.另一方面,您的hat使用RPi上的一个串口和一个GPIO行进行信令,因此您需要在代码中自己切换这条线路(正如您已经注意到的那样,这是非常低效率的,并且在大多数情况下无法可靠地工作),或者使用libmodbus,如我在上面的链接中所解释的那样。

只需按照我的答案上的步骤,并确保删除之前安装的libmodbus库的任何其他标准版本:

代码语言:javascript
运行
复制
sudo apt-get purge libmodbus*

如果您想继续使用Python,也可以将我的python包装器用于libmodbus。

正如我在回答中所解释的那样,这个技巧(软件信令)应该可以可靠地用于家庭项目,但我不推荐它用于关键任务或任何其他与安全相关的应用程序。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69393520

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档