2019全国大学生电子设计大赛-F题纸张计数

今年的全国电赛题目比往年来看容易了许多(可能是换了赞助商的缘故),为了方便获奖,挑选了其中最最简单的F题进行参赛,最终效果还算不错,虽然只是获得了省二等奖,但也是达到了预期的目标,因为国赛的题目太难了,不想去丢省的脸面。废话不说了,下面讲讲如何解题。

前言

自从发了这篇博客之后,很多师弟师妹们通过私信向我请教了这道题目的一些问题。这让我十分振奋!我很高兴这篇博客能够帮助到大家!为了使大家能够更快地做出本题,在此博开头先给大家一些建议,以供帮助。

建议如下:
① 阅读题目要求。阅读题目要求能够让我们清晰题目想要达到的效果,以及最重要的,极板的制作要求。
② 通读全文。本博虽有不足的地方:没有提到极板的制作方法;制作完成后的使用方法…等等。但通过仔细反复地阅读和实践,是能够找到解决问题的方法和思路的。而本博的不足,倘若将来有充足的时间,将会重塑此博,补上弥留的不足,尽最大的努力帮大家解决问题。
③ 翻阅评论。本博有着丰富的评论,您可以通过翻阅评论查找所需要解答的问题。若没有您想要的答案,可以留下评论,我会抽空进行解答。

在此感谢您的浏览。

更新

2022.05.09 将源码放入开源仓库

题目

2019全国大学生电子竞赛题目-F题
题目中有一些很细节的规定,像双面板只能一面带铜,一块极板只能连接一根导线等等。功能上至少要包括:
① 短路报警
② 校准电路,获得纸张数量相关参数
③ 一键检测并报警,检测时长不大于5秒

方案选择与渊源

①FDC2214
在开赛的时候,国内的电赛讨论群里的大佬就给出了解题思路:用FDC2214(赞助方的)测出两极板电容值,然后换算成纸张厚度,跟18年的手势识别大同小异,代码小改即可解题。于是,我们的队伍兴高采烈地下载了手势的代码,在淘宝下了单。不得不说,一块200左右的板子硬生生被炒到了800块的价钱!好在我们下手得早,500块入的手。
等了一天,终于板子的快递到了。正当我捉摸着怎么修改代码的时候,队友告诉我板子的串口没有数据了,而且一上电32板子电源指示灯就灭了。我换给队友我的32板,接连试了3块都不行…我把2214接过来用万用表一测,VCC跟GND的焊盘居然是通的!再测走线居然也是!心里寻思,完了完了,这板子是凉了。赶紧联系商家,商家说只能修不能换,因为已经没货了!后来等到比赛结束,这板子还没有寄来…

②NE555
正在苦恼板子烧坏之际,灵机一动搜索测电容芯片,发现NE555能扛大任!一查原理图具备,代码简单,赶紧下单顺丰加急。

NE555原理及原理图

参考资料:
百度文库-555振荡电路测量电容的实验
百度提问-关于555电容测量电路分析
自制简易电容测量表电路
CSDN-关于电容和频率的关系

NE555测电容的原理图网上有很多的资料,而且555是一款很老的芯片了,价格也不会很贵。我们拿到555的芯片以后,就照着网上的原理图用面包板接了一块测试电路,原理图如下:
电容测试原理图
如图所示,仅需要两个电阻,一个电容,一个二极管(二极管可以不要),还有一个核心元件555就构成了电容测量电路。

可能你会有疑问,
① 电阻跟电容的参数应该如何选择?
这个问题一开始也困扰我。随着探索的深入,加上后面的实验,发现了一些规律。R1与R2越大,相同的电容值测出的频率会变小。而C1电容选取过大,可能导致无法测量,所以网上大部分原理图,将C1设为定值0.01uF。这里我没深究C1,想要了解的读者自行探索。

