部品 · 読了まで15分

Arduino指紋センサーガイド:AS608、R307とドアロック

Arduinoで指紋センサーを使う方法を解説します。AS608/R307の配線の色と電源、Adafruit Fingerprintによる登録と照合、リレー式ドアロック、ESP32での使い方とトラブル対処まで。

指紋センサーを使うと、Arduinoのプロジェクトがワンタッチで「誰ですか?」と問いかけ、登録された指を認識したときにドアや引き出し、金庫を開けられるようになります。ホビー電子工作で最もよく使われるのは、AS608やR307をベースにした光学式モジュールです。指の画像をモジュール内部で処理し、指紋を自分のメモリに保存して、Arduinoには「ID 3と一致」のような短い答えだけを返します。そのため、Arduino Unoのような小さなボードでも、数百人分の指紋ロックを楽に動かせます。

このガイドでは、センサーの仕組み、メーカーによって配線の色が違っても正しく接続する方法、Adafruit Fingerprintライブラリを使った指紋の登録(enroll)と照合、IDと信頼度スコアの意味を学びます。続いて、リレーと12 Vのソレノイドで実際のドアロックを作り、同じことをESP32とRaspberry Pi Picoでも行い、悪名高い「Did not find fingerprint sensor」エラーを一歩ずつ解決します。

6線のコネクターが付いたAS608光学式指紋センサー
AS608光学式指紋センサー:プリズム付きの読み取り窓、画像を処理するDSPチップ、細い線のコネクターセット。配線の色は販売店によって異なります。

指紋センサーとは?仕組みを解説

AS608やR307のようなモジュールは光学式センサーです。ガラスに指を置くと、内部のLEDがその下にあるプリズムを照らします。指紋の隆線(山の部分)はガラスに触れるため光の反射が変わり、谷線(溝の部分)は触れません。小さなカメラがこの模様を約500 dpiのグレースケール画像として撮影します。モジュール内のDSPチップは、隆線が途切れたり分岐したりする点(特徴点、minutiae)を抽出し、数百バイトの特徴ファイル(character file)に変換します。同じ指から取った2つの特徴ファイルを組み合わせるとテンプレートができ、このテンプレートがID番号とともにセンサー自身のフラッシュメモリに保存されます。

照合のときは、センサーが新しい画像を再び特徴ファイルに変換し、保存されているすべてのテンプレートと比較します。この1:N検索は通常1秒もかからずに終わり、最後にセンサーは一致したIDと、一致の強さを示す信頼度スコア(confidence)を返します。ポイントは、指紋の画像がArduinoに届くことは一切なく、重い処理はすべてセンサー内で行われることです。Arduinoはシリアルポート(UART)経由でコマンドを送り、短い返答を読むだけです。

項目AS608モジュールR307FPM10A / ZFM-20
電源電圧3.3 V4.2〜6 V(通常は5 V)3.6〜6 V
登録可能数通常300(一部のボードは162)1000162
インターフェースUART(TTL)、初期値57600 bpsUART(TTL)、初期値57600 bpsUART(TTL)、初期値57600 bps
タッチ検出ピンあり(WAK + Vt)あり(Touch + 3.3VT)ほとんどなし
セキュリティレベル1〜51〜51〜5
他人受入率(FAR)< 0.001%< 0.001%< 0.001%
ArduinoライブラリAdafruit FingerprintAdafruit FingerprintAdafruit Fingerprint

表の値は販売店やボードのリビジョンによって異なることがあり、特に登録可能数はばらつきます。最も確実なのは、下のテストスケッチを実行して、センサー自身が報告する容量を読むことです。ここで3つの用語も整理しておきましょう。IDはメモリ内でのテンプレートの格納番号(0から「容量−1」まで)、セキュリティレベルは1(最も緩い)から5(最も厳しい)までの段階で照合のしきい値を決めるもの、信頼度スコアは一致するたびにセンサーが返す類似度のスコアです。

配線の色と電源:どの線をどこにつなぐ?

指紋センサーで最も多い失敗は、配線の色が標準だと思い込むことです。同じモデルでも、ある販売店では赤・黒・黄・白、別の販売店では赤・黒・緑・青の線で届くことがあり、Adafruitでさえセンサーのバージョンごとに異なる色の配置を載せています。ですから色で判断せず、センサーの裏やコネクターの横にあるピン表記と、販売店の図を確認してください。AS608モジュールのピンは通常6本で、V+(Vi)、TX、RX、GND、WAK(Touch)、Vt(3.3VT)です。基本的な使い方なら最初の4本だけで十分です。

