pdf-icon

Arduino入門

2. デバイス&サンプル

6. アプリケーション

Unit Fingerprint2 Arduino チュートリアル

1. 準備作業

2. 注意事項

ピン互換性
各ホストのピン配置が異なるため、ご使用前に製品ドキュメントのピン互換表を参照し、実際の配線に合わせてサンプルプログラムを修正してください。

3. サンプルプログラム

  • 本チュートリアルで使用するメインコントローラはCoreS3で、Unit Fingerprint2と組み合わせて使用します。本指紋認証モジュールはUART通信を採用しています。実際の配線に合わせてプログラム内のピン定義を修正してください。接続後の対応UART IOは G17 (RX)G18 (TX) です。

3.1 LED制御

指紋センサーにはRGB LEDが内蔵されており、PS_ControlBLN関数を使って色やモードを設定できます。必要に応じて以下の定義を利用してください。

PS_ControlBLN

関数プロトタイプ:

fingerprint_status_t PS_ControlBLN(
    fingerprint_led_control_mode_t mode,  
    fingerprint_led_color_t startColor,  
    fingerprint_led_color_t endColor,  
    uint8_t loopCount = 0             
) const;

パラメータ:

  • mode:LEDモード。下記fingerprint_led_control_mode_t参照。
  • startColor:開始色。下記fingerprint_led_color_t参照。通常のブリージングモードのみ有効。
  • endColor:終了色。下記fingerprint_led_color_t参照。
  • loopCount:ループ回数。0は無限ループ、NはN回ループ。ブリージング・フラッシュモードのみ有効。

戻り値:

  • FINGERPRINT_OK:成功
  • その他の値は失敗。詳細はライブラリのfingerprint_status_tを参照。

関連定義:

  • fingerprint_led_control_mode_t
typedef enum {
  FINGERPRINT_LED_BREATHING = 1,  // 普通呼吸灯 / Normal breathing light
  FINGERPRINT_LED_FLASHING  = 2,  // 闪烁灯 / Flashing light
  FINGERPRINT_LED_ON        = 3,  // 常开灯 / Always on
  FINGERPRINT_LED_OFF       = 4,  // 常闭灯 / Always off
  FINGERPRINT_LED_FADE_IN   = 5,  // 渐开灯 / Fade in
  FINGERPRINT_LED_FADE_OUT  = 6   // 渐闭灯 / Fade out
} fingerprint_led_control_mode_t;
  • fingerprint_led_color_t
typedef enum {
  FINGERPRINT_LED_COLOR_OFF    = 0x00,  // 全灭 / All off
  FINGERPRINT_LED_COLOR_BLUE   = 0x01,  // 蓝灯 / Blue
  FINGERPRINT_LED_COLOR_GREEN  = 0x02,  // 绿灯 / Green
  FINGERPRINT_LED_COLOR_CYAN   = 0x03,  // 青色灯 (蓝+绿) / Cyan (Blue + Green)
  FINGERPRINT_LED_COLOR_RED    = 0x04,  // 红灯 / Red
  FINGERPRINT_LED_COLOR_PURPLE = 0x05,  // 紫色灯 (蓝+红) / Purple (Blue + Red)
  FINGERPRINT_LED_COLOR_YELLOW = 0x06,  // 黄色灯 (绿+红) / Yellow (Green + Red)
  FINGERPRINT_LED_COLOR_WHITE  = 0x07   // 白色灯 (蓝+绿+红) / White (Blue + Green + Red)
} fingerprint_led_color_t;
備考
電源投入時、デフォルトは無限ループの青色ブリージングです。PS_ControlBLNで設定した内容は電源OFFで保存されません。
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
#include <Arduino.h>
#include <M5UnitFingerprint2.hpp>    
#include <M5Unified.hpp>          

M5Canvas canvas(&M5.Lcd);   
M5UnitFingerprint2 fp2(&Serial1, 17, 18);  // Initialize fingerprint sensor

void setup() {
    Serial.begin(115200);             
    M5.begin();                      
    fp2.begin();// Hardware Interface Init                  
    canvas.createSprite(320, 240); 
    canvas.fillScreen(TFT_BLACK); 
    canvas.setTextColor(TFT_WHITE); 
    canvas.setFont(&fonts::FreeMonoBold9pt7b);

    // Activate the fingerprint module (prepares it to accept commands; must required)
    if (fp2.PS_ActivateFingerprintModule() == FINGERPRINT_OK) { // Software-based activation, ready to receive commands
      canvas.drawString("Fingerprint2 Ready", 2, 45);  
      Serial.printf("Fingerprint2 Ready\n");          
    } else {
      canvas.drawString("Fingerprint2 Init Failed", 2, 45); 
      Serial.printf("Fingerprint2 Init Failed\n");    
    }
    canvas.pushSprite(0, 0);
}

