前言
2020年10月10日至10月13日,我与人组队参加了TI杯辽宁省大学生电子设计竞赛,所选题目为G题——非接触物体尺寸形态测量。在这次竞赛中我主要负责程序相关工作,其中涉及到STM32单片机、OPENMV图像识别模块、激光测距模块、串口屏上位机开发等诸多方面的知识,积累了相当多的经验。经过一个月的前期准备与四天三夜的刻苦奋斗,最终取得了省二等奖的优异成绩。
整理这个笔记,也是对竞赛做一个全面回顾,总结竞赛过程中遇到的困难与解决问题的方法,列举相关参考资料,为今后的读研与工作提供一些参考。
题目要求
设计并制作一个非接触式物体形状和尺寸自动测量装置,测量被测目标的形状、 尺寸、 测量头中心点与被测目标之间的距离等参数,并用激光束指示出被测目标的中心位置。硬件与软件准备
STM32单片机
STM32是高性能,低成本,低功耗的嵌入式微控制器。本次竞赛采用的STM32F103ZET6型号单片机,作为整个测量系统的控制中心使用,实现程序的整体流程控制,对二维云台的舵机PWM控制,以及与OPENMV图像识别模块、激光测距模块、串口屏的信息交换处理。
所用IDE为Keil μVision V5.21.1.0
STM32的学习资料可以在此下载 正点原子资料下载中心
OPENMV视觉模块
OpenMV是一款低价,可扩展的机器视觉模块。本次竞赛采用OPENMV2-M3摄像头,该模块采用STM32F427VG微处理器与OV7725感光元件。可以通过编写简单的Python语言脚本,实现数据采集和图像处理。在本次竞赛中用于识别区域内色块,进行相应处理实现形状识别功能。
OPENMV参考资料: OPENMV中文入门教程 OpenMV
Cam快速参考
使用与之配套的OPENMV IDE进行程序开发。
USART HMI串口屏
USART
HMI串口屏是一款编程简单,易于调试的可触摸显示模块。可以通过图形化软件快速制作显示界面。在本次竞赛中用于显示测距与形状识别结果信息,同时为形状识别提供测量启动按键。本次竞赛使用中景园2.8寸TFT
LCD串口屏。
USART HMI参考资料: USART
HMI入门教程
使用与之配套的USART HMI IDE进行程序开发。
激光测距模块
本次竞赛采用摩天MyAntenn-L1型号激光测距模块。与超声波测距模块相比,激光测距模块可以更为灵敏,精确度高,且可以满足用激光束指示出被测目标的中心位置之要求。
二维云台
二维云台有两个自由度,通过控制两个舵机的角度即可实现任意对任意方向的瞄准。本次竞赛将OPENMV视觉模块与激光测距模块安装在二维云台上,通过回传的图像确定下一时刻舵机的移动方向,做一个简单的闭环控制,最后使激光测距模块指向待测图形的中心。
蜂鸣器/LED指示灯
作为单片机启动,串口屏按键以及测量结束的提示信号。
硬件设计
稳压电路
采用LM2596S-ADJ来实现12V到6.5V(云台供电)的稳压和5V的稳压。LM2596S-ADJ是德州仪器(TI)生产的3A电流输出降压开关型集成稳压芯片,它内含固定频率振荡器(150KHZ)和基准稳压器(1.23v),并具有完善的保护电路、电流限制、热关断电路等功能,使它的性能很稳定。利用该器件只需极少的外围器件便可构成高效稳压电路。所以,LM2596S-ADJ稳压芯片十分适合系统的稳压电路设计。
电路接线图

系统实物图

STM32F103ZET6与其他器件的连接
- 串口屏—USART1—PA9(TX),PA10(RX)
- 激光测距模块—USART2—PA2(TX),PA3(RX)
- OPENMV视觉模块—USART3—PB10(TX),PB11(RX)
- 舵机PWM—TIM3—PA6(CH1),PA7(CH2)
- 蜂鸣器与指示灯—PE14,PE15
软件设计
STM32程序总流程图

