地鐵刷卡、上下班門禁打卡、高鐵進(jìn)站刷身份證、Apple Pay 購(gòu)物……這些日常使用場(chǎng)景,都使用了 NFC 非接觸式識(shí)別和互聯(lián)技術(shù),極大地方便了人們的生活。
不過(guò),目前市面上常見(jiàn)的NFC無(wú)線讀卡器都使用 WIFI或藍(lán)牙進(jìn)行數(shù)據(jù)傳輸,功耗較高、且傳輸距離有限。而如果采用 LoRaWAN?傳輸,則可以解決上述問(wèn)題。事實(shí)上,基于 LoRaWAN?的 NFC 讀卡器優(yōu)點(diǎn)突出:
1、LoRaWAN?的傳輸距離遠(yuǎn)、接收靈敏度高、且功耗低
2、采用LoRaWAN?無(wú)線傳輸?shù)淖x卡器安裝部署方便
3、能使用電池供電、可持續(xù)使用半年以上。
本文將通過(guò)瑞科慧聯(lián)的模塊化開(kāi)發(fā)套件 WisBlock 教大家快速搭建一個(gè)支持LoRaWAN?的無(wú)線讀卡器,讓這個(gè)讀卡器讀到電子標(biāo)簽數(shù)據(jù)時(shí),可以自動(dòng)將數(shù)據(jù)上傳到 LoRaWAN?服務(wù)器上。WisBlock 其實(shí)是一個(gè)物聯(lián)網(wǎng)解決方案設(shè)計(jì)生態(tài)系統(tǒng),由可拼接的模塊和易于使用的軟件工具組成,可加快物聯(lián)網(wǎng)產(chǎn)品生產(chǎn)周期、縮短上市時(shí)間。
搭建 LoRaWAN?NFC 讀卡器概述
本次搭建使用的硬件是瑞科慧聯(lián)(RAK)的 WisBlock 套件,MCU 選擇的是RAK4631WisBlock Core 模塊,該模塊采用強(qiáng)大的 Nordic nRF52840 MCU,可以支持藍(lán)牙 5.0(藍(lán)牙低能耗),以及 Semtech最新的 LoRa?收發(fā)器 SX1262,支持 LoRa?和藍(lán)牙兩種通信模式。
該 NFC 還選擇了 WisBlock 套件的 RAK13600 NFC 讀卡器模組,它使用的是 PN532芯片,可以支持 ISO/ICE 14443A/B 卡類型的讀寫,而且還搭配了一個(gè)蜂鳴器模組 RAK18001,當(dāng) NFC 刷卡有效時(shí),蜂鳴器會(huì)發(fā)出響聲提醒。
對(duì)了,該 NFC 讀卡器的搭建還會(huì)使用到瑞科慧聯(lián)(RAK)的低代碼開(kāi)發(fā)平臺(tái) RUI3,它為 WisBlock 提供包含傳感器驅(qū)動(dòng)接口、無(wú)線發(fā)送接口等豐富的 API接口函數(shù),這樣我們只需要寫少量的應(yīng)用代碼就可以完成此產(chǎn)品搭建了。
硬件電路搭建
硬件準(zhǔn)備
首先我們需要準(zhǔn)備 RAK4631 模塊、RAK5005-O 底板、RAK13600 NFC 讀卡器、RAK18001 蜂鳴器、兩張 ISO 14443B 卡、一根 LoRa?天線、一根 NFC天線、一個(gè) Unify 外殼、一根藍(lán)牙天線(安裝在外殼內(nèi))。

硬件組裝
把 RAK4631 模塊扣在 CPU SLOT 的位置,RAK13600 扣在 IO SLOT 的位置,RAK18001 扣在 SLOT A(或者SLOT B),并且使用螺絲把模組固定。
連接NFC天線、LoRa?天線、藍(lán)牙天線,并安裝至外殼中。硬件組裝完成之后就可以進(jìn)行軟件設(shè)置。

軟件環(huán)境搭建
在Arduino IDE中添加 RAK4631-R 開(kāi)發(fā)板
打開(kāi) Arduino IDE,進(jìn)入“文件 > 首選項(xiàng)”

