勝手な電子工作・・

勝手なオリジナル電子工作に関する記事を書きます

簡単にできる指紋照合(Arduino-Unoで)2021.9.12にプログラム更新

f:id:a-tomi:20210903205017j:plain

殆どのスマホ指紋認証ができるようになりましたが、指紋は登録したくないという人が多いかもしれません。私もですがね^^; 指紋は個人が確実に特定できる優秀なバイオメトリクス。なのでネット機器に入れるのは躊躇してしまいます。

ところが、最近出回っている指紋センサーモジュールの性能とコスパが凄いのに気づいてしまいました。そうなると、どうしても試してみたくなりますね・・。もう長い長い自粛期間ですからね。

ネットにつながないDIY機器に使う目的なら、こんなに便利なものはない。安心して使ってみるということにしましょう^^;

指紋取込のしかけ

多く使われているのは、光学式、静電容量式、電界式など。スマホ内蔵センサーは静電容量式ですが、ここで使うのは光学式です。

f:id:a-tomi:20210903205320j:plain

説明が少し長くなりそうな予感がします。自分の記録用も兼ねた記事のためすみませんねm(_ _ )m

製作に直接関係しないところは青い文字で書いておきますので、お急ぎの方はそこは読み飛ばしてもかまいません。

光学式ではプリズムの45度斜面に指紋を当て二等面の片側からLED光を照射、反対側面から撮った像が加工されます。ガラス内の45度斜面なので光は全反射しますが、指紋の凸部(隆線)があたる部分だけが乱反射するのを利用して指紋を撮像しています。

f:id:a-tomi:20210903205501j:plain

上の写真は、前面すべてがプリズムの45度の斜面です。そこに指をあてるわけです。

使うセンサーモジュール

試すセンサーモジュールは海外ネットで購入。驚くほど低価格で売られていました。

f:id:a-tomi:20210903205603j:plain

“fingerprint”と&で“AS608”や”FPM-10a”などの検索語を使い、多く出回っていそうなものを選びました。注文後10日で届きました。書かれているカタログ仕様では、セキュリティレベルの設定(1~5)により、FAR(他人を通す間違いFalse Acceptance Ratio)は0.001%未満、FRR(本人を否定する間違いFalse Rejection Ratio)は1.0%未満にセットできます。

指紋登録は127種をセットできるので、1つの指を複数エントリー登録したりすればFRR(否定される間違い)の心配はないでしょうね。別の指を入れるのもいいですし。

指紋の自動照合システムは一昔前ならこの100~1000倍も高価だったと思います。今のしくみならAIが多少使われているかな?しかし調べた限り畳み込み層のマトリクスなどは使われていません。つまり長年の指紋照合技術が撮像素子やMCUの能力向上のおかげでこの性能とコストになった感じです。

このセンサーの場合、内蔵MCUはARM Cortex-MベースのSynoChip社AS608で、144MHz、Flash512KB、RAM128KB。データシートでみると通信インターフェイスはひととおりを装備しています。ただしモジュールの実装は次のようになっていて、UART接続が想定されています。製品によってコネクターのピンの並びが異なりますが、どれもUARTを想定している感じです。

f:id:a-tomi:20210903205752j:plain

さて、こういうDIY向きセンサーモジュールの使い方を調べる最近の格好のサイトは"EleCrow"だと思います。とくに中国で作られたものは満載です。

https://www.elecrow.com/wiki/index.php?title=Main_Page

Fingerprintセンサーのガイドとしては次のようなページがあります。

f:id:a-tomi:20210903205911j:plain

PCでの接続テスト

このサイトでWindows10 PC 用の”SFGdemo”プログラムが紹介され、無料でダウンロードできます。オープンソース・ハードの指紋センサー共通に使えるプログラムのようです。

なお、別途AdafruitのFingerprintライブラリーから同じプログラムがたどれますが、そこに示されているダウンロード対象は、なんとウィルスチェッカーで弾かれます。

EleCrowからのダウンロードは何も問題ありませんでした。