センサーのピン機能Arduino UnoESP32Raspberry Pi Pico
V+ / Vi / VCC電源3.3V(AS608)または5V(R307)3V3(R307は5V/VIN)3V3(OUT)(R307はVBUS)
GNDグラウンドGNDGNDGND
TXセンサーからのデータ出力D2(SoftwareSerialのRX)GPIO 16(RX2)GP1(UART0 RX)
RXセンサーへのデータ入力D3(SoftwareSerialのTX)GPIO 17(TX2)GP0(UART0 TX)
WAK / Touch指検出信号(任意)D4GPIO 27GP2
Vt / 3.3VTタッチ回路用の電源(任意)3.3V3V33V3(OUT)
ほとんどのAS608ボードは3.3 Vで動作し、3.3V表記のセンサーに5 Vを加えると、壊れて元に戻らないことがあります。一方R307は5 Vが必要で、3.3 Vではまったく反応しないこともよくあります。Unoの3.3Vピンは公式には50 mAまでしか流せませんが、光学式センサーは画像を撮影するときにより多くの電流を消費します(Adafruitは自社の光学式センサーの動作電流を最大120 mAとしています)。ボードがランダムにリセットしたり、センサーがたびたび見つからなくなったりする場合は、AMS1117のような外部の3.3 Vレギュレーターからセンサーに電源を供給し、GNDを共通にしてください。UnoのD3ピンは5 Vを出力するので、3.3 VセンサーのRXラインに1 kΩ + 2 kΩの分圧回路を入れるのが最も安全です。

WAK(またはTouch)ピンは、センサーの低消費電力なタッチ検出回路につながっています。Vtピンに3.3 Vを加えておくと、指がガラスに触れた瞬間に信号レベルが変わります。多くのモジュールではHIGHになりますが、LOWになるものもあるので、手元のボードで確かめてください。電池駆動のロックなら、MOSFETでメイン電源を切ってVtだけに電源を残し、WAK信号でマイコンをスリープから起こしてから、そのときだけセンサーをオンにする使い方ができます。

Adafruit Fingerprintライブラリのインストール

  1. Arduino IDEで「ツール」>「ライブラリを管理」を開き、Adafruit Fingerprint Sensor Libraryを検索してインストールします。ライブラリを追加したことがなければ、Arduinoにライブラリを追加する方法を参照してください。
  2. このライブラリは、AS608、R307、R503、FPM10A、ZFMシリーズなど、同じコマンドセットを使うすべてのセンサーで動きます。コードの変更は不要です。
  3. 「ファイル」>「スケッチ例」には、enroll(登録)、fingerprint(照合)、delete(1件削除)、emptyDatabase(全件削除)の例があります。
  4. UnoやNanoでは、センサーをSoftwareSerialでD2とD3につなぐので、USB接続が使う0番ピンと1番ピンをふさぎません。Mega、Leonardo、ESP32のように2つ目のハードウェアシリアルポートを持つボードでは、Serial1やSerial2を使います。

最初のテスト:センサーは見つかる?

登録の前に、センサーがArduinoと通信できているか確かめましょう。下のスケッチは、まず初期値の57600 bpsでセンサーを探し、見つからなければほかのよく使われるボーレートを試します。センサーが見つかると、応答したボーレート、報告された容量、セキュリティレベル、保存されている指紋の数をシリアルモニタに表示します。シリアルモニタは9600 baudに設定するのを忘れないでください。これはセンサーの通信速度とは関係ありません。

C++ (Arduino IDE)
1#include <Adafruit_Fingerprint.h>
2#include <SoftwareSerial.h>
3
4SoftwareSerial fpSerial(2, 3);            // D2 = RX (sensör TX), D3 = TX (sensör RX) / D2 = RX (sensor TX), D3 = TX (sensor RX)
5Adafruit_Fingerprint finger(&fpSerial);
6
7const uint32_t rates[] = {57600, 9600, 19200, 38400, 115200};   // denenecek hızlar / baud rates to try
8
9void setup() {
10  Serial.begin(9600);
11  Serial.println(F("Sensor araniyor / searching for sensor..."));
12  bool found = false;
13  for (uint8_t i = 0; i < 5 && !found; i++) {
14    finger.begin(rates[i]);               // 1 sn bekler, portu açar / waits 1 s, opens the port
15    if (finger.verifyPassword()) {        // sensör cevap verdi mi? / did the sensor answer?
16      Serial.print(F("Bulundu / found @ "));
17      Serial.println(rates[i]);
18      found = true;
19    }
20  }
21  if (!found) {
22    Serial.println(F("Did not find fingerprint sensor :("));
23    while (1) delay(1);
24  }
25  finger.getParameters();                 // kapasite ve ayarları oku / read capacity and settings
26  Serial.print(F("Kapasite / capacity: "));
27  Serial.println(finger.capacity);
28  Serial.print(F("Guvenlik / security level: "));
29  Serial.println(finger.security_level);
30  finger.getTemplateCount();              // kayıtlı şablon sayısı / number of stored templates
31  Serial.print(F("Kayitli iz / templates: "));
32  Serial.println(finger.templateCount);
33}
34
35void loop() {
36}

指紋をステップごとに登録する

登録では、センサーが同じ指の画像を2回別々に撮影し、2つのバッファー(CharBuffer1とCharBuffer2)に特徴ファイルとして保存して、それらを1つのテンプレートにまとめ、選んだIDに書き込みます。Adafruitに付属のenroll例は1〜127のIDを尋ね、1バイトの変数に格納します。下の簡略版はIDを16ビットで保持し、上限をセンサーの実際の容量から取得するので、300件や1000件のセンサーのすべての枠を使えます。ライブラリの手順は次のとおりです。

  1. getImage():ガラスの上に指が置かれるまで画像の撮影を試み続けます。指がないときはFINGERPRINT_NOFINGERを返します。
  2. image2Tz(1):1枚目の画像を特徴ファイルに変換し、バッファー1に入れます。
  3. 指をいったん離し、同じ指をもう一度置きます。image2Tz(2)が2枚目の画像をバッファー2に入れます。
  4. createModel():2つのバッファーを比較してまとめます。一致しなければFINGERPRINT_ENROLLMISMATCHを返します。
  5. storeModel(id):テンプレートをセンサーのフラッシュメモリに永続的に書き込みます。電源が切れても消えません。
