我参加了电子设计竞赛...

 

成果

北京市二等奖
notion image
 

方案

我其实对电子电路这块是一窍不通的,也就擅长写写代码调调单片机。然而做电赛软硬兼顾才吃香,要不怎么要求三人组队参赛呢。
 
经过我们仨人深(一)思(拍)熟(脑)虑(门),就选 F 题了。题目要求,两个金属极板间放若干张纸张,每个极板上仅引出一根线连接到设备上,仅据此就得知道里面夹着多少张纸。(还不如做个电子秤,70g一张纸)
 
测电容!
 
两个极板对齐摆放就是一个电容器,里面夹着纸或者其他东西都会改变这个电容器的电容,而我们只需要做两件事情
  • 测出电容
  • 找出电容值与纸张数量的对应关系
 
感觉这道题最难地方在于
🤕
测量很容易实现,测量准确实属不易
 

测量值范围预估

(不是我算的我也不知道怎么算反正就是这个样子
题目要求金属极板的面积为 2.5 平方厘米,两个极板间压的足够紧(没有空气)的情况下一张纸的电容约为570 pF ,十张纸的电容约为 57 pF ,20 张纸的电容约为 23.5 pF ,30 张纸的电容约为11.75 pF。
 
所以,纸越越难区分,设计的最小测量精度为 1.17 pF。
 
 

测量电容

“两极板以及极板间的待测纸张构成了一个大电容,容值随着纸张数的不同发生变化。我们将这个大电容接入由 555 计数器构成的多谐振荡器电路中,通过大电容连续的充、放电过程,使得 555 计数器被不断复位、置位,从而输出一定谐振频率的方波,得以将测量纸张数目的问题在转变为测电容之后,再进一步转变为对频率的测量。“
notion image
 

单片机和电容测量电路的桥梁 FPGA

我们需要做一个高频计数器,由于我们选用的是 Arduino Mega2560 作为主控,不管使用什么方法频率计也就在 10K 左右。而 555 输出的是一个方波,周期即电容充放电的周期,通过测量周期长度,也就是测量高频晶振在周期内的震荡次数,以精确测量电容值。
 
我们利用了一块叫 小脚丫🦶 的FPGA板子,做了个16位计数器,通过16根线和 Arduino Mega2560 相连(谁让它IO口就是多呢),相互不设控制,FPGA每测量一整个周期的计数更新一次16根线的数值,相当于一个计数器+锁存器了。
 
此外,利用PLL IP核(锁相环) ,我们把 小脚丫🦶 片载的 16Mhz 晶振做了 12 倍频,高达 96Mhz,大大大大大大大大的提高了测量的精度。
 
如果用单片机实现,这一定是一个既消耗资源,又考验算法性能的工作,但如果换一个方式,就很简单,很简单。也就20行左右的 Verilog 代码。(前提是得接触过 FPGA,数字逻辑课、计组课设课没白上
notion image

单片机 Arduino Mega2560

为什么选这块板子呢
  • 不要重复造轮子 (库多随便调,懒癌晚期患者)
  • 丰富的IO接口(要不是为了连上 小脚丫🦶的16根线.....)
  • 简单易用,快速上手(说白了就是菜)
notion image
得益于以上优点,让一块OLED屏幕显示英文仅需要4根线和几行代码 😊

测量器

老师好厉害,真的。
印了块电路板,中间腐铜当金属板,我就问问,这谁想的出来!
notion image
  • 两块极板精准对接,提高测量精度
  • 一个大夹子直接夹上,提高测量精度
  • 看着美观精巧,实操测量人员心情愉悦,提高测量精度
 
在这里实名感谢🙏提供夹子的大兄弟,没有你(的夹子)我们不可能走到现在这一步!

动手

(这我就不是很擅长了,虽然我焊接啥的都会!,但就是良品率低,很低很低的那种
notion image
我当时怎么就不多拍一些照片呢,也不至于现在找不到图还得靠表情包凑数。之后是再补图吧 2333

编码

PlatformIO + CLion = ❤️

Arduino IDE虽然用着方便,但既不支持代码格式化,又没有智能补全,实属智障IDE。
CLion虽然聪慧过人,但仅支持识别 CMake 这一种构建方式。
brew install platformio # 安装platformio工具链 platformio lib install 135 # Adafruit SSD1306 屏幕驱动 platformio lib install 188 # Adafruit_GFX 图形库 platformio init --ide clion # 刷新一下对CMake的支持
PlatformIO 有自己的构建方式,生成的 CMakeLists.txt 只是用来打酱油的(让 CLion 可以智能提示和错误检查)
 

小屏幕

void setup_screen() { if (!disp.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32 Serial.println("SSD1306 allocation failed"); for (;;); // Don't proceed, loop forever } disp.setTextSize(1); // Normal 1:1 pixel scale disp.setTextColor(WHITE); // Draw white text disp.setCursor(0, 0); // Start at top-left corner disp.setRotation(2); //屏幕装反了软件来调整 disp.cp437(true); } void disp_menus() { disp.clearDisplay(); disp.setCursor(0, 0); disp.println("Adjust 15 | TEST"); disp.println("Adjust 5 | Adjust 25"); disp.println(" | (BACK)"); disp.display(); }
 

小脚丫 STEP FPGA MX02 V2

module Counter( input sig, input clk, output reg [15:0] out ); wire clk2; reg [15:0] cnt; reg [4:0] ct; initial begin out <= 16'b0000000000000000; cnt <= 16'b0000000000000000; // 脉冲计数器 ct <= 4'b0000; // 对555输出的方波进行分频,提高测量精度 end pll PLLX(.CLKI(clk),.CLKOP(clk2)); // 调用IP核的倍频器 always @(posedge clk2) begin if(sig == 1 && ct == 4'b1111) cnt = 0; // 测完一个测量周期就清空计数器 else cnt = cnt + 1; end always @(posedge sig) begin if(ct == 4'b1111) begin // 这里相当于一个锁存器,保持out始终为周期完整的测量结果 out = cnt; ct = 0; end else ct = ct+1; end endmodule
 

马上就要封箱了!

赛事DDL前,应该做些什么?
印象中是2019年8月10日晚上8点就要停止比赛,不管做得怎么样,都要把作品和设计报告装在一个箱子里,贴上封条,静待专家测试。
 
那8月10日的下午,就是一个很关键的时间段。
是应该多做一些,还是应该少做一些,以及要保持一个怎样的心态,才算良好。
 
当时我们已经能精准测量并识别1~30张纸了,使用的是查表法,预先将不同数量厚度的纸张的读数值记录下来,写在程序中,再次测量的据此得出纸张数量。考虑到周围环境以及不同品牌纸张对结果的影响,我们也做了分点校准程序(我们假设误差对于不同数量的纸张的影响是相同的)。
 
于是,我们是进一步提高1~30张纸的对应表的精度,还是测量并记录更大范围的对应表呢?
 
对于第一件事情,提高精度的方法无非多次测量取平均,完整测量一次大约需要1小时的时间。
对于第二件事情,亦是测量更多的数据。
 
这两件事情的决策,即在提高作品稳定性和提高作品分数上之间二选一。想了想,跟高中数学考试快交卷的时候,把这剩余的时间用来检查前面做过的题,还是再攻克攻克难题,很相似。
 
实际上,这两件事情哪个都没有做 23333
现在回过头来想想,似乎做什么对结果影响都不大。
 

现场测试

(不让用手机,照片肯定是莫得了
紧张什么的就不说了,都这样。其他组做的也挺有意思的,我看见前一个组,用按着两个金属板,读数后,人工查阅一张打印出来的对应表。
notion image
notion image