SFGdemoを使うには、PCとセンサーの間をシリアル通信で繋ぐ必要があります。センサーにシリアル~USBコンバータを接続して使ってももいいですが、Arduino-IDEでUSB接続したArduinoUnoをダミーで仲介役にすれば、より簡単ですしセンサーへの電源供給もできて便利ですね。

下に示すダミースケッチをIDEArduino Unoに書き込みIDEを終了します。次にセンサーのRxとTxの端子をそれぞれUnoの同名端子につなぎ、PCでSFGdemoを起動します。そのやり方やSFGdemo操作手順も、EleCrowではしっかり説明されています。

電源供給に注意センサーモジュールへの電源供給は仕様上は3.3Vでも5Vでも良いことになっていますが、使ったセンサーモジュールでは、5V供給でコミュニケーションエラーがしばしば生じていました。調べるとセンサーモジュールが返事をしない状態になります。PCBを観察するとQ6のレギュレータが省かれている感じなので、試しにArduino Uno側から3.3Vを供給してみたら、なんと問題は解消しました!(シリアル信号はそのままです、5V-tolerantのようです)。これはArduinoとの接続の場合も同じですから、製品によってはご注意ください。(2021.9.12追記:コネクターに3.3Vと直接書いてあるモデルなら、信号レベルコンバーターを介して信号線2本とも5Vから製品側を3.3Vに変換する方が安心ですね。それを指紋センサーの複数のモデルやってみましたらどれもそれでOKです。また、製品の若干の発熱もだいぶ減るので3.3Vがお勧めかも。)

PCとの接続テストに使ったダミープログラムは次です。

/***********************************************
 * Dummy sketch for Arduino as;
 *      PC-USB to sensor-Serial converter
 *      and a DC Power-Supply for sensors
 **********************************************/
void setup() {
}
void loop() {
}
// ***** end of sketch *****

 

指紋センサーモジュールが妥当に動くかをこれで調べるついでに、使う指をこのプログラムで登録しておくこともできますね。

f:id:a-tomi:20210903210242j:plain

取り込んだ指紋の画像は解析されバイナリーデータにして扱われます。つまり画像自体はメモリーに取り込まず、データ化されたものがセンサーモジュール内にテンプレートとして蓄積されます。

調べる対象の指紋もデータ化されてから使われます。そういうわけなので、蓄積データは少量ですみ、そこから画像自体を復元することはできませんしシステム的にはその必要もないわけです。

指紋の自動照合

指紋は隆線(凸部)と谷線(凹部)の高低差が約50μm、隆線間が約400μm。模様全体としての特徴もあります。そして幼児から何年たっても変わらない、さらにDNAが同じ双子でも違うという驚くほど精巧なバイオメトリクスですね。

指紋照合には、2世紀以上にわたる知恵により、各指紋の「特徴点」(minutiaマイヌーシア)が現代でも使われています。

f:id:a-tomi:20210903210549j:plain

自動照合の歴史上は指紋の中央点、デルタ部分、ドットなど他の特徴点、あるいは特徴点間の隆線数など、撮像品質や処理性能を補う工夫がなされたものもあります。しかし現代(参照:ISO/IEC19794-2:Cor.1:2012)では、例えば上図に◎で示したような限られた特徴点だけでも照合に十分です。

国際標準では特徴点のxy座標と隆線の方向(右水平からの時計回り角度t)の3データ(x,y,t)が使われます。

xy座標原点は左端中央ですが、(x,y,t)は原点の移動も照合角度の調整も演算だけで簡単にできるわけなので、どこに設定してもよいわけです。特徴点は1指紋がもつ通常50~150点の中の数十だけ(統計学的には12点以上でよい)を使えば十分。ISOの指紋テンプレートではx,yを各2バイト(14ビット)、方向を1バイト、それに品質1バイトとし、1特徴点を6バイトに収めます。ただし中身がどのシステムも共通かと言えばそうではなく、原点位置やアルゴリズムなどにも依存するものです。