void loop() {
    fp2.PS_ControlBLN(FINGERPRINT_LED_BREATHING, FINGERPRINT_LED_COLOR_GREEN, FINGERPRINT_LED_COLOR_BLUE, 0); /// 0-endless loop, N-loop N times
    delay(2000);
    fp2.PS_ControlBLN(FINGERPRINT_LED_FLASHING, FINGERPRINT_LED_COLOR_RED, FINGERPRINT_LED_COLOR_RED, 0); /// 0-endless loop, N-loop N times
    delay(2000);
    fp2.PS_ControlBLN(FINGERPRINT_LED_FADE_IN, FINGERPRINT_LED_COLOR_CYAN, FINGERPRINT_LED_COLOR_CYAN, 0); 
    delay(2000);
    fp2.PS_ControlBLN(FINGERPRINT_LED_FADE_OUT, FINGERPRINT_LED_COLOR_YELLOW, FINGERPRINT_LED_COLOR_YELLOW, 0); 
    delay(2000);
    fp2.PS_ControlBLN(FINGERPRINT_LED_ON, FINGERPRINT_LED_COLOR_PURPLE, FINGERPRINT_LED_COLOR_PURPLE, 0); 
    delay(2000);
}  

3.2 指紋画像取得・表示

cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
#include <Arduino.h>
#include <M5UnitFingerprint2.hpp>
#include <M5Unified.hpp>

M5Canvas canvas(&M5.Lcd);
int fingerPresentCount = 0;              // Counter for consecutive finger detection

M5UnitFingerprint2 fp2(&Serial1, 17, 18);  // Fingerprint sensor

bool displayFingerprintImage(M5UnitFingerprint2& fp2, uint32_t maxBufferSize, M5Canvas& canvas,
                             int displayX, int displayY, uint8_t rotation);

void setup() {
    Serial.begin(115200);
    M5.begin();
    fp2.begin();

    canvas.createSprite(320, 240);
    canvas.fillScreen(TFT_BLACK);
    canvas.setTextColor(TFT_WHITE, TFT_BLACK);
    canvas.setFont(&fonts::FreeMonoBold9pt7b);
    canvas.drawString("Unit Fingerprint2 Image", 2, 0);
    Serial.println("<-------Unit Fingerprint2 Image------->");
    canvas.drawLine(0, 20, 320, 20, TFT_WHITE);

    // Activate fingerprint sensor module
    if (fp2.PS_ActivateFingerprintModule() == FINGERPRINT_OK) {
      canvas.drawString("Fingerprint2 Ready", 2, 45);
      canvas.drawString("Please place finger......", 2, 75);
      Serial.printf("Fingerprint2 Ready\n");
    } else {
      canvas.drawString("Fingerprint2 Init Failed", 2, 45);
      Serial.printf("Fingerprint2 Init Failed\n");
    }

    canvas.pushSprite(0, 0);
}

void loop() {
    M5.update();  
    delay(200);    // Light delay to reduce CPU usage
    fingerprint_status_t result = fp2.PS_GetImage();
    // PS_GetImage can be replaced by PS_GetImageInfo to further verify the quality of the fingerprint image. 
    if (result == FINGERPRINT_OK) {
      fingerPresentCount++;
      Serial.printf("Finger detected! Count: %d/3\n", fingerPresentCount);
      canvas.fillRect(0, 41, 320, 240, TFT_BLACK);
      canvas.setCursor(2, 60);
      canvas.printf("Finger detected! Count: %d/3\n", fingerPresentCount);
      canvas.pushSprite(0, 0);
      // Show fingerprint image after 3 consecutive detections
      if (fingerPresentCount >= 3) {
        Serial.println("Entering displayFingerprintImage.");
        if (displayFingerprintImage(fp2, 1024 * 16, canvas, 56, 100, 1)) {
          Serial.println("Fingerprint image displayed successfully.");
          delay(1000);
        } else {
          Serial.println("Failed to display fingerprint image.");
        }
        canvas.pushSprite(0, 0);
        fingerPresentCount = 0;   // Reset count
      }
    } else {
      // No finger detected, reset count
      if (fingerPresentCount > 0) {
        Serial.println("Finger removed, resetting count.");
        fingerPresentCount = 0;
      }
    }
}

