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

12 KiB
Raw Blame History

程序控制文档

#复盘/0 #临时/备忘 #状态/待处理

20260115-备忘-主题名-文件内容

一句话描述

[__增加 L 指令控制灯光, L+W50+Y30调整范围0~100]


一、基本说明

  • 版本号v3.7.5
  • 适用算法OCR、色块、AprilTag
  • 串口波特率115200
  • 协议详情参见附录:通信协议规范
  • 关联文档:参数调试v1.0.10

建议先阅读关联文档,再来阅读本文档。


二、支持算法列表

算法ID 名称 简介说明
0 开机默认状态,无算法运行
1 色块检测 默认 LAB 参数为 0需配合 S 指令设置颜色范围
2 Apriltag 检测 Apriltag 标签,返回 ID 与旋转角度
3 OCR 光学字符识别
4 交叉点 检测交叉点中心区域

三、串口发送格式

操作 指令字符 参数格式与说明 示例命令
开启指定算法 N <算法ID>
立即切换当前运行算法
N1(启动色块检测)
设置LAB参数 S <参数ID>+LMin+LMax+AMin+AMax+BMin+BMax>
用于色块检测的颜色范围LAB色彩空间0~255
S1+0+100+30+80+20+70
设置串口应答模式 A <模式>
-n:定时上报,间隔 n 毫秒
0:关闭上报
n>0仅上报第n个目标后自动切回 A0
A-500
A0
A2
缩放画面比例 Z <缩放倍数>
以画面中心为基准缩放。Z100=原始尺寸,Z150=放大至150%
Z100
Z150
设置分辨率 R <分辨率>
格式:宽x高,如 552x368
R552x368
设置检测框显示项 D +标识符+状态
标识符: i, x, y, w, h, v, r, cx, cy
状态: 1=显示, 0=隐藏
D+i1+cx1+cy1
D+i1+x0+y0
设置色块算法参数 C +合并开关+合并距离+最小X比例+最小Y比例
合并开关:1=开启,0=关闭
合并距离n>=0小于n个像素的色块会被合并
最小X比例0100
最小Y比例0
100
(面积阈值=最小X尺寸 * 最小Y尺寸色块的面积、宽度和高度分别不低于面积阈值、最小Y尺寸否则不返回。)
C+1+30+0+0(合并30像素间距色块)
C+0+30+0+0(不合并)
C+0+30+30+50不合并色块的面积、宽度、高度分别不低于面积阈值、最小Y尺寸否则不返回)

合并默认为 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 目标序号 第几个被检测到的目标(从 1 开始递增)
x 中心点 X 坐标 目标在图像中的横向像素坐标
y 中心点 Y 坐标 目标在图像中的纵向像素坐标
w 宽度 目标包围框宽度(像素)
h 高度 目标包围框高度(像素)
v 结果值 根据算法不同:
• Apriltag → 标签 ID
• 色块 → 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) 校验码,覆盖 headerbody 所有字段,低位在前

二、字段详解

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 是否为响应帧:
0=请求;
1=响应或主动上报(此时 Bit 5 必须为 1
Bit 6 resp_ok 响应结果:
请求时保留;
响应时 1=成功,0=失败
Bit 5 is_report 是否为主动上报:
请求时保留;
响应时 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校验码

  • 覆盖范围:从 headerbody 所有字节
  • 小端序存储,先发低位再发高位

三、完整示例

十进制示例:

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语言

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;
}

方法二:查表法(推荐用于性能敏感场景)

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);
}