② 频率是怎么来的?
555定时器的3号引脚输出端输出的并不是直接测出的电容值,而是频率值。也正是因为如此,F题的解题思路从电容转到了频率上。我们并不需要真的去知道每张纸所带有的电容是多大,而只需要知道通过这张纸的谐振频率是多大即可。

③ 那么R1与R2多大比较合适?
没有实验谁都没有发言权。我们小组一开始给R1与R2的值是随意的,给了200与200,结果数码管输出的数据十分庞大;换上了2M的电阻,结果数据又十分小,无论纸张增加或是减少,都无法看到数据的细腻变化。那么电阻的大小选择,既要看到变化,又不能变化得过于敏感。最终选定两个200K作为参考值。还有一个地方是,R1与R2并不是一定要相等,可以不等。

解决了上面的疑问,虽然对555芯片还不是那么深的了解,但基本已经能够使用它了。两个极板任意一端接入555的2号引脚,另一端接地;555的3号引脚接入单片机的计数器引脚。

单片机

单片机这里也有一些话要说的。

首先举办方规定:

竞赛实物制作所使用的“单片机最小系统板”应仅含单片机芯片、键盘与显示装置、存储器、A/D、 D/A ,否则取消测试资格。

那么也就意味着蜂鸣器电路要外置于单片机最小系统。于是乎,我们的蜂鸣器是集成在555电路板上的。但是在前期的调试中,我们是拿普中科技的开发板(黄白外壳)作为单片机最小系统板来进行代码编写的。到了后期准备了两个方案,一是仿照普通科技的开发板电路图自制一块开发板,二是卸下规定以外且无需用到的板上外设。结果自制的板子后面不知道什么缘故没法测试,还是采取方案二拿去参赛了,现场评委虽然看出是用的开发板但也没有说是违规,让我们进行了测试。

还有一个问题是,为什么选用单片机?
其实一开始选用的是stm32F103的最小系统。但当时是为了配合FDC2214而选择的方案。我虽然学过stm32,但感觉拿来比赛还是有一些不稳,担心出一些无法调试的问题,其实还是32用得少的缘故。当然在这次比赛中也遇到很多51的问题,像代码过长内存不够放,51算力差造成的计算缓慢等等问题,折腾了不少时间,但最终还是克服了难题。希望看完本文的你,有能力还是要把核心计算机升级为32比较好。

言归正传
上面的555电路中实际上就只需要引出三条线插到开发板上,分别是VCC、GND、OUT这三条线。电源不说大家都懂,剩下OUT只需要接到P3^5的引脚上。

整个工作原理是:单片机开启定时器0定时200ms,同时开启定时器1的计数功能,P3^5引脚也就是定时器1的计数引脚,由于555是一直不间断地在工作(一上电就工作),形成的矩形信号就会一直稳定地通过它的3号引脚进行输出,并且被单片机的计数器捕获,当定时200ms时间到,关闭计数。单片机通过一定时期内的采样信号计算出这段信号的频率,最终将频率转成数码管的数字显示出来。

用户功能1:校准
说校准其实是有点好听了,其实是录入。每放上一张纸就将当前纸张数量对应的频率录入到单片机的存储器中。这样也就相当于制作了一个表格,该表格有不同张数的对应频率。

用户功能2:计算张数
在校准的前提下,放入纸张,按下按键,单片机查找当前频率对应下的纸张数量,通过数码管进行显示。

用户功能3:短路报警
当两块极板直接接触时,也就是频率为零的时刻,单片机会触发蜂鸣器进行警报。不用过于担心短路会损坏电路,因为555上的电流极小,经过测试,几分钟内的短路不会造成芯片的损坏。