bool displayFingerprintImage(M5UnitFingerprint2& fp2, uint32_t maxBufferSize, M5Canvas& canvas,
                             int displayX, int displayY, uint8_t rotation) {
    // Allocate buffer for image
    uint8_t* imageBuffer = (uint8_t*)malloc(maxBufferSize);
    if (imageBuffer == nullptr) {
      Serial.println("Failed to allocate memory for image buffer.");
      canvas.setCursor(2, 60);
      canvas.printf("Memory allocation failed");
      return false;
    }
    // Upload image data from sensor
    uint32_t actualImageSize = 0;
    fingerprint_status_t result = fp2.PS_UpImage(imageBuffer, maxBufferSize, actualImageSize);
    if (result == FINGERPRINT_OK) {
      Serial.printf("Image uploaded successfully, size: %d bytes\r\n", actualImageSize);
      // Display image info on canvas
      canvas.fillRect(0, 41, 320, 240, TFT_BLACK);
      canvas.setCursor(2, 60);
      canvas.printf("Image size: %d bytes", actualImageSize);

      if (actualImageSize > 0) {
        const int imageWidth = 80;
        const int imageHeight = 208;
        for (int y = 0; y < imageHeight && y < 220; y++) {   // Limit height
          for (int x = 0; x < imageWidth && x < 200; x++) {  // Limit width
            int byteIndex = (y * imageWidth + x) / 2;
            if (byteIndex < actualImageSize) {
              // Extract 4-bit pixel value
              uint8_t pixelValue;
              if ((y * imageWidth + x) % 2 == 0) {
                pixelValue = imageBuffer[byteIndex] & 0x0F;
              } else {
                pixelValue = (imageBuffer[byteIndex] & 0xF0) >> 4;
              }
              // Map 4-bit to grayscale RGB565
              uint8_t grayValue = pixelValue * 17;  // Scale to 0-255
              uint16_t rgb565 = ((grayValue >> 3) << 11) | ((grayValue >> 2) << 5) | (grayValue >> 3);
              // Compute rotated pixel position
              int drawX, drawY;
              switch (rotation) {
                case 0:  // No rotation
                  drawX = displayX + x; drawY = displayY + y; break;
                case 1:  // 90 degrees clockwise
                  drawX = displayX + imageHeight - 1 - y; drawY = displayY + x; break;
                case 2:  // 180 degrees
                  drawX = displayX + imageWidth - 1 - x; drawY = displayY + imageHeight - 1 - y; break;
                case 3:  // 270 degrees (counterclockwise)
                  drawX = displayX + y; drawY = displayY + imageWidth - 1 - x; break;
                default:  // Default: 90 degrees clockwise
                  drawX = displayX + imageHeight - 1 - y; drawY = displayY + x; break;
              }
              canvas.drawPixel(drawX, drawY, rgb565);
            }
          }
        }
      }
      free(imageBuffer);
      return true;
    } else {
      Serial.println("Failed to upload image.");
      canvas.setCursor(2, 60);
      canvas.printf("Failed to upload image");
      free(imageBuffer);
      return false;
    }
}

3.3 指紋登録

本サンプルは自動登録方式(PS_AutoEnroll関数を使用)を採用しています。ユーザーは指をセンサーに置くだけで、システムが自動的に画像取得・特徴抽出・テンプレート生成を行い、最終的に指紋テンプレートをモジュール内のデータベースに保存します。段階的に登録したい場合は、Fingerprint2 シリアル通信プロトコルを参照し、PS_GetImagePS_GenCharPS_RegModelPS_StoreCharなどの関数を使用してください。

PS_AutoEnroll

関数プロトタイプ:

fingerprint_status_t PS_AutoEnroll(
    uint16_t ID,
    uint8_t enrollCount,
    fingerprint_auto_enroll_flags_t flags,
    uint8_t* param1 = nullptr,
    uint8_t* param2= nullptr,
    PS_AutoEnrollCallback_t callback = nullptr
) const; 

パラメータ:

  • ID:指紋のユニークID(0~99)。
  • enrollCount:登録時に取得する指紋サンプル数。有効値は1~6。値が大きいほどテンプレートの信頼性が高まりますが、登録時間も長くなります。
  • flags:登録オプション。ビットごとに組み合わせ可能。詳細はfingerprint_auto_enroll_flags_tを参照。
  • param1param2:オプションの出力パラメータ。param1 -- ステージコード、param2 -- ステータス/エラーコード。詳細は下記ps_auto_enroll_param1_t/fingerprint_auto_enroll_stage_tps_auto_enroll_param2_tを参照。
  • callback:コールバック関数(オプション)。各ステージ完了時に呼び出されます(PS_AutoEnroll使用時は複数回呼び出されます)。詳細はライブラリ内のPS_AutoEnroll定義を参照。