照合する際の1指紋は隆線が読みやすいように加工され、このセンサーの場合は検査対象の数十の特徴点が128バイトに収められています。テンプレートファイルとしても1つの指(ID)登録に512バイトです。画像を直接蓄えるよりもずっと効率が良いわけ。

特徴点による指紋照合の原理の発案は、実に19世紀!英国のゴルトン(Sir Francis Galton)が現代の認証技術に使われているMinutia(マイヌーシア=特徴点)での照合法を見出しました。著書Finger Prints(1892年)に詳しく書かれています。分厚いですが次のリンクから無料でダウンロード可能です。

https://galton.org/books/finger-prints/galton-1892-fingerprints-1up.pdf

そして、照合の自動化は1970年にNBS(米国標準局)のJ. H. Wegsteinらが初めて開発しました。この原理が現在の照合方法のベースとして長年使われてきています。このセンサーモジュールでも同じことです。

https://nvlpubs.nist.gov/nistpubs/Legacy/TN/nbstechnicalnote538.pdf

f:id:a-tomi:20210903210938j:plain

余談が長引きましたがここからようやく本題です^^;

センサーに当てる指の向き

指紋センサーにあてる指先はおそらく上向きだろうと想像しますが、モジュール単体だと角度が邪魔をして難しいです。テストのために適当な台をつけてみました。

f:id:a-tomi:20210903211110j:plain

PCにつないでセンサーを確認

上で少し説明しましたが、Arduinoをツールとして使い、センサーをPCと直接シリアル接続する際の様子は次の写真です。使う端子はV+、Gnd、Tx、Rxだけなので他の余計なワイヤーは後でソケットからピンごと抜き取るとか、面倒ならカットしてもいいですね。センサーへの電源供給は前に書いたとおり最終的には3.3Vに変更しました。

f:id:a-tomi:20210903211211j:plain

PCでのテストは全てうまく動きました。SFGdemoでは指紋の映像が見えるので、適切な指の当て方などがわかりました。そして、台に載せてわざわざ指を上向きに当てなくとも、センサーをつかむ形で指を下向きにして登録しても、照合時も同じ向きにすれば何ら問題ないことがわかりました^^

PCでのこのテストではセンサーのTx,RxをそれぞれArduinoピンのTx,Rxにつなぎますが、以後のArduino自体でのテストでのソフトウェアシリアルで使うTx,Rxピンでは逆につなぎますから十分ご注意ください。

 

Arduinoでのテスト開始

ここからはいよいよArduinoでのテストをします。センサーからのTxをArduino―UnoのPin2(ソフトウェアシリアルのRx)へ、RxをPin3(ソフトウェアシリアルのTx)へ接続し直します。

まずは指紋の登録(Enroll)です。

Adafruit_Fingerprintライブラリーのスケッチ例"Enroll"がそのまま使えます。ただし、グローバル変数を922バイト(Unoの45%)も使う状況では、後での好きな加工には支障が出そうです。

「最大32256バイトのフラッシュメモリのうち、スケッチが7002バイト(21%)を使っています。最大2048バイトのRAMのうち、グローバル変数が922バイト(45%)を使っていて、ローカル変数で1126バイト使うことができます。」

よって書き換えて次のように減量しておきました。これだとグローバル変数の18%しか使いません。

(この型の指紋センサーの他のモデルでも動くよう、スケッチを2021.09.12に更新しました。それをつけます。)

/*******************************************************************
   Fingerprint enrollment test V.01  as of Sept.12,2021
      Initial version: Aug.23, 2021  modified by Akira Tominaga
      V.01: Retry-interval shortened for all FP models * 9/12/'21
      using Adafruit_Fingereprint library and example,
      with BSD license, described in the bottom of this sketch.
*******************************************************************/
#include "Adafruit_Fingerprint.h"
#define sRx 2
#define sTx 3
SoftwareSerial sSer(sRx, sTx);
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&sSer);
uint8_t id;           // ID# for fingerprint

