پروژه ار اف ای دی خوان/نویس با ماژول RFID RDM630/RDM6300 در آردوینو
RDM630 و RDM6300 از Seeedstudio دو نوع مختلف از خوانندههای RFID هستند، حتی اگر آنها اغلب با هم اشتباه گرفته شوند. علاوه بر نامهای مشابه، دلیل دیگر سردرگمی ممکن است این باشد که آنها همان طرح پین و پروتکل انتقال را به اشتراک میگذارند. براساس دانش من، علاوه بر همان عملکرد فنی، آنها چیز دیگری را با هم مشترک ندارند (مانند تولید کننده یکسان، نسخه پیشین / جانشین و غیره). معمولاً شما باید قادر باشید RDM630 Seeedstudio را با قیمت حدود 10-15 دلار و RDM6300 را با قیمت حدود 1-3 دلار خریداری کنید. به نظر من، تفاوت قیمت به راحتی قابل توجیه است زیرا RDM630 مستحکمتر است و فواصل خواندن بسیار بالاتری را اجازه میدهد.
هر دو خواننده در فرکانس 125 کیلوهرتز کار میکنند و اجازه میدهند تا برچسبهای سازگار با EM4100 خوانده شوند. برچسبهای دیگر (برای مثال برچسبهای EM4305) نمیکنند (یا ممکن است) با این خوانندهها کار نکنند.
توجه: معمولا خواننده های RFID ار اف ای دی 125khz و کارت های آن فقط قادر به خواندن هستند و عملیات نوشتن در آن ها وجود دارد.
در این آموزش، نحوه استفاده از RDM6300 و RDM630 با Arduino Uno را نشان میدهیم. خوشبختانه، هر دو خواننده RFID از یک پروتکل از طریق اتصال سریال استفاده میکنند. در نتیجه، همان کد منبع میتواند برای کار کردن هر دو خواننده استفاده شود. بنابراین، بدون توجه به اینکه شما صاحب RDM630 یا RDM6300 هستید، این آموزش باید برای شما مفید باشد اگر میخواهید آن را با Arduino کار کنید.
وسایل مورد نیاز
- Arduino Uno
- سیم پل
- Seeedstudio RDM630 *
- RDM6300
- برچسبهای 125 کیلو هرتز (برای سازگاری EM4100 بررسی کنید)
اگر به دنبال RDM630 هستید، لطفاً به خاطر داشته باشید که بسیاری از پیشنهادات به اشتباه برچسب گذاری شده است. شما محصولات زیادی را میتوانید پیدا کنید که به عنوان “RDM630” تبلیغ میشوند، اگرچه آنها از نوع RDM6300 هستند. بنابراین، به تصاویر نزدیک نگاه کنید.
پین های RDM630 / RDM6300
پین های RDM630و RDM6300 دقیقاً همان هم هستند. در مجموع، RDM630 / RDM6300 دارای 9 پین است که Vcc و GND دو بار وجود دارند. پین Vcc باید به یک DC 5V متصل شود. ANT1 و ANT2 برای اتصال یک آنتن به برد استفاده میشوند. معمولاً، هم RDM630 و هم RDM6300 در حال حاضر با یک آنتن میآیند. با این حال، امکان تغییر آنتن وجود دارد، به عنوان مثال به یک آنتن سفارشی. TX برای انتقال دادهها و RX برای بازیابی دادهها استفاده میشود. پین LED میتواند برای جستجوی سریع اینکه آیا برچسب RFID با موفقیت خوانده شده است یا خیر، استفاده شود. اگر برچسب RFID وجود نداشته باشد، پین LED در 5V (HIGH) قرار دارد. اگر RFID خوانده شود، پین LED به مدت چند لحظه به 0V (LOW) میرود (بله، از HIGH به LOW میرود!).
کد نمونه برای آردوینو UNO
همانطور که قبلاً گفته شد، سورس کد میتواند با هر دو مدل استفاده شود (من کد را با هر دو مدل آزمایش کردم). در اصل، وقتی برچسب RFID شناسایی شد، RDM630 / RDM6300 یک فریم با 14 بایت ارسال میکند: هدر [1 بایت]، داده [10 بایت]، checksum [2 بایت] و دم [1 بایت]. هدر (یا پیشوند) همیشه 0x02 است. به طور مشابه، دم همیشه 0x03 است. فیلد داده شامل مقادیر HEX کدگذاری شده ASCII است. گاهی اوقات، تولید کنندگان تمایل دارند فیلد داده برچسب RFID را به دو قسمت تقسیم کنند: نسخه و برچسب. بنابراین، بسته به نوع برچسب RFID شما، دو بایت اول داده ممکن است نسخه باشد و 8 بایت دیگر برچسب RFID واقعی باشد. این نکته را در سورس کد در نظر گرفته شده است. برای محاسبه checksum از فیلد داده، لازم است یک عمل XOR را روی همه ورودیهای داده انجام دهید.
// (c) Michael Schoeffler 2018, http://www.mschoeffler.de
#include <SoftwareSerial.h>
const int BUFFER_SIZE = 14; // RFID DATA FRAME FORMAT: 1byte head (value: 2), 10byte data (2byte version + 8byte tag), 2byte checksum, 1byte tail (value: 3)
const int DATA_SIZE = 10; // 10byte data (2byte version + 8byte tag)
const int DATA_VERSION_SIZE = 2; // 2byte version (actual meaning of these two bytes may vary)
const int DATA_TAG_SIZE = 8; // 8byte tag
const int CHECKSUM_SIZE = 2; // 2byte checksum
SoftwareSerial ssrfid = SoftwareSerial(6,8);
uint8_t buffer[BUFFER_SIZE]; // used to store an incoming data frame
int buffer_index = 0;
void setup() {
Serial.begin(9600);
ssrfid.begin(9600);
ssrfid.listen();
Serial.println("INIT DONE");
}
void loop() {
if (ssrfid.available() > 0){
bool call_extract_tag = false;
int ssvalue = ssrfid.read(); // read
if (ssvalue == -1) { // no data was read
return;
}
if (ssvalue == 2) { // RDM630/RDM6300 found a tag => tag incoming
buffer_index = 0;
} else if (ssvalue == 3) { // tag has been fully transmitted
call_extract_tag = true; // extract tag at the end of the function call
}
if (buffer_index >= BUFFER_SIZE) { // checking for a buffer overflow (It's very unlikely that an buffer overflow comes up!)
Serial.println("Error: Buffer overflow detected!");
return;
}
buffer[buffer_index++] = ssvalue; // everything is alright => copy current value to buffer
if (call_extract_tag == true) {
if (buffer_index == BUFFER_SIZE) {
unsigned tag = extract_tag();
} else { // something is wrong... start again looking for preamble (value: 2)
buffer_index = 0;
return;
}
}
}
}
unsigned extract_tag() {
uint8_t msg_head = buffer[0];
uint8_t *msg_data = buffer + 1; // 10 byte => data contains 2byte version + 8byte tag
uint8_t *msg_data_version = msg_data;
uint8_t *msg_data_tag = msg_data + 2;
uint8_t *msg_checksum = buffer + 11; // 2 byte
uint8_t msg_tail = buffer[13];
// print message that was sent from RDM630/RDM6300
Serial.println("--------");
Serial.print("Message-Head: ");
Serial.println(msg_head);
Serial.println("Message-Data (HEX): ");
for (int i = 0; i < DATA_VERSION_SIZE; ++i) {
Serial.print(char(msg_data_version[i]));
}
Serial.println(" (version)");
for (int i = 0; i < DATA_TAG_SIZE; ++i) {
Serial.print(char(msg_data_tag[i]));
}
Serial.println(" (tag)");
Serial.print("Message-Checksum (HEX): ");
for (int i = 0; i < CHECKSUM_SIZE; ++i) {
Serial.print(char(msg_checksum[i]));
}
Serial.println("");
Serial.print("Message-Tail: ");
Serial.println(msg_tail);
Serial.println("--");
long tag = hexstr_to_value(msg_data_tag, DATA_TAG_SIZE);
Serial.print("Extracted Tag: ");
Serial.println(tag);
long checksum = 0;
for (int i = 0; i < DATA_SIZE; i+= CHECKSUM_SIZE) {
long val = hexstr_to_value(msg_data + i, CHECKSUM_SIZE);
checksum ^= val;
}
Serial.print("Extracted Checksum (HEX): ");
Serial.print(checksum, HEX);
if (checksum == hexstr_to_value(msg_checksum, CHECKSUM_SIZE)) { // compare calculated checksum to retrieved checksum
Serial.print(" (OK)"); // calculated checksum corresponds to transmitted checksum!
} else {
Serial.print(" (NOT OK)"); // checksums do not match
}
Serial.println("");
Serial.println("--------");
return tag;
}
long hexstr_to_value(char *str, unsigned int length) { // converts a hexadecimal value (encoded as ASCII string) to a numeric value
char* copy = malloc((sizeof(char) * length) + 1);
memcpy(copy, str, sizeof(char) * length);
copy[length] = '\0';
// the variable "copy" is a copy of the parameter "str". "copy" has an additional '\0' element to make sure that "str" is null-terminated.
long value = strtol(copy, NULL, 16); // strtol converts a null-terminated string to a long value
free(copy); // clean up
return value;
}
اگر سورس کد را روی آردوینو اجرا کنید و یک برچسب RFID را نزدیک آنتن نگه دارید، مانیتور سریال Arduino IDE باید چیزی شبیه به این را خروجی دهد. در ویدیوی یوتیوب اجرا شدن پروژه را مشاهده می کنید.
منابع
منابع:
https://mschoeffler.com/2018/01/05/arduino-tutorial-how-to-use-the-rdm630-rdm6300-rfid-reader/
دیدگاهتان را بنویسید