描述
<p style="line-height:1.8;">注:* 为必填项</p>
<p style="line-height:1.8;"><strong><span style="color:#0093e6;">请在报名阶段填写 ↓</span></strong></p>
<p style="line-height:1.8;"> </p>
<h3 style="line-height:1.8;">* 1、项目功能介绍</h3>
<hr>
<p style="line-height:3;"><span style="font-size:18px;">1. 语音控制功能</span></p>
<ul style="line-height:1.8;">
<li>语音指令识别</li>
</ul>
<p style="line-height:1.8;"> 通过ASR Pro模块识别关键词(如“出发”、“停车”、“开灯”、“关灯”)</p>
<p style="line-height:1.8;"> 支持自定义唤醒词和指令集(天问51Block图形化配置)</p>
<ul style="line-height:1.8;">
<li>语音反馈机制</li>
</ul>
<p style="line-height:1.8;"> 执行指令时通过麦克风播报自定义词(如“出发喽”)</p>
<ul style="line-height:1.8;">
<li>指令传输</li>
</ul>
<p style="line-height:1.8;"> ASR Pro通过串口向STM32发送指令码(例:0x01启动巡线,0x02紧急停止)</p>
<p style="line-height:3;"><span style="font-size:18px;">2. 视觉巡线功能</span></p>
<ul style="line-height:1.8;">
<li>路径识别核心算法</li>
</ul>
<p style="line-height:1.8;"> python</p>
<p style="line-height:1.8;"> # 二值化处理</p>
<p style="line-height:1.8;"> # 线性回归拟合</p>
<p style="line-height:1.8;"> # 发送端点坐标+斜率</p>
<ul style="line-height:1.8;">
<li>重要动态参数</li>
</ul>
<p style="line-height:1.8;"> 斜率(判断整体方向)</p>
<p style="line-height:1.8;"> 端点坐标(计算路径偏移量)</p>
<p style="line-height:3;"><span style="font-size:18px;">3. 运动控制功能</span></p>
<ul style="line-height:1.8;">
<li>双环PID控制架构</li>
</ul>
<table style="border-collapse:collapse;width:47.6653%;height:96px;">
<tr>
<td style="width:18.0592%;text-align:center;"><em>控制环</em></td>
<td style="width:18.0335%;text-align:center;"><em>算法类型 </em></td>
<td style="width:33.6069%;text-align:center;"><em> 功能</em></td>
<td style="width:115.026%;text-align:center;"><em>参数示例</em></td>
</tr>
<tr>
<td style="width:18.0592%;text-align:center;">速度环</td>
<td style="width:18.0335%;text-align:center;">PI控制</td>
<td style="width:33.6069%;text-align:center;">维持恒定速度</td>
<td style="width:115.026%;text-align:center;">Kp=-400, Ki=-1.8</td>
</tr>
<tr>
<td style="width:18.0592%;text-align:center;">转向环</td>
<td style="width:18.0335%;text-align:center;">PD控制</td>
<td style="width:33.6069%;text-align:center;">动态调整前轮转向角</td>
<td style="width:115.026%;text-align:center;">Kp=15, Kd=300</td>
</tr>
</table>
<ul style="line-height:1.8;">
<li>电机控制逻辑</li>
</ul>
<p style="line-height:1.8;"> 接收串口指令后输出PWM波驱动电机</p>
<p style="line-height:1.8;"> 速度环+转向环输出量计算</p>
<p style="line-height:3;"><span style="font-size:18px;">4. 多设备协同通信</span></p>
<ul style="line-height:1.8;">
<li>串口协议设计</li>
</ul>
<table style="border-collapse:collapse;width:47.3032%;height:115px;">
<tr style="height:22px;">
<td style="width:31.4452%;height:22px;text-align:center;"><em>设备</em></td>
<td style="width:52.0268%;height:22px;text-align:center;"><em>数据格式 </em></td>
<td style="width:83.8878%;height:22px;text-align:center;"><em> 波特率</em></td>
</tr>
<tr style="height:38px;">
<td style="width:31.4452%;height:38px;text-align:center;">ASR Pro → STM32 </td>
<td style="width:52.0268%;height:38px;text-align:center;">[CMD]</td>
<td style="width:83.8878%;height:38px;text-align:center;">115200</td>
</tr>
<tr style="height:55px;">
<td style="width:31.4452%;height:55px;text-align:center;">OpenMV → STM32</td>
<td style="width:52.0268%;height:55px;text-align:center;">[0xa3, 0xb3, bottom_x, theta, 0xc3] </td>
<td style="width:83.8878%;height:55px;text-align:center;">115200</td>
</tr>
</table>
<p style="line-height:3;"><span style="font-size:18px;">5. 状态指示系统</span></p>
<ul style="line-height:1.8;">
<li>LED指示灯逻辑:语音激活:大LED灯亮/断1次</li>
</ul>
<p style="line-height:1.8;"><span style="font-size:18px;">6. 异常处理机制</span></p>
<ul>
<li style="line-height:1.8;">路径丢失检测:OpenMV未识别到直线时发送错误标志码</li>
</ul>
<p style="line-height:1.8;"> </p>
<h3 style="line-height:1.8;">*2、项目属性</h3>
<hr>
<p style="line-height:1.8;">项目首次公开,为原创<br>项目未参与其他比赛,未答辩</p>
<p style="line-height:1.8;"> </p>
<h3 style="line-height:1.8;">* 3、开源协议</h3>
<hr>
<p>GPL3.0</p>
<p style="line-height:1.8;"> </p>
<p style="line-height:1.8;"><strong><span style="color:#0093e6;">请在竞赛阶段填写 ↓</span></strong></p>
<p style="line-height:1.8;"> </p>
<h3 style="line-height:1.8;">*4、硬件部分</h3>
<hr>
<p style="line-height:1.8;">我一般都是写代码的角色,不会画板子,所以画的板子都是简单的模块堆积。</p>
<p style="line-height:1.8;"><img src="//image.lceda.cn/pullimage/95IpG8yZwSn2By7U2iPfjA3xTTGTc9RhknTsG3hV.png" width="320" height="275" alt="95IpG8yZwSn2By7U2iPfjA3xTTGTc9RhknTsG3hV.png"></p>
<p style="line-height:1.8;">一共两块板子:控制板(STM32,asrpro,openmv,蓝牙等)和供电板(12v,7v,5v,3.3v降压模块等)。分开是为了省钱,大学生比赛比较多,做其他项目只需要改控制板,最后直接把供电板插上去就好了,不需要再买降压模块也不用再焊接了。</p>
<p style="line-height:1.8;"><img src="//image.lceda.cn/pullimage/QHUtvxvrAlSVBXQG32j8DDaMoJtf0cNS8QgcxY6k.jpeg" width="334" height="251" alt="QHUtvxvrAlSVBXQG32j8DDaMoJtf0cNS8QgcxY6k.jpeg"></p>
<p style="line-height:1.8;">各模块增加100μF电解电容+0.1μF陶瓷电容滤波</p>
<p style="line-height:1.8;">我板子画的比较烂,你们可以自己画。具体引脚连接保持一致就行,这样代码烧上就能动</p>
<p style="line-height:1.8;"> </p>
<p style="line-height:1.8;"> </p>
<h3 style="line-height:1.8;">*5、软件部分</h3>
<hr>
<p><strong>1. ASRPRO</strong>:<br>asrpro用天问51编程,我买的asrpro是带type-c下载的比较方便,天问51软件下载和烧录方法网上都是的,搜一下就好了,还有官方qq交流群。<br>下面是我的asrpro引脚配置和图形化编程,非常的简单</p>
<p style="line-height:1.8;"><img src="//image.lceda.cn/pullimage/59taOUvTyJobp3vhD2UrSs7YanQoHuS0g4JohiK3.png" width="721" height="437" alt="59taOUvTyJobp3vhD2UrSs7YanQoHuS0g4JohiK3.png"></p>
<p style="line-height:1.8;"> </p>
<p><strong>2. OPENMV:</strong><br> 主要功能:通过摄像头捕捉图像,进行二值化、形态学处理和线性回归来识别巡线,然后通过串口发送数据给STM32。<br><span style="font-size:16px;"> 算法流程:</span>图像采集 → 预处理 → 二值化 → 形态学处理 → 线性回归 → 数据解析 → 串口通信</p>
<div> 辅助函数:</div>
<pre><span style="font-size:14px;"><span style="font-size:16px;"> def get_endpoint(line):
#获取直线下端点
#原理:在巡线应用中,y坐标越大代表越靠近小车前方
(x1, y1, x2, y2) = line.line() # 获取直线端点坐标
if y1 > y2:
return (x1, y1) # 端点1更靠近底部
else:
return (x2, y2) # 端点2更靠近底部
def theta_change(theta):
#角度归一:将OpenMV的0-180度范围转换为-90到+90度
#便于STM32理解左右转向指令
if theta > 90:
theta = theta - 180 # 将[91,179]映射到[-89,-1]
return theta
else:
return theta </span><span style="font-size:16px;"># [0,90]保持不变</span><br></span></pre>
<div> 二值化分割: <span style="font-size:16px;">img.binary([THRESHOLD])</span></div>
<div> 基于LAB色彩空间的阈值分割,将巡线区域变为白色(255),背景变为黑色(0),LAB色彩空间对光照变化不敏感,提高鲁棒性</div>
<div> 线性回归检测: <span style="font-size:16px;">line </span><span style="font-size:16px;">=</span><span style="font-size:16px;"> img</span><span style="font-size:16px;">.</span><span style="font-size:16px;">get_regression</span><span style="font-size:16px;">(</span><span style="font-size:16px;">[</span><span style="font-size:16px;">(</span><span style="font-size:16px;">100</span><span style="font-size:16px;">,</span><span style="font-size:16px;">100</span><span style="font-size:16px;">)</span><span style="font-size:16px;">]</span><span style="font-size:16px;">,</span><span style="font-size:16px;"> robust</span><span style="font-size:16px;">=</span><span style="font-size:16px;">True</span><span style="font-size:16px;">)</span></div>
<div>
<p> 通信协议设计:<br> 帧结构: [帧头1][帧头2][数据1][数据2][帧尾]<br> 0xA3 0xB3 bottom_x theta 0xC3</p>
<p> 特殊状态编码:<br> - (200, 200): 巡线丢失状态<br> - bottom_x: 下端点的x坐标(0-79)<br> - theta: 归一化角度(-90到+90)</p>
</div>
<p style="line-height:1.8;"> </p>
<p style="line-height:1.8;"><strong>3. STM32:</strong></p>
<div>多环控制:</div>
<p> 速度环(PI) ←→ 转向环(PD) ←→ 电机输出<br> ↑ ↑<br> 编码器反馈 OpenMV<br>速度环PI控制算法:</p>
<pre><span style="font-size:16px;">int velocity_PID_value(int velocity_measure, int velocity_calcu)
{
float a = 0.3; // 一阶低通滤波系数
// 偏差计算
velocity = velocity_measure - velocity_calcu;
// 一阶低通滤波:滤除高频噪声
filt_velocity = a * velocity + (1 - a) * last_filt_velocity;
// 积分项累加(注意:此处可能需考虑积分限幅时机)
velocity_sum += filt_velocity;
// 积分限幅(抗积分饱和)
I_xianfu(2000);
// 更新历史值
last_filt_velocity = filt_velocity;
// PI控制器输出:P项 + I项
return VKp * filt_velocity + VKi * velocity_sum;
}</span></pre>
<p>OpenMV视觉转向环(PD控制):</p>
<pre><span style="font-size:16px;">float turn_mv_x_PID_value(float Target_x, float True_x)
{
// 偏差计算:实际值 - 目标值(注意符号定义)
mv_x_err = True_x - Target_x;
// 微分项计算:当前偏差 - 上次偏差
err_difference_x = mv_x_err - last_mv_x_err;
// 更新历史值
last_mv_x_err = mv_x_err;
// PD控制器输出:P项 + D项
return MKp * mv_x_err + MKd * err_difference_x;
}</span></pre>
<p>控制参数:</p>
<p style="padding-left:40px;">速度环参数 (VKp=-400, VKi=-1.7) 快速响应速度变化,缓慢消除稳态误差,避免振荡</p>
<p style="padding-left:40px;">视觉转向环参数 (MKp=15, MKd=430) 保证转向响应性,强烈抑制超调,提高转向平滑性,无积分项避免在视觉跳动时产生累积误差</p>
<div>参数整定:</div>
<div>
<p style="padding-left:40px;">先P后I最后D:先调Kp至临界振荡,然后加入Ki、Kd</p>
<p style="padding-left:40px;">速度环:先保证速度稳定,再优化动态响应</p>
<p style="padding-left:40px;">转向环:在直道调试Kp,在弯道调试Kd</p>
</div>
<p>典型问题:</p>
<p style="padding-left:40px;">振荡:降低Kp或增加Kd</p>
<p style="padding-left:40px;">响应慢:增加Kp或降低滤波系数</p>
<p style="padding-left:40px;">稳态误差:适当增加Ki(需谨慎)</p>
<p style="padding-left:40px;">超调大:增加Kd或降低Kp</p>
<p> </p>
<p>中断服务函数框架:</p>
<pre><span style="font-size:16px;">void EXTI9_5_IRQHandler(void)
{
// 10ms周期执行的控制逻辑
// 传感器数据采集与处理
// PID控制算法执行
// 电机输出计算与加载
EXTI_ClearITPendingBit(EXTI_Line5); // 清除中断挂起位
}</span></pre>
<p style="line-height:1.8;">具体见源码</p>
<p style="line-height:1.8;"> </p>
<p>串口通信:</p>
<p style="padding-left:40px;">ASR Pro语音 → 0x50/0x51 → asrpro_start_flag → 主控制使能</p>
<p style="padding-left:40px;">OpenMV视觉 → (x,θ)数据 → pwm_mv_flag → 视觉巡线使能</p>
<p style="padding-left:40px;"> ↓</p>
<p style="padding-left:40px;"> PID控制器 → 电机差速输出</p>
<p style="padding-left:40px;"><strong>USART1</strong>:<br>语音指令通道(ASR Pro → STM32)</p>
<p style="padding-left:40px;">单字节指令协议,简单高效</p>
<p style="padding-left:40px;">实时控制:LED开关、巡线启停</p>
<p style="padding-left:40px;"><strong>USART2</strong>:<br>视觉数据通道(OpenMV → STM32)</p>
<p style="padding-left:40px;">5字节定长数据包协议</p>
<p style="padding-left:40px;">双帧头+帧尾校验,保证数据可靠性</p>
<p style="padding-left:40px;">包含坐标数据和巡线状态信息</p>
<pre><span style="font-size:16px;">
/*串口2中断服务程序(接收OpenMV视觉数据包-5字节协议)*/
void USART2_IRQHandler(void)
{
static int i=0;
if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET)
{
openmv_data[i++] = USART_ReceiveData(USART2);
if(openmv_data[0]!=0xa3) i=0; // 帧头0xA3
if((i==2)&&(openmv_data[1]!=0xb3)) i=0; // 帧头0xB3
// 完整数据包接收完成判断
if(i==5)
{
i = 0;
if( Data_test(openmv_data) )
{
bottom_x = openmv_data[2]; // 第3字节: 路线下端x坐标(0-79正常值, 200为丢失标志)
theta = openmv_data[3]; // 第4字节: 路线角度(-90~+90度)
if(bottom_x==200 && theta==200) //表示巡线丢失
{
pwm_mv_flag=0; // 禁用巡线
}
else
{
pwm_mv_flag=1; // 启用巡线
}
}
}
}
}
/*包完整性校验函数*/
int Data_test(int data[])
{
if(data[0]!=0xa3) return 0; // 帧头1
if(data[1]!=0xb3) return 0; // 帧头2
if(data[4]!=0xc3) return 0; // 帧尾
return 1;
}</span></pre>
<p style="line-height:1.8;">通过分层协议设计和严格的数据校验,确保语音与视觉控制的实时性和可靠性</p>
<p style="line-height:1.8;"><span style="color:#95a5a6;font-size:14px;"> </span></p>
<p style="line-height:1.8;"> </p>
<h3 style="line-height:1.8;">*6、BOM清单</h3>
<hr>
<p style="line-height:1.8;">模块的话原理图里都标注名字了,都是常用模块,自行购买<img src="//image.lceda.cn/pullimage/Ic2U8qEj4aJ4rXehozsEVVkVMSMbhDuJtpRmS0s6.png" width="1200" height="343" alt="Ic2U8qEj4aJ4rXehozsEVVkVMSMbhDuJtpRmS0s6.png"></p>
<h3 style="line-height:1.8;">*7、大赛LOGO验证</h3>
<hr>
<p style="line-height:1.8;"><img src="//image.lceda.cn/pullimage/9KUTieQVj2hmkx4dQba3wk9SLtzOINRygKcYpu1c.jpeg" width="272" height="244" alt="9KUTieQVj2hmkx4dQba3wk9SLtzOINRygKcYpu1c.jpeg"></p>
<p style="line-height:1.8;"> </p>
<h3 style="line-height:1.8;">* 8、演示您的项目并录制成视频上传</h3>
<hr>
<p style="line-height:1.8;"> </p>
<p style="line-height:1.8;"> </p>
<p style="line-height:1.8;"><span style="font-size:14px;"><a href="/posts/42551e8f2f2548cabc1c36626a42da94" target="_blank">前往查看更多详情 ></a></span></p>
<p style="line-height:1.8;"> </p>
评论(2)