void setup() { // ***** Arduino setup() *****
  Serial.begin(9600);
  while (!Serial) {}
  delay(100);
  Serial.println(F("\n*Enroll*"));
  finger.begin(57600);
  if (finger.verifyPassword() == false) {
    Serial.println(F("No sensor :("));
    while (true) {}
  }
  Serial.print(F("Sensor"));
  finger.getParameters();
  Serial.print(F(" Stat=0x")); Serial.print(finger.status_reg, HEX);
  Serial.print(F(" ID=0x")); Serial.print(finger.system_id, HEX);
  Serial.print(F(" Capa=")); Serial.print(finger.capacity);
  Serial.print(F(" Sec.lvl=")); Serial.print(finger.security_level);
  Serial.print(F(" Dev.adr=")); Serial.print(finger.device_addr, HEX);
  Serial.print(F(" Pkt=")); Serial.print(finger.packet_len);
  Serial.print(F(" Baud=")); Serial.println(finger.baud_rate);
}

void loop() { // ***** Arduino loop() *****
  Serial.println(F("\nGive ID#(1-127) to set"));
  id = readnumber();
  if ((id == 0) | (id > 127)) { // invalid #, retry!
    return;
  }
  Serial.print(F("#"));
  Serial.println(id);
  while (!getFPtoEnroll() );
}
/*********************************************
 *    User defined functions
 *********************************************/
// ***** read number from Serial input *** readnumber() *****
uint8_t readnumber(void) {
  uint8_t num = 0;
  while (num == 0) {
    while (! Serial.available());
    num = Serial.parseInt();
  }
  return num;
}
// ***** get fingerprint enroll ***  getFPtoEnroll() *****
uint8_t getFPtoEnroll() {
  int p = -1;
  Serial.println(F("Place finger")); 
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        Serial.println(F("Img taken"));
        break;
      case FINGERPRINT_NOFINGER:
        break;
      case FINGERPRINT_PACKETRECIEVEERR:
        Serial.println(F("Com.err"));
        break;
      case FINGERPRINT_IMAGEFAIL:
        Serial.println(F("Img err"));
        break;
      default:
        Serial.println(F("Unknown err"));
        break;
    }
  }
  // OK success!
  p = finger.image2Tz(1);
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println(F("Img Okay")); 
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println(F("Img messy"));
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println(F("Com.err"));
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println(F("No feature"));
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println(F("Img err"));
      return p;
    default:
      Serial.println(F("Unknown err"));
      return p;
  }
  Serial.println(F("Remove finger"));
  delay(2000);
  p = 0;
  while (p != FINGERPRINT_NOFINGER) {
    p = finger.getImage();
  }
  Serial.print("For ID#"); 
  Serial.print(id);
  p = -1;
  Serial.println(F(", same finger again"));
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        Serial.println(F("Img taken"));
        break;
      case FINGERPRINT_NOFINGER:
        break;
      case FINGERPRINT_PACKETRECIEVEERR:
        Serial.println(F("Com.err"));
        break;
      case FINGERPRINT_IMAGEFAIL:
        Serial.println(F("Img err"));
        break;
      default:
        Serial.println(F("Unknown err"));
        break;
    }
  }
  // OK success!
  p = finger.image2Tz(2);
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println(F("Img converted"));
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println(F("Img messy"));
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println(F("Communication .err"));
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println(F("No feature"));
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println(F("Img err"));
      return p;
    default:
      Serial.println(F("Unknown err"));
      return p;
  }
  // OK converted!
  Serial.print(F("Checking FP#"));  Serial.println(id);
  p = finger.createModel();
  if (p == FINGERPRINT_OK) {
    Serial.println(F("Matched!"));
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println(F("Com.err"));
    return p;
  } else if (p == FINGERPRINT_ENROLLMISMATCH) {
    Serial.println(F("No match"));
    return p;
  } else {
    Serial.println(F("Unknown err"));
    return p;
  }
  Serial.print(F("*** FP#")); Serial.print(id);
  p = finger.storeModel(id);
  if (p == FINGERPRINT_OK) {
    Serial.println(F(" enrolled! ***"));
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println(F("Com.err"));
    return p;
  } else if (p == FINGERPRINT_BADLOCATION) {
    Serial.println(F("Bad loc."));
    return p;
  } else if (p == FINGERPRINT_FLASHERR) {
    Serial.println(F("Flash err"));
    return p;
  } else {
    Serial.println(F("Unknown err"));
    return p;
  }
  return true;
}
/*******************************************************************
  This is an example sketch for our optical Fingerprint sensor
  Designed specifically to work with the Adafruit BMP085 Breakout
  ----> http://www.adafruit.com/products/751
  These displays use TTL Serial to communicate, 2 pins are required to
  interface
  Adafruit invests time & resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!
  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution.
*******************************************************************/
// ***** end of program *****

 