戻り値:

  • FINGERPRINT_OK:成功
  • その他の値は失敗。詳細はライブラリのfingerprint_status_tを参照。

PS_AutoEnroll_callback

関数プロトタイプ:

bool PS_AutoEnroll_callback(
    uint16_t ID,
    fingerprint_status_t confirmationCode,
    uint8_t param1,
    uint8_t param2,
    int packetCount
) const;

パラメータ:

  • ID:現在登録中の指紋ID。
  • confirmationCode:現在のステージのステータスコード。FINGERPRINT_OKは成功。詳細はライブラリのfingerprint_status_tを参照。
  • param1:現在のステージコード。詳細はps_auto_enroll_param1_tを参照。
  • param2:現在のステータス/エラーコード。詳細はps_auto_enroll_param2_tを参照。
  • packetCount:コールバック関数が呼び出された回数(現在までに処理されたデータパケット数)。0からカウント。

関連定義:

  • fingerprint_auto_enroll_flags_t

    typedef enum {
      FINGERPRINT_AUTO_ENROLL_DEFAULT              = 0x0000, // 默认设置 / Default setting
      FINGERPRINT_AUTO_ENROLL_NO_STATUS_RETURN     = (1 << 2), // 注册过程中不返回当前状态 / Don't return current status during enrollment
      FINGERPRINT_AUTO_ENROLL_ALLOW_OVERWRITE_ID   = (1 << 3), // 允许覆盖已存在的ID号 / Allow overwriting existing ID
      FINGERPRINT_AUTO_ENROLL_FORBID_DUPLICATES    = (1 << 4), // 禁止指纹重复注册 / Forbid duplicate fingerprint enrollment
      FINGERPRINT_AUTO_ENROLL_NO_LIFT_REQUIRED     = (1 << 5), // 采集间不要求手指离开 / No finger lift required between captures
    } fingerprint_auto_enroll_flags_t;
  • ps_auto_enroll_param1_t

    typedef enum : uint8_t {
      PS_AUTO_ENROLL_PARAM1_LEGAL_CHECK   = 0x00, // 指纹合法性检测 / Fingerprint legality check
      PS_AUTO_ENROLL_PARAM1_GET_IMAGE     = 0x01, // 获取图像 / Get image
      PS_AUTO_ENROLL_PARAM1_GEN_CHAR      = 0x02, // 生成特征 / Generate characteristics
      PS_AUTO_ENROLL_PARAM1_LIFT_FINGER   = 0x03, // 判断手指离开 / Check finger lift
      PS_AUTO_ENROLL_PARAM1_MERGE_TEMPLATE= 0x04, // 合并模板 / Merge template
      PS_AUTO_ENROLL_PARAM1_VERIFY        = 0x05, // 注册验证 / Enrollment verification
      PS_AUTO_ENROLL_PARAM1_STORE         = 0x06  // 存储模板 / Store template
    } ps_auto_enroll_param1_t;
  • ps_auto_enroll_param2_t

typedef enum : uint8_t {
    PS_AUTO_ENROLL_PARAM2_OK                = 0x00, // 指纹合法性检测 / Fingerprint legality check
    PS_AUTO_ENROLL_PARAM2_MERGE_TEMPLATE    = 0xF0, // 合并模板 / Merge template
    PS_AUTO_ENROLL_PARAM2_FINGER_DUPLICATED = 0xF1, // 检验该手指是否已注册 / Check if finger is already registered
    PS_AUTO_ENROLL_PARAM2_STORE_TEMPLATE    = 0xF2, // 存储模板 / Store template
} ps_auto_enroll_param2_t;

下記サンプルではコールバック関数を使って現在の登録プロセスの状態を取得し、情報をフィードバックします。

cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
#include <Arduino.h>
#include <M5UnitFingerprint2.hpp>    
#include <M5Unified.hpp>          

M5Canvas canvas(&M5.Lcd);   
M5UnitFingerprint2 fp2(&Serial1, 17, 18);  // Initialize fingerprint sensor

uint16_t enrollID = 0;                // Unique ID for the fingerprint being enrolled (range: 0~99, cycles after 99)
const uint8_t enrollCount = 3;        // Number of fingerprint samples needed to create a reliable template (3 = standard)
bool waitingForTouch = true;          // Flag to track if the system is waiting for a screen touch to start enrollment