C++ (Arduino IDE)
1#include <Adafruit_Fingerprint.h>
2#include <SoftwareSerial.h>
3
4SoftwareSerial fpSerial(2, 3);            // D2 = RX, D3 = TX
5Adafruit_Fingerprint finger(&fpSerial);
6
7void setup() {
8  Serial.begin(9600);
9  finger.begin(57600);
10  if (!finger.verifyPassword()) {
11    Serial.println(F("Did not find fingerprint sensor :("));
12    while (1) delay(1);
13  }
14  finger.getParameters();                 // gerçek kapasiteyi öğren / learn the real capacity
15  Serial.println(F("Kayit modu / enroll mode"));
16}
17
18// Parmak gelene kadar bekle, görüntüyü tampona çevir / wait for a finger, convert the image into a buffer
19bool captureTo(uint8_t slot) {
20  while (finger.getImage() != FINGERPRINT_OK) delay(50);
21  uint8_t p = finger.image2Tz(slot);
22  if (p != FINGERPRINT_OK) {
23    Serial.print(F("Goruntu kotu / bad image, kod / code 0x"));
24    Serial.println(p, HEX);
25    return false;
26  }
27  return true;
28}
29
30void loop() {
31  Serial.print(F("ID gir / enter ID (1-"));
32  Serial.print(finger.capacity - 1);
33  Serial.println(F("):"));
34  while (!Serial.available()) delay(10);
35  uint16_t id = Serial.parseInt();
36  while (Serial.available()) Serial.read();   // satır sonunu temizle / clear the line ending
37  if (id == 0 || id >= finger.capacity) return;
38
39  Serial.println(F("Parmagini koy / place your finger"));
40  if (!captureTo(1)) return;
41  Serial.println(F("Kaldir / remove your finger"));
42  delay(1000);
43  while (finger.getImage() != FINGERPRINT_NOFINGER) delay(50);   // parmak kalkana kadar / until the finger is lifted
44
45  Serial.println(F("Ayni parmagi tekrar koy / place the same finger again"));
46  if (!captureTo(2)) return;
47
48  uint8_t p = finger.createModel();       // iki görüntüyü birleştir / merge the two images
49  if (p == FINGERPRINT_ENROLLMISMATCH) {
50    Serial.println(F("Fingerprints did not match"));
51    return;
52  }
53  if (p != FINGERPRINT_OK) return;
54
55  p = finger.storeModel(id);              // sensörün flash belleğine yaz / write to the sensor's flash
56  if (p == FINGERPRINT_OK) {
57    Serial.print(F("Kaydedildi / stored, ID #"));
58    Serial.println(id);
59  } else {
60    Serial.print(F("Kayit hatasi / store error 0x"));
61    Serial.println(p, HEX);
62  }
63}
シリアルモニタにIDを入力してEnterを押し、指示に従います。登録の質が、その後のすべての照合の質を決めます。指はガラスの中央に強く押しつけずに置き、2枚目の画像では角度をほんの少しだけ変えてください。毎日使うロックなら、同じ指を2つの異なるIDで登録する(1回は平らに、1回は少し傾けて)と、拒否される率がはっきり下がります。どのIDが誰のものかはメモしておきましょう。センサーが知っているのは番号だけで、名前は知りません。

指紋の照合:IDと信頼度スコア

照合では、まずgetImage()で画像を撮影してimage2Tz()で変換し、それから保存済みのテンプレートを検索します。ライブラリには検索関数が2つあります。fingerFastSearch()は高速ですが、ライブラリが送るコマンドは最初の163件(ID 0〜162)しか調べません。fingerSearch()はgetParameters()で読み取った容量全体を検索します。162より大きいIDを使うならfingerSearch()を使い、setup()で必ずgetParameters()を呼んでください。呼ばないと、ライブラリは初期値の容量64を前提にして、最初の64件しか検索しません。

検索が成功すると、finger.fingerIDで一致した記録の番号が、finger.confidenceで信頼度スコアが得られます。一致するかどうかは、センサーがセキュリティレベルに基づいてすでに判定しており、スコアは一致の強さを示すだけです。きちんと登録された指なら、スコアはだいたい数十から数百の間に収まります。より厳しいロックにしたい場合は、setSecurityLevel(4)やsetSecurityLevel(5)でしきい値を上げるか、コード内に独自の下限を加えます(たとえば50未満はすべて拒否する)。しきい値を高くすると他人を受け入れてしまう可能性は下がりますが、本人を拒否してしまう可能性は上がります。自分の指で試しながらバランスを見つけてください。