可能你又有疑惑了:
①为什么定时器要定时200ms?
这其实并不会对结果造成多大的影响,主要还是51单片机过于落后的因素。设想把定时周期加大,那么计数的值将会变大,而且数据的更新速度会变慢,超出单片机的存储(24C02的存储能力)与计算(加权平均得出更准确的频率,下文细讲)能力。
②一共能录入几张纸的数据?
纸张的频率存储数量理论上取决于24C02的存储能力,这里采用的外部存储器就是24C02。它本身能够存储255个字节的数据,但由于频率的大小在int型数据的大小范围内,51单片机规定int为2个字节的数据,那么存储力应该为255/2≈127(除去短路频率0)。但是,随着纸张数量的增加,厚度不断增大,频率也在增大,当频率值超过65535时,纸张数量也就失去了意义。其次,纸张数量的增大,频率波动会变小,纸张数量之间的频率边界会变得模糊,如果单单仅由本文的电路组成,无其他放大或者滤波电路,温漂控制电路的话,即使存入数据,也会随着频率的波动而产生巨大的误差。而由于比赛时间的紧迫,目前测试纸张数量仅到40张左右,且误差能控制在1张以内。

在比赛时,仅有30分钟的校准时间。本来我预算是要有两次校准,一次测试一次做最终答案,就草率地决定仅录入34张纸张的频率。结果在经过测试之后,一直是零误差,队友决定直接测试而不再进行第二次校准。当然在前30张测试结果很理想。规则是评委给我们一叠一叠的纸,并且不可人工数纸张的数量,只能机测,结果的对错只有评委知晓。我们知道结果理想是因为评委一直对结果说正确,直到最后一组,30+的发挥,测不出数据…因为我们仅仅录入了34张的数据,而那一叠纸,估摸得到40张。因此错失国赛的机会…

③如何确保当前纸张该频率就是准确的?
这个问题其实有点难。因为电容的特性很多人都知道,面积、间距、介质都会造成对其参数造成影响。这反映到现实中是什么一种状况,下面举一点例子。
面积的影响:
如果两块板对得不齐,一会正一会斜,那这数据肯定是不准确的,这是毫无疑问的。那么固定板子就是一个问题,如何让其固定相对面积保持不变,又能塞入纸张,我在交流群里看到了如下的答案。
在这里插入图片描述
没错,这几种方案都是很值得借鉴的。还有一种类似于复印机的合板设计,也能确保100%对齐。基于此些方案的借鉴,我们最终选定穿柱的方法,仿机械固定。下图是我们的设计。
在这里插入图片描述

间距的影响:
你会发现有些小组在上层的极板上放置了一些重物,这就是为了确保间距的稳定。因为纸张是微弹性的物质,压扁与不压是有一定差距的,而这个差距会造成电容值的跳变,反馈到电路中就是频率的跳变。所以我们借鉴了别人的方案,在极板上固定了一把锤子。

在比赛现场有评委拿出手机对着我们的作品进行拍照,还点点头地跟我们说,真的是一把锤子,我们点点头说,是个锤子。

介质的影响:
这是最致命的。最轻最直接的影响是纸张的新旧程度。新纸比较平滑,外表面积小;旧纸比较粗糙,外表面积比新纸大。所以新纸与旧纸是两种不同的介质。比较中等间接的影响是周围环境的温度。我在交流群中看到,有的参赛队伍为了抑制温漂,还做了温度检测电路,可以看出人家的用心良苦、环境对测量结果的残酷影响。最严重的影响是极板,这个问题略微难以表达。极板经过打磨之后(表面积增大),能存储的电量会上升,且打磨过的、通电的状态下的极板会加速氧化,其实氧化是一件好事,因为氧化铜的面积更大,但是氧化是一个过程,好在比赛的时间间隔不长且有校准功能。不然制作好的极板与测试的极板肯定是有所不同。极板还有一种情况就是,被触摸过的极板也会造成偏差。因为被触摸的极板在通电的状态下会吸附手上的杂质,所以也会造成偏差,而且这个问题也是很容易被忽视的。