void setup() {
    Serial.begin(115200);             
    M5.begin();                      
    fp2.begin();                  
    canvas.createSprite(320, 240); 
    canvas.fillScreen(TFT_BLACK); 
    canvas.setTextColor(TFT_WHITE); 
    canvas.setFont(&fonts::FreeMonoBold9pt7b);
    canvas.drawString("Unit Fingerprint2 Enroll", 2, 0);
    Serial.println("<-------Unit Fingerprint2 Enroll------->"); 
    canvas.drawLine(0, 20, 320, 20, TFT_WHITE);

    // Activate the fingerprint module (prepares it to accept commands; required before enrollment/verification)
    if (fp2.PS_ActivateFingerprintModule() == FINGERPRINT_OK) { // Software-based activation
      canvas.drawString("Fingerprint2 Ready", 2, 45);  
      Serial.printf("Fingerprint2 Ready\n");          
    } else {
      canvas.drawString("Fingerprint2 Init Failed", 2, 45); 
      Serial.printf("Fingerprint2 Init Failed\n");    
    }

    // Set sensor work mode: 1 = Always-on (sensor stays active), 0 = Timed sleep (auto-sleeps to save power)
    fp2.PS_SetWorkMode(1);
    fp2.PS_Empty();// Clear all fingerprint database

    // Prompt user to touch the screen to start fingerprint enrollment
    canvas.drawString("Touch screen to enroll", 2, 70);
    canvas.pushSprite(0, 0);  // Update LCD with all canvas content (renders drawn elements)
    Serial.println("Waiting for touch to start enrollment...");  // Debug message for user action
}

void loop() {
    M5.update(); 
    if (waitingForTouch) {
        if (M5.Touch.getCount() && M5.Touch.getDetail().wasPressed()) {
            waitingForTouch = false; 
            canvas.fillRect(0, 70, 320, 170, TFT_BLACK);  
            canvas.setCursor(2, 70);
            canvas.printf("Enrolling Fingerprint ID: %d", enrollID); 
            canvas.drawString("Place finger to enroll...", 10, 90); 
            canvas.pushSprite(0, 0);  
            Serial.printf("Start enrolling fingerprint, ID=%d. Please place your finger...\n", enrollID); 

            uint8_t param1 = 0, param2 = 0; 
            // Start automatic enrollment:
            // Parameters: ID, sample count, flags (overwrite existing ID + no finger lift needed), output params, callback
            fingerprint_status_t result = fp2.PS_AutoEnroll(
                enrollID, enrollCount, 
                (fingerprint_auto_enroll_flags_t)(FINGERPRINT_AUTO_ENROLL_ALLOW_OVERWRITE_ID |
                                                  FINGERPRINT_AUTO_ENROLL_NO_LIFT_REQUIRED),
                &param1, &param2, PS_AutoEnroll_callback);

            canvas.fillRect(0, 90, 320, 150, TFT_BLACK); 
            if (result == FINGERPRINT_OK) {
                canvas.setCursor(2, 100);
                canvas.printf("ID:%d Enroll Success!", enrollID);
                Serial.printf("Fingerprint enrolled successfully! ID=%d\n", enrollID);
                enrollID = (enrollID + 1) % 100; 
            } else {
                canvas.drawString("Enroll Failed!", 2, 100);
                Serial.println("Fingerprint enrollment failed!"); 
            }
            canvas.drawString("Touch screen to enroll next", 10, 130);
            canvas.pushSprite(0, 0); 
            waitingForTouch = true; 
            delay(200); 
        }
    }
    delay(20); 
}

