由于关于RFID的实验比较少,所以尝试对RFID进行学习与实验。大一下半学期学习了c语言程序设计,可以简单运用ARDUINO语言来编写程序。我们之前没有硬件知识储备,所以最好的方式就是利用已经现成的设备来扩展我们的项目。
一、项目组成员及分工
二、 项目成果简介
Arduino RFID的模块的射频读写芯片是飞利浦的 MF RC522。通过设计可以保存和写入十张学生的一卡通卡号,对已经保存起来的卡号运行通过,对不记录在案的卡号运行失败,蜂鸣器报警。
三、项目立项与研究的目的、意义
大一下半学期学习了c语言程序设计,可以简单运用ARDUINO语言来编写程序。我们之前没有硬件知识储备,所以最好的方式就是利用已经现成的设备来扩展我们的项目。扩展后把感应器嵌入和装备到教室、图书馆、餐厅、停车场、校门、实验室、会议室、校车、宿舍楼等物体并连接它们,形成所谓“物联网”,并通过超级计算机和云计算服务中心将“物联网”和“软件应用系统平台”整合起来,实现通信服务、教学工作、学习活动、管理工作和学校设施的整体结合。运用该系统,可以实现在全校范围内的内部消费、门禁点开门、刷考勤、身份认证等功能,代替校内的所有证件,给校园管理带来便利,大幅提升校园管理的效率。
四、项目研究的主要内容
(一)实验内容
1、从串口打印IC卡的类型和序列号。
2、实现显示IC卡的类型,并记录。
3、实现以十六进制显示IC卡的序列号,并记录。
4、测试最大的识别距离。
(二)实验材料
1.计算机一台;
2.Arduino UNO R3开发板一块;
3.USB-串口线一根;
4.RFID-RC522 模块一个;
5.标准S50空白卡一张;
6.S50异形卡一个(钥匙扣形状);
7.直排、弯排插针各一条;
8.杜邦线一排。
(二)材料准备:
Miafre 1 s50 感应式IC卡
◇ 芯 片: Philips Mifare 1 S50
◇ 存储容量: 8Kbit ,16个分区,每分区两组密码
◇ 工作频率: 13.56MHZ
◇ 通讯速度: 106Kboud
◇ 读写距离: 2.5—10CM
◇ 读写时间: 1-2MS
◇ 工作温度: -20℃-85℃
◇ 擦写次数: >100000次
◇ 数据保存: >10年
◇ 规 格: 0.87×85.5×54/ 非标卡
◇ 封装材料: PVC、PET、0.13铜钱
◇ 封装工艺: 超声波自动植线/自动碰焊
◇ 制作标准: ISO 14443, ISO 10536
◇ 应用范围: 企业/校园一卡通、公交储值卡、高速公路收费、停车场、小区管理等
(三)RC522模块各引脚功能
SDA – 串行数据线(IIC接口时的I/O线);在SPI接口中为NSS(从机标志管脚);
SCK – 连接MCU的SCK信号;
MOSI – MCU输出,RC522接收(即主设备输出,从设备输入);
MISO – RC522输出,MCU接收(即从设备输出,主设备输入);
IRQ – 中断请求输出;
GND – 接地;
RST – 复位;
3.3V – VSS,工作电压,若使用的事5V的MCU,注意分压。
管脚对应关系:
RFID模块 Arduino UNO
VCC 3.3V
RST 5V
GND GND
MISO 12
MOSI 11
SCK 13
NSS 10
IRQ (不接)
电路图
(一)开始实验
把MFRC522.h和MFRC522.cpp两个文件拷贝library文件夹下,这样程序在运行时才可以引用库文件。基于Dr.Leong、Miguel Balboa和Siren Thing Andersen的读写教程改编而成。
第一小组负责电路的搭建,第二小组负责对RFID的针脚进行焊接
第一小组同学负责寻卡过程
#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN); // 新建MFRC522端口
void setup() {
Serial.begin(9600); // 初始化和计算机的连续交流
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
//Serial.println("Scan a MIFARE Classic PICC to demonstrate Value Blocks.");
}
(二)第一小组同学负责防冲突过程
void loop() {
//读卡
// Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
MFRC522::MIFARE_Key key;
for (byte i = 0; i < 6; i++) {
key.keyByte[i] = 0xFF;
}
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
// Now a card is selected. The UID and SAK is in mfrc522.uid.
// Dump UID 打印卡号
Serial.print("Card UID:");
Serial.print("card id size:" );
Serial.println(mfrc522.uid.size);
for (byte i = 0; i < mfrc522.uid.size; i++) {
Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
Serial.print(mfrc522.uid.uidByte[i], HEX);
Serial.print("(");
Serial.print(mfrc522.uid.uidByte[i]);
Serial.print(")");
}
Serial.println();
// // Dump PICC type 打印近场应答设备的类型
// byte piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
// Serial.print("PICC type: ");
// Serial.println(mfrc522.PICC_GetTypeName(piccType));
// if ( piccType != MFRC522::PICC_TYPE_MIFARE_MINI
// && piccType != MFRC522::PICC_TYPE_MIFARE_1K
// && piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
// //Serial.println("This sample only works with MIFARE Classic cards.");
// return;
// }
// In this sample we use the second sector (ie block 4-7). the first sector is = 0
// choose to read the sector from 0 = first sector 段(sector)的编号是从0开始的
// 本程序准备用2号分区(段,2号段的序号为1)
byte sector = 1;
// block sector 0-3(sector0) 4-7(sector1) 8-11(sector2)
// blocchi di scrittura da 0-3(sector0) 4-7(sector1) 8-11(sector2)
// 2号段(分区)中包含数据快4-7(在本程序中分别叫block A、B、C和trailerblock),其中的尾块
// trailerBolck可能是用于记录验证分区密码的结果
byte valueBlockA = 4;
byte valueBlockB = 5;
byte valueBlockC = 6;
byte trailerBlock = 7;
byte status;
// Authenticate using key A.
// A boot authentication A
//Serial.println("Authenticating using key A...");
//防冲突
// 先验证Key A(密码组1)
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print("PCD_Authenticate() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
// Authenticate using key B.
// avvio l'autentificazione B
//Serial.println("Authenticating again using key B...");
// 先验证Key B(密码组2)
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, &key, &(mfrc522.uid));
if (status != MFRC522::STATUS_OK) {
Serial.print("PCD_Authenticate() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
// Writing new value block A
Serial.println("Writing new value block A(4) : the first block of the sector TWO ");
byte value1Block[] = { 1,2,3,4, 5,6,7,8, 9,10,255,12, 13,14,15,16, valueBlockA,~valueBlockA,valueBlockA,~valueBlockA };
status = mfrc522.MIFARE_Write(valueBlockA, value1Block, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print("MIFARE_Write() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
}
/*
// Writing new value block B
// Scrivo i valori per il Sector B
Serial.println("Writing new value block B");
byte value2Block[] = { 255,255,255,255, 0,0,0,0, 0,0,0,0, 255,255,255,255, valueBlockB,~valueBlockB,valueBlockB,~valueBlockB };
status = mfrc522.MIFARE_Write(valueBlockB, value2Block, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print("MIFARE_Write() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
}
// Writing new value block D
// Scrivo i valori per il Sector C
Serial.println("Writing new value block C");
byte value3Block[] = { 255,255,255,255, 0,0,0,0, 0,0,0,0, 255,255,255,255, valueBlockC,~valueBlockC,valueBlockC,~valueBlockC };
status = mfrc522.MIFARE_Write(valueBlockC, value3Block, 16);
if (status != MFRC522::STATUS_OK) {
Serial.print("MIFARE_Write() failed: ");
Serial.println(mfrc522.GetStatusCodeName(status));
}
*/
(三)第三小组同学负责读/写卡过程
Serial.println("Read block A(4) : the first of the sector TWO");
byte buffer[18];
byte size = sizeof(buffer);
// change this: valueBlockA , for read anather block
status = mfrc522.MIFARE_Read(valueBlockA, buffer, &size);
Serial.print("Sector : 0 Value :");
Serial.println(buffer[0]);
Serial.print("Sector : 1 Value :");
Serial.println(buffer[1]);
Serial.print("Sector : 2 Value :");
Serial.println(buffer[2]);
Serial.print("Sector : 3 Value :");
Serial.println(buffer[3]);
Serial.print("Sector : 4 Value :");
Serial.println(buffer[4]);
Serial.print("Sector : 5 Value :");
Serial.println(buffer[5]);
Serial.print("Sector : 6 Value :");
Serial.println(buffer[6]);
Serial.print("Sector : 7 Value :");
Serial.println(buffer[7]);
Serial.print("Sector : 8 Value :");
Serial.println(buffer[8]);
Serial.print("Sector : 9 Value :");
Serial.println(buffer[9]);
Serial.print("Sector :10 Value :");
Serial.println(buffer[10]);
Serial.print("Sector :11 Value :");
Serial.println(buffer[11]);
Serial.print("Sector :12 Value :");
Serial.println(buffer[12]);
Serial.print("Sector :13 Value :");
Serial.println(buffer[13]);
Serial.print("Sector :14 Value :");
Serial.println(buffer[14]);
Serial.print("Sector :15 Value :");
Serial.println(buffer[15]);
//byte value1Block[] = { 1,2,3,4, 5,6,7,8, 9,10,255,12, 13,14,15,16, valueBlockA,~valueBlockA,valueBlockA,~valueBlockA };
if (
buffer[0] == 1 &&
buffer[1] == 2 &&
buffer[2] == 3 &&
buffer[3] == 4 &&
buffer[4] == 5 &&
buffer[5] == 6 &&
buffer[6] == 7 &&
buffer[7] == 8 &&
buffer[8] == 9 &&
buffer[9] == 10 &&
buffer[10] == 255 &&
buffer[11] == 12 &&
buffer[12] == 13 &&
buffer[13] == 14 &&
buffer[14] == 15 &&
buffer[15] == 16
){
// sel a scrittura è uguale alla lettura allora e stato un successo !!
Serial.println("Read block A(4) : the first of the sector TWO : success");
Serial.println(":-)");
}else{
// scrittura Fallita
Serial.println("Read block A(4) : the first of the sector TWO : no match - write don't work fine ");
Serial.println(":-( ");
}
// risponde successo
//Serial.println(mfrc522.GetStatusCodeName(status));
// Dump the result
//mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
// Halt PICC
mfrc522.PICC_HaltA();
// Stop encryption on PCD
mfrc522.PCD_StopCrypto1();
}
近耦合IC卡——Mifare 1
________________________________________
目前市场上应用较多的是载波频率为 13.56MHz,工作距离在 2.5~10cm 的近耦合IC卡,其国际标准为ISO/IEC 14443。
Philips 是世界上最早研制 RFID 卡的公司,其 Mifare 技术已经被制定为 IS0/IEC 14443 TYPE A 国际标准。
Mifare 1 卡的特性
pass
Mifare 1 芯片逻辑结构
Mifare 1芯片内部结构较为复杂,可分为射频接口、数字处理单元、EEPROM三部分:
射频接口:在 RF 射频接口电路中,包括有波形转换模块。它可接收读写器上的 13.56MHZ 的无线电调制频率,一方面送调制/解调模块,另一方面进行波形转换,然后对其整流滤波,接着对电压进行稳压等进一步的处理,最终输出供给卡片上的电路工作。 防冲突模块:如果有多张Mifare 1卡片处在读写器的天线的工作范围之内时,防冲突模块的防冲突功能将被启动工作:根据卡片的序列号来选定一张卡片。被选中的卡片将直接与读写器进行数据交换,未被选择的卡片处于等待状态,准备与读写器进行通信。 认证模块:在选中一张卡片后,任何对卡片上存储区的操作都必须要经过认证过程,只有经过密码校验才可对数据块进行访问。Mifare 1 卡片上有 16 个扇区,每个扇区都可分别设置各自的密码,互不干涉。因此每个扇区可独立地应用于一个应用场合。整个卡片可以设计成“一卡通”形式来应用。 控制和算术运算单元:这一单元是整个卡片的控制中心,是卡片的“大脑”。它主要对整个卡片的各个单位进行微操作控制,协调卡片的各个步骤;同时还对各种收/发的数据进行算术运算处理、CRC 运算处理等等。 EEPROM 接口:连接到 EEPROM。 加密单元:Mifare 的 CRYPTO1 数据流加密算法将保证卡片与读写器通信时的数据安全。 EEPROM:1K 字节,分 16 个扇区。每扇区 4个块,每块 16 字节。
缓冲区的第一个扇区的第二块地址有误,导致无法识别存在的卡号,所以产生问题。目前已解决。
五、项目研究过程与方法(包含研究方法、研究过程、资料与数据来源等)
基于Dr.Leong、Miguel Balboa和Siren Thing Andersen的读写教程改编而成。
参考深圳职业技术学院电子与信息工程学院《IC卡公交收费机设计(三)——MIFARE 1卡读写软件设计》和腾博科技有限公司《第二十四章RFID读卡器实验》
参考唐海琳《基于MF RC500的RFID读写器的天线及匹配电路设计》。
参考谢振华, 赖声礼, 陈鹏的《RFID 技术和防冲撞算法》、
参考《智能卡技术(第四版)——IC卡、RFID标签与物联网(清华大学计算机系列教材)》(王爱英 主编)
,清华大学出版社
六、项目创新点(或特色)
(一)扩展实验
在已有的实验基础上,对已经读写出来的复旦卡的卡号进行反馈,于是继续扩充电路,在D2端口和D3端口分别连接发光二极管,防止电压会烧毁LED灯,在每个LED灯串联一个220Ω的电阻,D4端口上连接开源蜂鸣器。
电路图
(二)实验内容:
定义一个二维数组,可以保存十张学生的一卡通卡号,对已经保存起来的卡号运行通过,对不记录在案的卡号运行失败,蜂鸣器报警。
#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.
int ledpins[2] = {3,2};
byte ValidCardID[10][4];
int flag = 1; //1-on, 0-off
int pinSpeaker = 0;
void setup() {
Serial.begin(9600); // Initialize serial communications with the PC
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
//Serial.println("Scan a MIFARE Classic PICC to demonstrate Value Blocks.");
ValidCardID[0][0] = 197;
ValidCardID[0][1] = 119;
ValidCardID[0][2] = 93;
ValidCardID[0][3] = 45;
for(int i=0; i<2; i++){
pinMode(ledpins[i], OUTPUT);
}
clear();
digitalWrite(1, LOW);
}
void loop() {
// Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
MFRC522::MIFARE_Key key;
for (byte i = 0; i < 6; i++) {
key.keyByte[i] = 0xFF;
}
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
// Now a card is selected. The UID and SAK is in mfrc522.uid.
// Dump UID 打印卡号
//Serial.print("Card UID:");
//Serial.print("card id size:" );
//Serial.println(mfrc522.uid.size);
for (byte i = 0; i < mfrc522.uid.size; i++) {
//Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
//Serial.print(mfrc522.uid.uidByte[i], HEX);
//Serial.print("(");
Serial.println(i);
byte num1 = mfrc522.uid.uidByte[i];
byte num2 = ValidCardID[i];
Serial.print(num1);
Serial.print(":");
Serial.println(num2);
if(num1 != num2){
warning();
flag = 0;
return;
}
//Serial.print(mfrc522.uid.uidByte[i]);
//Serial.print(")");
}
if(flag==1){
pass();
}
Serial.println();
// Dump PICC type 打印近场应答设备的类型
byte piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
// Serial.print("PICC type: ");
// Serial.println(mfrc522.PICC_GetTypeName(piccType));
if ( piccType != MFRC522::PICC_TYPE_MIFARE_MINI
&& piccType != MFRC522::PICC_TYPE_MIFARE_1K
&& piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
//Serial.println("This sample only works with MIFARE Classic cards.");
return;
}
// 每次循环结束前恢复初始值
flag = 1;
}
void warning(){
digitalWrite(ledpins[1], HIGH);
digitalWrite(pinSpeaker, HIGH);
delay(1000);
digitalWrite(ledpins[1], LOW);
digitalWrite(pinSpeaker, LOW);
}
void pass(){
digitalWrite(ledpins[0],HIGH);
delay(1000);
digitalWrite(ledpins[0], LOW);
}
void clear(){
for(int i=0; i<2; i++){
digitalWrite(ledpins[i], LOW);
}
}
(三)实验结果:
1.登记过的卡片,成功识别,绿色LED等闪烁一秒后熄灭
2.未登记的卡片,认定为非法,红色LED灯闪烁一秒后熄灭,同时,蜂鸣器产生频率一定的声响。
七、项目研究存在的问题、建议
目前我们分析问题可能和以下方面有关:
- 实验中途执行至防冲突模块发生异常,返回卡号不正确
建议以后对复旦卡写入的研究时,使用出厂时识别线圈不存在质量问题的卡,在进行实验的时候,尽可能选择更为先进可靠的实验仪器及测量器具,缓冲区的第一个扇区的第二块地址有误,导致无法识别存在的卡号,所以产生问题。目前已解决。
八、项目完成预期目标情况
预期完成目标:
(一)根据材料和Arduino RFID套件了解 RFID 的基本概念和射频卡的工作原理;熟悉 Arduino 和 RC522RFID 模块的使用;测试 RC522 模块对卡的识别。
(二)结题时已完成目标:
RC522 模块对卡的写入数据,成功返回卡号。登记过的卡片,成功识别,绿色LED等闪烁一秒后熄灭。未登记的卡片,认定为非法,红色LED灯闪烁一秒后熄灭,同时,蜂鸣器产生频率一定的声响。
九、项目研究工作的自我评价分析与总结
(一)通过此次科研项目研究工作,我们体会了科研项目研究的真实过程,我们小组成员认真构思项目,将大量时间用于实验过程,包括射频模块的焊接全过程,以及材料分析数据等,养成认真思考,分析实验数据,计划下一步的良好习惯。当然研究工作中我们也有许多不足的地方,比如知识面不够广,软件处理数据技术不成熟等,但是在老师和学长的带领下都一一解决了。
(二)通过此次科研项目总结出项目研究工作过程中,在实践研究工作前应当寻找,思考有研究价值的方向,然后对相关文献进行大量的阅读,才能有一个良好的项目研究计划,在计划的过程中还应当考虑实验条件的影响,例如我们实验过程中很多地方就受到读卡距离的阻碍,从而使得实际结果与计划不能协调一致的情况。进行科研项目研究还应当学会多种数据收集,数据处理,以及对数据的分析,从而指导下一步实验。