在进入测试之前,有一组队伍出来后说,校准的时候用的是新纸,测量的时候用的是旧纸。旧纸被前面的队伍压得很扁没有弹性,导致测出来的数据都漂了,误差不止一两张。这就是典型的介质跟间距造成的双重影响。如果没有极好的弥补方案,失败是在所难免的结果了。好在我们校准与测试的时候,用的都是新纸。应该是评委方意识到了这个问题。

那么说了这么多,怎么解决这个问题呢?其实如果是面积、温度、介质这种情况,上面已经给出了相对的解决方案,但在我们的设计中,并没有加入温度检测的电路,所以我们的设计也不是绝对完善的。但在间距的处理上,我用算法对它进行了优化,那就是——加权平均。

参考资料:
关于卡尔曼滤波和粒子滤波最直白的解释
如果你懂得卡尔曼滤波,应该采用更为高级的滤波算法。我这里采用加权平均,核心思想也是借鉴于卡尔曼滤波算法。因为卡尔曼滤波的权重可以是人为规定的,这里正是如此。
根据观察可以发现,下一秒的频率值永远比上一秒的频率值更准确(在仅考虑间距的状态下),因此可以分配给下一秒的频率权重值更大,而上一秒的权重更小。在算法中,我一共在一秒内采集5个数据(200ms定时采集一次),那么这5个数据一定有着不同的权重值。我人为设定为第一秒权重为0.1;第二秒权重为0.1;第三秒权重为0.2;第四秒权重为0.3;第五秒权重为0.3,权重总和为1。那么这个新数据肯定是这五个数据的加权平均值。将新数据作为最终当前纸张的频率值。
这种算法的好处在于,不会盲目地取五个数据总和求平均。而是根据该数据在当前的时间段来判断是否应该充分地信任它。反应到现实中的理解就是:下一秒被压的纸张状态肯定比上一秒被压的状态更真实,数据更可信,状态更牢固。

当然,在这种算法的加持下,频率数据理论上会趋于更加稳定。但实际测试状态中,温度还是在不断地对电容进行影响。所以在校准时,选定哪个点作为纸张的频率值,还是需要耐心等待,等到频率跳变不大时取用该点值比较好。

代码讲解

代码一共有270行,对于单片机来说还是有点多的。这里不会详细讲解每一句代码,仅挑选重要的部分进行解释。
① 加权平均计算频率值
声明一个频率数组与一个瞬间频率并作初始化。

typedef unsigned int u16;

u16  Freq = 0; //瞬间频率
u16  Freq_array[6]={0};//多次频率求均值

在主函数的无限循环中,检测是否定时结束,当定时结束,做出如下操作。
先取出计数器中的频率值,定时器分为高八位和低八位,高八位需要*256进行数据恢复。

	Freq = Freq + TL1;
	Freq = Freq + (TH1*256);

将得到瞬间频率传给Freq_array[4]。这里Freq_array[]数组的时间顺序依次往前,也就是Freq_array[0]存储的频率值时间最早,Freq_array[4]存储的频率值时间最新。每一次定时结束就把旧数据往前传,再传入新的数据,实现数据的不断更新。

	Freq_array[0] = Freq_array[1];
	Freq_array[1] = Freq_array[2];
	Freq_array[2] = Freq_array[3];
	Freq_array[3] = Freq_array[4];
	Freq_array[4] = Freq ;

最后将五个数据加权平均,得到频率的稳定值。当然需要经过一秒钟,数据才会开始稳定,理论上时间越久越稳定。

	Freq_array[5] = Freq_array[0]*0.1 + 
					Freq_array[1]*0.1 + 
					Freq_array[2]*0.2 + 
					Freq_array[3]*0.3 + 
					Freq_array[4]*0.3;

② 校准存储频率值
校准用到的按键是外部中断1,首先定义按键。声明一个纸张计数变量。

sbit KeySure=P3^3;  //定义按键K4
u16  NumOfTest = 0;//计数起始位

