该项目的想法是从RS485设备中获取数据,并编写出来供以后可视化。
我不知道该如何从传感器发送和接收数据。从其文件中:
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
中使用的代码
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
库:
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对于像我拥有的设备这样的快速响应速度很慢,因此我设法获得了以下响应:
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,用于实现用于通信的pymodbus
和libmodbus
方法:
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
。
发布于 2021-10-13 10:37:15
这是Modbus上软件与硬件信令的一个教科书示例。
您的USB- of 485提供自动硬件信令和它的工作在箱外.另一方面,您的hat使用RPi上的一个串口和一个GPIO行进行信令,因此您需要在代码中自己切换这条线路(正如您已经注意到的那样,这是非常低效率的,并且在大多数情况下无法可靠地工作),或者使用libmodbus,如我在上面的链接中所解释的那样。
只需按照我的答案上的步骤,并确保删除之前安装的libmodbus库的任何其他标准版本:
sudo apt-get purge libmodbus*
如果您想继续使用Python,也可以将我的python包装器用于libmodbus。
正如我在回答中所解释的那样,这个技巧(软件信令)应该可以可靠地用于家庭项目,但我不推荐它用于关键任务或任何其他与安全相关的应用程序。
https://stackoverflow.com/questions/69393520
复制相似问题