戻り値シリアルモニタのメッセージ意味と対処
FINGERPRINT_OK (0x00)Image taken / Stored!(撮影完了 / 保存完了)処理が成功しました。
FINGERPRINT_NOFINGER (0x02)No finger detected(指が検出されない)ガラスに指がありません。ループ内で待ち続けます。
FINGERPRINT_PACKETRECIEVEERR (0x01)Communication error(通信エラー)応答パケットを受信できません。配線、ボーレート、電源を確認してください。
FINGERPRINT_IMAGEFAIL (0x03)Imaging error(撮影エラー)画像を撮影できませんでした。指を置き直してください。
FINGERPRINT_IMAGEMESS (0x06)Image too messy(画像が乱れている)画像がぼやけています。ガラスを掃除してください。指が湿りすぎているか、乾きすぎている可能性もあります。
FINGERPRINT_FEATUREFAIL (0x07)Could not find fingerprint features(特徴点が見つからない)特徴が足りません。指を中央に置き、軽く押してください。
FINGERPRINT_NOTFOUND (0x09)Did not find a match(一致なし)一致する記録がありません。指が登録されていないか、うまく登録できていなかった可能性があります。
FINGERPRINT_ENROLLMISMATCH (0x0A)Fingerprints did not match(2回の指紋が一致しない)登録時の2枚の画像が一致しませんでした。もう一度やり直してください。
FINGERPRINT_BADLOCATION (0x0B)Could not store in that location(その位置に保存できない)IDが容量の範囲外です。getParameters()で上限を読み取ってください。
FINGERPRINT_FLASHERR (0x18)Error writing to flash(フラッシュ書き込みエラー)センサーのメモリに書き込めませんでした。電源と配線を確認してください。

リレーとソレノイドで作る指紋ドアロック

では、すべてを組み合わせて、登録済みの指なら3秒間開き、未登録の指なら3回ビープ音を鳴らし、5回続けて失敗するとシステムを30秒間ロックするドアロックを作りましょう。ロックには12 Vのソレノイドロックを使います。ソレノイドは0.5〜1 Aの電流を消費するので、絶対にArduinoのピンに直接つないではいけません。間にリレーモジュールかロジックレベルMOSFETを入れてください。配線は次のとおりです。リレーモジュールのVCCとGNDをArduinoの5VとGNDに、INピンをD8に、アクティブブザーをD9につなぎます。12 VのACアダプターのプラスをリレーのCOM端子に、リレーのNO端子をソレノイドのプラスに、ソレノイドのマイナスをアダプターのマイナスにつなぎます。

ソレノイドはコイルなので、電流を切った瞬間に高い逆起電圧が発生します。そのため、ソレノイドと並列に1N4007のダイオードを逆向きにつないでください。ダイオードの帯のある側をプラス側にします。リレーの代わりにMOSFETを使う場合は、IRLZ44NのようなロジックレベルのMOSFETを選び、12 V電源のマイナスをArduinoのGNDにつなぎます。詳しくはMOSFETで大電流を駆動するを、MOSFETのピンの並びはトランジスタのピン配置ツールで確認してください。

C++ (Arduino IDE)
1#include <Adafruit_Fingerprint.h>
2#include <SoftwareSerial.h>
3
4SoftwareSerial fpSerial(2, 3);            // D2 = RX, D3 = TX
5Adafruit_Fingerprint finger(&fpSerial);
6
7const int RELAY_PIN = 8;                  // röle modülü IN / relay module IN
8const int BUZZER_PIN = 9;                 // aktif buzzer / active buzzer
9const uint8_t RELAY_ON = LOW;             // çoğu röle modülü LOW ile çeker / most relay modules switch on LOW
10const uint8_t RELAY_OFF = HIGH;
11const uint16_t MIN_CONFIDENCE = 50;       // ek güven eşiği / extra confidence threshold
12const unsigned long OPEN_MS = 3000;       // kilidin açık kalma süresi / unlock time
13
14uint8_t failCount = 0;
15
16void setup() {
17  digitalWrite(RELAY_PIN, RELAY_OFF);     // açılışta kilitli kalsın / stay locked at power-up
18  pinMode(RELAY_PIN, OUTPUT);
19  pinMode(BUZZER_PIN, OUTPUT);
20  Serial.begin(9600);
21  finger.begin(57600);
22  if (!finger.verifyPassword()) {
23    Serial.println(F("Did not find fingerprint sensor :("));
24    while (1) delay(1);
25  }
26  finger.getParameters();                 // fingerSearch için kapasite / capacity for fingerSearch
27}
28
29// Eşleşen ID; parmak yoksa -1, tanınmadıysa -2 / matching ID; -1 no finger, -2 not recognised
30int readFinger() {
31  if (finger.getImage() != FINGERPRINT_OK) return -1;
32  if (finger.image2Tz(1) != FINGERPRINT_OK) return -2;
33  if (finger.fingerSearch(1) != FINGERPRINT_OK) return -2;
34  if (finger.confidence < MIN_CONFIDENCE) return -2;
35  return finger.fingerID;
36}
37
38void beep(int count, int ms) {
39  for (int i = 0; i < count; i++) {
40    digitalWrite(BUZZER_PIN, HIGH);
41    delay(ms);
42    digitalWrite(BUZZER_PIN, LOW);
43    delay(ms);
44  }
45}
46
47void loop() {
48  int id = readFinger();
49  if (id >= 0) {
50    Serial.print(F("Hos geldin / welcome, ID #"));
51    Serial.print(id);
52    Serial.print(F(", guven / confidence "));
53    Serial.println(finger.confidence);
54    failCount = 0;
55    beep(1, 100);
56    digitalWrite(RELAY_PIN, RELAY_ON);    // kilidi aç / unlock
57    delay(OPEN_MS);
58    digitalWrite(RELAY_PIN, RELAY_OFF);   // yeniden kilitle / lock again
59  } else if (id == -2) {
60    failCount++;
61    Serial.println(F("Yetkisiz / not authorised"));
62    beep(3, 80);
63    if (failCount >= 5) {                 // 5 hatada 30 sn bekle / 30 s lockout after 5 failures
64      Serial.println(F("30 sn kilitli / locked for 30 s"));
65      delay(30000);
66      failCount = 0;
67    }
68    delay(1000);
69  }
70  delay(50);
71}
このプロジェクトは学習や趣味にはぴったりですが、それだけでは本格的なセキュリティシステムとはいえません。光学式センサーはよくできた指紋の型でだませることがありますし、配線に手が届く人ならリレーを直接動かせてしまいます。実際のドアに使う場合は、電子回路を室内側に置き、機械式の鍵など別の開け方を残し、停電時にロックがどうなるかも考えておきましょう。箱型のソレノイドは通常、電源がないとロックされたままですが、電磁ロックは開いてしまいます。ソレノイドに長時間通電したままにしないでください。コイルが熱くなって壊れることがあります。

