方案解析:纸张计数装置-测多少张不重要,关键是准确!(源码开源)
我们是来自中国民航大学的参赛队员(胡冀威王启鑫 莫浩杰),在2019全国电赛F题中取得国一的成绩,在此分享我们的作品,感谢达尔闻邀约。
作品的源码可以在“达尔闻说”公众号,回复:F题代码,即可获得。
我们的作品应用FDC2214电容传感器芯片测量电容值所用的LC谐振原理,采用矩阵压缩拟合算法和中值平均滤波算法,设计并制作一套应用电容传感器FDC2214计量纸张的系统。系统主要由STM32F407处理器及其最小系统、FDC2214电容传感器芯片及其外围电路、二线制平行电容极板及其固定结构构成。
赛前准备:我们组一开始准备时就准备的控制类,也做了往年的一些真题,比如风力摆、板球控制系统等等,也准备了单片机控制板,电机驱动板等常用的模块。8月1日清单公布后至7日赛题公布之前,我们组参照网上的一些赛题预测与自己的想法来准备了一些器件,按照控制类的惯例买了云台、小车…,怎么说呢?

仔细读题后感觉这题和2018年的手势识别题很像,只不过要求变高了,要求极板大小50mm,线长500mm。找了块FDC2214的板子接上极板后放几张纸测试了下,数据变化还挺大的,方案基本可行,便确定了题目。

FDC2214传感器板:

极板:极板粘贴在上层的亚克力板和下层的纤维板上,为了保证极板的突出不会让纸张产生形变,周围贴了一圈垫片用来把纸张垫起来。垫片就是将极板上的铜层腐蚀掉后做成的。极板通过屏蔽线连接FDC2214的IN0A、IN0B。

软件代码(开源)
FDC2214传感器配置:根据数据手册上的说明得知,当传感器配置为差分模式时,具有更高的灵敏度,因此在程序上将传感器配置为差分模式。为了能测量更多的纸张数量,将传感器配置为全电流模式,增强驱动力。
- /*!
- * @brief FDC2214初始化函数
- * @return 1:成功;0:失败
- * @since v1.0 * Sample usage: FDC2214_Init();
- */ uint8_t FDC2214_Init(void)
- {
- uint16_t deviceID = 0;
- deviceID = FDC2214_Read16(FDC2214_Addr, FDC2214_DEVICE_ID); //读器件ID
- if (deviceID == FDC2214_ID) { FDC2214_Reset();
- FDC2214_SetRcount(FDC2214_Channel_0, 600); //600 cycles 转换周期 FDC2214_SetSettleCount(FDC2214_Channel_0, 200); //200 cycles 等待时间 FDC2214_SetChannelClock(FDC2214_Channel_0, 2, 1); //设置时钟分频,1分频,40MHz FDC2214_SetActiveChannel(FDC2214_Channel_0); //开启通道0
- FDC2214_SetCurrentMode(0); //全电流激活模式
- FDC2214_SetClockSource(1); //外部时钟源
- FDC2214_SetHighCurrentMode(1); //高电流传感器驱动
- FDC2214_SetMUX_CONFIG(0, FDC2214_Channel_Sequence_0_1, FDC2214_Bandwidth_10M); //关闭自动扫描,10MHz带宽
- FDC2214_SetSleepMode(0); //退出睡眠状态,开始工作
- return 1;
- }
- return 0;
- }
纸张数的计算:DealData_BaseData是一个数组,记录了不同纸张数的FDC2214读数,比如DealData_BaseData[0]记录的是1张纸的FDC2214读数、DealData_BaseData[1]记录的是22张纸的FDC2214读数,以此类推。通过计算当前读数与基准值的误差,然后进行排序,最小的即为最接近的纸张数。
- static int cmpfunc(const void *a, const void *b) { return ((dealData *)a)->error - ((dealData *)b)->error; } //计算纸张数uint16_t DealData_Calculate(void) { uint32_t dataTemp = 0; dataTemp = FDC2214_Data;//缓存FDC2214数据 DealData_Init(0); for (uint16_t i = 0; i < PAPER_COUNT; i++) { DealData_ErrorData[i].error = fabs((double)((int32_t)dataTemp - (int32_t)DealData_BaseData[i])); //记录当前值与存储基准值的误差 } qsort(DealData_ErrorData, PAPER_COUNT, sizeof(dealData), cmpfunc); //将误差从小到大快速排序 return DealData_ErrorData[0].index;//返回最小值,及最接近的值 }
自校准程序:因为采用对数函数进行拟合y=A*ln(x)+B,需要计算出2个参数A、B,采用矩阵来计算这两个参数,这样的优点是可以输入多个已知数来进行计算,提高准确度。矩阵运算库采用的是CMSIS-DSP库。计算后得出A、B两个参数,将这两个参数带入y=A*ln(x)+B中,计算出当纸张数为X时的理论FDC2214读数,然后将这个数填入DealData_BaseData作为基准值。
自校准程序以及作品的全部程序,可以在“达尔闻说”公众号,回复:F题代码,即可获得。
-
单片机就不用多说了,TI的、ST的都行,找一款自己用得最熟的。把常用的程序模块化,比如ADC、PWM、定时器、OLED显示等等。用的时候直接复制过来用,可以节约很多时间。 -
程序上尽量有一个可以调参数的菜单,这样可以脱机调参数,而不必每次都连电脑改参数了。菜单推荐GitHub上一个开源的OLED菜单SOLGUI,用起来也比较方便。https://github.com/MaxwellXyao/SOLGUI_V2 -
常用的模块还是要多备点,能自己做的尽量自己做,避免出现2018年TI杯省赛那样要求在板子上打上序列号。