OPENMV视觉模块
OPENMV程序总流程图

OPENMV程序总流程图如上图所示,测量分为“普通测量”与“追踪测量”两种。
普通测量模式下,激光测距模块已事先对准待测图形中心,可以直接调用OPENMV内置库函数识别特定色块,读取色块的各项信息,以此可以判断出待测图形的形状。将图形形状等信息以串口信号形式发送至单片机,结合单片机接收到的来自激光测距模块的距离信息。即可根据相似三角形原理计算出图形的尺寸(正方形或三角形的边长、圆的直径)。为提高测量精确度,这里采取了多次读取求平均值的方法。
追踪测量模式下,激光测距模块未对准待测图形中心,如果摄像头没有观察到待测图形色块,则向单片机发送“移动”信号,控制舵机按照设定好的方式来回运动(从左到右,从上到下,覆盖可能找到色块的所有方向);摄像头观察到色块后,向单片机发送“对准”信号,通过一个简单的闭环控制使激光测距模块对准色块中心(设定值为摄像头视野中心坐标,实际值为色块在摄像头视野中的坐标,被控量为两个舵机的PWM值)。完成对准后所执行程序同普通测量模式。
非接触式物体尺寸测量原理

本次竞赛的物体尺寸测量基于相似三角形原理,公式如下所示: \[\frac{L} {x} = \frac{ {L'} } {f}\]
首先进行一次测试以求出摄像头焦距\(f\),可以将某已知边长\(L\)的物体放置在摄像头前已知距离\(x\)的位置,使用测试程序测量像素点的长度\(L'\),便可用上式求出摄像头焦距\(f\),该值为固定值,一旦确定便不会改变。
普通测量或追踪测量模式下,通过来自激光测距模块的距离\(x\),与来自OpenMV摄像头模块的像素点长度\(L’\),以及固定的摄像头焦距\(f\),便可以求出待测物体的长度\(L\)。
形状识别原理

本次竞赛待测形状有正方形、圆形与正三角形,如上图所示。
调用OPENMV摄像头模块的库函数img.find_blobs
可以识别摄像头内所有符合要求的色块blobs
。使用自定义的函数find_max(blobs)
筛选出最大的色块max_blob
,一般情况下是待测色块。
调用库函数img.draw_rectangle(max_blob.rect())
可为待测色块绘制一个矩形将其包住,如上图所示。
可以获取到待测色块矩形的像素点长与宽,两者乘积即为矩形像素点面积\(S_{square}\)。此外还可以通过max_blob.pixels()
得到色块像素点面积\(S_{blob}\)(即图中蓝色区域面积)。
设二者比值\(\frac{S_{blob}}{S_{square}} =
k\),则可根据\(k\)值区分不同的形状,由上图可知正方形\(k = 1\),圆形\(k
= \frac{\pi }{4} \approx 0.785\),正三角形\(k = 0.5\)。
结合实际情况,当\(k \geqslant
0.9\)时,判断图形为正方形;当\(k
\leqslant 0.6\)时,判断图形为三角形;其余情况为圆形。
USART HMI串口屏

串口屏使用USART
HMI配套IDE进行图形界面的编辑与程序烧录。本次竞赛所用串口屏主界面如上图所示。按下“普通测量”或“追踪测量”键后,串口屏将向STM32单片机发送不同的串口信号。STM32接到信号后向OPENMV视觉模块发送串口信号,蜂鸣器鸣响提示,OPENMV根据不同的信号按照图5所示程序流程进行测量。
至于立体测量,竞赛时间有限没做出来。
激光测距模块
STM32单片机与激光测距模块的通信通过单片机的串口USART2实现,设置波特率为38400。
根据摩天MyAntenn-L1型号激光测距模块参考手册,结合实际情况使用快速测距模式。
在STM32主函数写下代码printf("iFACM");
便可启用快速测距模式。
注意这里需要对printf函数进行重定义,重定义代码位于usart.c文件下,具体如下:
(这里将原有例程中的USART1改成了USART2。这样才能用printf通过USART2发送字符串信号。)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
_sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
while((USART2->SR&0X40)==0);//循环发送,直到发送完毕
USART2->DR = (u8) ch;
return ch;
}
USART2串口中断函数如下所示,通常串口接收到的数据以0x0d,0x0c结尾。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18void USART2_IRQHandler(void) //串口2中断服务程序
{
u8 Res;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断
{
Res = USART_ReceiveData(USART2); //读取接收到的数据
if(Res!=0x0d&&Res!=0x0a)
{
USART_RX_BUF2[USART_RX_STA2] = Res ;//USART_RX_BUF2
USART_RX_STA2++;
}
else
{
USART_RX_STA2 = 0;
Distance_cal();
}
}
}1
2
3
4
5
6
7
8
9
10
11void Distance_cal(void)//数据处理
{
if(USART_RX_BUF2[0]=='D'&&USART_RX_BUF2[3]=='.')
{
dis=(USART_RX_BUF2[2]-48)*1000+(USART_RX_BUF2[4]-48)*100+(USART_RX_BUF2[5]-48)*10+(USART_RX_BUF2[6]-48);
}
else if(USART_RX_BUF2[0]=='D'&&USART_RX_BUF2[4]=='.')
{
dis=(USART_RX_BUF2[2]-48)*10000+(USART_RX_BUF2[3]-48)*1000+(USART_RX_BUF2[5]-48)*100+(USART_RX_BUF2[6]-48)*10;
}
}
二维云台
二维云台的两个舵机采用PWM控制,分别使用定时器TIM3的CH1与CH2通道。TIM1为20ms的定时器中断,根据外部状态(识别色块过程中的二维云台“移动”或“对准”状态)每隔20ms对舵机PWM值进行更新。
通过来自OPENMV摄像头的信息判断二维云台的工作状态。摄像头未识别到色块时,二维云台处于“移动”状态,舵机按照设定好的方式来回运动,搜寻目标色块;摄像头识别到色块后,二维云台处于“对准”状态,通过一个简单的闭环控制使激光测距模块对准色块中心,以便接下来的测量。
蜂鸣器/LED指示灯
使用TIM1定时器中断,根据外部状态(串口屏是否有按键按下,是否完成测量)每隔20ms对蜂鸣器与LED指示灯状态进行更新。
后续与总结
这次竞赛基本上发挥了自己本科阶段在单片机电子方面的全部实力,最后做出来的东西也实现了测距、判断物体形状与尺寸的基本功能。当然软件上还有一些bug,不过将将能用。
记得竞赛结束前大概两个小时,我一时手贱改了改程序还不备份,结果整个系统全不能用了,全都不好使了。当时心态彻底炸了,因为其实不改也行。还好使用Ctrl+Z大法把程序恢复到了修改前的状态,在竞赛结束前一小时一切恢复正常。这里特地感谢帮我稳住心态,提供安慰的队友。接下来仓促地写了写设计报告,随后封箱等待测评。
测评是在竞赛结束两周后,鬼知道这两周时间会发生什么,设备还好不好用。不过还好一切正常,最终拿了省二等奖(这次电赛我们学校成绩不咋好,二十五个队伍就拿了两个二等奖和三个三等奖)。
参加电赛的那个学期,基本上算是我大学阶段的高光时刻了,除了电赛还拿了其他几个比赛的奖,当然这里也有取舍,有一些比赛我就放弃了。随后就是下坡路了,考研一战寄了,二战将将考上本校,二战复试结束后暂时也没什么事,所以就搭建了这个博客。
既然已经到谷底了,就该触底反弹了,虽然接下来会遇到新的挑战,落入新的谷底,但是干就完了!任何时刻都不轻言放弃。