ESP32で指紋センサーを使う:Serial2での接続

ESP32にはハードウェアシリアルポートが3つあるので、SoftwareSerialは不要で、センサーをUART2(Serial2)につなぎます。ESP32は3.3 Vで動作するため、AS608の信号レベルとぴったり合い、分圧回路もいりません。注意が必要なのはピンだけです。現在のArduino-ESP32コア(3.x)では、Serial2の初期ピンは古いチュートリアルにあるようなGPIO 16/17ではなく、GPIO 4(RX)とGPIO 25(TX)になっています。そのため、ピンをSerial2.begin()に明示的に渡してください。ライブラリのbegin()は、先に設定したピンをそのまま使います。手元のボードのピン配置はピン配置ツールで確認できます。

C++ (Arduino IDE)
1#include <Adafruit_Fingerprint.h>
2
3#define FP_RX 16                          // ESP32 RX2 <- sensör TX / sensor TX
4#define FP_TX 17                          // ESP32 TX2 -> sensör RX / sensor RX
5const int RELAY_PIN = 23;                 // röle modülü IN / relay module IN
6
7Adafruit_Fingerprint finger(&Serial2);
8
9void setup() {
10  Serial.begin(115200);
11  pinMode(RELAY_PIN, OUTPUT);
12  digitalWrite(RELAY_PIN, HIGH);          // LOW tetiklemeli röle kapalı / active-LOW relay off
13  Serial2.begin(57600, SERIAL_8N1, FP_RX, FP_TX);   // pinleri açıkça ver / set the pins explicitly
14  finger.begin(57600);                    // önceki pinleri korur / keeps the pins set above
15  if (!finger.verifyPassword()) {
16    Serial.println("Did not find fingerprint sensor :(");
17    while (true) delay(10);
18  }
19  finger.getParameters();
20  finger.getTemplateCount();
21  Serial.printf("Kapasite / capacity: %u, kayitli / stored: %u\n", finger.capacity, finger.templateCount);
22}
23
24void loop() {
25  if (finger.getImage() == FINGERPRINT_OK && finger.image2Tz(1) == FINGERPRINT_OK) {
26    if (finger.fingerSearch(1) == FINGERPRINT_OK) {
27      Serial.printf("ID #%u, guven / confidence %u\n", finger.fingerID, finger.confidence);
28      digitalWrite(RELAY_PIN, LOW);       // kilidi aç / unlock
29      delay(3000);
30      digitalWrite(RELAY_PIN, HIGH);      // yeniden kilitle / lock again
31    } else {
32      Serial.println("Did not find a match");
33      delay(1000);
34    }
35  }
36  delay(50);
37}

ESP32-WROVERモジュールを搭載したボードでは、GPIO 16と17がPSRAMに使われています。このようなボードでは、FP_RXとFP_TXをたとえば25と26に変更してください。ESP32-C3にはUARTが2つしかないのでSerial2はありませんが、同じコードをSerial1と好きな2本のピンで使えます。Wi-Fiがあるので、入室のたびにタイムスタンプ付きでサーバーに記録したり、未登録の指を検出したときにTelegramボットでスマホに通知を送ったりできます。

Raspberry Pi PicoとMicroPythonで指紋センサーを使う

AdafruitのライブラリにはMicroPython版の公式なものはありませんが、センサーのプロトコルは単純なので、数行のコードで直接やり取りできます。すべてのパケットは開始コードEF 01で始まり、そのあとに4バイトのアドレス(初期値はFF FF FF FF)、パケットの種類(01がコマンド、07が応答)、2バイトの長さ、コマンドとそのパラメーター、最後に種類・長さ・データのバイトを合計した2バイトのチェックサムが続きます。応答の最初のデータバイトは確認コードで、00が成功、02が指なし、09が一致なしです。下のコードはセンサーを確認して容量を読み取り、ガラスの上の指をIDと信頼度スコアで識別します。Picoは3.3 Vで動作するので、AS608を3V3(OUT)ピンに直接つなげます。Picoが初めてなら、Raspberry Pi Picoとは?から始めるとよいでしょう。