校准功能,是为了把纸张与频率联系在一起。所以每n张纸的频率都需要在机器上过一遍。这里声明的NumOfTest 初始值为0,表明存储的数据地址从0开始,每存储一张纸则增加2个地址位,因为上文说到频率为int型,存储的数据只有一个字节,所以存储一个频率值需要两个地址位。其实0张纸的频率可以跳过不用测量,直接将NumOfTest初始化为2。只不过我为了防止出错,在main函数中,用两个地址位存储了数据“0”,所以初始化时才设置为0。.

//外部中断1的中断函数
void Int1()	interrupt 2		
{
	delay(3000);	 //延时消抖
	if(KeySure==0)
	{
		At24c02Write(NumOfTest,Freq_array[5]/255);
		NumOfTest++;
		delay(2000);
		At24c02Write(NumOfTest,Freq_array[5]%255);
		NumOfTest++;
		delay(2000);
		
		//蜂鸣器报警、数码管显示
	}
}

At24c02Write(,);函数是24c02的封装函数,可以向24c02写入数据。写入的第一个参数是地址,如果是纸张数为1,那么高位数据地址为2,低位数据地址为3。写入的第二个参数是数据内容,高位数据/255取整存入,低位数据取余存入。每次存储数据需要时间间隔,否则会导致存储失败。

③ 读取频率值计算纸张数
声明一个变量用于存储读取到纸张数。
再定义纸张存储时地址空间的总大小。该大小不可以太大,最大为256,上文提到过。将其值除以2位存储的纸张张数。这里仅设置为40张,即80。该值越大,单片机计算得越久,得出结果所需要的时间也就越久。
定义外部中断0按键。

char Num = 0;//当前纸张数量
#define AllNUM   80
sbit KeyAddNum=P3^2;  //定义按键K3

写一个纸张计算函数,函数有点长,有点绕,慢慢看很容易看懂。

//张数计算函数
unsigned char CalPaperNum(u16 frequence)
{
	char i;
	
	int freq1,num11,num12;	//n-1 张纸时的频率
	int freq2,num21,num22;	//n 张纸时的频率
	int freq3,num31,num32;	//n+1 张纸时的频率
	unsigned char PaperNum;

	for(i=2; i<AllNUM-3 ;i+=2)	//AllNUM-3 是为了预留空间,当n=80时,n+1会超额
	{
		num11 = At24c02Read(i-2);
		delay(1000);
		num12 = At24c02Read(i-1);
		delay(1000);
		freq1 = num11*255 + num12;	//取出n-1张纸的频率
		
		num21 = At24c02Read(i);
		delay(1000);
		num22 = At24c02Read(i+1);
		delay(1000);
		freq2 = num21*255 + num22;	//取出n张纸的频率
		
		num31 = At24c02Read(i+2);
		delay(1000);
		num32 = At24c02Read(i+3);
		delay(1000);
		freq3 = num31*255 + num32;	//取出n+1张纸的频率
		
		//在频率表前后点范围内查询该频率对照的纸张数量
		if(
			(freq2 -(0.4) * (freq2 - freq1) <= frequence) 
			&& (frequence < freq2 + (0.6)*(freq3 - freq2))
		  ) 
		{
		 	PaperNum = i/2;
			return PaperNum;	
		}
	 	
	}
	return 0;
}

实现外部中断0的计算功能,并用数码管显示纸张数,同时蜂鸣器进行报警提示运算结束。

//外部中断0的中断函数
void Int0()	interrupt 0		
{
	delay(1000);	 //延时消抖
	if(KeyAddNum==0)
	{
		Num = CalPaperNum(Freq_array[5]);
		//数码管显示
		DisplayData[7]=smgduan[Num/10];
		DisplayData[6]=smgduan[Num%10];

		//蜂鸣器报警
	}
}

这里比较难懂的是
① AllNUM-3
这是为了防止n+1的地址超出规定而取不到数据会造成报错。
② 怎么理解这段代码
(freq2 -(0.4) * (freq2 - freq1) <= frequence)
&& (frequence < freq2 + (0.6)*(freq3 - freq2))
这段代码不是凭空捏造的,是经过试验得出来的。

