GrabBag/App/DroneScrewbolt/Doc/ModbusTCP_Protocol.md
2026-06-26 17:55:15 +08:00

142 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 无人机螺杆检测 — ModbusTCP 协议(板二 ↔ 外部 PLC / 上位机)
| 版本 | 日期 | 说明 |
|------|------------|------|
| V1.0 | 2026-05-22 | 初版 |
## 一、协议概览
无人机螺杆双板系统的两板之间使用 **ZeroMQ**(控制 REQ-REP / 结果 PUB-SUB与车间侧的 PLC、上位机通信使用 **ModbusTCP**
ModbusTCP 通讯主要发生在 **板二DroneScrewCtrl****外部控制器** 之间:
```
┌──────────┐ Modbus TCP ┌──────────┐ ZMQ ┌──────────┐
│ PLC/HMI │ ────────────> │ Ctrl │ ────────> │ Server │
│ 上位机 │ <──────────── │ (板二) │ <──────── │ (板一) │
└──────────┘ 状态/结果 └──────────┘ 结果上传 └──────────┘
```
- **TCP 端口**`502`Modbus 默认)
- **Slave ID**`1`
- **字节序**:寄存器内大端(按 Modbus 标准),跨寄存器多字数据低字在前(与项目其它 App 保持一致,可通过配置 `byteOrder` 切换)
- **触发模型**:上位机写入控制寄存器触发 → Ctrl 转发到 Server → Server 检测结果反馈到 Ctrl → Ctrl 写入到上位机可读取的输入/保持寄存器
## 二、地址映射
寄存器分为 4 个区段:
| 区段 | 类型 | 地址范围 | 用途 |
|---------------|-------------------|-------------------|---------------------------------|
| 控制命令 | Holding (FC06/16) | `40001 ~ 40020` | 由上位机写入,触发动作 |
| 实时状态 | Input (FC04) | `30001 ~ 30030` | 由 Ctrl 写出,上位机读取系统状态 |
| 检测结果 | Holding (FC03/04) | `40101 ~ 40200` | 当前一帧检测结果 |
| 参数配置 | Holding (FC03/06) | `40301 ~ 40360` | 算法 / 相机参数透传 |
> Modbus 寄存器使用 1 基地址展示PDU 实际为 0 基)。
### 2.1 控制命令(上位机写)
| 寄存器 | 名称 | 取值 |
|--------|-------------------|-----------------------------------------------------------------------------------------------|
| 40001 | `CMD` | `1`=启动持续检测 / `2`=停止持续 / `3`=单次检测 / `10`=请求下一条结果 / `99`=心跳 |
| 40002 | `CMD_ID` | 命令序列号(防止重复触发) |
| 40003 | `TARGET` | `0`=自动 / `1..N`=指定相机 |
| 40004 | `PARAM_BLOCK` | 1=触发同步参数下发;写入后 Ctrl 读取 40301~40360 一次性更新 |
| 40005 | `RESERVED` | 保留 |
### 2.2 实时状态(上位机读 / Ctrl 写)
| 寄存器 | 名称 | 取值 |
|--------|---------------------|-----------------------------------------------------------------------------------------------|
| 30001 | `WORK_STATUS` | `0`=Idle / `1`=Connecting / `2`=Streaming / `3`=Detecting / `9`=Error |
| 30002 | `SERVER_CONNECTED` | `0`=未连接 / `1`=已连接 |
| 30003 | `CAMERA_CONNECTED` | `0`=Server 端相机断开 / `1`=已连接 |
| 30004 | `ERROR_CODE` | 最近错误码0=无错误) |
| 30005 | `LAST_CMD_ACK` | 最近一次完成的 CMD_ID |
| 30006~30009 | `RTSP_FRAME_FPS`,`STREAM_BPS_KB`,`LATENCY_MS`,`CPU_LOAD` | 监控用 |
| 30010~30015 | `VERSION_*` | 软件 / 算法版本 |
### 2.3 检测结果(写入 1 帧后再写下一帧)
寄存器 40101 ~ 40200 共 100 个寄存器,按以下结构组织:
| 偏移 | 名称 | 说明 |
|---------|-------------------|------|
| +0 | `FRAME_ID_HI` | 帧号高 16 位 |
| +1 | `FRAME_ID_LO` | 帧号低 16 位 |
| +2~+5 | `TIMESTAMP[4]` | 微秒时间戳64 位) |
| +6 | `IMG_WIDTH` | 图像宽 |
| +7 | `IMG_HEIGHT` | 图像高 |
| +8 | `BOX_COUNT` | 检测目标数量 (`N`,最多 18) |
| +9 | `RESULT_INDEX` | 写 `0..N-1` 表示当前发送的第几个目标(配合 40001=`10` 翻页) |
| +10 | `SUCCESS` | `1`=成功 / `0`=失败 |
| +11~+15 | 保留 | — |
| +16~+20 | `BOX[0]` | `cls,score×100,x,y,w,h` 5 个字score×100 为整数百分比) |
| +21~+25 | `BOX[1]` | … |
| … | … | 最多 18 个 box占用 16~105 偏移),余量保留 |
### 2.4 参数配置(写入后通过 ZMQ 透传到 Server
| 寄存器 | 名称 | 说明 |
|--------|-----------------------|------|
| 40301 | `SCORE_TH ×1000` | 置信度阈值(千分位定点) |
| 40302 | `NMS_TH ×1000` | NMS 阈值 |
| 40303 | `INPUT_WIDTH` | 模型输入宽 |
| 40304 | `INPUT_HEIGHT` | 模型输入高 |
| 40305 | `MODEL_TYPE` | 0=YOLO, 1=自定义 |
| 40310 | `EXPOSURE_TIME_US_HI` | 曝光时间高 16 位μs |
| 40311 | `EXPOSURE_TIME_US_LO` | 曝光时间低 16 位 |
| 40312 | `GAIN ×100` | 增益(百分位定点) |
| 40320 | `RTSP_REQUEST` | 0=保持当前 RTSP 配置 / 1=请求重新发布 RTSP URL |
| 40330~40359 | `MODEL_PATH[]` | 模型路径 ASCII每寄存器 2 字符,截止 0x00 |
## 三、典型时序
### 3.1 启动一次单帧检测
```
PLC Ctrl Server (ZMQ)
│ │ │
│── 40001 := 3 ─────────▶ │ │
│ 40002 := SEQ │── ZMQ REQ {"cmd":"single"} ─▶│
│ │◀─── REP {"ok":true}──────────│
│ │ │
│ │◀─── PUB topic="result", json │
│ │ 写 40101..40200 │
│◀── 30005 := SEQ ─────────│ │
│ 30001 := Detecting │ │
│── FC03(40101..40200) ──▶ │ (读结果) │
```
### 3.2 启动持续检测
`40001=1 → Ctrl 转发 start → Server 持续 PUB → Ctrl 每帧覆盖写入 40101~40200并将 FRAME_ID 写到 30005 之后让 PLC 轮询`
### 3.3 多目标翻页
如果一次检测有 `BOX_COUNT > 18`PLC 反复写 `40001=10` 触发下一页结果Ctrl 在内部维护索引)。
## 四、错误码ERROR_CODE
| 码值 | 含义 |
|--------|------|
| 0 | 正常 |
| 1001 | Server 离线 |
| 1002 | RTSP 拉流断开 |
| 1003 | ZMQ 控制超时 |
| 2001 | 相机端连接失败Server |
| 2002 | 相机取流超时 |
| 3001 | 算法异常 |
| 9999 | 未知错误 |
## 五、实现入口
板二的 ModbusTCP 服务通过现有 `Module/ModbusTCPServer` 提供:
- 启动:`MainWindow``InitApp` 中调用 `IVrModbusTCPServer::CreateObject``Init(502, slaveId=1)`
- 寄存器更新:`DroneScrewCtrlPresenter::onResultReceived` 收到 ZMQ 结果后,调用 `WriteRegisters(40101, ...)`
- 命令解析:在 `OnModbusWriteCallback(startAddr, data, count)` 中识别 40001~40020 区段并触发对应 ZMQ 命令
> 真实接入时根据上位机厂商习惯调整字节序(`byteOrder` 配置项),结构上无需改变。