IoT
Adafruit
NeoPixel
ESP32
NefryBT
NefryDay 10

ダァ シエリイェスなクリスマス

こんにちは、ポキオです。
Nefry Advent Calendar 2017の10日目を担当します。

昨日のyamacho1111さんの記事、実益を兼ねた非常に興味深いIoTでした。GASを使って簡単にクローリングするのもスマートでした!私のブログでもGASを扱ってきましたが、IoTとの親和性が非常に高いのおすすめです。

今年のAdvent Calendarネタの総まとめ

今思えば、随分前から京急ガジェットに情熱を注いできました。

そして、今年のAdvent Calendarでは今まで書いてきたコードをライブラリ化した話をメインにやってきました。

これらの集大成として、Nefry BT + EmotionalBlink + ESP32Keikyuで、京急の運行状況をさり気なく教えてくれるクリスマスツリーを作ります!

用意するもの

Nefry BT

秋葉原のツクモさんで売ってたラスイチのNefry BT。今回は、Nefry BTのディスプレイやBT機能を一切使わないので、Nefry BTのバージョンを1.0.0にロールバックして使っています。

LEDテープ

Amazonで売ってた899円のLEDテープ(1mで30個のLEDがついてるやつ)。Amazon Prime対応で、気づいたら注文ボタン押してた。

輝きが足りないクリスマスツリー

3COINS(300円均一のショップ)で買った安いやつ。娘(2才)はサンタさんとクリスマスツリーの区別がつかないため、非常に厄介。クリスマスツリーを買っただけなのに「サンタさんが来た!」とはしゃいでいた。

EmotionalBlink

EmotinalBlink
https://github.com/pokiiio/EmotionalBlink

Adafruit NeoPixelなLEDやLEDテープをいい感じに光らせてくれるライブラリ。以前ブログでこのライブラリを紹介したところ「誰得だよ」っていう至極真っ当な意見を頂きましたが、イルミネーションを光らせてナンボな師走に於いては、このライブラリが火を噴きます。

ESP32Keikyu

ESP32Keikyu
https://github.com/pokiiio/ESP32Keikyu

GitHubで京急の運行状況を扱ったライブラリを作っているのは僕だけです!(2017/12/08時点、自分調べ)皆さんにも、気軽に京急の運行状況を知ってほしい、そう思って作ったライブラリです。ESP32用ESP8266用を用意していますので、皆さんも是非使って下さい。

作る

ハードウェアな部分

まず、LEDテープの配線。

と言っても、LEDテープには5VGNDDI(信号端子)だけしか無く、LEDはすべて数珠つなぎにつながってます。それらの端子を、Nefry BTの3.3VGNDD2につなぎます。5Vに繋いでないけど、動いてるから良いや(遠い目)

配線はこれだけ。

ソフトウェアな部分

Nefry BTでやるのは、

①Wi-Fi接続 ⇒ ②LED初期化 ⇒ ③京急運行状況確認 ⇒ ④それに応じて光らせる ⇒ ③ ⇒ ④ ⇒ ・・・

こんな感じ。①はNefry BTに予め設定済みのアクセスポイントに接続されるので、コード上の処理は不要。

②はAdafruit NeoPixelのリファレンス通りに宣言。先程、信号端子をD2に挿したので、コード上で以下のように宣言しておく。

#define PIN D2 // マイコン内蔵RGB LEDの信号線を繋いだピン番号:D2ピン
#define NUMLED 30 // マイコン内蔵RGB LEDの個数:今回は30個

// NeoPixel(LED)の宣言
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMLED, PIN, NEO_GRB + NEO_KHZ800);

③はESP32Keikyuを使って取得します。

int keikyuStatus = Keikyu.getStatus();

この関数を呼ぶだけ。ステータスの詳細は以下のようになってます。

#define KEIKYU_STATUS_UNKNOWN 0           // 京急の運行情報が取得できません
#define KEIKYU_STATUS_NORMAL 1            // 京急は平常通り運転してます
#define KEIKYU_STATUS_DELAYED 2           // 遅れています
#define KEIKYU_STATUS_TERRIBLE 3          // ダイヤが乱れています
#define KEIKYU_STATUS_STOPPED 4           // 運転を見合わせています
#define KEIKYU_STATUS_DELAYED_DUE_TO_JR 5 // JRからの振替輸送受託のため遅れています

④はEmotinalBlinkで光らせます。通常はクリスマスっぽい光らせ方をしたいので、

Blink.likeHolidaySeason(&pixels, NUMLED, INTERVAL_SEC * 1000);

Blink.likeHolidaySeason()で聖なる夜を演出します。が、京急が遅れているときは、じんわり点滅させます。

Blink.softly(&pixels, NUMLED, r, g, b);

このr, g, bを運行状況によって変化させることで、京急の運行状況を知らせます。こんな感じでコーディングしていきます!(サンプルコードを最後に載せておきますので御覧ください)

