## 引言
在工业物联网(IIoT)领域,边缘计算设备扮演着至关重要的角色。RK3506作为一款高性能、低功耗的边缘计算芯片,非常适合用于工业数据采集场景。本文将介绍如何基于RK3506构建一个完整的Modbus-TCP传感器采集系统,包括传感器模拟器、采集器开发和测试验证。
## 项目架构设计
### 整体架构
整个系统采用**分布式架构**,由三个核心组件组成:
- **传感器模拟器**(PC端):模拟Modbus从机,生成传感器数据,支持故障注入
- **RK3506采集器**(RK3506开发板):定时轮询传感器,数据解析,异常检测
- **LLM服务**(云端/本地):接收异常事件,生成专业诊断报告
### 组件分工
| 组件 | 运行平台 | 职责 |
|------|----------|------|
| **传感器模拟器** | PC | 模拟Modbus从机,生成传感器数据,支持故障注入 |
| **RK3506采集器** | RK3506开发板 | 定时轮询传感器,数据解析,异常检测 |
| **LLM服务** | 云端/本地 | 接收异常事件,生成专业诊断报告 |
## Modbus协议原理
### RTU vs TCP
Modbus协议有两种主要传输模式:
**RTU模式**:基于串行通信(RS-485),使用CRC16校验,适合长距离传输。
**TCP模式**:基于以太网,使用MBAP(Modbus Application Protocol)头,传输速度更快,适合网络环境。
由于项目初期没有USB转485硬件,本文重点介绍**Modbus-TCP模式**。
### MBAP头结构
Modbus-TCP报文由6字节MBAP头和PDU(Protocol Data Unit)组成:
```
┌──────┬──────┬──────┬──────┬──────┬──────┐
│ 事务ID │ 协议ID │ 长度 │ 从站地址 │ 功能码 │ ...数据... │
│ (2字节) │ (2字节) │ (2字节) │ (1字节) │ (1字节) │ │
└──────┴──────┴──────┴──────┴──────┴──────┘
0-1 2-3 4-5 6 7
```
- **事务ID**:用于匹配请求和响应
- **协议ID**:固定为0(Modbus协议)
- **长度**:后续字节数(包括从站地址)
- **从站地址**:目标设备地址(0-247)
- **功能码**:操作类型(0x03=读保持寄存器)
### 常用功能码
| 功能码 | 名称 | 用途 |
|--------|------|------|
| 0x03 | 读保持寄存器 | 读取传感器数据 |
| 0x06 | 写单个寄存器 | 控制设备参数 |
| 0x10 | 写多个寄存器 | 批量控制 |
## 传感器模拟器实现
### 设计思路
模拟器使用Python实现,支持异步TCP服务器,模拟4个Modbus从机:
- **Slave 1**:环境传感器(温度、湿度)
- **Slave 2**:振动传感器(X/Y/Z轴、RMS)
- **Slave 3**:电力传感器(电压、电流、功率)
- **Slave 4**:管道传感器(压力、流量)
### 核心代码
#### 传感器数据更新逻辑
```python
def update(self, t):
if self.slave_id == 1:
# 环境传感器:模拟正弦波动
temp = 25.0 + math.sin(t / 30) * 1.5
humi = 50.0 + math.sin(t / 45) * 4.0
# 故障注入:高温故障
if self.fault == 'high_temp':
elapsed = time.time() - self.fault_start
ramp = min(elapsed / 300.0, 1.0)
temp = 55.0 + ramp * 30.0 # 从55°C逐渐升至85°C
self.registers[0] = int(temp * 10) # 温度×10
self.registers[1] = int(humi * 10) # 湿度×10
```
#### TCP请求处理
```python
def handle_tcp_request(self, request):
if len(request) < 12:
return None
trans_id = (request[0] << 8) | request[1]
proto_id = (request[2] << 8) | request[3]
length = (request[4] << 8) | request[5]
slave = request[6]
func = request[7]
if slave != self.slave_id or proto_id != 0:
return None
addr = (request[8] << 8) | request[9]
count = (request[10] << 8) | request[11]
if func == 0x03: # 读保持寄存器
pdu_len = 3 + count * 2
response = bytearray()
response.append(trans_id >> 8)
response.append(trans_id & 0xFF)
response.append(0x00) # 协议ID高字节
response.append(0x00) # 协议ID低字节
response.append(pdu_len >> 8)
response.append(pdu_len & 0xFF)
response.append(self.slave_id)
response.append(0x03)
response.append(count * 2)
for i in range(count):
val = self.registers[addr + i]
response.append((val >> 8) & 0xFF)
response.append(val & 0xFF)
return bytes(response)
```
### 运行模拟器
```bash
# 启动TCP模拟器,注入高温故障到Slave 1
python3 simulator/modbus_slave_sim.py \
--mode tcp \
--tcp-port 7502 \
--slaves 1,2,3,4 \
--fault high_temp \
--fault-slave 1
```
## RK3506采集器开发
### 交叉编译环境
RK3506使用ARM架构,需要配置交叉编译工具链:
```bash
# 工具链配置文件
source ~/3506-toolchain/host/environment-setup
# 关键环境变量
# CC=arm-buildroot-linux-gnueabihf-gcc
# CFLAGS=-march=armv8-a+crc -mtune=cortex-a55
# ARCH=arm
# CROSS_COMPILE=arm-buildroot-linux-gnueabihf-
```
### 项目结构
```
src/
├── main.c # 主程序入口
├── modbus_transport.h # 传输层抽象接口
├── modbus_tcp.c # TCP传输实现
├── modbus_rtu.c # RTU传输实现
├── sensor_map.h # 传感器映射定义
├── sensor_map.c # 传感器数据处理
├── anomaly.h # 异常检测接口
├── anomaly.c # 异常检测算法
├── event_json.h # 事件序列化接口
├── event_json.c # JSON序列化实现
├── llm_client.h # LLM客户端接口
├── llm_client.c # LLM客户端实现
├── serial_port.h # 串口接口
└── serial_port.c # 串口实现
```
### 传输层抽象设计
采用**策略模式**设计传输层,RTU和TCP共用一套接口:
```c
typedef struct modbus_transport {
int (*connect)(modbus_transport_t *t);
int (*read)(modbus_transport_t *t, uint8_t *buf, int len, int timeout_ms);
int (*write)(modbus_transport_t *t, const uint8_t *buf, int len);
void (*close)(modbus_transport_t *t);
} modbus_transport_t;
typedef struct {
modbus_transport_t base;
const char *host;
int port;
int sockfd;
} modbus_tcp_t;
```
### 传感器映射配置
定义传感器与Modbus寄存器的映射关系:
```c
sensor_map_t sensor_maps[MAX_SENSORS] = {
{
"env", 1, 0, 2,
{0.1, 0.1},
{"temperature", "humidity"},
{"C", "%RH"}
},
{
"vibration", 2, 0, 4,
{0.01, 0.01, 0.01, 0.01},
{"x", "y", "z", "rms"},
{"mm/s", "mm/s", "mm/s", "mm/s"}
},
{
"power", 3, 0, 3,
{0.1, 0.1, 0.1},
{"voltage", "current", "power"},
{"V", "A", "W"}
},
{
"pipe", 4, 0, 2,
{0.01, 0.01},
{"pressure", "flow"},
{"MPa", "m3/h"}
}
};
```
### 主循环设计
```c
while (1) {
// 创建TCP连接(每次轮询新建连接)
fd = socket(AF_INET, SOCK_STREAM, 0);
// ... 设置超时、连接服务器 ...
for (int i = 0; i < sensor_map_count; i++) {
sensor_data_t *data = &sensors[i];
uint16_t raw[MAX_FIELDS];
// 读取保持寄存器
ret = modbus_read_holding_registers_tcp(fd,
data->map->slave_id,
data->map->start_addr,
data->map->count, raw);
if (ret == MODBUS_ERR_OK) {
data->comm_error_count = 0;
sensor_data_update(data, raw);
print_sensor_data(data);
// 异常检测(第二篇介绍)
anomaly_event_t event;
if (anomaly_detect(data, &event)) {
handle_anomaly(&event);
}
} else {
data->comm_error_count++;
printf("[%s] Slave %d: COMM ERROR (%d)\n",
data->map->name, data->map->slave_id, ret);
}
usleep(100000); // 100ms间隔
}
close(fd);
sleep(POLL_INTERVAL_SEC); // 1秒轮询间隔
}
```
### 编译脚本
```bash
#!/bin/bash
cd "$(dirname "$0")"/..
echo "Building for RK3506..."
source ~/3506-toolchain/host/environment-setup
mkdir -p build
cd build
cmake ..
make -j4
echo "Build completed. Output: build/modbus_collector"
```
## 测试验证
### 编译部署
```bash
# 编译
bash scripts/build.sh
# 部署到RK3506
scp build/modbus_collector root@<RK3506_IP>:/root/
# 赋予执行权限
ssh root@<RK3506_IP> "chmod +x /root/modbus_collector"
```
### 运行采集器
```bash
# 在RK3506上运行
./modbus_collector --mode tcp --host <SIMULATOR_IP> --port <PORT>
```
### 测试结果
```
Starting RK3506 Modbus-TCP Collector
TCP host: <SIMULATOR_IP>:<PORT>
Polling sensors...
--- 13:19:30 ---
[env] Slave 1: temperature=85.00°C, humidity=51.00%RH
[vibration] Slave 2: x=0.71mm/s, y=0.15mm/s, z=0.15mm/s, rms=0.74mm/s
[power] Slave 3: voltage=24.40V, current=1.40A, power=34.50W
[pipe] Slave 4: pressure=0.64MPa, flow=54.72m3/h
```
所有4个传感器数据均成功采集,数据格式正确。
## 总结
本文介绍了基于RK3506的工业边缘采集系统的第一部分——Modbus-TCP通信与传感器数据采集。主要内容包括:
1. **系统架构设计**:分布式架构,PC端模拟器 + RK3506采集器
2. **Modbus协议原理**:MBAP头结构、功能码解析
3. **传感器模拟器**:Python实现,支持4类传感器和故障注入
4. **RK3506采集器**:C语言开发,传输层抽象设计
5. **测试验证**:编译部署成功,所有传感器数据正常采集
**下一篇预告**:将介绍异常检测算法、LLM智能诊断集成和异步处理优化。
---
**项目源码**:[rk3506-modbus-llm](https://github.com/xxx/rk3506-modbus-llm)
**技术交流**:欢迎在评论区留言讨论!
---
> **提示**:本文是系列文章的第一篇,第二篇将深入讲解异常检测与LLM智能诊断。如果你觉得本文对你有帮助,欢迎点赞、收藏、关注!
