Introduction(介绍)
这篇文章是应ST NFC开发大赛的邀约而写。
目前NFC已经被广泛应用,最常用的场景是门禁和支付,像我每天上班都至少需要使用NFC 3次,一次用来刷开小区的大门,一次用来刷开公司的电梯,还需要有一次刷开公司的门禁。我在频繁使用这些卡的时候,不禁有了一个想法。我可以把很多卡都放在都一个终端设备里面,并且通过采集一些和卡对应的周围影像来自动识别找到相应的卡,从而获取正确的鉴权。周围影像可以是刷卡器的样子,或者是周围的环境场景等等。NFC也有加密认证的功能,然而这往往需要提供加密认证的厂商去和各种读卡装置进行标识和适配,非常麻烦,现在也很难得到广泛的推广,例如中移动的带鉴权功能的SIM卡等。
在我这次Demo里面,我想展示如何使用神经网络识别图像,并且通过识别找到图像对应的NFC ID,发送到开发板上和NFC读卡装置获取的NFC ID进行比对,并在LCD上显示鉴权的结果。这可能和我们上节所说的具体用途有点出入,但由于时间紧迫,我尽可能在一个月的开发周期内的把实现的机理展示清楚,并且后继如果开发时间允许,只需要很简单的把NFC读卡装置的功能转换为Card Emulation功能就可以实现上述的所有功能。

这是整个开发项目的第一节,我们需要来介绍一下项目的架构和开发板的具体准备过程。

Technical Background (技术背景)
整个系统将被分为两部分,影像识别和NFC识别。这两个部分将通过USB CDC(ACM) 来通讯。如下图所示:
arch1.png
这个架构非常简单;基于此我安排在Image Recognition端的是Linux的工作环境,运行在我的i7的thinkpad上,NFC Card Reader则是用了ST25R3916的开发板,我们会在上面跑一个RTOS,并且基于此来开发更多的功能。
下面我们需要把软件开发的工作进一步细化如下:
Image Recognition:
1. 我会基于CNN(Convolutional Neural networks)来training我们的影像集。
2. 我会选取YaleDataset来作为样本影像集,当然后面你可以修改成你自己的。
3. 我会需要做一个基本的UI来展示training和识别的过程。
4. 我需要有个模块和开发板进行通讯。
NFC Card Reader:
1. 我需要有个UI能使能我的识别模块。
2. 我需要有个RTOS能方便的扩展我的功能。
3. 我需要有个USB模块来和PC进行通讯。
基本上就是这么多了,看上去一个月的闲暇时间刚刚好用来做这么一个小工程。

NFC Card Reader Software Setup(开发板的开发工作)
board.jpg
细心的同学可能发现上面有一些可疑的絮状物,那是我的猫经常在我写代码的时候趴在我的板子上留下的,也许它把上面的排针当作是按摩。
开发板的资料都可以从ST的官网上面下载到,包含UserManual文档和Code Base。这给我后继的开发工作带来了很大的便利。我打算就基于官网的代码来做一些后继开发。
1. 我需要有个RTOS来方便扩展我的功能
ST的example代码是一个单程工作方式,所有的工作都在main里面完成,当然还有其他的一些中断。我很不喜欢这样的工作方式,因为:
1.1 单程工作方式非常的浪费资源和能量,这一点是显而易见的,如果没有事情做,CPU都是在空跑。作为Demo也许并不很关心这个,但是在真正开发产品的时候,这是一个必须要考虑的点。
1.2 模块的扩展性很差,RTOS经常为提供一些进程间通讯和信号量的机制,这可以大大的减少你的开发工作。单程工作方式,你往往要为如何同步和通讯大费脑筋。
RTOS选择的空间很多,我最后选择了FreeRTOS,这个也是我最喜欢用的,它不光提供了OS相关所有的功能,还提供了一个内存管理器,这也许能方便我处理比较大的图片,毕竟单片机的内存还是太小了。
集成这个RTOS,你需要:
*修改中断向量
*配置堆和栈的空间
*分配task
*修改中断通讯方式(Touch driver从Polling方式改成Interrupt Signal方式)
以下是修改好的代码树,这些代码都会在github上公开。基本的软件架构是,一个task main会在loop里面等待信号量,其他的模块在中断中发signal给这个main task,从而触发它做一些工作。
code.png
2. 我需要有个USB模块来进行通讯
因为我的thinkpad上跑的是Linux,虽然example代码里面带了一个HID的驱动,但是在Linux上操作使用并不特别方便。为了更快的开发,我选择了USB CDC ACM来作为通讯的媒介。这个驱动在ST的官网上也能拿到参考的driver。在Linux上,这就是一个串口,操作起来相当方便,特别是在python这种特别上层的工具里面。
开发这个USB CDC ACM,你需要:
* 准备ACM的emulation Profile,我们这边直接用了ST的PID,UID和相关的string说明,这样你在电脑上看到的是一个STM32 USB Modem bla bla这样的字串。
* 配置和响应USB OTG的中断
相关的代码树的修改和工作起来后USB的通讯节点都展示在下面图片中:
code2.png usb.png

3. 我需要有个UI来调用我的模块
我打算直接使用ST的example代码来安放我的模块,我打算就放在Card ReadWrite这个模块中。具体工作的时候,在点开这个模块的时候,我会自动启动USB CDC的使能,而在退出这个模块的时候,我需要关闭USB CDC的使能。在这个模块里面,我会和PC通讯来和影像识别一起鉴权。
为了让我自己的模块更加突出,我修改了ST example代码的图标,当我点击左上角的图标时候,就会启动我的模块。
board2.jpg

具体的代码分享在:https://github.com/imwangwang/st25r-nfc

下一章里面,我会介绍如何在thinkpad Linux Python下面开发一个基于CNN的人脸识别系统。

下一章:
NFC双重认证的安全门禁系统, PART2
NFC双重认证的安全门禁系统, PART3