142 lines
8.2 KiB
Markdown
142 lines
8.2 KiB
Markdown
# 无人机螺杆检测 — 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` 配置项),结构上无需改变。
|