指紋の登録

そして指を登録(Enroll)しますが、テストでは右手は操作に使うので、左手の人差し指、中指、薬指を登録しました。念のためにそれぞれIDを3つ登録して、人差し指(1,11,21)、中指(2,12,22)、薬指(3,13,23)としておきました。こうすれば多少乱暴に指をあててもRejectされて困るようなことはないでしょうからね。

Arduino IDEのシリアル出力は次のようなものになります。


*Enroll*
Sensor Stat=0x0 ID=0x0 Capa=150 Sec.lvl=3 Dev.adr=FFFFFFFF Pkt=128 Baud=57600

Give ID#(1-127) to set
#1
Place finger
Img taken
Img Okay
Remove finger
For ID#1, same finger again
Img taken
Img converted
Checking FP#1
Matched!
*** FP#1 enrolled! ***

Give ID#(1-127) to set
#2
Place finger
Img taken
Img Okay
Remove finger
For ID#2, same finger again
Img taken
Img converted
Checking FP#2
Matched!
*** FP#2 enrolled! ***

Give ID#(1-127) to set

 

指紋の照合

次に、指紋の照合(Identify)をします。

Adafruit_Fingerprintライブラリーのスケッチ例Fingerprintがそのまま使えますが、グローバル変数を同様にたっぷり使うため、そうはいきません。こちらは今後確実に応用に使うわけなので。次のように大きく減量して必要最小限に書き換えました。十分小さいですね!これならUnoでも余裕たっぷりです。エラー検出時の処理は、本番ではどっちみち再処理を実行するわけなので、余計なメッセージ出力を削減。

(この型の指紋センサーの他のモデルでも動くよう、スケッチを2021.09.12に更新しました。それをつけます。)

/*******************************************************************
   Fingerprint identification test V.01
      Initial version: Aug.23, 2021  modified by Akira Tominaga
      V.01: Retry-interval shortened for all FP models   * 9/12/'21
      using Adafruit_Fingereprint library and examples,
      with BSD license, described in the bottom of this sketch.
*******************************************************************/
#include "Adafruit_Fingerprint.h"
#define sRx 2
#define sTx 3
SoftwareSerial sSer(sRx, sTx);
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&sSer);

void setup() { // ***** Arduino setup() *****
  Serial.begin(9600);
  Serial.println(F("\n*FP identification*"));
  finger.begin(57600);
  if (finger.verifyPassword() == false) {
    Serial.println(F("No sensor :("));
    while (true) {}
  }
  finger.getTemplateCount();
  if (finger.templateCount == 0) {
    Serial.print(F("No template"));
    while (true) {};
  }
}
void loop() { // ***** Arduino loop() *****
  Serial.print(F("\nPlace finger."));
  while (finger.getImage() != FINGERPRINT_OK) {
  }
  while (finger.image2Tz() != FINGERPRINT_OK) {
  }
  uint8_t p = finger.fingerSearch();
  if (p == FINGERPRINT_OK) {
    uint8_t fID = finger.fingerID;
    uint8_t fCf = finger.confidence;
    Serial.print(F("\n*** Match! with #")) ;
    Serial.print(fID);
    Serial.print(F(" confidence="));
    Serial.println(fCf);
    delay(5000);
  } else if (p == FINGERPRINT_NOTFOUND) {
    Serial.println(F("\n*** No match!"));
    delay(1500);          // wait after unmatch
  } else {
  }                       // in other cases, do nothing
  delay(500);             // loop in a slow pace
}
/*******************************************************************
  This is an example sketch for our optical Fingerprint sensor
  Designed specifically to work with the Adafruit BMP085 Breakout
  ----> http://www.adafruit.com/products/751
  These displays use TTL Serial to communicate, 2 pins are required to
  interface
  Adafruit invests time & resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!
  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution.
*******************************************************************/
// ***** end of program *****

 

