juechafun/01-项目/2512-MaixCam竞赛版/模块-程序控制-文档说明.md
2026-01-15 10:01:16 +08:00

238 lines
12 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

# 程序控制文档
---
## 一、基本说明
- **版本号**`v3.5.5`
- **适用算法**OCR、色块、AprilTag
- **串口波特率**115200
- **协议详情参见**[附录:通信协议规范](#附录:通信协议规范)
- **关联文档**:参数调试`v1.0.10`
>建议先阅读关联文档,再来阅读本文档。
---
## 二、支持算法列表
| 算法ID | 名称 | 简介说明 |
| ---- | -------- | ----------------------------- |
| `0` | 空 | 开机默认状态,无算法运行 |
| `1` | 色块检测 | 默认 LAB 参数为 0需配合 `S` 指令设置颜色范围 |
| `2` | Apriltag | 检测 Apriltag 标签,返回 ID 与旋转角度 |
| `3` | OCR | 光学字符识别 |
| `4` | 交叉点 | 检测交叉点中心区域 |
---
## 三、串口发送格式
| 操作 | 指令字符 | 参数格式与说明 | 示例命令 |
| ------------ | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| **开启指定算法** | `N` | `<算法ID>`<br>立即切换当前运行算法 | `N1`(启动色块检测) |
| **设置LAB参数** | `S` | `<参数ID>+LMin+LMax+AMin+AMax+BMin+BMax>`<br>用于色块检测的颜色范围LAB色彩空间0~255 | `S1+0+100+30+80+20+70` |
| **设置串口应答模式** | `A` | `<模式>`<br>`-n`:定时上报,间隔 n 毫秒<br>`0`:关闭上报<br>`n>0`仅上报第n个目标后自动切回 `A0` | `A-500`<br>`A0`<br>`A2` |
| **缩放画面比例** | `Z` | `<缩放倍数>`<br>以画面中心为基准缩放。`Z100`=原始尺寸,`Z150`=放大至150% | `Z100`<br>`Z150` |
| **设置分辨率** | `R` | `<分辨率>`<br>格式:`宽x高`,如 `552x368` | `R552x368` |
| **设置检测框显示项** | `D` | `+标识符+状态`<br>标识符: `i`, `x`, `y`, `w`, `h`, `v`, `r`, `cx`, `cy`<br>状态: `1`=显示, `0`=隐藏 | `D+i1+cx1+cy1`<br>`D+i1+x0+y0` |
| **设置色块算法参数** | `C` | `+合并开关+合并距离+最小X比例+最小Y比例`<br>合并开关:`1`=开启,`0`=关闭<br>合并距离n>=0小于n个像素的色块会被合并<br>最小X比例0~100<br>最小Y比例0~100<br>(`面积阈值=最小X尺寸 * 最小Y尺寸`色块的面积、宽度和高度分别不低于面积阈值、最小Y尺寸否则不返回。) | `C+1+30+0+0`(合并30像素间距色块)<br>`C+0+30+0+0`(不合并)<br>`C+0+30+30+50`不合并色块的面积、宽度、高度分别不低于面积阈值、最小Y尺寸否则不返回) |
---
## 四、串口接收格式
返回数据以 `#` 开头,`!` 结尾
### 基础通用格式适用于色块、OCR等
```
#i{x}y{y}w{w}h{h}v{v}!
```
### 特殊格式 - Apriltag含旋转角度
```
#i{i}x{x}y{y}w{w}h{h}v{v}r{r}!
```
### 字段含义说明
| 字段 | 含义 | 说明 |
| --- | -------- | ----------------------------------------------------------- |
| `i` | 目标序号 | 第几个被检测到的目标(从 `1` 开始递增) |
| `x` | 中心点 X 坐标 | 目标在图像中的横向像素坐标 |
| `y` | 中心点 Y 坐标 | 目标在图像中的纵向像素坐标 |
| `w` | 宽度 | 目标包围框宽度(像素) |
| `h` | 高度 | 目标包围框高度(像素) |
| `v` | 结果值 | 根据算法不同:<br>• Apriltag → 标签 ID<br>• 色块 → LAB 参数组 ID如 S1/S2 |
| `r` | 旋转角度 | 仅Apriltag |
### 示例输出(色块检测)
若检测到三个色块:
```
#i1x100y120w50h50v1!
#i2x200y160w60h60v1!
#i3x300y200w55h55v1!
```
### 输出排序规则
多个目标按以下优先级排序:
1. **X 坐标升序**
2. **Y 坐标升序**
---
# 附录:通信协议规范
## 一、数据帧结构
| 字段名 | 长度 | 描述 |
|----------------|----------|----------------------------------------------------------------------|
| `header` | 4B (LE) | 帧头标识,固定值 `0xAA 0xCA 0xAC 0xBB`,先发 `0xAA` |
| `data_len` | 4B (LE) | 数据总长度 = `flags + cmd + body + crc` 的字节数 |
| `flags` | 1B | 控制标志位,含响应类型、状态、版本等 |
| `cmd` | 1B | 命令类型,预定义命令从 255 递减,自定义命令范围 `0 ~ CMD_APP_MAX` |
| `body` | nB | 变长数据体,最大支持 `(2^32 - 1)` 字节 |
| `CRC16_IBM` | 2B (LE) | 校验码,覆盖 `header``body` 所有字段,低位在前 |
---
## 二、字段详解
### 1. Header帧头
- 固定 4 字节:`0xAA 0xCA 0xAC 0xBB`
- 发送顺序:`AA → CA → AC → BB`
### 2. Data Length数据长度
- 小端序编码表示后续所有字段flags + cmd + body + crc的总字节数
- 示例:`0x00000009` → 实际发送:`09 00 00 00`
### 3. Flags控制标志
| 位位置(从高到低) | 名称 | 含义说明 |
|--------------------|-------------|--------------------------------------------------------------------------|
| Bit 7 | `is_resp` | 是否为响应帧:<br>`0`=请求;<br>`1`=响应或主动上报(此时 Bit 5 必须为 1 |
| Bit 6 | `resp_ok` | 响应结果:<br>请求时保留;<br>响应时 `1`=成功,`0`=失败 |
| Bit 5 | `is_report` | 是否为主动上报:<br>请求时保留;<br>响应时 `1`=上报,`0`=普通响应 |
| Bit 4~2 | Reserved | 保留位,未来扩展使用 |
| Bit 1~0 | `version` | 协议版本号,当前为 `1`(仅不兼容升级时修改) |
> 示例:`0x00` 表示:非响应、协议版本 1
### 4. Cmd命令类型
- 1 字节,预定义命令从 `255` 开始递减
- 自定义命令范围:`0` ~ `maix.protocol.CMD.CMD_APP_MAX`
### 5. Body数据体
- 变长字段,内容由 `cmd` 决定
- 字符串按 ASCII 顺序逐字节发送(如 `"hello"``68 65 6C 6C 6F`
### 6. CRC16_IBM校验码
- 覆盖范围:从 `header``body` 所有字节
- 小端序存储,先发低位再发高位
---
## 三、完整示例
### 十进制示例:
| header | data_len | flags | cmd | body | crc |
|-------------|----------|-------|-----|---------|---------|
| 3148663466 | 9 | 0 | 1 | "hello" | 17451 |
### 十六进制示例:
| header | data_len | flags | cmd | body | crc |
|----------|--------------|-------|-----|----------------|---------|
| 0xBBACCAAA | 0x00000009 | 0x00 | 0x01 | 68 65 6c 6c 6F | 0x442B |
### 最终字节流(十六进制,按发送顺序):
```
AA CA AC BB 09 00 00 00 00 01 68 65 6C 6C 6F 2B 44
```
> ✅ 注意:所有多字节字段均采用**小端序**,字符串按原顺序发送。
---
### 四、CRC16 实现
### 方法一直接计算法C语言
```c
unsigned short crc16_IBM(unsigned char *ptr, int len) {
unsigned int i;
unsigned short crc = 0x0000;
while(len--) {
crc ^= *ptr++;
for (i = 0; i < 8; ++i) {
if (crc & 1)
crc = (crc >> 1) ^ 0xA001;
else
crc = (crc >> 1);
}
}
return crc;
}
```
### 方法二:查表法(推荐用于性能敏感场景)
```c
const unsigned int crc16_table[256] = {
    0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
    0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
    0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
    0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
    0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
    0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
    0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
    0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
    0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
    0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
    0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
    0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
    0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
    0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
    0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
    0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
    0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
    0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
    0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
    0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
    0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
    0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
    0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
    0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
    0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
    0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
    0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
    0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
    0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
    0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
    0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
    0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040,
};
unsigned short crc16_IBM(const unsigned char *ptr,int len)
{
    unsigned short crc = 0x0000;
    while(len--)
    {
        crc = (crc >> 8) ^ crc16_table[(crc ^ *ptr++) & 0xff];
    }
    return (crc);
}
```
---