M5stackでFeliCa リーダーを作った話



# なぜ作ったか
弊社の私の所属部署では、座席抽選Webアプリ（自社ツール、というか、私のチーム謹製）を用いたフリーアドレスを実施しています。

定期券、社員証を「ぴっ」で抽選が出来たら面白いのではと思い、作ってみました。

# つかっているもの

- [M5Stack](https://www.switch-science.com/catalog/3647/)
- [FeliCa リーダー・ライター RC-S620S](https://www.switch-science.com/catalog/353/)
- [FeliCa RC-S620S/RC-S730 ピッチ変換基板のセット(フラットケーブル付き)　](https://www.switch-science.com/catalog/1029/)
- 線材少々

## 最初のプロトタイプ
<img width="544" alt="スクリーンショット 2019-12-01 21.23.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29641/f2539204-7ffe-6298-6e2c-749800fcbb33.png">

電源（3V3とGNDと16,17をつなぐだけ）

## 最終形態
<img width="378" alt="スクリーンショット 2019-12-01 21.26.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29641/1cc6223a-513e-30ee-4f60-104f7b13933e.png">

紆余曲折のあと、ダイソーの吸盤でモニタフレームに張り付きました。

# ブロック図
ざっくり、こんな感じ。
<img width="1091" alt="スクリーンショット 2019-12-01 21.34.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29641/e24eb120-a018-4da2-d6fe-1fd3f5bb442d.png">

# M5Stack
開発にはArduinoを使用しました。

## RC-S620S
[Sony謹製のライブラリ](http://blog.felicalauncher.com/sdk_for_air/?page_id=2699)　が公開されています。
しかし、Serialが1で固定されているため、ライブラリを一部変更する必要があります。（Serialがとられると、デバッグも出来ないので）

RCS620S.cppの300行以降に4カ所あるSerialをSerial2に変更するだけです。

## シリアルポートの指定

下のソースの通り　`Serial2.begin(SERIAL_BOUND, SERIAL_8N1, 16, 17);`でRC-S620Sに繋がります。

## Felicaの読み込み
Felicaカードは、ライブラリのサンプルで読み込むことが可能です。くせ者は、モバイルSuica（Apple）です。

通常、下ソースの「＜＜ここ」に「ワイルドカード：0xFFFF」をしているすると、カードタイプに応じた情報が読み取られます。

しかし、モバイルSuicaの場合、「SUICAのコード：0x0003」を指定しないと反応しません。
苦肉の策ですが（Pythonのライブラリを参考）モバイルSuicaと通常カードを交互に読むことで双方に対応させました。


``` cpp:felicaReader.ino
#include <RCS620S.h>

#define SERIAL_BOUND     115200
#define COMMAND_TIMEOUT  400
#define POLLING_INTERVAL 500
#define SD_PN            4

#define SYSCODE_SUICA 0x0003
#define SYSCODE_DEF   0xFFFF

#define SENSE_ITERATIONS 10
#define SENSE_INTERVAL   10


RCS620S rcs620s;

int iterations;
uint16_t targetSys; 

void setup() {
  // put your setup code here, to run once:
  int ret;
  
  Serial.begin(SERIAL_BOUND);
  Serial2.begin(SERIAL_BOUND, SERIAL_8N1, 16, 17);

  ret = rcs620s.initDevice();
  delay(10);
  Serial.print("Init RCS620s ");
  while(!ret) {
    delay(100);
    Serial.print(".");
  };
  Serial.println(".");
  Serial.println("Connect RCS620S");

  iterations = 0;
  targetSys = SYSCODE_SUICA;
}

void loop() {
  // put your main code here, to run repeatedly:
  int ret, i, interval;
  
  rcs620s.timeout = COMMAND_TIMEOUT;
  
  if(targetSys == SYSCODE_SUICA && iterations >= SENSE_ITERATIONS){
    targetSys = SYSCODE_DEF;
    interval = POLLING_INTERVAL;
    iterations = 0;
  }else{
    targetSys = SYSCODE_SUICA;
    interval = SENSE_INTERVAL;
    iterations++;
  }
  
  ret = rcs620s.polling(targetSys);  ＜＜ここ

  if(ret) {
    Serial.print("--> find:");
    
    for(i = 0; i < 8; i++)
    {
      if(rcs620s.idm[i] / 0x10 == 0) Serial.print(0);
      Serial.print(rcs620s.idm[i], HEX);
    }
    Serial.println(".");
  }
  rcs620s.rfOff();
  delay(interval);
}

```

また、ソースの記載通りですが、FecliaのIDmを利用しています。正直よろしくないですが、

- 勤怠ではなく、座席抽選であること
- 既存のカード（定期券、社員証など）を幅広く使いたかった

などを言い訳に、よしとしています。

# 作ってみて
プロトタイプとFelica情報読み取り、自社アプリのAPIキックまでは結構簡単にできたのですが、

- M5Stackの画面遷移
- 連続運用
- バージョンアップ（バグ対応ともいう）

と、通常のアプリ開発と同じところで時間がかかるものですね。（あたりまえですが）