در این مقالۀ آموزشی نحوۀ اتصال حسگر اثرانگشت خازنی R502/R503 به Arduino رو بهتون آموزش میدیم. این حسگر، اثرانگشت کاربر رو ثبت، ذخیره میکنه و با سایر اثرانگشتهای موجود در پایگاه داده تطبیق میده. به طور کلی از این حسگر برای دسترسی دادن به کاربران یا حضور و غیاب استفاده میشه.
حسگرهای اثرانگشت زیادی در بازار وجود داره و ما قبلاً در پروژههامون از حسگر پیشرفته GT511C3 هم استفاده کردیم؛ علاوه بر دقت خیلی زیاد، سرعت این حسگر در تشخیص و شناسایی اثرانگشت (مدت زمان پاسخ) هم خیلی بالاست. این حسگر به جای روش نوری، از پردازش تصویر دوربین برای تشخیص اثرانگشتها استفاده میکنه که با استفاده از لینک زیر میتونید به این پروژه دسترسی داشته باشید.
اما در این نوشتار، جزئیات و مشخصات فنی حسگر اثرانگشت R502/R503 رو با هم مرور میکنیم و با کارکردش آشنا میشیم. علاوه بر این، حسگر خازنی R502/R503 رو با استفاده از کتابخانه Adafruit به Arduino وصل میکنیم و شیوۀ ثبت و آزمایش اثرانگشتها رو هم یاد میگیریم.
فهرست قطعات موردنیاز
لیست قطعات مورد نیاز
-
برد Arduino Nano یا Arduino UNO
-
حسگر R502 / R503
-
کابل های جامپر
کارکرد حسگر اثرانگشت خازنی
حسگر اثرانگشت خازنی برخلاف حسگرهای نوری اثرانگشت، از الگوریتم متفاوتی استفاده میکنن. پویشگرهای اثرانگشت خازنی به جای ایجاد یک تصویر سنتی از اثرانگشت، از آرایههایی از مدارهای خازن کوچک برای جمعآوری داده استفاده میکنن.
با توجه به اینکه خازنها بارالکتریکی ذخیره میکنن، اگر اونا رو به صفحات رسانا که روی سطح اسکنر قرار دادن وصل کنیم میشه ازشون برای رهگیری جزئیات اثرانگشت استفاده کرد. وقتی که برجستگی انگشت روی صفحه رسانا قرار بگیره بار الکتریکی ذخیرهشده اندکی تغییر میکنه. در مقابل، فاصلۀ بین اثرانگشت و صفحه رسانا باعث میشه که بار خازن تغییر چندانی نکنه. برای رهگیری این تغییرات از یک مدار مجتمع آپ امپ استفاده میشه؛ این تغییرات رو میشه با یک مبدل آنالوگ به دیجیتال ثبت کرد.
پس از ثبت، این دادههای دیجیتال تحلیل میشن و ویژگیهای منحصر به فرد و خاص اثرانگشت مشخص میشن.
حسگر اثرانگشت R502/R503
R503 مشهورترین و ارزانترین حسگر اثرانگشت خازنی هست که در بازار موجوده. تراشه این حسگر از ادغام تراشههای جمعآوری تصویر و الگوریتم با یکدیگه طراحی شده. نقطه قوت این حسگر اینه که با شرایط اثرانگشت سازگاره، چه انگشت خشک باشه، خیس باشه، برجستگیهای کمتری داشته باشه یا حتی انگشتهای پیر فرقی نمیکنه در هر صورت نرخ تشخیص این سنسور بالاست. تفاوت سنسور R502 و R503 در اینه که سنسور R502 کوچکتر و ظریفتره.
حسگر اثرانگشت با ولتاژ 3/3 ولت کار میکنه و زمانی که در حال ثبت اثرانگشته جریان مصرفی اون حدود 18 میلی آمپر و وقتی که در حالت آماده باش هست جریان مصرفی به طور میانگین به 2 میکرو آمپر میرسه. این حسگر از رابط سریال استفاده میکنه و به نرخ باود پیشفرضِ 57600bps ارتباط برقرار میکنه. این حسگر میتونه حداکثر 200 اثرانگشت رو ثبت کنه. این حسگر اثرانگشت از Arduino، Android، ویندوز و لینوکس پشتیبانی میکنه. برای آشنایی بیشتر با این حسگر از لینک زیر استفاده کنین:
مشخصات فنی
- رابط: RS232 (TTL)
- وضوح تصویر: 508 DPI
- ولتاژ: DC 3.3v
- جریان کاری (ثبت اثرانگشت): 18mA
- جریان در حالت بیکار(تشخیص اثرانگشت): ولتاژ آماده به کار لمسی: 3v، میانگین جریان: 2uA
- ظرفیت حسگر: 200 اثرانگشت
- آرایه سنجش: 192*192 پیکسل
- رنگ LED: آبی و قرمز
- سرعت پویش: < 0.2 ثانیه
- سرعت تآیید: < 0.3 ثانیه
- الگوی تطبیق: 1:1; 1:N
- نرخ رد کردن اشتباه (FRR): ≤0.01%
- نرخ پذیرش اشتباه (FAR): ≤0.00001%
- نرخ باود (UART): (9600 × N) bps where N = 1 ~ 12(default N = 6, ie 57600bps)
طرح پینهای حسگر R502/R503
در مجموع این حسگر اثرانگشت 6 تا سیم داره که در جدول زیر مشاهده میکنین:
اتصال حسگر اثرانگشت R502/R503 به Arduino
در این قسمت بهتون نشون میدیم که چجوری میشه حسگر اثرانگشت R502/R503 رو به Arduino وصل کرد. تصویر اتصال این دو تا قطعه رو در تصویر زیر میتونین مشاهده کنین.
این حسگر اثرانگشت یک قطعه مبتنی بر سریال می باشد. پین VCC و GND حسگر رو به پین 3.3v و GND برد Arduino وصل کنین. به همین ترتیب، Tx (سیم زرد) و Rx (سیم سبز) رو به ترتیب به D2 و D3 برد Arduino وصل کنین. سیم آبی یک سیم بلااستفاده است و به برد وصلش نمیکنیم. سیم سفید رو به 3.3V وصل کنین.
سنسور اثرانگشت رو میتونین مستقیماً به Arduino وصل کنین.
کد حسگر اثرانگشت R503/502
یک کتابخانه Arduino از Adafruit برای حسگر اثرانگشت R502/R503 وجود داره. کتابخانه Adafruit Fingerprint Sensor رو میتونین از Github دانلود کنین.
برای ثبت و خواندن (بررسی) اثرانگشت دو تا کد مجزا وجود داره. کد مربوط به ثبت اثرانگشت، دادههای اثرانگشت رو در حافظه EEPROM ذخیره میکنه. در مقابل، کد مربوط به خواندن، اثرانگشتی که در حافظه EEPROM ذخیره شده رو میخونه و با اثرانگشتی که پویش شده تطبیق میده.
کد ثبت اثرانگشت
#include <Adafruit_Fingerprint.h> #if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__) // For UNO and others without hardware serial, we must use software serial... // pin #2 is IN from sensor (GREEN wire) // pin #3 is OUT from arduino (WHITE wire) // Set up the serial port to use softwareserial.. SoftwareSerial mySerial(2, 3); #else // On Leonardo/M0/etc, others with hardware serial, use hardware serial! // #0 is green wire, #1 is white #define mySerial Serial1 #endif Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); uint8_t id; void setup() { Serial.begin(9600); while (!Serial); // For Yun/Leo/Micro/Zero/... delay(100); Serial.println("\n\nAdafruit Fingerprint sensor enrollment"); // set the data rate for the sensor serial port finger.begin(57600); if (finger.verifyPassword()) { Serial.println("Found fingerprint sensor!"); } else { Serial.println("Did not find fingerprint sensor :("); while (1) { delay(1); } } Serial.println(F("Reading sensor parameters")); finger.getParameters(); Serial.print(F("Status: 0x")); Serial.println(finger.status_reg, HEX); Serial.print(F("Sys ID: 0x")); Serial.println(finger.system_id, HEX); Serial.print(F("Capacity: ")); Serial.println(finger.capacity); Serial.print(F("Security level: ")); Serial.println(finger.security_level); Serial.print(F("Device address: ")); Serial.println(finger.device_addr, HEX); Serial.print(F("Packet len: ")); Serial.println(finger.packet_len); Serial.print(F("Baud rate: ")); Serial.println(finger.baud_rate); } uint8_t readnumber(void) { uint8_t num = 0; while (num == 0) { while (! Serial.available()); num = Serial.parseInt(); } return num; } void loop() // run over and over again { Serial.println("Ready to enroll a fingerprint!"); Serial.println("Please type in the ID # (from 1 to 127) you want to save this finger as..."); id = readnumber(); if (id == 0) {// ID #0 not allowed, try again! return; } Serial.print("Enrolling ID #"); Serial.println(id); while (! getFingerprintEnroll() ); } uint8_t getFingerprintEnroll() { int p = -1; Serial.print("Waiting for valid finger to enroll as #"); Serial.println(id); while (p != FINGERPRINT_OK) { p = finger.getImage(); switch (p) { case FINGERPRINT_OK: Serial.println("Image taken"); break; case FINGERPRINT_NOFINGER: Serial.println("."); break; case FINGERPRINT_PACKETRECIEVEERR: Serial.println("Communication error"); break; case FINGERPRINT_IMAGEFAIL: Serial.println("Imaging error"); break; default: Serial.println("Unknown error"); break; } } // OK success! p = finger.image2Tz(1); switch (p) { case FINGERPRINT_OK: Serial.println("Image converted"); break; case FINGERPRINT_IMAGEMESS: Serial.println("Image too messy"); return p; case FINGERPRINT_PACKETRECIEVEERR: Serial.println("Communication error"); return p; case FINGERPRINT_FEATUREFAIL: Serial.println("Could not find fingerprint features"); return p; case FINGERPRINT_INVALIDIMAGE: Serial.println("Could not find fingerprint features"); return p; default: Serial.println("Unknown error"); return p; } Serial.println("Remove finger"); delay(2000); p = 0; while (p != FINGERPRINT_NOFINGER) { p = finger.getImage(); } Serial.print("ID "); Serial.println(id); p = -1; Serial.println("Place same finger again"); while (p != FINGERPRINT_OK) { p = finger.getImage(); switch (p) { case FINGERPRINT_OK: Serial.println("Image taken"); break; case FINGERPRINT_NOFINGER: Serial.print("."); break; case FINGERPRINT_PACKETRECIEVEERR: Serial.println("Communication error"); break; case FINGERPRINT_IMAGEFAIL: Serial.println("Imaging error"); break; default: Serial.println("Unknown error"); break; } } // OK success! p = finger.image2Tz(2); switch (p) { case FINGERPRINT_OK: Serial.println("Image converted"); break; case FINGERPRINT_IMAGEMESS: Serial.println("Image too messy"); return p; case FINGERPRINT_PACKETRECIEVEERR: Serial.println("Communication error"); return p; case FINGERPRINT_FEATUREFAIL: Serial.println("Could not find fingerprint features"); return p; case FINGERPRINT_INVALIDIMAGE: Serial.println("Could not find fingerprint features"); return p; default: Serial.println("Unknown error"); return p; } // OK converted! Serial.print("Creating model for #"); Serial.println(id); p = finger.createModel(); if (p == FINGERPRINT_OK) { Serial.println("Prints matched!"); } else if (p == FINGERPRINT_PACKETRECIEVEERR) { Serial.println("Communication error"); return p; } else if (p == FINGERPRINT_ENROLLMISMATCH) { Serial.println("Fingerprints did not match"); return p; } else { Serial.println("Unknown error"); return p; } Serial.print("ID "); Serial.println(id); p = finger.storeModel(id); if (p == FINGERPRINT_OK) { Serial.println("Stored!"); } else if (p == FINGERPRINT_PACKETRECIEVEERR) { Serial.println("Communication error"); return p; } else if (p == FINGERPRINT_BADLOCATION) { Serial.println("Could not store in that location"); return p; } else if (p == FINGERPRINT_FLASHERR) { Serial.println("Error writing to flash"); return p; } else { Serial.println("Unknown error"); return p; } return true; }
بعد از بارگذاری کد، سریال ماینتور رو باز کنین. مانیتور ازتون میخواد ID اثرانگشت رو که عددی بین 1 تا 127 هست رو تایپ کنین.
حالا عدد ID رو در صفحه سریال مانیتور وارد و ارسال کنین. با دنبال کردن دستورالعملهای روی صفحه، اثرانگشت رو ثبت کنین.
برای ثبت اثرانگشت، انگشتتون رو روی حسگر قرار بدید.
اثرانگشت با موفقیت ثبت شد. بدین روش میتونین چندین اثرانگشت رو ثبت کنین.
کد شناسایی اثرانگشت
#include <Adafruit_Fingerprint.h> int u=0; int relay=5; #if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__) // For UNO and others without hardware serial, we must use software serial... // pin #2 is IN from sensor (GREEN wire) // pin #3 is OUT from arduino (WHITE wire) // Set up the serial port to use softwareserial.. SoftwareSerial mySerial(2, 3); #else // On Leonardo/M0/etc, others with hardware serial, use hardware serial! // #0 is green wire, #1 is white #define mySerial Serial1 #endif Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); void setup() { pinMode(relay,OUTPUT); Serial.begin(9600); while (!Serial); // For Yun/Leo/Micro/Zero/... delay(100); Serial.println("\n\nAdafruit finger detect test"); // set the data rate for the sensor serial port finger.begin(57600); delay(5); if (finger.verifyPassword()) { Serial.println("Found fingerprint sensor!"); } else { Serial.println("Did not find fingerprint sensor :("); while (1) { delay(1); } } Serial.println(F("Reading sensor parameters")); finger.getParameters(); Serial.print(F("Status: 0x")); Serial.println(finger.status_reg, HEX); Serial.print(F("Sys ID: 0x")); Serial.println(finger.system_id, HEX); Serial.print(F("Capacity: ")); Serial.println(finger.capacity); Serial.print(F("Security level: ")); Serial.println(finger.security_level); Serial.print(F("Device address: ")); Serial.println(finger.device_addr, HEX); Serial.print(F("Packet len: ")); Serial.println(finger.packet_len); Serial.print(F("Baud rate: ")); Serial.println(finger.baud_rate); finger.getTemplateCount(); if (finger.templateCount == 0) { Serial.print("Sensor doesn't contain any fingerprint data. Please run the 'enroll' example."); } else { Serial.println("Waiting for valid finger..."); Serial.print("Sensor contains "); Serial.print(finger.templateCount); Serial.println(" templates"); } } void loop() // run over and over again { getFingerprintID(); delay(50); //don't ned to run this at full speed. } uint8_t getFingerprintID() { uint8_t p = finger.getImage(); switch (p) { case FINGERPRINT_OK: Serial.println("Image taken"); break; case FINGERPRINT_NOFINGER: Serial.println("No finger detected"); finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_BLUE); finger.LEDcontrol(FINGERPRINT_LED_OFF, 0, FINGERPRINT_LED_RED); return p; case FINGERPRINT_PACKETRECIEVEERR: Serial.println("Communication error"); return p; case FINGERPRINT_IMAGEFAIL: Serial.println("Imaging error"); return p; default: Serial.println("Unknown error"); return p; } // OK success! p = finger.image2Tz(); switch (p) { case FINGERPRINT_OK: Serial.println("Image converted"); break; case FINGERPRINT_IMAGEMESS: Serial.println("Image too messy"); return p; case FINGERPRINT_PACKETRECIEVEERR: Serial.println("Communication error"); return p; case FINGERPRINT_FEATUREFAIL: Serial.println("Could not find fingerprint features"); return p; case FINGERPRINT_INVALIDIMAGE: Serial.println("Could not find fingerprint features"); return p; default: Serial.println("Unknown error"); return p; } // OK converted! p = finger.fingerSearch(); if (p == FINGERPRINT_OK) { Serial.println("Found a print match!"); finger.LEDcontrol(FINGERPRINT_LED_FLASHING, 25, FINGERPRINT_LED_PURPLE, 10); delay(1000); if(u==0) { digitalWrite(relay,HIGH); u=1; } else if(u==1) { digitalWrite(relay,LOW); u=0; } } else if (p == FINGERPRINT_PACKETRECIEVEERR) { Serial.println("Communication error"); return p; } else if (p == FINGERPRINT_NOTFOUND) { finger.LEDcontrol(FINGERPRINT_LED_FLASHING, 25, FINGERPRINT_LED_RED, 10); delay(1000); Serial.println("Did not find a match"); return p; } else { Serial.println("Unknown error"); return p; } // found a match! Serial.print("Found ID #"); Serial.print(finger.fingerID); Serial.print(" with confidence of "); Serial.println(finger.confidence); return finger.fingerID; } // returns -1 if failed, otherwise returns ID # int getFingerprintIDez() { uint8_t p = finger.getImage(); if (p != FINGERPRINT_OK) return -1; p = finger.image2Tz(); if (p != FINGERPRINT_OK) return -1; p = finger.fingerFastSearch(); if (p != FINGERPRINT_OK) return -1; // found a match! Serial.print("Found ID #"); Serial.print(finger.fingerID); Serial.print(" with confidence of "); Serial.println(finger.confidence); return finger.fingerID; }
بعد از ثبت اثرانگشتها، برای خواندن اثرانگشتی که در دیتابیس ذخیره شده کد بالا رو بارگذاری کنین.
اگر انگشتتون رو روی حسگر بذارید میتونین دادههای ذخیره شده رو بخونین.