// Callback function for PS_AutoEnroll: updates status during each enrollment stage (runs automatically)
// Returns true to continue enrollment, false to abort (based on success of current stage)
bool PS_AutoEnroll_callback(uint16_t ID, fingerprint_status_t confirmationCode, uint8_t param1, uint8_t param2, int packetCount) {
    static int enrollStep = 0;  // Static variable: tracks current sample step (persists between callback calls)
    switch (param1) {
        // Stage 1: Capture fingerprint image from sensor
        case FINGERPRINT_AUTO_ENROLL_GET_IMAGE:
            if (confirmationCode == FINGERPRINT_OK) {
                enrollStep++;  // Increment step after successful image capture
                canvas.setCursor(10, 90);
                canvas.fillRect(0, 90, 320, 150, TFT_BLACK);  // Clear previous status
                canvas.printf("#%d:Image acquired success", enrollStep);  // Show step success
                Serial.printf("#%d:Image acquired success\n", enrollStep);  // Debug step success
            }
            break;
        
        // Stage 2: Extract fingerprint features (converts image to digital template data)
        case FINGERPRINT_AUTO_ENROLL_GEN_CHAR:
            if (confirmationCode == FINGERPRINT_OK) {
                canvas.setCursor(10, 110);
                canvas.printf("#%d:Feature generated success", enrollStep);  // Show feature success
                Serial.printf("#%d:Feature generated success\n", enrollStep);  // Debug feature success
            }
            break;
        
        // Stage 3: Merge multiple feature samples into a single, reliable template
        case FINGERPRINT_AUTO_ENROLL_MERGE_TEMPLATE:
            if (confirmationCode == FINGERPRINT_OK) {
                canvas.setCursor(10, 130);
                canvas.printf("Template merged success");  // Show merge success
                Serial.println("Template merged success");  // Debug merge success
            }
            break;
        
        // Stage 4: Verify merged template (ensures template is valid for future recognition)
        case FINGERPRINT_AUTO_ENROLL_VERIFY:
            if (confirmationCode == FINGERPRINT_OK) {
                canvas.setCursor(10, 150);
                canvas.printf("Template verified success");  // Show verification success
                Serial.println("Template verified success");  // Debug verification success
            }
            break;
        
        // Stage 5: Save verified template to sensor memory (links to enrollment ID)
        case FINGERPRINT_AUTO_ENROLL_STORE_TEMPLATE:
            if (confirmationCode == FINGERPRINT_OK) {
                canvas.setCursor(10, 170);
                canvas.printf("Template stored success,ID=%d", ID);  // Show storage success + ID
                Serial.printf("Template stored success,ID=%d\n", ID);  // Debug storage success
                enrollStep = 0;  // Reset step counter for next enrollment
            }
            break;
        
        default:
            break;  // Ignore unrecognized stages
    }
    canvas.pushSprite(0, 0); 
    return (confirmationCode == FINGERPRINT_OK);  // Continue enrollment only if current stage succeeded
} 

3.4 指紋認証

本サンプルは自動認証方式(PS_AutoIdentify関数を使用)を採用しています。ユーザーは指をセンサーに置くだけで、システムが自動的に画像取得・特徴抽出・テンプレート照合を行い、最終的にマッチング結果を返します。段階的に認証したい場合は、Fingerprint2 シリアル通信プロトコルを参照し、PS_GetImagePS_GenCharPS_Searchなどの関数を使用してください。

PS_AutoIdentify

関数プロトタイプ:

fingerprint_status_t PS_AutoIdentify(
    uint8_t securityLevel,               
    uint16_t ID,                       
    fingerprint_auto_verify_flags_t flags,
    uint16_t& matchedID,       
    PS_AutoIdentifyCallback_t callback = nullptr
) const;

パラメータ:

  • securityLevel:セキュリティレベル。0または1。値が大きいほどマッチングが厳しくなります。
  • ID:認証対象の指紋ID範囲。0xFFFFは全登録指紋を対象、他の値は指定IDのみ比較。
  • flags:認証オプション。ビットごとに組み合わせ可能。詳細は下記fingerprint_auto_verify_flags_tを参照。
  • matchedID:出力パラメータ。マッチした指紋IDを返します。
  • callback:コールバック関数(オプション)。各ステージ完了時に複数回呼び出され、認証進捗のリアルタイムフィードバックに利用できます。

戻り値:

  • FINGERPRINT_OK:認証成功
  • その他の値は失敗。詳細はライブラリのfingerprint_status_tを参照。

PS_AutoIdentify_callback

bool PS_AutoIdentify_callback(
    uint8_t securityLevel,                 
    fingerprint_status_t confirmationCode, 
    uint8_t param,                         
    uint16_t matchedID,                 
    uint16_t matchScore,                 
    int packetCount                    
);

パラメータ:

  • securityLevelPS_AutoIdentifyに渡したパラメータと同じ。
  • confirmationCode:現在のステージのステータスコード。FINGERPRINT_OKは成功。詳細はライブラリのfingerprint_status_tを参照。
  • param:現在のステージコード。詳細は下記ps_auto_identify_param_tを参照。
  • matchedID:出力パラメータ。マッチした指紋IDを返します。
  • matchScore:出力パラメータ。マッチスコアを返します。値が大きいほど一致度が高いです。
  • packetCount:コールバック関数が呼び出された回数(現在までに処理されたデータパケット数)。0からカウント。

関連定義:

  • fingerprint_auto_verify_flags_t
typedef enum {
    FINGERPRINT_AUTO_VERIFY_DEFAULT          = 0x0000, // 默认设置 / Default setting
    FINGERPRINT_AUTO_VERIFY_NO_STATUS_RETURN = (1 << 2), // 验证过程中不返回当前状态 / Don't return current status during verification
} fingerprint_auto_verify_flags_t;
  • ps_auto_identify_param_t
