题目链接:基于互联网的摄像测量系统(D 题)-- 2021 年全国大学生电子设计竞赛_行走的皮卡丘-CSDN博客
在这次电赛取得了安慰奖(省三等奖),但是在测试的时候,单摆长度和角度值精度都完美达标,同时思路也受到了评委老师的肯定。所以今天打算把测量思路分享出来。
我们组选择的方案是:stm32f1战舰板(正点原子)+LCD+OV7725(因为三个设备需要和交换机相连接,战舰的板载资源恰好有对应的接口)。当时在网络上,交流群里流传了这题的做法,使用树莓派等设备是主流方案。但是碍于水平的有限,只掌握了stm32、51、模电数电的基本知识,只能硬着头皮选择stm32来做。于是任务就分成了两部分:三个单片机之间的通信和单摆(把题目的模型简化,其实就是个单摆)长度的测量,角度的话有了两个节点的长度然后tan就可求到。这篇文章主要解释长度的测量(电赛没有做出好成绩就是因为三个单片机之间的通信出了问题,当时老师认为通信能完成就能冲击国奖)。
首先阅读完题目,联想到我们学习过的知识,可以判断该题目其实就是单摆。经过资料的查询得到了很关键的两个信息:1.单摆的长度只与单摆运动周期有关。2.在比赛条件下(室内)空气阻尼等因素对单摆周期影响不太大。所以测量单摆长度就转变成为了测量运动周期,然后就想到了只要知道单摆出现在同一点的时间便得到了周期,理论可行,就开始写代码。
//首先是两个for组成的循环,目的就是为了处理LCD上的图像,一个像素点一个像素点的处理。。
//把LCD上显示的图像(320*270)左上角为原点建立二维坐标系
for(i=0;iIDR&0XFF; //读数据
OV7725_RCK_H;
color<<=8;
OV7725_RCK_L;
color|=GPIOC->IDR&0XFF; //读数据
OV7725_RCK_H;
gm_red = color>>11;//图像是RGB565格式,这样就得到了R红区的值
//这里用了二值化的处理,原因是没有掌握彩色图像的处理方式,缺点也很明显,就是需要很好的场地环境
//二值化处理后,激光笔(当时我们贴了纯黑色胶带)就是图像中的黑色部分,表现出来的就是一块黑色形状是矩形.
if(gm_red<=set_value) //set_value是设定值,也就是二值化的界限,当时在我们组自
//己的实验环境下理想值是7
{
color=0x0000;//黑色
}
else
{
color=0xffff;//白色
}
if(color==0x0000)//如果像素点是黑色
//这个if内部的代码,实际就是框住黑色区域,这个是题目基本要求之一
//(x1,y1),(x2,y2):矩形的对角坐标
//利用正点LCD的LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2)就可以在LCD上画出矩形,所以只要找到黑色区域的中点坐标(x,y)然后利用简单的加减法就可以在LCD上框出黑色矩形区域,也就是我们的激光笔,有了思路,开始写代码。
{
if(j<270)
{
biaozhi_x+=j;//将黑色像素点的X坐标累加
biaozhi++;
if(biaozhi>20)//如果这行出现了20个黑色像素点,则可以记录y值,这也是抗干扰的
//的一种方法,可以消除频幕上黑色噪点的影响
{
biaozhi_y+=i;//把y值记录下来
num++; //记录了多少次y值
biaozhi=0; //将标志位清0
}
}
}
else//如果是白色则不处理
{
biaozhi=0;
}
LCD->LCD_RAM=color; //将图像还原到LCD
}
}
//自闭之路
POINT_COLOR=RED;//画笔用红色,红色醒目,我想得到一个红色的框
//下面的两行代码就是为了得到比较精准的黑色区域中点坐标(x,y),也是经过实验效果改进的
biaozhi_x=biaozhi_x/(20*(num+6));
biaozhi_y=biaozhi_y/num;
有了上面代码求出来黑色矩形区域(激光笔)中点坐标(biaozhi_x,biaozhi_y)就可以开始完成:1.视频上框选激光笔 2.测量出单摆的长度。
if(biaozhi_x<10||biaozhi_y<10)//为了让框出现的自然,在x<10,y<10这块区域不显示红框
{
//也就是不处理,其实可以用一个if的,但是当时准备在这块区域显示length
}
else
{
int t=1;//t就是1
k[0]=biaozhi_y;//这里在前面设定了一个数组:int k[2]={0},到了下面就知道它有什么用了
//下面的函数也就是我们提到的画框函数,根据重点坐标画一个长100,宽20的矩形,这个也是调
//试出来可以框住黑色部分(激光笔)的大小
LCD_DrawRectangle(biaozhi_x-50,biaozhi_y-10,biaozhi_x+50,biaozhi_y+10);
//下面的代码我认为是核心部分,因为对我们组这样三个基本跟着例程走的人是挑战,真正的挑战
if(((k[1]-k[0])>t)&&n!=2&&n!=3)//在每一次处理LCD图像前,我们令k[1]=k[0],其实得到
//的就是上一次biaozhi_y的值,将他们做差和t比较大小
//再根据多重if判断就可以得到周期!也就是把捕捉俩次
//到一个点的问题简化出来了
{
n=1;
}
if(n==1&&((k[1]-k[0])<(-1*t)))
{
n=2;
shu=tim_a=0;//将tim_a清0,tim_a 在下面做出解释,其实就是得到时间
}
if(n==2&&((k[1]-k[0])>t))
{
y_min=biaozhi_y;
x_min=biaozhi_x;
n=3;
}
if(n==3&&((k[1]-k[0])<(-1*t)))
{
n=4;
shu=tim_a;
y_max=biaozhi_y;
x_max=biaozhi_x;
}
T=shu*0.01; //处理一下,这里的T和L都是doule型
L=T*T*9.8/(4*3.1415926*3.1415926); //放大了10*4,就是单摆公式
L_chen=(u32) L;//ceil(L);
if(y_max>y_min)
{chazhi_y=y_max-y_min;}
else
{chazhi_y=y_min-y_max;}
//发送到终端与A的差值做比较,取差值大的数所对应的L为长度
LCD_ShowxNum(120,120,(u32)chazhi_y,3,16,0); //相当于求夹角中的x值。
这里贴一点补充:
void Timer1CountInitial(void)
{
//定时=36000/72000x2=0.001s=1ms;这个计算方法很好用,真的很好,算是为数不多的技巧吧。
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 10-1;//自动重装值(此时改为10ms)
TIM_TimeBaseStructure.TIM_Prescaler = 720-1;//时钟预分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频1
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);
TIM_ClearFlag(TIM1,TIM_FLAG_Update);
TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);
TIM_Cmd(TIM1, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
}
void TIM1_UP_IRQHandler(void)
{
//TIM_TimeBaseStructure.TIM_Period = 100-1;//自动重装值(此时进中断的周期为100ms)
if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
{
tim_a++;
}
TIM_ClearITPendingBit(TIM1,TIM_IT_Update);
}
这个是单摆公式:。
分享就止步于此,最后的测试效果,长度和角度的精确度很高,我记得当时老师说我们可能是湖北省精度最高的,老师要求摆长为100cm,底部角度35°,我们节点1测出99.997,节点二100.870,角度的出来是34.几,当时测量了几组,我只有这组(因为是第一组)记得非常清楚,当时老师就很吃惊,然后也表示了他的惋惜。很遗憾的是我在家里没有条件进行实验,开学过后,可能会将实验结果带给大家。