首先需要进行简单的模型分析,如下图。
在这里插入图片描述
从图我们可以看到,采样得到的频率值只是一个个孤立的点。这里仅列举三个相邻的频率值作为参考。而n张纸对应的频率却是在一定的频率范围之内。且彼此的范围不能有重叠的部分,也不能有遗漏的部分。也就是说,如果测出来的频率值落在某个区间内,即以该范围内的频率值对应的纸张数作为测量的纸张数。如下图。
在这里插入图片描述
那么这个边界如何取得呢?或者说,我们应该判定这个边界到底有多大?起初我拟定边界为,后者减去前者的一半作为边界。
即freq2的边界为 [ (freq2-freq1)/2 , (freq3-freq2)/2 ]。
结果发现纸张数一致地偏大1张。那么也就是说整个区间应该向左进行移动。于是不再采用五五分的形式,而是采用四六分的形式划分区间。也就得到了上面的那条判断语句。具体的计算就交给读者你自己来操作了,这里不作详细解释了。

原理图

这是改进后的原理图1.0版本
在这里插入图片描述

下载

经过上面的讲解,难点部分也就讲得七七八八了。如果想知道更多的细节,那么可以下载源码进行学习,下面是源码的下载链接。

纸张计数开源仓库 包含如下内容:
① 纸张计数51单片机代码
② 原理图和极板PCB的立创EDA文件

总结

在这一次的比赛中,我觉得收获最多的是坚持。很多事情都不是说做一次,走别人走的路就能够顺利成功的,而是要不断的尝试,俗话说:实践出真知。尤其是在团队中,不要被一时的失败蒙蔽,尽可能地去尝试,才会得到收获。而坚持能提供源源不断的动力。

其次是不要大意。一个不小心的决策,让我们错失了国赛的机会。虽然知道自己做的东西实力就在那里,但它确实没有发挥最好的水准,而这个失误是决策造成的。

希望看完这篇文章的你,也能够有所收获。

  • 261
    点赞
  • 926
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 225
    评论
2015年全国大学生电子设计竞赛C是一个需要实践和创新能力的挑战性目,要求参赛者设计一种能够以最小尺寸和成本实现数字化仪表及物理量测量的方案。这个目的答案可能因参赛者的不同设计思路而有所不同。以下是一种可能的答案。 在这个设计中,我们采用了一种微型化的数字脉冲计数器方案。我们使用了一个特殊的传感器来获取待测物理量,例如温度、压力或光强。传感器将物理量转化为模拟电信号,然后通过一个模拟信号处理电路进行前置处理。 模拟信号处理电路中,我们使用了运算放大器和滤波电路来放大和滤除不需要的频率成分。这样可以保证信号的准确度和稳定性。经过模拟信号处理后,我们将信号输入到一个数字脉冲计数器中。 数字脉冲计数器是由一个单片机和一组计数电路组成的。当模拟信号通过计数器时,单片机将每一个触发的脉冲计数下来。通过事先设定的频率和采样时间,单片机可以计算出所需测量物理量的数值。 为了实现最小尺寸和成本效益,我们采用了一种高集成度的单片机和表面贴装技术。这种设计方案不仅仅能够满足测量要求,而且还能够在成本和尺寸上进行优化。 此外,我们还可以添加一些附加功能来提高设计方案的灵活性和实用性。例如,我们可以增加数据存储功能,将测量结果存储在内存或者存储介质中。这样可以方便用户随时查看历史测量数据。 综上所述,这是一种能够以最小尺寸和成本实现数字化仪表及物理量测量的方案。当然,不同的设计思路可能会导致不同的答案,但这个答案应该在设计思路、原理和关键技术上是合理的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 225
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金三亲

用现在的金钱换取未来的金钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值