typedef enum {
    PS_AUTO_IDENTIFY_PARAM_LEGAL_CHECK   = 0x00, // 指纹合法性检测 / Fingerprint legality check
    PS_AUTO_IDENTIFY_PARAM_GET_IMAGE     = 0x01, // 获取图像 / Get image
    PS_AUTO_IDENTIFY_PARAM_VERIFY        = 0x05, // 已注册指纹比对 / Registered fingerprint matching
} ps_auto_identify_param_t;

下記サンプルではコールバック関数を使って現在の認証状態を取得し、情報をフィードバックします。

cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
#include <Arduino.h>
#include <M5UnitFingerprint2.hpp>
#include <M5Unified.hpp>

M5Canvas canvas(&M5.Lcd);
M5UnitFingerprint2 fp2(&Serial1, 17, 18);  // Initialize fingerprint sensor

void setup() {
    Serial.begin(115200);
    M5.begin();
    fp2.begin();
    canvas.createSprite(320, 240);
    canvas.fillScreen(TFT_BLACK);
    canvas.setTextColor(TFT_WHITE);
    canvas.setFont(&fonts::FreeMonoBold9pt7b);
    canvas.drawString("Unit Fingerprint2 Identify", 2, 0);
    Serial.println("<-------Unit Fingerprint2 Identify------->");
    canvas.drawLine(0, 20, 320, 20, TFT_WHITE);

    if (fp2.PS_ActivateFingerprintModule() == FINGERPRINT_OK) {
        canvas.drawString("Fingerprint2 Ready", 2, 45);
        Serial.printf("Fingerprint2 Ready\n");
    } else {
        canvas.drawString("Fingerprint2 Init Failed", 2, 45);
        Serial.printf("Fingerprint2 Init Failed\n");
    }

    fp2.PS_SetWorkMode(1);
    canvas.pushSprite(0, 0);
}

void loop() {
    M5.update();

    canvas.fillRect(0, 70, 320, 170, TFT_BLACK);
    canvas.setCursor(2, 70);
    canvas.drawString("Place finger to identify...", 10, 90);
    canvas.pushSprite(0, 0);
    Serial.println("Start identifying fingerprint. Please place your finger...");

    uint16_t matchedID = 0;
    // Start automatic identification:
    // Parameters: security level(0 or 1), ID, flags, output matchedID, callback
    fingerprint_status_t result = fp2.PS_AutoIdentify(
        0, 0xFFFF, FINGERPRINT_AUTO_VERIFY_DEFAULT,
        matchedID, PS_AutoIdentify_callback);

    canvas.fillRect(0, 90, 320, 150, TFT_BLACK);
    if (result == FINGERPRINT_OK) {
        canvas.setCursor(2, 100);
        canvas.printf("Identify Success! ID:%d", matchedID);
        Serial.printf("Fingerprint identified! ID=%d\n", matchedID);
        delay(1000);
    } else {
        canvas.drawString("Identify Failed!", 2, 100);
        Serial.println("Fingerprint identification failed!");
    }
    canvas.pushSprite(0, 0);
    delay(20);
}

// Callback function for PS_AutoIdentify: updates status during each identification stage
bool PS_AutoIdentify_callback(uint8_t securityLevel, fingerprint_status_t confirmationCode, uint8_t param, uint16_t matchedID, uint16_t matchScore, int packetCount) {
    switch (param) {
        // Stage 1: Capture fingerprint image
        case PS_AUTO_IDENTIFY_PARAM_GET_IMAGE:
        if (confirmationCode == FINGERPRINT_OK) {
            canvas.setCursor(10, 90);
            canvas.fillRect(0, 90, 320, 150, TFT_BLACK);
            canvas.printf("Image acquired success");
            Serial.println("Image acquired success");
        }
        break;
        // Stage 2: Matching fingerprint
        case PS_AUTO_IDENTIFY_PARAM_VERIFY:
        if (confirmationCode == FINGERPRINT_OK) {
            canvas.setCursor(10, 110);
            canvas.printf("Match ID:%d Score:%d", matchedID, matchScore);
            Serial.printf("Match ID:%d Score:%d\n", matchedID, matchScore);
        } else {
            canvas.setCursor(10, 110);
            canvas.printf("No Fingerprint Matched");
            Serial.println("No Fingerprint Matched");
        }
        break;
        default:
        break;
    }
    canvas.pushSprite(0, 0);
    delay(500);
    return (confirmationCode == FINGERPRINT_OK);
} 

3.5 登録済み指紋の削除

本指紋モジュールはID指定による指紋テンプレートの削除のみサポートしています。削除前にIDを認証で取得する必要があります。全ての指紋テンプレートを消去したい場合はPS_Empty関数を使用してください。

cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
#include <Arduino.h>
#include <M5UnitFingerprint2.hpp>
#include <M5Unified.hpp>

