juechafun/01-项目/2512-MaixCam竞赛版/模块-程序控制-文档说明.md

247 lines
13 KiB
Markdown
Raw Permalink 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.17`
- **适用算法**色块、AprilTag、OCR、交叉点、二维码、人脸、情绪、自学习分类
- **串口波特率**115200
- **协议详情参见**[附录:通信协议规范](#附录:通信协议规范)
---
## 二、支持算法列表
| 算法ID | 名称 | 简介说明 |
| ---- | -------- | ------------------------------------ |
| `0` | 空 | 开机默认状态,无算法运行 |
| `1` | 色块检测 | 默认 LAB 参数为 0需配合 `S` 指令设置颜色范围 |
| `2` | Apriltag | 检测 Apriltag 标签,返回 ID 与旋转角度 |
| `3` | OCR | 光学字符识别 |
| `4` | 交叉点 | 检测交叉点中心区域 |
| `5` | 二维码 | 二维码识别 |
| `6` | 人脸 | 人脸识别,需预先使用`人脸识别`程序学习人脸 |
| 7 | 情绪 | 识别”愤怒“、”厌恶“、”恐惧“、”开心“、”悲伤“、”惊讶“、”平静“ |
| 8 | 自学习分类 | 需预先使用”自学习分类“程序学习类别 |
---
## 三、串口发送格式
| 操作 | 指令字符 | 参数格式与说明 | 示例命令 |
| ------------ | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| **开启指定算法** | `N` | `<算法ID>`<br>立即切换当前运行算法 | `N1`(启动色块检测) |
| **设置颜色开关** | `S` | <颜色ID>+开关状态<br>颜色ID<br>- 0 对所有颜色进行更新<br>- 1~9 支持的颜色ID<br>开关状态:<br>- 0 关闭该颜色<br>- 1 开启该颜色 | `S0+1`(开启所有颜色)<br>`S1+1` (开启颜色1),<br>`S1+0` (关闭颜色1) |
| **设置串口应答模式** | `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尺寸否则不返回) |
| 设置灯光 | L | L+W50+Y50<br>`+白光比例+黄光比例`<br>白光比例0~100<br>黄光比例0~100<br><br>注意设置灯光时建议使用N0指令关闭算法避免串口消息混杂<br><br>若设置成功,串口返回`#i1x0y0w0h0v1`,反之,串口返回`#i1x0y0w0h0v0` | `L+W50Y50`设置白光比例为50、黄光比例为50 |
> 合并默认为 x 5 y 5
---
## 四、串口接收格式
返回数据以 `#` 开头,`!` 结尾
### 基础通用格式适用于色块、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{i}x{x}y{y}w{w}h{h}v{v}s{s}!
```
### 字段含义说明
| 字段 | 含义 | 说明 |
| --- | -------- | ----------------------------------------------------------- |
| `i` | 目标序号 | 第几个被检测到的目标(从 `1` 开始递增) |
| `x` | 中心点 X 坐标 | 目标在图像中的横向像素坐标 |
| `y` | 中心点 Y 坐标 | 目标在图像中的纵向像素坐标 |
| `w` | 宽度 | 目标包围框宽度(像素) |
| `h` | 高度 | 目标包围框高度(像素) |
| `v` | 结果值 | 根据算法不同:<br>• Apriltag → 标签 ID<br>• 色块 → LAB 参数组 ID如 S1/S2 |
| `r` | 旋转角度 | 仅Apriltag |
| `s` | 置信度 | 仅人脸识别算法当前人脸ID的分数 |
### 示例输出(色块检测)
若检测到三个色块:
```
#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);
}
```
---