亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

自制网络化 RFID 读卡器:Arduino + ENC28J60 以太网 + MFRC522

组件与物料

Mifare MFRC522 RFID 模块 ×1
Arduino UNO(或任意 Arduino) ×1
ENC28J60 以太网模块 ×1
跳线(公对公/公对母) 若干
面包板 ×1
电脑(联网) ×1

必需工具

应用与在线服务

项目简介

想给家里或办公室加 RFID 门禁/考勤系统?商业方案动辄 $200-$2000,太贵!我和朋友决定用不到 $100 做一个功能更强的系统——联网 Arduino RFID 读卡器,加 $20 还能控制门锁。原本为高中学生考勤设计,希望学校采纳。

开始前的准备(必做)

需安装两个库:

  1. UIPEthernet:GitHub
  2. MFRC522:GitHub

放入 Program Files(x86)/Arduino/Libraries/ 并重启 Arduino IDE。

硬件连接

  1. Arduino Nano 插面包板
  2. 查阅开发板引脚图找到 SPI 引脚(下文可修改)
  3. Arduino 10 (SS) → 以太网模块 CS
  4. Arduino 12 (MISO) → RFID MISO 和 以太网 SO
  5. Arduino 11 (MOSI) → RFID MOSI 和 以太网 SI
  6. Arduino 13 (SCK) → RFID SCK 和 以太网 SCK
  7. Arduino 9 → RFID RST
  8. Arduino 8 → RFID SSN(因以太网占用 10)
  9. Arduino 5/4/3 → RGB LED 的绿/蓝/红(配 330Ω 电阻)
  10. AC-DC 电源模块(3.3V/5V >700mA)接面包板正负极
  11. Arduino GND 与电源 GND 共地
  12. RFID 和以太网的 VCC/GND 接电源输出(注意:两模块仅支持 3.3V!严禁 5V,必要时分压)
  13. LED VCC 接 Arduino 3.3V 或电源 3.3V
  14. 以太网模块接网线,确保与电脑同一局域网
  15. USB 连接 Arduino 与电脑

代码配置

代码注释详细,主要修改网络参数:

运行步骤

  1. 接通 AC-DC 电源
  2. Arduino 连电脑 USB
  3. 确保同一网络
  4. 烧录修改后的代码
  5. 启动 Python/C++ 等 TCP 服务端
  6. 复位 Arduino
  7. 蓝灯亮起后刷卡,服务端收到 ID 即成功

LED 状态含义:

若 Arduino 卡顿 >30 秒亮红灯,可能原因:供电不足、服务端未运行、网络不通、IP 填错。排查建议:关闭防火墙、放行端口 23、路由器端口映射、有线直连路由器、更换大功率电源。

注意:代码不含门锁控制,如需门禁功能需自行添加。

代码

Arduino 代码

/* 引脚定义见代码注释 */
#include <UIPEthernet.h>
#include <SPI.h>
#include <MFRC522.h>

#define RST_PIN 9
#define SS_PIN 8

byte sector = 0, blockAddr = 0, trailerBlock = 1;
int red = 3, blue = 4, green = 5;
EthernetClient client;
MFRC522 mfrc522(SS_PIN, RST_PIN);
MFRC522::MIFARE_Key key;
signed long timeout;

void setup() {
  pinMode(red, OUTPUT); pinMode(blue, OUTPUT); pinMode(green, OUTPUT);
  Reset(); Serial.begin(9600);
  SPI.begin();
  uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};
  IPAddress mip(192,168,1,160), mdns(8,8,8,8), mgate(192,168,1,5), msubnet(255,255,255,0);
  Ethernet.begin(mac, mip, mdns, mgate, msubnet);
  Serial.println("Succesful connection");
  for(int t=255;t>0;t--){ analogWrite(red,t); delay(10); }
  mfrc522.PCD_Init();
  for(byte i=0;i<6;i++) key.keyByte[i]=0xFF;
  Serial.println(F("Scan a Card")); dump_byte_array(key.keyByte, MFRC522::MF_KEY_SIZE);
  timeout=0; delay(2000); Reset();
}

void loop() {
  if(!mfrc522.PICC_IsNewCardPresent()){ digitalWrite(blue,LOW); return; }
  if(!mfrc522.PICC_ReadCardSerial()) return;
  digitalWrite(blue,HIGH);
  byte piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
  if(piccType!=MFRC522::PICC_TYPE_MIFARE_MINI && piccType!=MFRC522::PICC_TYPE_MIFARE_1K && piccType!=MFRC522::PICC_TYPE_MIFARE_4K){ Error(); return; }
  byte status, buffer[18], size=sizeof(buffer);
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  if(status!=MFRC522::STATUS_OK){ Error(); return; }
  status = mfrc522.MIFARE_Read(blockAddr, buffer, &size);
  if(status!=MFRC522::STATUS_OK){ Error(); }
  mfrc522.PICC_HaltA(); mfrc522.PCD_StopCrypto1();

  if(client.connect(IPAddress(192,168,1,100),23)){
    timeout=millis()+1000; Serial.println("Client connected");
    String ID = dump_byte_array(buffer,size); client.println(ID); Serial.println("sent:"+ID); delay(10);
    while(client.available()==0){ if(timeout-millis()<0) goto close; }
    int sz; while((sz=client.available())>0){
      uint8_t* msg=(uint8_t*)malloc(sz); sz=client.read(msg,sz); Serial.write(msg,sz);
      if(sz==sizeof("g")-1) Pass(); else Error(); free(msg);
    }
    close: client.stop();
  }else{ Serial.println("Couldn't connect to Server"); Error(); }
  Reset();
}

String dump_byte_array(byte *buffer, byte bufferSize){
  String out=""; for(byte i=0;i

Python 服务端示例

import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        self.data = self.request.recv(1024).strip()
        print "{} wrote:".format(self.client_address[0])
        print self.data
        # SQL 逻辑:若匹配发送 "g" 并记录,否则发送 "bb"
        self.request.sendall("g")

if __name__ == "__main__":
    HOST, PORT = "", 23
    server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
    server.serve_forever()

最新代码见 GitHub。

原理图

接线照片见附件。

制造工艺

  1. 贺卡产业:历史、生产与未来趋势
  2. 信用卡:历史、设计、制造与未来趋势
  3. Arduino RFID 门锁系统 – RC522 模块实现安全门禁
  4. 打造安全的 Arduino RFID 门锁——分步指南
  5. 基于 Arduino 与 Python 的可靠 RFID 考勤系统
  6. DIY 蓝牙控制 Arduino 间谍小车
  7. FlickMote:基于手势的智能家居红外遥控器
  8. DIY Arduino TV-B-Gone:万能关机遥控器
  9. 自制大尺寸LED主时钟带闹钟功能 — 12米外清晰可见
  10. Find Me:基于 Arduino 与蓝牙的智能寻物器制作指南
  11. Arduino 项目优化供电方案:从按键开关到电池监测与数据记录
  12. 基于 Arduino 的 Amiga 软盘读取器:低成本开源数据恢复方案