これで照合をするとArduino IDEのシリアルに結果が正しく出ます。指の置き方によってリジェクト(FRR)が出ることがありますが、指の置き方をやり直せばよいだけです。

間違い容認(FAR)のほうは色々やっても全く生じません。たいしたものです!!

Arduino IDEのシリアル出力は次のようなものです。


*FP identification*

Place finger.
*** No match!

Place finger.
*** Match! with #1 confidence=169

Place finger.

Confidenceは合致のスコア集計数値です。50ぐらい以上が合致とされるようですが、セキュリティレベルの設定によってその閾値が決まるようです。セキュリティレベルの設定は今後やってみることにします。

 

プロトコルの確認

センサーとはどのようなやり取りをしているでしょうか。オシロで観察します。

最初のパスワード確認プロトコルは次のもの。

f:id:a-tomi:20210903212641j:plain

意外に単純そうですね。それなら、というわけでロジックアナライザーでやり取りを確認してみました。これは照合ですがプロトコルはわりと単純で意外にスピーディです。

f:id:a-tomi:20210903212731j:plain

f:id:a-tomi:20210903212743j:plain

全体をデコードした例が次です。

	Time [s]	Decoded 
	Tx	
	0.0000000	0xEF
	0.00018625	0x01
	0.0003795	0xFF
	0.00056525	0xFF
	0.00075125	0xFF
	0.00093725	0xFF
	0.0011230	0x01
	0.00131675	0x00
	0.00150425	0x07
	0.00169225	0x13
	0.0018805	0x00
	0.00206925	0x00
	0.0022580	0x00
	0.0024530	0x00
	0.00264150	0x00
	0.00282950	0x1B
	Rx	
	0.00395725	0xEF
	0.00414875	0x01
	0.00434025	0xFF
	0.00453175	0xFF
	0.00472325	0xFF
	0.0049150	0xFF
	0.0051065	0x07
	0.0052980	0x00
	0.0054895	0x03
	0.0056810	0x00
	0.0058725	0x00
	0.0060640	0x0A
	Tx	
	0.00634925	0xEF
	0.0065415	0x01
	0.00672875	0xFF
	0.0069145	0xFF
	0.0070945	0xFF
	0.00728025	0xFF
	0.00747225	0x01
	0.0076600	0x00
	0.00784725	0x03
	0.00803575	0x1D
	0.0082235	0x00
	0.0084115	0x21
	Rx	
	0.00975175	0xEF
	0.00994325	0x01
	0.0101350	0xFF
	0.0103265	0xFF
	0.0105180	0xFF
	0.0107095	0xFF
	0.01090125	0x07
	0.01109275	0x00
	0.01128425	0x05
	0.01147575	0x00
	0.0116675	0x00
	0.0118590	0x09
	0.01205075	0x00
	0.01224225	0x15
	Tx	
	0.01254425	0xEF
	0.0127365	0x01
	0.01292375	0xFF
	0.0131095	0xFF
	0.0132955	0xFF
	0.0134815	0xFF
	0.01368125	0x01
	0.01386875	0x00
	0.01405625	0x03
	0.0142445	0x01
	0.01443275	0x00
	0.01463475	0x05
	Rx	
	0.095171	0xEF
	0.0953625	0x01
	0.095554	0xFF
	0.0957455	0xFF
	0.095937	0xFF
	0.0961285	0xFF
	0.096320	0x07
	0.0965115	0x00
	0.096703	0x03
	0.0968945	0x02
	0.097086	0x00
	0.0972775	0x0C

 

