行空板如何获取RS485设备数据 - RS485风速变送器
## 行空板如何获取RS485设备数据 - **RS485风速变送器**## 1-介绍:RS-485协议
RS-485协议,是一种串行通信协议,用于在多个设备之间进行数据传输。它是一种差分信号通信协议,可以实现长距离、高速、可靠的数据传输。
RS-485协议使用两根传输线(A线和B线)进行数据传输,其中一个设备充当主设备,其他设备充当从设备。主设备负责控制通信的开始和结束,以及数据的传输速率。从设备只有在主设备允许的情况下才能发送数据。
RS-485协议具有以下特点:
- 高速传输:RS-485协议支持较高的数据传输速率,可以达到几十兆比特每秒的速度。
- 远距离传输:由于差分信号的使用,RS-485协议可以在较长的距离上进行数据传输,通常可覆盖数千米的距离。
- 抗干扰能力强:RS-485协议采用差分信号传输,可以有效地抵抗电磁干扰和噪声,提供可靠的数据传输。
- 多设备通信:RS-485协议支持多个设备之间的通信,主设备可以与多个从设备进行双向通信。

## 2-以RS485风速传感器为例((https://www.dfrobot.com.cn/goods-3195.html)):

详细wiki介绍:(https://wiki.dfrobot.com.cn/SKU_SEN0483_RS485_Wind_Speed_Transmitter)
从wiki中可以得到这个传感器的一些关键信息:
### 2.1-线色说明
| 颜色 | 功能 |
| :--- | :---------- |
| 红色 | 电源正 |
| 黑色 | 电源负 |
| 黄色 | RS485+/A/T+ |
| 绿色 | RS485-/B/T- |
### 2.2-通讯协议:
- 主机(在这里是行空板)通过串口(使用串口转rs485模块)与从机(这里是风速传感器)通信,波特率为 9600 bps。
**通讯方式很简单**:主机按照协议发一串查询数据给从机,从机接受到查询指令后将风速数据返回给主机,然后主机接受到数据解析就可以得到风速值了。
读寄存器0x0000,即风速的测量值
- 主机查询帧(16进制):02 03 00 00 00 01 84 39(8byt)
| 从机地址 | 功能码 | 寄存器起始地址 | 寄存器长度 | 校验码高位 | 校验码低位 |
| :------- | :----- | :------------- | :--------- | :--------- | :--------- |
| 1byt | 1byt | 2byt | 2byt | 1byt | 1byt |
| 0x02 | 0x03 | 0x00 0x00 | 0x00 0x01| 0x84 | 0x39 |
- 从机应答帧(16进制):02 03 02 00 25 3D 9F(7byt)
| 从机地址 | 功能码 | 有效字节数 | 数据区 | 校验码高位 | 校验码低位 |
| :------- | :----- | :--------- | :-------- | :--------- | :--------- |
| 1byt | 1byt | 1byt | 2byt | 1byt | 1byt |
| 0x02 | 0x03 | 0x02 | 0x00 0x25 | 0x3D | 0x9F |
风速值为(16进制,原码)00 25 = 0x0025 = 37,那么风速测量值为37 / 10 = 3.7m/s
因此,要获取风速测量值,主机需要通过串口发送查询帧,并解析从机应答帧中的数据。
## 3-行空板串口通讯:
在行空板上有两种方法可以引出串口:
-1、USB接口插一个USB串口转RS
485模块( https://www.dfrobot.com.cn/goods-2997.html )
- 2、使用行空板金手指上的UART串口(P0和P3),然后使用一个UART转RS485模块( https://www.dfrobot.com.cn/goods-3283.html )

前面介绍了**RS485风速变送器**的通讯协议,接下来将两种方法的使用步骤进行介绍。
## 3.1-使用USB串口通讯
### 3.1.1-USB转485模块和行空板接线图

### 3.1.2-接线说明
根据接线说明,把**RS485风速变送器**其中的黄色和绿色分别接到**USB转485模块**A/B,需要注意电压问题:
- **RS485风速变送器**供电电压:7-24V
- **USB转485模块**供电电压:5V
因此需要额外外接电源,测试中我使用的使用12V电源。
### 3.1.3-编程
全部接好以后,就直接插上行空板USB,进行编程.
示例代码:
```python
import serial
import time
#使用的是USB转串口,因此不需要使用pinpong库
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=0.5) #USB转RS485模块的串口编号
while True:
query_frame = # 查询帧
ser.write(query_frame)
time.sleep(1)
try:
response_frame = ser.read(7)# 读取从机应答帧,根据应答帧格式修改字节数
byte4 = response_frame# 获取第4位数据
byte5 = response_frame# 获取第5位数据
value = ((byte4 << 8) + byte5) / 10 #根据风速传感器说明计算风速值
print("风速值:", value)
time.sleep(0.1)
except:
print("无数据")
```
测试结果:

### 3.1.4-数据校验
上面的案例中,我们直接读取了第4和5位获取风速值,实际上在通讯中可能会存在数据丢失一部分的情况,因此从机返回的数据里面还有校验码,通过将接收到的数据做计算与校验码比对,可以确保接收到的数据是正确的。
- 示例代码:
```python
import serial
import time
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=0.5)
def calculate_checksum(data):
checksum = 0xFFFF# 初始校验码值
for byte in data:
checksum ^= byte# 异或操作
for _ in range(8):
if checksum & 0x0001:# 最低位为1
checksum >>= 1# 右移一位
checksum ^= 0xA001# 异或操作
else:
checksum >>= 1# 右移一位
return checksum.to_bytes(2, byteorder='little')# 返回校验码的字节表示,小端序
def validate_response_frame(frame):
if len(frame) < 5:
return False
received_checksum = frame[-2:]# 从应答帧中提取接收到的校验码
expected_checksum = calculate_checksum(frame[:-2])# 计算期望的校验码
return received_checksum == expected_checksum
while True:
query_frame = # 查询帧
ser.write(query_frame)# 发送查询帧
time.sleep(0.1)
try:
response_frame = ser.read(7)# 读取从机应答帧
if validate_response_frame(response_frame):
byte4 = response_frame# 获取第4位数据
byte5 = response_frame# 获取第5位数据
value = (( byte4<< 8) + byte5) / 10
print("风速值:", value)
else:
print("应答帧校验失败")
time.sleep(0.1)
except:
print("无数据")
```
测试结果:

## 3.2-使用金手指上的UART引脚通讯
### 3.2.1-RS485转UART和行空板接线图

### 3.2.2-接线说明
- 需要外部供电12V
### 3.2.3-编程
示例代码:
```python
# -*- coding: utf-8 -*-
import time
from pinpong.board import Board, UART
#使用的是行空板金手指上的UART口,因此使用pinpong库
Board().begin()#初始化,选择板型,不输入板型则进行自动识别
#硬串口1 P0-RX P3-TX
uart1 = UART(0)
uart1.init() #默认波特率为9600
while True:
query_frame = # 查询帧
uart1.write(query_frame)
time.sleep(1)
try:
response_frame = uart1.read(7)# 读取从机应答帧,根据应答帧格式修改字节数
byte4 = response_frame# 获取第4位数据
byte5 = response_frame# 获取第5位数据
value = ((byte4 << 8) + byte5) / 10
print("风速值:", value)
time.sleep(0.1)
except:
print("无数据")
```
测试结果:

### 3.2.4-数据校验
通过校验码,来确定数据的准确性,示例代码:
```python
import time
from pinpong.board import Board, UART
Board().begin()# 初始化,选择板型,不输入板型则进行自动识别
# 硬串口1 P0-RX P3-TX
uart1 = UART(0)
uart1.init()# 默认波特率为9600
def calculate_checksum(data):
checksum = 0xFFFF# 初始校验码值
for byte in data:
checksum ^= byte# 异或操作
for _ in range(8):
if checksum & 0x0001:# 最低位为1
checksum >>= 1# 右移一位
checksum ^= 0xA001# 异或操作
else:
checksum >>= 1# 右移一位
return checksum.to_bytes(2, byteorder='little')# 返回校验码的字节表示,小端序
def validate_response_frame(frame):
if len(frame) < 5:
return False
received_checksum = frame[-2:]# 从应答帧中提取接收到的校验码
expected_checksum = calculate_checksum(frame[:-2])# 计算期望的校验码
return received_checksum == expected_checksum
while True:
query_frame = # 查询帧
uart1.write(query_frame)# 发送查询帧
time.sleep(0.1)
try:
response_frame = uart1.read(7)# 读取从机应答帧
if validate_response_frame(bytes(response_frame)): # 与USB通讯不一样的,需要转化成字节串
byte4 = response_frame# 获取第4位数据
byte5 = response_frame# 获取第5位数据
value = (( byte4<< 8) + byte5) / 10
print("风速值:", value)
else:
print("应答帧校验失败")
time.sleep(0.1)
except:
print("无数据")
```
测试结果:

## 4-常见问题:
## 如何查看usb转rs485模块的串口号
在行空板终端使用如何命令可以查看所有的串口编号,通过把USB转485插上查询一次,拔掉查询一次,多出来的串口就是这个模块的串口号。
```
ls /dev/tty*
```

有的USB转rs485模块使用的驱动在行空板上没有,例如PL2303驱动,则通过上述方法无法查询到串口,这里提供一下PL2303驱动的安装方法,如果找到串口了可忽略下文:
把附件**PL2303G_Unihiker_Driver.zip**放进行空板根目录后,输入下面命令:
```
unzip PL2303G_Unihiker_Driver.zip
```
```
cd PL2303G_Unihiker_Driver
```
```
chmod 777 install.sh
```
```
bash install.sh
```
输入最后一条指令会出现以下:

再次查询
```
ls /dev/tty*
```
出现下图,说明安装成功

{:6_209:}{:6_209:}{:6_209:}
页:
[1]