カードかざしたらピコーンと鳴らせてみたいと思ったのですが、鳴らすためのブザー用意するのも面倒だったので、カードかざしたらピカ!と光るLチカ(LEDをチカチカさせる)に挑戦してみました。
調査
カードかざしたら反応するモジュールはどれ?
Suicaの技術あたりから攻めるのがよさそうなので、「Suica 仕様」で検索すると、「非接触型IC」という言葉が出てきました。
「非接触型IC チップ」で検索してみると、どうも「RFID」という技術ということです。
電子工作絡みで検索する時、「自作」というキーワードを入れると鉄板です。
今回も「RFID 自作」で検索すると、それっぽいのがいっぱい出てきました。
電子工作系は、古いと2000年の歴史、ではなくて西暦2000年頃からの記事もあって、現在も手に入るのかどうかよくわからない内容もあります。金額と調達可能性、開発の簡単さ(本当の難易度は実際やってみないとわからないので、加工しなくていいかとか、部品点数が少ないかとかをみる)を考慮して、モジュールを選定します。
調査していくと、Arduinoと組み合わせてRFIDでLチカがそこそこ見つかりました。実績があるRFID-RC522モジュールがよさそうです。
参考URL
Wifiとも接続したいよ
Lチカできたら、その後はカードかざしたらインターネット接続して何かしたいよね、ということで将来を見据えてWifiモジュールで単体でArduinoとして使える、ESP-WROOM-02と組み合わせることにしました。
※今回の記事では、最終的にESP-WROOM-02上でLチカさせてますが、Wifiとして外部にHTTPリクエスト送ったりしていません。
どうESP-WROOM-02とRFID-RC522を接続するの?
物理的につなげても、両方のモジュールがお話できないといけません。RFID-RC522の通信仕様をみると、SPI/UART/I2Cと書いてあるのですが、SPI以外の通信方法が可能かどうかわからなかったので、SPIで通信することにしました。(サンプルもあるので)
SPI通信のピンを確認すると、SS/MOSI/MISO/SCKの4本が最低必要なようです。また使っているかどうかわからないのですが、リセット用の信号線もRFID-RC522に接続されているので用意します。
ESP-WROOM-02のブレークアウトボードのピン設定の詳細がいまいち確認できないのですが、どうもmikroBUS規格互換だということで、そちらを見るのがよさそうということに気づきました。(なので+5VのところがESP-WROOM-02では無効化されている)
参考URL
用意するもの
モジュール
- ESP-WROOM-02+ブレークアウトボード マイクロテクニカ
- RFID-RC522 Amazon 検索:RC522
- AE-FT234X 秋月電子通商
※(リンク先はたぶん今回説明するのと同等品。購入時の参考まで)
その他(今回使用したもの)
- ブレッドボード(長)
- ブレッドボード用 ジャンパーワイヤ各種
- USBケーブル(PCと接続できる端子と、AE-FT234Xと接続できる端子が両端にあるケーブル)
- 発光ダイオード(赤) x 2 (電源確認用と、Lチカ用)
- 1KΩ抵抗 x 2 (LED用 ※抵抗の値は発光ダイオードの許容範囲にあわせて適宜調整してください)
- 0.1μF積層セラミックコンデンサ x 1 (パスコン用)
- 出力DC3.3V スイッチング電源(AC100Vコンセントから安定的に電源取得するため)
- スイッチング電源用DCジャック
開発環境
- MacBook Air (OS X Yosemite)
- Arduino IDE 1.6.5
作業手順
- Arduino IDEにESP-WROOM-02の開発ボード追加を行います
- こちらを参考にしてください→ 技適済み格安高性能Wi-FiモジュールESP8266をArduinoIDEを使ってIoT開発する為の環境準備を10分でやる方法
- Arduino IDEのメニューの「ツール」から、ボードを「Generic ESP8266 Module」に設定します。設定はデフォルトのままで変更していません。
- Arduino IDEにRC522のライブラリを追加します
- MFRC522:githubから、一式をZIPダウンロードします。
- Arduino IDEのメニューの「スケッチ」→「Add .ZIP Library..」から、ダウンロードしたファイルを選択します。
- Arduino IDEのメニューの「ファイル」→「スケッチの例」の下の方に「MFRC522」という項目が追加されていたら追加完了です。
- ブレッドボード上に配線します
- ESP-WROOM-02モジュールの下の空間を利用できると、配線がすっきりします
- 発光ダイオードは向きがあるので注意
- USBケーブルでMacとAE-FT234Xを接続します
- Arduino IDEのメニューの「ツール」から、ポートを「/dev/cu.usbserial~」にします。(環境によって~の後がいろいろ変わるようです)
- プログラムをコンパイルしてESP-WROOM-02に書き込みます。
- ESP-WROOM-02側のモードを書き込みモードにしないと、Arduino IDEで書き込めない旨のエラー表示となります
- USBからは電源供給せずに、3.3Vのスイッチング電源側から供給しますので、USBとは別にスイッチング電源を接続して通電状態としてください(少なくともESP-WROOM-02には電源が供給されていないと書き込めません)
- MFRC522ライブラリをESP-WROOM-02デバイスで使おうとすると、コンパイル時に、「WARNING: library MFRC522 claims to run on [avr, STM32F1] architecture(s) and may be incompatible with your current board which runs on [esp8266] architecture(s).」といって、警告が出ます。出ますが、コンパイル通るし動くので無視しました。
- Arduino IDEがプログラム書き込んだ後、自動的にリセットされてESP-WROOM-02がフラッシュROMから立ち上がります。なので、そのままでも動きます。USBからのケーブルは抜きたい人は、一度電源切って、USB周りのケーブル抜いて、フラッシュROM起動モードにしてから再度電源ONにしてください。
ブレッドボードに全部載せた
左上の3本ぐらい明後日の方向に伸びているのが、AE-FT234Xにつながっています(小さすぎてUSBのケーブルの重さでブレッドボードから離れてしまうので、あえて外しています)
これはプログラムの書き込みとシリアルコンソールでのデバッグに使うだけなので、動作時はこの明後日の方向に伸びているケーブルは外しています。
ちなみに電源はスイッチングアダプタから直供給で、電源スイッチとかはないです。
動かしてみた
実際に動かしてみました。RFID-RC522買ったらついてきたカードをかざすとカードが検出されます。
横方向に外れた場合にLEDが光らなくなる(カード未検出となる)のは理解しやすいですが、縦方向も10cm程度離すとLED光りませんでした。
回路図
電子回路作ったら清書しましょうという教えに従い、作成しました。
回路図エディタBSch3V利用させて頂きました。とても使いやすいですね。
プログラム(Arduino)
ESP-WROOM-02のフラッシュROMを書き込みモードにして、Arduino IDEから突っ込むプログラムは以下になります。
- SSピンと、REESTピンは自由に変更可能です。変更可能なのですが、ESP-WROOM-02のGPIO15ピン使おうとすると、どうも挙動があやしいので、GPIO15ピンは使わない方がいいかもしれません。(ジャンパー設定で使っているからかもしれませんし、ESP-WROOM-02のリセット挙動に使うピンらしいのでそのせいかもしれません)
- 先ほども書きましたが、WifiでIPアドレス取得しているだけで、HTTP通信とかしていません。ただ、IPアドレスは取得しているので、SSIDとパスワードは必要です(不要なら削ってください)
/*
* ESP-WOORM-02とMFRC522を接続する
* 2015/10/12
*
* 配線(SPI通信):
* ESP-WROOM-02 : MFRC522
* GPIO 5 -> SDA(1) - ESP-WROOM-02側はSS_PINで定義
* GPIO14 -> SCK(2)
* GPIO13 -> MOSI(3)
* GPIO12 <- MISO(4)
* RQ(5) - 未使用
* GND(6) - GNDにつなぐ
* GPIO16 -> RST(7) - ESP-WROOM-02側はRST_PINで定義
* 3V3(8) - 電源につなぐ
*
* LED: GPIO 4
*
*/
#include <SPI.h>
#include <MFRC522.h>
#include <ESP8266WiFi.h>
#define RST_PIN 16 // MFRC522用リセットピンGPIO NO
#define SS_PIN 5 // MFRC522用SS(SDA)ピンGPIO NO
MFRC522 mfrc522(SS_PIN, RST_PIN); // MFRC522のインスタンスを作成
#define CARD_PRESENT_PIN 4 // MFRC522にカードが検知されたら光らせるGPIO NO
bool cardset; // MFRC522にカードが検知されているかどうか
int timeoutcount; // MFRC522からカードが連続で離れた回数を記録
const char* ssid = "xxxxxxxx"; // ESP-WROOM-02用 Wifi SSID(各自設定してください)
const char* password = "xxxxxxxxxxxx"; // ESP-WROOM-02用 Wifi パスワード(各自設定してください)
void setup() {
// UART接続初期化
Serial.begin(115200); // UARTの通信速度を変更したい場合はこちらを変更
delay(10);
// カード検出用のGPIO初期化
pinMode(CARD_PRESENT_PIN, OUTPUT);
digitalWrite(CARD_PRESENT_PIN, LOW);
// MFRC522用変数初期化
cardset = false;
timeoutcount = 0;
// MFRC522のスケッチのDumpInfoを参考にした。ref) https://github.com/miguelbalboa/rfid
SPI.begin(); // SPI初期化
mfrc522.PCD_Init(); // MFRC522初期化
ShowReaderDetails(); // MFRC522 Card Readerのバージョンを返す。00かFFなら配線間違いの可能性
// とりあえずWifiにつなぐ
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Print the IP address
Serial.println(WiFi.localIP());
}
void loop() {
// カードの検出
if ( !mfrc522.PICC_IsNewCardPresent()) {
// 検出されなかった場合の処理
if (cardset) {
// すでにカードが検出されていた場合で、連続4回未検出になったらLEDをLOWにする
// 検出後、タイムアウトと検出を繰り返すのでその対策
if (timeoutcount > 4) {
digitalWrite(CARD_PRESENT_PIN, LOW);
Serial.println("LED LOW");
cardset = false;
timeoutcount = 0;
} else {
// 4回以内なら連続未検出回数を増やす
timeoutcount++;
}
}
delay(5);
return;
}
// カードが初めてor改めてセットされた場合、LEDをHIGHにする
if (!cardset) {
digitalWrite(CARD_PRESENT_PIN, HIGH);
Serial.println("LED HIGH");
cardset = true;
}
timeoutcount = 0;
delay(100);
}
// MFRC522のスケッチのDumpInfoのまま。ref) https://github.com/miguelbalboa/rfid
// LICENSE:https://github.com/miguelbalboa/rfid/blob/master/UNLICENSE
void ShowReaderDetails() {
// Get the MFRC522 software version
byte v = mfrc522.PCD_ReadRegister(mfrc522.VersionReg);
Serial.print(F("MFRC522 Software Version: 0x"));
Serial.print(v, HEX);
if (v == 0x91)
Serial.print(F(" = v1.0"));
else if (v == 0x92)
Serial.print(F(" = v2.0"));
else
Serial.print(F(" (unknown)"));
Serial.println("");
// When 0x00 or 0xFF is returned, communication probably failed
if ((v == 0x00) || (v == 0xFF)) {
Serial.println(F("WARNING: Communication failure, is the MFRC522 properly connected?"));
}
}
免責事項
回路図どおり、プログラムどおりに作っても動かなかったらごめんなさい。無保証です。
おまけ
今回「動かしてみた」で使った動画は、デジタルカメラの動画モードで撮影→ffmpegで変換してアニメーションGIFとして作成しました。GUIで編集するよりも手軽で綺麗なアニメーションGIFが作れました。
- 入力動画を横320、縦は入力動画のアスペクト比に合わせて縮小
$ ffmpeg -i input_origin.MP4 -vf scale=320:-1:flags=lanczos -strict -2 -y input_mini.mp4
- 今回の動画で抽出したい部分を抽出するため、開始16秒から4秒間分だけ出力する
$ ffmpeg -i input_mini.mp4 -ss 16 -t 4 -strict -2 -y input_mini_16_4.mp4
- 最適化されたパレット画像を生成(fpsを10に設定)
- `$ ffmpeg -i input_mini_16_4.mp4 -vf fps=10,palettegen=stats_mode=diff -y mp4_palette.png'
- パレット画像を利用してアニメーションGIFを生成(fpsを10に設定)
$ ffmpeg -i input_mini_16_4.mp4 -i mp4_palette.png -lavfi fps=10,paletteuse -y output.gif
動画フォーマットは圧縮が効いているのですが、アニメーションGIFにするとファイルサイズが肥大化するので、1Mbyte以内に収めようと思うと、5秒程度が限界ですね。