單擊圖中圖標(biāo),修改“附加開(kāi)發(fā)板管理器網(wǎng)址”選項(xiàng),將 RAK4631-R WisBlock Core 添加中 Arduino 開(kāi)發(fā)板管理器中。

現(xiàn)在復(fù)制這個(gè) URL https://raw.githubusercontent.com/RAKWireless/RAKwireless-Arduino-BSP-Index/main/package_rakwireless.com_rui_index.json 并粘貼至下圖所示區(qū)域。如果已存在其他鏈接,將上述鏈接粘貼至新的一行。完成后,單擊“好”。

重啟 Arduino IDE。 進(jìn)入“工具 > 開(kāi)發(fā)板:“RAK4631” > 開(kāi)發(fā)板管理器”。

在搜索框中輸入“RAK”,窗口會(huì)自動(dòng)出現(xiàn)可用的RAKwireless WisBlock Core Boards,選擇“RAKwireless RUI nRF Boards”并安裝。

BSP 安裝完成后,根據(jù)圖中路徑選擇 RAKwireless WisBlock Core模塊。

安裝使用到的庫(kù)
現(xiàn)在安裝 RAK13600-PN532 庫(kù)和 Adafruit bus 庫(kù):


代碼開(kāi)發(fā)
LoRaWAN?部分的初始化,此函數(shù)可以初始化協(xié)議棧的所有參數(shù),入網(wǎng)方式是OTAA,用戶需要根據(jù)自己的頻段,入網(wǎng)參數(shù)修改此宏定義,代碼中使用的頻段是 AS923。
/************************************* LoRaWAN band setting: RAK_REGION_EU433 RAK_REGION_CN470 RAK_REGION_RU864 RAK_REGION_IN865 RAK_REGION_EU868 RAK_REGION_US915 RAK_REGION_AU915 RAK_REGION_KR920 RAK_REGION_AS923 *************************************/ #define OTAA_BAND (RAK_REGION_AS923) #define OTAA_DEVEUI {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88} #define OTAA_APPEUI {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88} #define OTAA_APPKEY {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88} void lora_init()
蜂鳴器采用的是 PWM 控制,所以要記住在未使用蜂鳴器時(shí),記得關(guān)閉輸出。
pinMode(BUZZER_CONTROL,OUTPUT); noTone(BUZZER_CONTROL);
NFC 芯片初始化代碼,采用 IIC 通信協(xié)議,初始化結(jié)束后,就可以使用 NFC的刷卡功能了。
nfc.begin(); uint32_t versiondata = nfc.getFirmwareVersion(); if (! versiondata) { Serial.print("Didn't find PN53x board"); while (1); // halt } // Got ok data, print it out! Serial.print("Found chip PN5"); Serial.println((versiondata >> 24) & 0xFF, HEX); Serial.print("Firmware ver. "); Serial.print((versiondata >> 16) & 0xFF, DEC); Serial.print('.'); Serial.println((versiondata >> 8) & 0xFF, DEC); // Set the max number of retry attempts to read from a card // This prevents us from waiting forever for a card, which is // the default behaviour of the PN532. nfc.setPassiveActivationRetries(0xFF); //configure board to read RFID tags nfc.SAMConfig(); Serial.println("Waiting for an ISO14443A card");
每間隔 1 秒循環(huán)讀取是否有 NFC 卡存在,如果讀取 ID 成功,蜂鳴器會(huì)響 150 毫秒左右,然后發(fā)送卡 ID 到 LoRaWAN?服務(wù)器上。
void loop(void) { boolean success; uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID uint8_t uidLength; // Length of the UID (4 or 7 bytes dep ending on ISO14443A card type) // Wait for an ISO14443B type cards (Mifare, etc.). When one is found // 'uid' will be populated with the UID, and uidLength will indicate // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength); if (success) { tone(BUZZER_CONTROL,4000); delay(150); noTone(BUZZER_CONTROL); Serial.println("Found a card!"); Serial.print("UID Length: "); Serial.print(uidLength, DEC); Serial.println(" byte s"); Serial.print("UID Value: "); for (uint8_t i = 0; i < uidLength; i++) { Serial.print(" 0x"); Serial.print(uid[i], HEX); } Serial.println(""); digitalWrite(ledPin1, HIGH); // LED turn on when input pin value is HIGH delay(150); digitalWrite(ledPin1, LOW); // /** Send the data package */ if (api.lorawan.send(uidLength, (uint8_t *) & uid, 2, true, 1)) { Serial.println("Sending is requested"); } else { Serial.println("Sending failed"); } // Wait 1 second before continuing delay(1000); } else { // PN532 probably timed out waiting for a card Serial.println("Timed out waiting for a card"); } }
數(shù)據(jù)日志
本地串口日志的信息如下所示:

RAK7268內(nèi)置LoRaWAN?服務(wù)器日志:

備注:全部源代碼如下所示
/** @file iso14443a_uid.ino @author rakwireless.com @brief This example will attempt to connect to an ISO14443A card and read card UID @version 0.1 @date 2021-10-14 @copyright Copyright (c) 2021 **/ /**************************************************************************/ #include #include #include // Click here to get the library: http://librarymanager/All#RAK13600-PN532 /************************************* LoRaWAN band setting: RAK_REGION_EU433 RAK_REGION_CN470 RAK_REGION_RU864 RAK_REGION_IN865 RAK_REGION_EU868 RAK_REGION_US915 RAK_REGION_AU915 RAK_REGION_KR920 RAK_REGION_AS923 *************************************/ #define OTAA_BAND (RAK_REGION_AS923) #define OTAA_DEVEUI {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88} #define OTAA_APPEUI {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88} #define OTAA_APPKEY {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88} // If using the breakout or shield with I2C, define just the pins connected #define PN532_IRQ (WB_IO6) #define PN532_RESET (WB_IO5) // Not connected by default on the NFC Shield #define BUZZER_CONTROL WB_IO1 uint8_t ledPin1 = LED_GREEN; uint8_t ledPin2 = LED_BLUE; // Or use this line for a breakout or shield with an I2C connection: NFC_PN532 nfc(PN532_IRQ, PN532_RESET); void lora_init(); void setup(void) { Serial.begin(115200); pinMode(WB_IO2, OUTPUT); digitalWrite(WB_IO2, HIGH); pinMode(BUZZER_CONTROL,OUTPUT); noTone(BUZZER_CONTROL); // initialize the LED pin as an output pinMode(ledPin1, OUTPUT); pinMode(ledPin2, OUTPUT); lora_init(); delay(300); while (!Serial) delay(10); Serial.println("Hello!"); nfc.begin(); uint32_t versiondata = nfc.getFirmwareVersion(); if (! versiondata) { Serial.print("Didn't find PN53x board"); while (1); // halt } // Got ok data, print it out! Serial.print("Found chip PN5"); Serial.println((versiondata >> 24) & 0xFF, HEX); Serial.print("Firmware ver. "); Serial.print((versiondata >> 16) & 0xFF, DEC); Serial.print('.'); Serial.println((versiondata >> 8) & 0xFF, DEC); // Set the max number of retry attempts to read from a card // This prevents us from waiting forever for a card, which is // the default behaviour of the PN532. nfc.setPassiveActivationRetries(0xFF); //configure board to read RFID tags nfc.SAMConfig(); Serial.println("Waiting for an ISO14443A card"); } void loop(void) { boolean success; uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type) // Wait for an ISO14443B type cards (Mifare, etc.). When one is found // 'uid' will be populated with the UID, and uidLength will indicate // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight) success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength); if (success) { tone(BUZZER_CONTROL,4000); delay(150); noTone(BUZZER_CONTROL); Serial.println("Found a card!"); Serial.print("UID Length: "); Serial.print(uidLength, DEC); Serial.println(" bytes"); Serial.print("UID Value: "); for (uint8_t i = 0; i < uidLength; i++) { Serial.print(" 0x"); Serial.print(uid[i], HEX); } Serial.println(""); digitalWrite(ledPin1, HIGH); // LED turn on when input pin value is HIGH delay(150); digitalWrite(ledPin1, LOW); // /** Send the data package */ if (api.lorawan.send(uidLength, (uint8_t *) & uid, 2, true, 1)) { Serial.println("Sending is requested"); } else { Serial.println("Sending failed"); } // Wait 1 second before continuing delay(1000); } else { // PN532 probably timed out waiting for a card Serial.println("Timed out waiting for a card"); } } void lora_init() { // OTAA Device EUI MSB first uint8_t node_device_eui[8] = OTAA_DEVEUI; // OTAA Application EUI MSB first uint8_t node_app_eui[8] = OTAA_APPEUI; // OTAA Application Key MSB first uint8_t node_app_key[16] = OTAA_APPKEY; if (!api.lorawan.appeui.set(node_app_eui, 8)) { Serial.printf("LoRaWan OTAA - set application EUI is incorrect! \r\n"); return; } if (!api.lorawan.appkey.set(node_app_key, 16)) { Serial.printf("LoRaWan OTAA - set application key is incorrect! \r\n"); return; } if (!api.lorawan.deui.set(node_device_eui, 8)) { Serial.printf("LoRaWan OTAA - set device EUI is incorrect! \r\n"); return; } if (!api.lorawan.band.set(OTAA_BAND)) { Serial.printf("LoRaWan OTAA - set band is incorrect! \r\n"); return; } if (!api.lorawan.deviceClass.set(RAK_LORA_CLASS_A)) { Serial.printf("LoRaWan OTAA - set device class is incorrect! \r\n"); return; } if (!api.lorawan.njm.set(RAK_LORA_OTAA)) // Set the network join mode to OTAA { Serial. printf("LoRaWan OTAA - set network join mode is incorrect! \r\n"); return; } if (!api.lorawan.join()) // Join to Gateway { Serial.printf("LoRaWan OTAA - join fail! \r\n"); return; } /** Wait for Join success */ while (api.lorawan.njs.get() == 0) { Serial.print("Wait for LoRaWAN join..."); api.lorawan.join(); delay(10000); } if (!api.lorawan.adr.set(true)) { Serial.printf ("LoRaWan OTAA - set adaptive data rate is incorrect! \r\n"); return; } if (!api.lorawan.rety.set(1)) { Serial.printf("LoRaWan OTAA - set retry times is incorrect! \r\n"); return; } if (!api.lorawan.cfm.set(1)) { Serial.printf("LoRaWan OTAA - set confirm mode is incorrect! \r\n"); return; } /** Check LoRaWan Status*/ Serial.printf("Duty cycle is %s\r\n", api.lorawan.dcs.get()? "ON" : "OFF"); // Check Duty Cycle status Serial.printf("Packet is %s\r\n", api.lorawan.cfm.get()? "CONFIRMED" : "UNCONFIRMED"); // Check Confirm status uint8_t assigned_dev_addr[4] = { 0 }; api.lorawan.daddr.get(assigned_dev_addr, 4); Serial.printf("Device Address is %02X%02X%02X%02X\r\n", assigned_dev_addr[0], assigned_dev_addr[1], assigned_dev_addr[2], assigned_dev_addr[3]); // Check Device Address Serial.println(""); }
-
nfc
+關(guān)注
關(guān)注
61文章
1650瀏覽量
182117 -
RAK
+關(guān)注
關(guān)注
0文章
48瀏覽量
2263
發(fā)布評(píng)論請(qǐng)先 登錄
MAX14502高速USB至SD讀卡器,提供旁路控制技術(shù)手冊(cè)
MAXQ1741用于磁卡讀卡器的DeepCover安全微控制器技術(shù)手冊(cè)

MAXQ1743 DeepCover安全磁卡讀卡器IC技術(shù)手冊(cè)

意法半導(dǎo)體ST25R系列NFC讀卡器新增車規(guī)產(chǎn)品
SE050是否可以完全依靠NFC電源運(yùn)行?
用于LEGIC Advant UID/序列號(hào)的NFC讀卡器,為什么無(wú)法讀取這些卡的UID/序列號(hào)?
可以使用基于PN7642的Pegoda智能卡讀卡器根據(jù)CCC要求定制NFC應(yīng)用嗎?
NFC卡的簡(jiǎn)單介紹及應(yīng)用

液顯ID讀卡器C#小程序開(kāi)發(fā)

PPEC inside 超導(dǎo) / 磁鐵電源,以搭積木的方式快速滿足您的磁鐵供電需求

TRF7970A NFC讀卡器天線多路復(fù)用

AGV讀卡器在AGV自動(dòng)搬運(yùn)小車上應(yīng)用方案

評(píng)論