MicroPython
1from machine import UART, Pin
2import time
3
4# GP0 = UART0 TX -> sensör RX, GP1 = UART0 RX <- sensör TX / sensor RX, sensor TX
5uart = UART(0, baudrate=57600, tx=Pin(0), rx=Pin(1), timeout=2000, timeout_char=100)
6HEADER = b'\xEF\x01\xFF\xFF\xFF\xFF'          # başlangıç kodu + adres / start code + address
7
8def command(*data):
9    while uart.any():                          # eski baytları at / drop stale bytes
10        uart.read()
11    length = len(data) + 2                     # veri + 2 bayt sağlama / data + 2-byte checksum
12    body = bytes([0x01, length >> 8, length & 0xFF]) + bytes(data)   # 0x01 = komut paketi / command packet
13    s = sum(body)
14    uart.write(HEADER + body + bytes([(s >> 8) & 0xFF, s & 0xFF]))
15    head = uart.read(9)                        # başlık + tip + uzunluk / header + type + length
16    if not head or len(head) < 9 or head[0] != 0xEF:
17        return None
18    n = (head[7] << 8) | head[8]
19    rest = uart.read(n)
20    if not rest or len(rest) < n:
21        return None
22    return rest[:-2]                           # sağlama hariç veri / data without checksum
23
24def ok(r):
25    return r is not None and r[0] == 0x00      # 0x00 = başarılı / success
26
27time.sleep(1)                                  # sensörün açılmasını bekle / let the sensor boot up
28if not ok(command(0x13, 0, 0, 0, 0)):          # VfyPwd: şifre 0 / password 0
29    print("Did not find fingerprint sensor")
30    while True:
31        time.sleep(1)
32
33p = command(0x0F)                              # ReadSysPara: sistem parametreleri / system parameters
34capacity = (p[5] << 8) | p[6] if ok(p) else 162
35print("Kapasite / capacity:", capacity)
36
37def identify():
38    if not ok(command(0x01)):                  # GenImg: parmak yoksa 0x02 / 0x02 = no finger
39        return None
40    if not ok(command(0x02, 1)):               # Img2Tz: CharBuffer1'e çevir / convert into CharBuffer1
41        return (-1, 0)
42    r = command(0x04, 1, 0, 0, capacity >> 8, capacity & 0xFF)   # Search: tüm kayıtlar / all records
43    if not ok(r):
44        return (-1, 0)                         # 0x09 = eşleşme yok / no match
45    return ((r[1] << 8) | r[2], (r[3] << 8) | r[4])   # (ID, güven / confidence)
46
47while True:
48    res = identify()
49    if res:
50        fid, score = res
51        if fid >= 0:
52            print("ID", fid, "guven / confidence", score)
53        else:
54            print("Eslesme yok / no match")
55        time.sleep(1)
56    time.sleep_ms(100)

「Did not find fingerprint sensor」エラーとそのほかのよくある問題

このメッセージは、ライブラリのverifyPassword()コマンドに対して、センサーから有効な応答が返ってこなかったことを意味します。センサーが壊れているという意味ではありません。ほとんどの場合、原因は配線、電源、ボーレートの間違いのどれかです。下の表を上から順に確認してください。

