Test Program of GT-511C3 / GT-511C31 Fingerprint reader module.
GT-511-C31 指紋スキャンモジュールを mbed で動かしてみる
年末に大阪日本橋にあるデジットに行くと,指紋スキャンモジュールを販売していました.
値段は少しお高め(三千円〜八千円超え)ですが,使えると色々と応用が出来そうなので,GT-511-C31を購入して mbed で動かしてみました.
使い方とか
このページにある GT511C3test をそのままプログラムとしてインポートして下さい.
クラスライブラリ化していますので,クラスライブラリを使う場合は,以下からインポートして下さい. ドキュメントが追いついていなくてすみません.テストプログラムを参考にして頂けたらと思います...
Import libraryGT511C3
Class library of fingerprint reader module "GT-511C3 / GT-511C31"
テストプログラムでは,mbed と p28,p27 でシリアル通信します.Vin と GND はそのまま mbed の 3.3V と GND が使えます.
finger.Enroll(11,progress); この関数の呼び出しで,ID番号11番に指紋を登録します.同じ指紋を3回あてると登録できます.
その後,finger.Identify(); の呼び出しで指紋があたっていれば認識して,同じ指紋であればID番号11番を返すはずです. それ以外の指紋があたっていると -1 を返します.
注意点として,指紋の登録あるいは認識をする場合は,必ず CmosLed を点灯させて下さい.点灯させると指紋検出面が青く光ります.これが消灯していると,指紋の検出が出来ないようです.
雑感
指紋の認識は,感覚的にですが1秒ほどで認識します.10本の指それぞれで色々な角度であててみましたが,誤認識無く,登録した指紋があたるとIDが返ります.説明書によると,「違う指紋を同じ指紋として誤る確率:0.001%未満」と言うことなので,10万回に1回の確率で間違えそうですが,実用レベルだと感じます.
うまく使うと,mbed で生体認証チックな事ができそうですね.
指紋認証器モドキ(自動ログインのデモ)
これは,青mbed ではなく,lpclcd と指紋スキャンモジュールを組み合わせて,指紋認証器モドキを作って Mac に自動ログインするプロトタイプです.
lpclcd は mbed と同じように USBKeyboard の様に振る舞わせることが出来ますので,登録された指紋があたると,lpclcd で USBKeyboard::printf("パスワード\n"); を実行してあたかもパスワードがUSB Keyboard で打ち込まれたかの様に動作させています.
この指紋認証器モドキのメリットは,PCから見ればUSBキーボードの様に見えるので,特別なドライバを必要としないことです.要するに「登録された指紋があたれば事前にプログラムされた文字列を lpclcd が代わりにタイプしてくれる」だけです.
実用を考えた時,セキュリティ強度は 強くはないでしょう.このテストプログラムは,パスワードを生文字列で抱き込んでいるので,バイナリレベルで解析すればすぐに生文字列が分かってしまいます.なので指紋認証器モドキです.
Diff: GT511C3.cpp
- Revision:
- 7:8b9ef3211cd0
- Parent:
- 6:016ad8f480d3
diff -r 016ad8f480d3 -r 8b9ef3211cd0 GT511C3.cpp --- a/GT511C3.cpp Fri Jan 03 15:52:29 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,348 +0,0 @@ -/** - * @section LICENSE - * - * Copyright (c) 2013 @tosihisa, MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING - * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * @section DESCRIPTION - * - * Fingerprint reader module "GT-511C3" class. - * - * http://www.adh-tech.com.tw/?22,gt-511c3-gt-511c31 - * http://www.adh-tech.com.tw/files/GT-511C3_datasheet_V1%201_20131127[1].pdf - * https://www.sparkfun.com/products/11792 - * https://github.com/sparkfun/Fingerprint_Scanner-TTL/ - */ - -#include "mbed.h" -#include "GT511C3.hpp" - -#define SET_AND_SUMADD(idx,val) sendbuf[idx]=((unsigned char)(val));sum += sendbuf[idx] - -int GT511C3::Init(void) -{ - baud(9600); - ClearLine(); - return 0; -} - -int GT511C3::SendCommand(unsigned long Parameter,unsigned short Command) -{ - unsigned char sendbuf[12]; - unsigned short sum = 0; - int idx = 0; - int i; - - SET_AND_SUMADD(idx,0x55); idx++; - SET_AND_SUMADD(idx,0xAA); idx++; - SET_AND_SUMADD(idx,0x01); idx++; - SET_AND_SUMADD(idx,0x00); idx++; - SET_AND_SUMADD(idx,Parameter & 0xff); idx++; - SET_AND_SUMADD(idx,(Parameter >> 8) & 0xff); idx++; - SET_AND_SUMADD(idx,(Parameter >> 16) & 0xff); idx++; - SET_AND_SUMADD(idx,(Parameter >> 24) & 0xff); idx++; - SET_AND_SUMADD(idx,Command & 0xff); idx++; - SET_AND_SUMADD(idx,(Command >> 8) & 0xff); idx++; - sendbuf[idx] = sum & 0xff; idx++; - sendbuf[idx] = (sum >> 8) & 0xff; idx++; - - for(i = 0;i < idx;i++){ - while(!writeable()); - putc(sendbuf[i]); - } - return 0; -} - -int GT511C3::RecvResponse(unsigned long *Parameter,unsigned short *Response) -{ - const unsigned char fixedbuf[4] = { 0x55,0xAA,0x01,0x00 }; - unsigned char buf[12]; - unsigned short sum = 0; - int i; - - *Parameter = 0; - *Response = CMD_Nack; - - for(i = 0;i < sizeof(buf);i++){ - while(!readable()); - buf[i] = getc(); - if(i < 9){ - sum += buf[i]; - } - if(i < 4){ - if(buf[i] != fixedbuf[i]){ - return -1; - } - } - } - if(buf[10] != (sum & 0xff)) - return -2; - if(buf[11] != ((sum >> 8) & 0xff)) - return -2; - - *Parameter = buf[7]; - *Parameter = (*Parameter << 8) | buf[6]; - *Parameter = (*Parameter << 8) | buf[5]; - *Parameter = (*Parameter << 8) | buf[4]; - - *Response = buf[9]; - *Response = (*Response << 8) | buf[8]; - - return 0; -} - -int GT511C3::RecvData(unsigned char *data,unsigned long size) -{ - const unsigned char fixedbuf[4] = { 0x5A,0xA5,0x01,0x00 }; - unsigned short sum = 0; - int i; - - for(i = 0;i < size;i++){ - while(!readable()); - *(data + i) = getc(); - if(i < (size-2)){ - sum += *(data + i); - } - if(i < 4){ - if(*(data + i) != fixedbuf[i]){ - return -1; - } - } - } - if(*(data + size - 2) != (sum & 0xff)) - return -2; - if(*(data + size - 1) != ((sum >> 8) & 0xff)) - return -2; - return 0; -} - -int GT511C3::SendRecv(unsigned short Command,unsigned long *Parameter,unsigned short *Response) -{ - int sts; - if((sts = SendCommand(*Parameter,Command)) == 0){ - *Parameter = 0; - if((sts = RecvResponse(Parameter,Response)) != 0){ - *Response = CMD_Nack; - *Parameter = NACK_IO_ERR; - } - } - if(*Response == CMD_Nack){ - LastError = *Parameter; - } - return sts; -} - -int GT511C3::ClearLine(void) -{ - while(readable()){ - (void)getc(); - } - return 0; -} - -int GT511C3::Open(void) -{ - unsigned long Parameter = 1; - unsigned short Response = 0; - unsigned char buf[4+sizeof(FirmwareVersion)+sizeof(IsoAreaMaxSize)+sizeof(DeviceSerialNumber)+2]; - int sts = 0; - - if((sts = Init()) != 0) - return -1; - - sts = SendRecv(CMD_Open,&Parameter,&Response); - if((sts != 0) || (Response != CMD_Ack)){ - return -1; - } - if((sts = RecvData(buf,sizeof(buf))) == 0){ - memcpy(&FirmwareVersion,&buf[4+0],sizeof(FirmwareVersion)); - memcpy(&IsoAreaMaxSize,&buf[4+sizeof(FirmwareVersion)],sizeof(IsoAreaMaxSize)); - memcpy(DeviceSerialNumber,&buf[4+sizeof(FirmwareVersion)+sizeof(IsoAreaMaxSize)],sizeof(DeviceSerialNumber)); - } - return sts; -} - -int GT511C3::WaitPress(int press) -{ - while(IsPress() != press); - return 0; -} - -int GT511C3::CmosLed(int onoff) -{ - unsigned long Parameter = onoff & 1; - unsigned short Response = 0; - int sts = 0; - - sts = SendRecv(CMD_CmosLed,&Parameter,&Response); - if((sts != 0) || (Response != CMD_Ack)){ - return -1; - } - return 0; -} - -int GT511C3::IsPress(void) -{ - unsigned long Parameter = 0; - unsigned short Response = 0; - int sts = 0; - sts = SendRecv(CMD_IsPressFinger,&Parameter,&Response); - if((sts != 0) || (Response != CMD_Ack)) - return 0; - if(Parameter != 0) - return 0; - return 1; -} - -int GT511C3::Capture(int best) -{ - unsigned long Parameter = best; - unsigned short Response = 0; - int sts = 0; - - sts = SendRecv(CMD_CaptureFinger,&Parameter,&Response); - if((sts != 0) || (Response != CMD_Ack)) - return -1; - return 0; -} - -int GT511C3::Enroll_N(int N) -{ - unsigned long Parameter = 0; - unsigned short Response = 0; - int sts = 0; - enum Command cmd; - - switch(N){ - default: - case 1: cmd = CMD_Enroll1; break; - case 2: cmd = CMD_Enroll2; break; - case 3: cmd = CMD_Enroll3; break; - } - sts = SendRecv(cmd,&Parameter,&Response); - if((sts != 0) || (Response != CMD_Ack)) - return -1; - return 0; -} - -int GT511C3::Identify(void) -{ - unsigned long Parameter = 0; - unsigned short Response = 0; - int sts = 0; - - sts = SendRecv(CMD_Identify,&Parameter,&Response); - if((sts != 0) || (Response != CMD_Ack)) - return -1; - return Parameter; -} - -int GT511C3::Enroll(int ID,int (*progress)(int status,char *msg)) -{ - unsigned long Parameter = 0; - unsigned short Response = 0; - int sts = 0; - - CmosLed(1); - - while(1){ - if((sts = (*progress)(1,"EnrollStart\n")) != 0) - return -9999; - Parameter = ID; - sts = SendRecv(CMD_EnrollStart,&Parameter,&Response); - if(sts != 0) - return sts; - if(Response != CMD_Ack) - return -100; - - if((sts = (*progress)(0,"Remove finger\n")) != 0) - return -9999; - WaitPress(0); - - while(1){ - if((sts = (*progress)(10,"Press finger to Enroll (1st)\n")) != 0) - return -9999; - WaitPress(1); - if(Capture(1) == 0) - break; - } - - if((sts = (*progress)(0,"Remove finger\n")) != 0) - return -9999; - if(Enroll_N(1) != 0) - continue; - WaitPress(0); - - while(1){ - if((sts = (*progress)(20,"Press finger to Enroll (2nd)\n")) != 0) - return -9999; - WaitPress(1); - if(Capture(1) == 0) - break; - } - - if((sts = (*progress)(0,"Remove finger\n")) != 0) - return -9999; - if(Enroll_N(2) != 0) - continue; - WaitPress(0); - - while(1){ - if((sts = (*progress)(30,"Press finger to Enroll (3rd)\n")) != 0) - return -9999; - WaitPress(1); - if(Capture(1) == 0) - break; - } - - if((sts = (*progress)(0,"Remove finger\n")) != 0) - return -9999; - if(Enroll_N(3) != 0) - continue; - WaitPress(0); - - if((sts = (*progress)(100,"Enroll OK\n")) != 0) - return -9999; - - break; - } - return 0; -} - -int GT511C3::CheckEnrolled(int ID) -{ - unsigned long Parameter = ID; - unsigned short Response = 0; - int sts = 0; - - sts = SendRecv(CMD_CheckEnrolled,&Parameter,&Response); - if((sts == 0) && (Response == CMD_Ack)) - return 0; //This ID is enrolled - return -1; -} - -int GT511C3::DeleteID(int ID) -{ - unsigned long Parameter = ID; - unsigned short Response = 0; - int sts = 0; - - sts = SendRecv(CMD_DeleteID,&Parameter,&Response); - if((sts == 0) && (Response == CMD_Ack)) - return 0; - return -1; -}