一卡通系统试验

由于关于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);
  }
}

(三)实验结果:
pass
1.登记过的卡片,成功识别,绿色LED等闪烁一秒后熄灭
stop
2.未登记的卡片,认定为非法,红色LED灯闪烁一秒后熄灭,同时,蜂鸣器产生频率一定的声响。

七、项目研究存在的问题、建议

目前我们分析问题可能和以下方面有关:

  • 实验中途执行至防冲突模块发生异常,返回卡号不正确

建议以后对复旦卡写入的研究时,使用出厂时识别线圈不存在质量问题的卡,在进行实验的时候,尽可能选择更为先进可靠的实验仪器及测量器具,缓冲区的第一个扇区的第二块地址有误,导致无法识别存在的卡号,所以产生问题。目前已解决。

八、项目完成预期目标情况

预期完成目标:

(一)根据材料和Arduino RFID套件了解 RFID 的基本概念和射频卡的工作原理;熟悉 Arduino 和 RC522RFID 模块的使用;测试 RC522 模块对卡的识别。

(二)结题时已完成目标:
RC522 模块对卡的写入数据,成功返回卡号。登记过的卡片,成功识别,绿色LED等闪烁一秒后熄灭。未登记的卡片,认定为非法,红色LED灯闪烁一秒后熄灭,同时,蜂鸣器产生频率一定的声响。

九、项目研究工作的自我评价分析与总结

(一)通过此次科研项目研究工作,我们体会了科研项目研究的真实过程,我们小组成员认真构思项目,将大量时间用于实验过程,包括射频模块的焊接全过程,以及材料分析数据等,养成认真思考,分析实验数据,计划下一步的良好习惯。当然研究工作中我们也有许多不足的地方,比如知识面不够广,软件处理数据技术不成熟等,但是在老师和学长的带领下都一一解决了。

(二)通过此次科研项目总结出项目研究工作过程中,在实践研究工作前应当寻找,思考有研究价值的方向,然后对相关文献进行大量的阅读,才能有一个良好的项目研究计划,在计划的过程中还应当考虑实验条件的影响,例如我们实验过程中很多地方就受到读卡距离的阻碍,从而使得实际结果与计划不能协调一致的情况。进行科研项目研究还应当学会多种数据收集,数据处理,以及对数据的分析,从而指导下一步实验。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

极客范儿

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值