症状考えられる原因対処
Did not find fingerprint sensor :((センサーが見つからない)TXとRXを同じ名前どうし(TX→TX)でつないでいるセンサーのTXはArduinoのRX(D2)へ、センサーのRXはTX(D3)へつなぎます。2本のデータ線を入れ替えても壊れることはないので、試してみてください。
Did not find fingerprint sensor :((センサーが見つからない)配線の色を信じているボード上のピン表記か販売店の図に従って配線し直し、GNDはテスターで確認します。
Did not find fingerprint sensor :((センサーが見つからない)電源が間違っている、または足りないAS608には3.3 V、R307には5 Vを供給します。Unoの3.3Vピンで足りなければ外部レギュレーターを使い、GNDを共通にします。
Did not find fingerprint sensor :((センサーが見つからない)センサーが別のボーレートで動いている最初のテストスケッチでボーレートのスキャンを実行し、見つかった値をfinger.begin()に入れます。
Did not find fingerprint sensor :((センサーが見つからない)センサーのパスワードが変更されているコンストラクターにパスワードを渡します:Adafruit_Fingerprint finger(&fpSerial, 0x12345678);
MegaやLeonardoでセンサーが見つからないSoftwareSerialはすべてのピンで受信できるわけではないSerial1を使います。MegaならRX1は19、TX1は18、LeonardoならRXは0、TXは1です。
ESP32でセンサーが見つからないSerial2の初期ピンが違う、またはPSRAMとの競合Serial2.begin(57600, SERIAL_8N1, RX, TX)でピンを明示的に指定します。WROVERでは16/17を使わないでください。
「Communication error」が頻繁に出るコネクターの緩み、長い線や細い線線は短くし、ブレッドボードではなくはんだ付けで接続し、電源に100 µFのコンデンサを追加します。
登録した指がよく拒否されるガラスの汚れ、指の乾燥や湿り、1つの角度でしか登録していない柔らかい布でガラスを拭き、同じ指を2つのIDで登録し、必要ならセキュリティレベルを2に下げます。
センサーが熱くなり、LEDがまったく点灯しない電源の逆接続、またはAS608に5 Vを加えたすぐに電源を切って配線を直してください。センサーが壊れている可能性があります。
問題を素早く絞り込むには、センサーをUSB-TTL変換モジュールにつなぎ、SFGDemoのようなWindows用のテストプログラムで確かめる方法があります。そこでセンサーが認識されれば、問題はArduino側の配線かコードにあります。また、シリアルモニタの速度(9600)とセンサーの速度(57600)は別物なので、混同しないようにしてください。

WaveshareのUART指紋リーダー:簡単な補足

WaveshareのUART指紋リーダーモジュールとコントローラーボード
Waveshare UART Fingerprint Reader:光学式センサーはフラットケーブルで、STM32F205プロセッサーを搭載した別のコントローラーボードにつながります。ボードにはVCCやGND、TXD、RXD、BL、RSTのピンがあります。

見た目は似ていますが、WaveshareのUART指紋リーダーはAS608やR307とは別のプロトコルを使います。コマンドは8バイト長で、先頭と末尾が0xF5になっており、初期速度は19200 bpsです。そのためAdafruit Fingerprintライブラリでは動かず、代わりにWaveshareのユーザーマニュアルにあるコマンド表とサンプルコードを使います。登録時には指を3回スキャンし、ユーザーごとに1〜3の権限レベルを設定でき、1:Nの照合は1つのコマンドで行えます。ボードは3.3 Vでも5 Vでも動作し、TXDをマイコンのRXに、RXDをTXにつなぎます。既製のライブラリやサンプルがたくさん欲しいならAS608かR307を、プロトコルのコードを自分で書くのが苦にならないならWaveshareがよい選択です。

指紋センサーを使ったプロジェクトのアイデア

  • 指紋で開く引き出しや金庫:サーボかソレノイドで開き、許可のない操作には警報を鳴らす小さな金庫です。サーボを使ったロック機構についてはサーボモーターとは?を参照してください。
  • 2段階認証のドア:まず指紋を、次にキーパッドでPINを求める、より安全な入口です。
  • カードか指か:同じロックにRFID RC522リーダーを追加し、カードを持っている人はカードで、それ以外の人は指で開けられるようにします。
  • 出席管理システム:学校やクラブ向けに各IDを名前と結びつけ、入室時刻を記録します。
  • ディスプレイ付きロック:OLEDディスプレイに歓迎メッセージとその人の名前を表示します。
  • ホームアラームと組み合わせる:指紋でセット・解除するArduinoのアラームシステムです。

数本の線と適切なライブラリがあれば、指紋センサーはプロジェクトに本物の本人確認の仕組みを加えてくれます。まずセンサーをテストし、指を丁寧に登録してから、リレーとソレノイドでロックを組み立てましょう。BlueGraysアプリには、スマート電子金庫、RFID認証、ESP32 RFIDドアロック、キーパッドのパスワードアプリといったセキュリティ系のプロジェクトがあり、どれもステップごとの回路図とコード付きなので、指紋センサーを追加するための土台としてそのまま使えます。

よくある質問

指紋センサーには何件の指紋を保存できますか?

モデルによって異なります。AS608ボードは通常300件(一部は162件)、R307は1000件、FPM10AとZFM-20は162件です。手元のセンサーの容量を知るには、getParameters()を呼んでfinger.capacityをシリアルモニタに表示してください。同じ指を2つのIDで登録すると、2枠使うことも覚えておきましょう。

指紋センサーは5Vと3.3Vのどちらで動きますか?

ほとんどのAS608ボードは3.3 Vが必要で、R307は4.2〜6 V、通常は5 Vで動作します。センサーのラベルと販売店の仕様を確認する前に電源を入れないでください。5 VのArduinoのTX出力を3.3 VセンサーのRXにつなぐときは、分圧回路を入れるのが最も安全です。

指紋はArduinoに保存されますか?電源を切ると消えますか?

いいえ、テンプレートはセンサー自身のフラッシュメモリに保存され、電源を切っても消えません。Arduinoを交換したり新しいコードを書き込んだりしても、記録はセンサーに残ります。Arduino側では、どのIDが誰のものかを管理するだけで済みます。必要ならそれをEEPROMに保存することもできます。

「Did not find fingerprint sensor」エラーはどう直せばいいですか?

まずTXとRXがクロスしているか確かめます。センサーのTXはArduinoのRXピン(UnoならD2)につなぎます。次に、電源の電圧が正しく電流が十分か、GNDが共通になっているかを確認します。それでも見つからない場合は、センサーが別のボーレートやパスワードを使っているのかもしれません。複数のボーレートを試すテストスケッチを実行してください。

AS608とR307の違いは何ですか?

どちらも同じコマンドセットを使う光学式センサーで、Adafruit Fingerprintライブラリの同じコードで動きます。主な違いは電源と容量です。AS608ボードは通常3.3 Vで動作して約300件を保存でき、R307は5 Vで動作して1000件まで保存できます。配線の前に、手元のモデルのラベルでピンの並びを確認してください。

保存した指紋はどうやって削除しますか?

1件だけ削除するにはfinger.deleteModel(id)を、すべて削除するにはfinger.emptyDatabase()を使います。ライブラリのdeleteとemptyDatabaseの例を使えば、シリアルモニタからこの操作ができます。削除したIDには、あとで新しい指紋を登録できます。

全プロジェクトを見る
スマート電子金庫
#92上級
プレミアム

スマート電子金庫

貴重品を保管できる、暗証番号で開く小さな金庫です。キーパッドで4桁の暗証番号を入力すると、正しければサーボモーターが解錠し、緑色のLEDが点灯してディスプレイに金庫の状態が表示されます。キーを押すたびにブザーが短く鳴ります。3回間違えると30秒間ロックアウトされます。暗証番号はいつでも変更でき、電源が切れても保持されます。

4.7(42)
63
ESP32のRFIDドアロック(RC522 + サーボモーター + OLED + ブザー + LED)
#137上級
プレミアム

ESP32のRFIDドアロック(RC522 + サーボモーター + OLED + ブザー + LED)

ESP32、RC522 RFIDモジュール、SG90サーボモーター、SSD1306 OLEDディスプレイ、アクティブブザー、LED2個を使ってスマートドアロックを作ります。カードを読み取ると、UIDをコード内に登録した許可済みカードの一覧と照合します。許可されたカードなら、サーボモーターを回して解錠し、緑色のLEDが点灯して短い音が2回鳴ります。5秒後に自動で施錠します。許可されていないカードでは赤色のLEDが点灯し、短い間隔で3回音を鳴らして警告し、読み取ったUIDをOLEDに表示します。実際のIoTセキュリティの仕組みを実践的に学べます。

4.8(9)
15
RFID認証
#54中級
プレミアム

RFID認証

マンションのカード式入館システムと同じ仕組みです。カードをRFIDリーダーに近づけると、Arduinoがカードの番号を登録済みの番号と比較します。登録済みのカードなら緑色、未登録のカードなら赤色のLEDが3秒間点灯し、結果はコンピューターの画面にも表示されます。カード式のドアや錠のプロジェクトの基礎をここで学べます。

4.8(64)
83
RFIDの値の読み取り
#53初級
プレミアム

RFIDの値の読み取り

建物のキーフォブや入館カードには、見えない識別番号が保存されています。このプロジェクトでは、その番号を読み取ります。カードをRFIDリーダーに近づけると、Arduinoがカードの番号をコンピューターの画面に表示します。カード式のドアや錠のプロジェクトで、どのカードに解錠を許可するかを決めるための第一歩です。

4.7(47)
61
4x4キーパッドとLCDで暗証番号ロック
#64上級
プレミアム

4x4キーパッドとLCDで暗証番号ロック

正しい暗証番号を知らないと開けられない、小さな電子ドアロックです。ハッシュキーを押してキーパッドから暗証番号を入力します。正しければ画面に入室許可が表示され、緑のLEDが点灯し、サーボモーターがドアを5秒間開けてから再び閉めます。間違っていれば赤のLEDが点灯します。建物や金庫のロックの仕組みを自分で作ります。

4.8(59)
75
ESP32 RFID RC522カードリーダー(LCD付き)
#123中級

ESP32 RFID RC522カードリーダー(LCD付き)

このプロジェクトでは、MFRC522を搭載したRC522 RFIDモジュールをSPIでESP32に接続し、カードやタグのUIDを読み取ります。ドアロック、会員システム、入退室管理などの基礎となる仕組みです。読み取ったUIDはLCDディスプレイに表示します。このバージョンでは、許可されたカードのリストとの照合は行いません。注意:RC522は3.3V専用です。5Vを供給するとモジュールが焼損します!

4.8(21)
39
リードスイッチ式ドアセンサー
#38初級
プレミアム

リードスイッチ式ドアセンサー

ライトを見るだけで、ドアが開いているか閉まっているか分かります。ドアに小さな磁石、ドア枠に磁石を検知するスイッチを取り付けます。ドアが閉まっているときは両者が並び、緑のLEDが点灯します。ドアが開いて磁石が離れると、赤いLEDが点灯します。家庭用警報装置のドアセンサーも、こんなシンプルな仕組みです。

4.7(34)
44
ESP32動体検知アラーム(PIR + ブザー + LED + Telegram)
#145上級
プレミアム

ESP32動体検知アラーム(PIR + ブザー + LED + Telegram)

PIRセンサーが動きを検知するとブザーとLEDを作動させ、同時にTelegramで持ち主に即座に通知するスマート防犯アラームです。アラームが繰り返される頻度を抑えるため、30秒のクールダウン(待ち時間)を設けています。この仕組みはPIRの検知が正しいかを確認したり、誤検知をなくしたりするものではありません。家の防犯、ガレージの監視、倉庫や作業部屋などに使えます。ESP32-CAMなら写真付きの通知を追加でき、通常のESP32 DevKit V1ではテキストで通知します。

0.0(0)
9