データシートに基づいてコマンドとレスポンスをよく整理すれば、Arduino以外のマイコンでも使えるようになりそうですね。今後のお楽しみとして。。

単体で使える形に

ここまでで、このセンサーが優れものであることと、うまく扱えることがよくわかりました。

Arduino単体で動かす例として、とりあえずはLCD出力をしてみました。それがこの記事冒頭の写真です。テストの様子の動画は次です。

youtu.be

この例のスケッチは次です。

(この型の指紋センサーの他のモデルでも動くよう、スケッチを2021.09.12に更新しました。それをつけます。)

/*******************************************************************
   Fingerprint identification & show the results to LCD   V.01
      Initial version: Aug.23, 2021  modified by Akira Tominaga
      V.01: Retry-interval shortened for all FP models * 9/12/'21
      using Adafruit_Fingereprint library and examples,
      with BSD license, described in the bottom of this sketch.
*******************************************************************/
#include "Adafruit_Fingerprint.h"
#include "Wire.h"
#include "LiquidCrystal_I2C.h"
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set address and pins
#define lcdC 20
#define lcdL 4
#define sRx 2
#define sTx 3
SoftwareSerial sSer(sRx, sTx);
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&sSer);

void setup() { // ***** Arduino setup() *****
  Serial.begin(9600);           // init. h/w serial for debug
  lcd.begin(20, 4);             // init. 20 x 4 LCD
  lcd.backlight();              // turn on lcd-backlight
  lcd.setCursor(0, 0);
  lcd.print(F("* Fingerprint test *"));
  lcd.setCursor(1, 3);
  lcd.print(F("(a-tomi.hatenablog)"));
  finger.begin(57600);          // init sSer and finger
  if (finger.verifyPassword() == false) {
    lcd.setCursor(3, 1);
    lcd.print(F("Error: No sensor."));
    while (true) {}
  }
  finger.getTemplateCount();
  if (finger.templateCount == 0) {
    lcd.setCursor(1, 1);
    lcd.print(F("Error: No template."));
    while (true) {};
  }
}
void loop() { // ***** Arduino loop() *****
  lcd.setCursor(2, 1);
  lcd.print(F("Place finger...   "));
  while (finger.getImage() != FINGERPRINT_OK) {
    lcd.setCursor(2, 2);
    lcd.print("  ...             ");
  }
  while (finger.image2Tz() != FINGERPRINT_OK) {
    lcd.setCursor(2, 2);
    lcd.print("  ,,,              ");
  }
  uint8_t p = finger.fingerSearch();
  if (p == FINGERPRINT_OK) {
    uint8_t fID = finger.fingerID;
    uint8_t fCf = finger.confidence;
    lcd.setCursor(2, 1);
    lcd.print(F("Match! with ID="));
    lcd.print(fID);
    lcd.setCursor(2, 2);
    lcd.print(F("confidence = "));
    lcd.print(fCf);
    lcd.print("  ");
    delay(5000);
  } else if (p == FINGERPRINT_NOTFOUND) {
    lcd.setCursor(2, 1);
    lcd.print(F("No match!         "));
    lcd.setCursor(2, 2);
    lcd.print(F("                  "));
    delay(2500);          // wait after unmatch
  } else {
  }                       // in other cases, do nothing
  delay(500);             // loop in a slow pace
}
/*******************************************************************
  This is an example sketch for our optical Fingerprint sensor
  Designed specifically to work with the Adafruit BMP085 Breakout
  ----> http://www.adafruit.com/products/751
  These displays use TTL Serial to communicate, 2 pins are required to
  interface
  Adafruit invests time & resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!
  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution.
*******************************************************************/
// ***** end of program *****

 

おまけですが、単にLEDでどの指かを示す装置。

f:id:a-tomi:20210903213537j:plain



おわりに

これなら指紋認証ロックなどはとても簡単にできそうですね。そのうち応用したいと思います。

以上、自分用の記録も兼ねて少し冗長でしたが、何らかのお役に立てば幸いです。

 

©2021 Akira Tominaga, All rights reserved.