指紋スキャナーモジュール　GT-521F52をM5stackで動くようにしてみる　M5stack編

#ArduinoUno向けのライブラリを書き換えて、M5stackで動くようにするにはどうすればいいのか？
前回の[指紋スキャナーモジュール　GT-521F52をM5stackで動くようにしてみる　デモ編](https://qiita.com/puraban/items/376f185f7502bfcaa93f)でわかるように、[Arduino用ライブラリ](https://github.com/sparkfun/Fingerprint_Scanner-TTL/tree/master/examples)はSoftwareSerialが実装されているArduinoUno用のライブラリなので、SoftwareSerialが実装されていないM5stackにインストールしようとしても動きません。
そこで今回はライブラリを書き換えることでM5stack上で動作するようにしてみようと思います。

#FPS_GT511C3.hをざっと読んでみる
まずはFPS_GT511C3.hをざっと読んでこのライブラリの構造を把握します。

```C+++
#include "Arduino.h"
#include "SoftwareSerial.h"
```
Arduino.hとSoftwareSerial.hをまずカレントディレクトリから探して読み込む設定になっています。
その下にはクラスが３つ定義されています。

- Command_Packet
- Response_Packet
- FPS_GT511C3

##Command_Packet
Command_Packetクラスはマイコンからセンサに送信するコマンドのパケットを定義する構造体とメソッド、定数等が定義されています。

##Response_Packet
Response_Packetクラスはセンサからマイコンに送信された信号をコマンドとして解釈し、取り扱うための構造体とメソッド、定数等が定義されています。

##FPS_GT511C3
FPS_GT511C3はセンサのインターフェースを定義するクラスです。
コンストラクタ、デストラクタ、そしてメソッドとして各種コマンドが定義されています。

さて、探しているものはここにありました。
今回はシリアル通信インターフェースをSoftwareSeriaからM5stackのSerial2に書き換えることで動作させることを目的としています。
なので単純にSoftwareSeriaで検索をかけると以下のプライベートな変数やオブジェクトが引っかかってきます。

```c++
private:
	 void SendCommand(byte cmd[], int length);
	 Response_Packet* GetResponse();
	 uint8_t pin_RX,pin_TX;
	 SoftwareSerial _serial;
```

SoftwareSerialのインターフェースは_serialと定義されていることがわかりました。
今回はインターフェースを書き換えることを目的としているので、このクラスを書き換えればおそらく問題なく動作するでしょう。


#FPS_GT511C3.hを書き換える
##インクルードするファイルを変更する

変更前

```C+++
#include "Arduino.h"
#include "SoftwareSerial.h"
```

変更後

```C+++
//#include "Arduino.h"
//#include "SoftwareSerial.h"
#include <M5Stack.h>
```

SoftwareSerialをSerial2としてM5Stackに移植する場合は[前回](https://qiita.com/puraban/items/376f185f7502bfcaa93f)を見てもらえばわかるように、

```C+++
#include <M5Stack.h>
```

だけをインクルードします。
これでインクルードするファイルの変更は完了です。

## SoftwareSerialインターフェースの定義をコメントアウトする
変更前

```c++
private:
	 void SendCommand(byte cmd[], int length);
	 Response_Packet* GetResponse();
	 uint8_t pin_RX,pin_TX;
	 SoftwareSerial _serial;
```

変更後

```c++
private:
	 void SendCommand(byte cmd[], int length);
	 Response_Packet* GetResponse();
	 uint8_t pin_RX,pin_TX;
	 //SoftwareSerial _serial;
```
M5StaskのESP32ではシリアル通信のインターフェースが３つ、ハードウェア実装されています。
SoftwareSerialは不要なのでコメントアウトしましょう。

これでヘッダファイルの書き換えは完了です。

#FPS_GT511C3.cppを書き換える
FPS_GT511C3のメソッドを検索して、_serialをSerial2に変更していきます。
変更箇所は10か所あります。

##FPS_GT511C3コンストラクタ
2か所あります。
変更前

```c++
FPS_GT511C3::FPS_GT511C3(uint8_t rx, uint8_t tx)
	: _serial(rx,tx)
{
	pin_RX = rx;
	pin_TX = tx;
	_serial.begin(9600);
	this->UseSerialDebug = false;
};
```

変更後

```c++
FPS_GT511C3::FPS_GT511C3(uint8_t rx, uint8_t tx)
{
	pin_RX = rx;
	pin_TX = tx;
	Serial2.begin(9600, SERIAL_8N1, rx, tx);
	this->UseSerialDebug = false;
};
```

このオブジェクトは_serial(rx,tx)で初期化されますが、これはSerial2.begin()に引数として与えるので不要です。
Serial2.begin()でボーレート、パリティとストップビットの指定、受信ピン、送信ピンを設定します。
これでコンストラクタの変更は完了です。

##FPS_GT511C3デストラクタ
1か所あります。
変更前

```c++
FPS_GT511C3::~FPS_GT511C3()
{
	_serial.~SoftwareSerial();
}
```

変更後

```c++
FPS_GT511C3::~FPS_GT511C3()
{
	//_serial.~SoftwareSerial();
}
```
デストラクタではFPS_GT511C3が破棄される際にSoftwareSerialのオブジェクトを削除するようになっています。
今回はSoftwareSerialを使用していないのでコメントアウトします。
これでデストラクタの変更は完了です。

##FPS_GT511C3のChangeBaudRateメソッド
２か所あります。
変更前

```c++			
_serial.end();
_serial.begin(baud);
```

変更後

```c++
Serial2.end();
Serial2.begin(baud, SERIAL_8N1,pin_RX,pin_TX);
```
シリアル通信のボーレートを変更するためにendメソッドで一度シリアル通信を終了した後、もう一度beginしています。
ピン番号のpin_RX,pin_TXはオブジェクト内部に記録されているのでそれを使用します。
これでChangeBaudRateメソッドの書き換えは完了です。

##FPS_GT511C3のSendCommandメソッド
１か所あります。

変更前

```c++
_serial.write(cmd, length);
```
変更後

```c++
Serial2.write(cmd, length)
```
_serial.write()をSerial2.write()に変更します。
これでSendCommandメソッドの書き換えは完了です。


##FPS_GT511C3のGetResponseメソッド
4か所あります。
1か所目
変更前

```c++
_serial.listen();
```

変更後

```c++
//_serial.listen();
```
listen()は複数のSoftwareSerialポートを開いている際に、指定したポートを受信モードに切り替えるメソッドです。SoftwareSerialは**複数作ることができる**が、**同時に複数のポートで送受信できない**という制限があります。Serial2はそういった制限がありませんので、このコードは不要です。コメントアウトします。

2か所目
変更前

```c++
firstbyte = (byte)_serial.read();
```

変更後

```c++
firstbyte = (byte)Serial2.read();
```
シリアルポートから１ビット目を読むコードです。
そのまま_serial.read()をSerial2.read()に書き換えます。

3か所目
変更前

```c++
while (_serial.available() == false) delay(10);
```

変更後

```c++
while (Serial2.available() == false) delay(10);
```
シリアルポートに文字が到着しているか10msごとに確認するコードです。
そのまま_serial.available()をSerial2.available()に書き換えます。 

4か所目
変更前

```c++
resp[i]= (byte) _serial.read();
```

変更後

```c++
resp[i]= (byte) Serial2.read();
```

resp配列にシリアルポートから読んだ情報を代入していくコードです。
そのまま_serial.read()をSerial2.read()に書き換えます。

これでGetResponseメソッドの変更は完了です。
合計１０か所を書き換えました。

#main.cppを書き換える
サンプルでは２か所変更します。
１か所目
変更前

```c++
#include "SoftwareSerial.h"
```

変更後

```c++
//#include "SoftwareSerial.h"
```

SoftwareSerial.hのインクルードをコメントアウトします。

２か所目
変更前

```c++
FPS_GT511C3 fps(4, 5);
```

変更後

```c++
FPS_GT511C3 fps(16, 17);
```
シリアル通信のピンをM5stackに合わせて変更します。
これでmain.cppの変更は完了です。

これで全てのファイルの変更が完了しました。
#実証
M5stakcに書き込んでシリアルモニタで動作を確認します。
##指紋の登録
FPS_Enrollをビルドして、センサ上に指を3回触れることで指紋を登録します。
![enrolltest.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216739/044d82f0-922b-1d15-ee0a-192d4c3e3b65.png)
\#1の指紋が登録されました。

##指紋が登録されたものであるか確認
FPS_Idfingerをビルドして、センサ上に指を触れさせることで指紋の照合を行います。
![Idfingertest.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216739/78990053-5335-d669-e596-01f098abfc0d.png)
一度Finger not found で失敗した後、ID:1の指紋を確認しました。

これでサンプルを動かすレベルでは、GT-521F52のArduino Uno用のライブラリをM5stackに移植できたことを確認しました。

#備考
##内部に登録された指紋情報の削除
サンプルでは指紋の情報をセンサ内部に一方的に登録していくだけになっています。
もし指紋の情報を削除する場合、[前回](https://qiita.com/puraban/items/376f185f7502bfcaa93f)のシリアルパススルーコードを書きこんで、デモソフトを使って削除してください。
##指紋登録数の変更
GT-521F52とGT-521F32は指紋の登録数が異なります。(GT-521F52が3000個、廉価版のGT-521F32は200個)このライブラリは200個までしか登録できませんので、登録数を変更する場合はFPS_GT511C3.cppで200を検索して3000に置き換えてください。ファイルにも「登録数を変えるときはここを書き換えてください」的に書かれています。