Let's blink!!

先程のLEDテープをクリスマスツリーに巻きつけます。

さぁ、Nefry BTを電源に繋いで光らせます。

京急が平常運転のとき

ふつーのクリスマスツリーっぽい光り方。綺麗ですね。

1.gif

京急が遅れてるとき

黄色い優しい光で、遅延を知らせます。まぁ、ちょっとくらいの遅れなら、京急は頑張ってくれます。

2.gif

京急のダイヤが大幅に乱れているとき

オレンジ色の光で、ヤバさを伝えます。さすがに京急も逝っとけダイヤになり始めますが、きっと京急は動いているので問題ないです。

3.gif

京急が運転見合わせをしているとき

赤い怪しげな光り方をします。運転見合わせと言いつつも、行けるところまで行っちゃうのが京急です。多分問題ないです。

4.gif

JRからの振替輸送を受託して遅れているとき

パリピのようにチカチカ光ります。京急に乗り慣れてない人がたくさん乗ってくるので、普段とは異なる混み方をします。それでも京急は頑張って走ってくれるので、大丈夫です。

5.gif

こんな感じです。

Tipsとか

  • 都度都度消灯(Blink.dismiss(&pixels, NUMLED);)をすると、綺麗に光ります。
  • わりと大電流が流れてそうなので、強力なモバイルバッテリーが必要。
  • オレンジ色は黄色と見分けがつかないので、ちょっと微妙なんですよね・・・。実際の光り方を見ながらRGBをチューニングする必要がありそう・・・。

そんなこんなで

京急の運行状況とクリスマスツリーのイルミネーションをリンクさせてみました。

いまやGoogle HomeやAmazon Echoなどに話しかければ情報を取得できる現代。逆に話しかけなくても、ボタン操作をしなくても、なんとなく情報を教えてくれるようなガジェットに無性に興味があります。あまりでしゃばりすぎず、でも確実に大切な情報をさり気なく伝えてくれるガジェットを今後も作っていきたいです。

明日はminwinminさんです!NefryBTはIoTを始めるにはもってこいのボード、どんなIoTの記事なのか楽しみです!

Appendix

サンプルコードを貼っておきます。

#include <Adafruit_NeoPixel.h>
#include <EmotionalBlink.h>
#include <ESP32Keikyu.h>

#define INTERVAL_SEC 1 * 60 // 運行情報を確認する間隔:1分
#define PIN D2 // マイコン内蔵RGB LEDの信号線を繋いだピン番号:D2ピン
#define NUMLED 30 // マイコン内蔵RGB LEDの個数:今回は30個

// NeoPixel(LED)の宣言
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMLED, PIN, NEO_GRB + NEO_KHZ800);

// 京急の運行情報を保持しておく変数
int keikyuStatus = KEIKYU_STATUS_UNKNOWN;

void setup() {
  // Serialの初期化
  Serial.begin(115200);
  Serial.println("");

  pixels.begin();
}

void loop() {
  // 一旦消灯
  Blink.dismiss(&pixels, NUMLED);

  // 情報取得
  keikyuStatus = Keikyu.getStatus();

  // ステータス表示
  Serial.println(String(keikyuStatus));

  // 運行情報に基いてLEDを光らせる
  blinkLed();
}

void blinkLed() {
  int r, g, b;

  // 一旦消灯
  Blink.dismiss(&pixels, NUMLED);

  switch (keikyuStatus) {
    case KEIKYU_STATUS_UNKNOWN:
      // 情報取得エラー時は1回だけ白く点灯
      Blink.softly(&pixels, NUMLED, 255, 255, 255);
      return;
    case KEIKYU_STATUS_NORMAL:
      // 通常時はホリデーシーズン点灯
      Blink.likeHolidaySeason(&pixels, NUMLED, INTERVAL_SEC * 1000);
      return;
    case KEIKYU_STATUS_DELAYED_DUE_TO_JR:
      // 振替輸送受託が理由で遅延している場合は、パリピ点滅
      Blink.likePartyPeople(&pixels, NUMLED, INTERVAL_SEC * 1000);
      return;
    case KEIKYU_STATUS_DELAYED:
      // 多少の遅れは黄色く光らせる
      r = 255;
      g = 255;
      b = 0;
      break;
    case KEIKYU_STATUS_TERRIBLE:
      // 大幅なダイヤ乱れはオレンジ色に光らせる
      r = 255;
      g = 128;
      b = 0;
      break;
    case KEIKYU_STATUS_STOPPED:
      // 運転見合わせ時は赤い点滅
      r = 255;
      g = 0;
      b = 0;
      break;
  }

  for (int i = 0; i < INTERVAL_SEC; i++) {
    Blink.softly(&pixels, NUMLED, r, g, b);
  }
}