M5Canvas canvas(&M5.Lcd);
M5UnitFingerprint2 fp2(&Serial1, 17, 18);  // Initialize fingerprint sensor

void setup() {
    Serial.begin(115200);
    M5.begin();
    fp2.begin();
    canvas.createSprite(320, 240);
    canvas.fillScreen(TFT_BLACK);
    canvas.setTextColor(TFT_WHITE);
    canvas.setFont(&fonts::FreeMonoBold9pt7b);
    canvas.drawString("Unit Fingerprint2 Delete", 2, 0);
    Serial.println("<-------Unit Fingerprint2 Delete------->");
    canvas.drawLine(0, 20, 320, 20, TFT_WHITE);

    if (fp2.PS_ActivateFingerprintModule() == FINGERPRINT_OK) {
        canvas.drawString("Fingerprint2 Ready", 2, 45);
        Serial.printf("Fingerprint2 Ready\n");
    } else {
        canvas.drawString("Fingerprint2 Init Failed", 2, 45);
        Serial.printf("Fingerprint2 Init Failed\n");
    }

    fp2.PS_SetWorkMode(1);
    fp2.PS_ControlBLN(FINGERPRINT_LED_BREATHING, FINGERPRINT_LED_COLOR_BLUE, FINGERPRINT_LED_COLOR_PURPLE, 0); /// 0-endless loop, N-loop N times
    canvas.pushSprite(0, 0);
}

void loop() {
    M5.update();

    canvas.fillRect(0, 70, 320, 170, TFT_BLACK);
    canvas.setCursor(2, 70);
    canvas.drawString("Place finger to delete...", 10, 90);
    canvas.pushSprite(0, 0);
    Serial.println("Please place your finger...");

    uint16_t matchedID = 0;
    // Start automatic identification:
    // Parameters: security level(0 or 1), ID, flags, output matchedID
    fingerprint_status_t result = fp2.PS_AutoIdentify(
        0, 0xFFFF, FINGERPRINT_AUTO_VERIFY_DEFAULT,
        matchedID);

    canvas.fillRect(0, 90, 320, 150, TFT_BLACK);
    if (result == FINGERPRINT_OK) {
        canvas.setCursor(2, 100);
        canvas.printf("Identified ID:%d", matchedID);
        Serial.printf("Identified ID:%d", matchedID);
        // Delete the matched fingerprint
        fingerprint_status_t delResult = fp2.PS_DeletChar(matchedID, 1);
        if (delResult == FINGERPRINT_OK) {
            canvas.setCursor(2, 120);
            canvas.printf("Deleted ID:%d Success!", matchedID);
            Serial.printf("Deleted fingerprint ID=%d Success!\n", matchedID);
        } else {
            canvas.setCursor(2, 120);
            canvas.printf("Delete ID:%d Failed!", matchedID);
            Serial.printf("Delete fingerprint ID=%d Failed!\n", matchedID);
        }
    } else {
        canvas.drawString("Identify Failed!", 2, 100);
        Serial.println("Fingerprint identification failed!");
    }
    canvas.pushSprite(0, 0);
    delay(2000);
} 

4. コンパイルと書き込み

  • ダウンロードモード:デバイスごとに書き込み前にダウンロードモードへ入る必要があります。手順は主制御デバイスによって異なります。詳細はArduino IDE入門ガイドページ下部のデバイス書き込み手順リストを参照してください。

  • CoreS3の場合、リセットボタンを約2秒長押しし、内部の緑色LEDが点灯したら離します。この状態でデバイスはダウンロードモードに入り、書き込み待機状態となります。

  • デバイスのポートを選択し、Arduino IDE左上のコンパイル・書き込みボタンをクリックして、プログラムのコンパイルと書き込みが完了するのを待ちます。

5. サンプル動作例

  • LED制御:緑青ブリージング、赤フラッシュ、シアンフェードイン、黄フェードアウト、紫常時点灯が順に切り替わります。
  • 指紋画像取得・表示:指を指紋センサーに置き、3回取得に成功すると指紋画像が表示されます。

  • 指紋登録:画面をタップし、指示に従って指を指紋センサーに置いて登録します。登録成功後はLEDが緑色に点灯し、画面にEnroll Successなどのメッセージが表示されます。
  • 指紋認証:指示に従って指を指紋センサーに置いて認証します。認証成功後はLEDが緑色に点灯し、画面にIdentify Successなどのメッセージが表示されます。
  • 登録済み指紋の削除:指示に従って指を指紋センサーに置いて削除します。画面にDeleted ID:X Successなどのメッセージが表示されます。
On This Page