カウントダウンだけで宴会は盛り上がるをIoT化してみた。

カンパイシェア <A HREF="https://qiita.com/kitazaki/items/14e5d8d24b181c16e106">(1)</A> <A HREF="https://qiita.com/kitazaki/items/1a1cdf77c6b9ccaa03d9">(2)</A> に引き続き宴会ネタで恐縮です。

```
Q. 飲み会で一番盛り上がる瞬間は？

A. カンパイ！
```

ということで、そのカンパイをさらに盛り上げるため、カウントダウンを組み合わせることにした。

![スクリーンショット 2018-03-16 15.27.59.png](https://qiita-image-store.s3.amazonaws.com/0/72479/a9040d00-233a-92ef-a60d-1e9782346de8.png)

参考にしたのはDPZの<A HREF="http://portal.nifty.com/kiji/180126201872_1.htm">「カウントダウンだけで宴会は盛り上がる」</A>である。

[![スクリーンショット 2018-03-13 14.52.55.png](https://qiita-image-store.s3.amazonaws.com/0/72479/fc88ecdd-e2d2-e146-cf5e-7e5fcd11584d.png)](http://portal.nifty.com/kiji/180126201872_1.htm)

新年でなく、なんでもないタイミングでもカウントダウンさえすれば盛り上がることを体現した事例で、カウントダウンとカンパイを組み合わせればさらに盛り上がることは必至である。

[![スクリーンショット 2018-03-13 20.41.31.png](https://qiita-image-store.s3.amazonaws.com/0/72479/88ff67bd-5045-e855-9405-c58d053ea076.png)]
(http://portal.nifty.com/kiji/180126201872_1.htm)

クラッカー噴出装置を製作 (IoT化) し、カンパイシェアでグラスをピカらせるのと同時にクラッカーを鳴らしてみることにした。

## 構成

スマートスピーカー (Google Home または Amazon Alexa) を入力として、Node-REDを経由してwebhookリクエストをMQTTリクエスト (Publish) へ変換し、Milkcocoa経由でカウントダウンIoT、カンパイシェア、ラズベリーパイ、PepperへMQTTリクエスト (Subscribe) を送る構成とした。

![カウントダウンIoT構成.png](https://qiita-image-store.s3.amazonaws.com/0/72479/621b817e-0fd7-1079-56dd-a5e060595503.png)

### カウントダウンIoT
MQTTリクエストを受信するとLEDバーを点灯し、リレー操作でギヤードモータを動作させ、クラッカーの引き出し紐を引かせる。

### カンパイシェア
MQTTリクエストを受信するとリングLEDを点灯し、振動モーターを動作させる。詳細の動作は<A HREF="https://qiita.com/kitazaki/items/1a1cdf77c6b9ccaa03d9">こちら</A>。

### ラズベリーパイ
MQTTリクエストを受信するとgoogle-home-notifierへ変換し、Google Homeにカウントダウンを発声させる。

### Pepper
MQTTリクエストを受信するとカウントダウンを発声させる。

## 配線図
カウントダウンIoTの配線図を説明する。

![スクリーンショット 2018-03-14 22.18.55.png](https://qiita-image-store.s3.amazonaws.com/0/72479/7ff6c6ec-835e-b3cb-6f60-357033bec1d0.png)

Wio-Node は Grove コネクタが 2ポート装備されているが、PORT0 はコードの書き換え用途のシリアルポートとして使用するため、PORT1 のみを使用して実現する。
PORT1には VCC、GND、IO4、IO5 が配線されているため、IO4 を LEDバー (WS2812) 制御用、IO5 をギヤードモータを操作するリレー操作用に割り当てる。VCC と GND は共用とする。

![カウントダウンIoT配線図.png](https://qiita-image-store.s3.amazonaws.com/0/72479/62a5a87a-df1d-14cf-6731-77d3f6b269b2.png)

これで Groveコネクタ 1本で制御できるようになった。A8 カードケースへ収めるため、電源は Li-Po バッテリーを使用する。(モバイルバッテリーなど USB 電源でも動作可。)

![スクリーンショット 2018-03-13 23.40.00.png](https://qiita-image-store.s3.amazonaws.com/0/72479/f3ee72fe-0f4f-6ca9-fcc2-f8be64e152e3.png)

## クラッカー噴出装置
クラッカー噴出装置は先行特許 <A HREF="https://astamuse.com/ja/published/JP/No/2013252401">特開2013-252401</A> が存在する。

![スクリーンショット 2018-03-17 10.55.01.png](https://qiita-image-store.s3.amazonaws.com/0/72479/43c26145-43bd-d2ca-2bd6-e8c91e52b394.png)

本発明はギヤードモータの軸にプーリー、または、クランクを取り付けて、クラッカー紐をプーリーに巻き付けて固定、または、クランクに固定して、モータを作動させることにより、プーリーの回転によるクラッカー紐の巻き上げ、または、クランクの引き上げによるクラッカー紐の引き下げでクラッカーを発砲させる仕組みである。プーリーにはクラッカー紐を取り付けるための穴が空けられており、クラッカー紐を穴に通して結んで固定される。(本広報にはクランクを用いた構成図の説明はない。)

侵害を回避するため、今回新たなクラッカー紐の引き出し機構を開発した。

![カウントダウンIoT配線図.png](https://qiita-image-store.s3.amazonaws.com/0/72479/bf6c5adb-ce5f-41f6-613c-3037d6ebd680.png)

ギヤードモータの軸にφ12.3の ツマミ を取り付けて、上部を十字に溝を掘り、クラッカー紐を <B>L字型</B> に挟み (モータを動作させてテンションが掛かった際にクラッカー紐が抜けないようにするため <B>L字型</B> に挟むことがポイント！)、モータを作動させることにより、クラッカー紐を引き下げる仕組みである。プーリーの穴にクラッカー紐を通して結んで固定させる必要は無く、クラッカー紐の取り付けもクラッカー発砲後の取り外しも容易となる。

つまみ部(拡大)
![つまみ(実物).png](https://qiita-image-store.s3.amazonaws.com/0/72479/fde47a30-ea23-93fa-5d6a-dff4bb128f18.png)

クラッカー装着図
![装着時(発報前).png](https://qiita-image-store.s3.amazonaws.com/0/72479/c406e6ed-b2e9-0c5d-7a6f-35f6705cb165.png)

クラッカー発砲後
![発報後.png](https://qiita-image-store.s3.amazonaws.com/0/72479/957820ec-6e8f-80f8-43e4-d4944035ce70.png)

## ソースコード
ソースコードは<A HREF="https://github.com/kitazaki/countdown_iot">こちら</A>。

```c:ESP8266_LED_MOTOR.ino
#include <ESP8266WiFi.h>
#include <Adafruit_NeoPixel.h>
#include <Milkcocoa.h>

#define WLAN_SSID       ""  // Wi-Fi
#define WLAN_PASS       ""  // Wi-Fi

#define MOTORPIN 5  // Wio-Node IO5 => MOTOR
#define LEDPIN 4    // Wio-Node IO4 => WS2812
#define NUMPIXELS 5   // Number of LEDs
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, LEDPIN, NEO_GRB + NEO_KHZ800);

WiFiClient client;

#define MILKCOCOA_APP_ID      ""  // MilkCocoa Application ID
#define MILKCOCOA_DATASTORE   ""  // MilkCocoa Datastore Name
#define MILKCOCOA_SERVERPORT  1883

const char MQTT_SERVER[] PROGMEM    = MILKCOCOA_APP_ID ".mlkcca.com";
const char MQTT_CLIENTID[] PROGMEM  = __TIME__ MILKCOCOA_APP_ID;

Milkcocoa milkcocoa = Milkcocoa(&client, MQTT_SERVER, MILKCOCOA_SERVERPORT, MILKCOCOA_APP_ID, MQTT_CLIENTID);

int red, green, blue, strength, timer;

void onpush(DataElement *elem) {
  Serial.println("onpush");
  Serial.print("r:");
  Serial.print(elem->getInt("r"));
  Serial.print(",g:");
  Serial.print(elem->getInt("g"));
  Serial.print(",b:");
  Serial.print(elem->getInt("b"));
  Serial.print(",s:");
  Serial.print(elem->getInt("s"));
  Serial.print(",t:");
  Serial.print(elem->getInt("t"));
  Serial.println();

  red = elem->getInt("r");
  green = elem->getInt("g");
  blue = elem->getInt("b");
  strength = elem->getInt("s");
  timer = elem->getInt("t");

  if (strength) {
//    countdown(red, green, blue);
    countdown(255, 0, 0);
    digitalWrite(MOTORPIN, HIGH); 
    delay(5000);
    digitalWrite(MOTORPIN, LOW); 
  } else {
    led(0, 255, 0);
  }
}

void led(int v_r, int v_g, int v_b) {
  strip.setBrightness(50);
  for(int i=0;i<NUMPIXELS;i++){
    strip.setPixelColor(i, strip.Color(v_r, v_g, v_b));
    strip.show();
    delay(50);
  }
}

void countdown(int v_r, int v_g, int v_b) {
  strip.setBrightness(50);
  int v_t;
  if (timer) {
    v_t = timer;
  } else {
    v_t = NUMPIXELS;
  }
  for(int i=0;i<v_t;i++){
    strip.setPixelColor(i, strip.Color(v_r, v_g, v_b));
    strip.show();
  }
  for(int i=0;i<v_t;i++){
    strip.setPixelColor(v_t-i-1, strip.Color(0, 0, 0));
    strip.show();
    delay(1000);
  }
}

void setupWiFi() {
  Serial.println(); Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WLAN_SSID);
  WiFi.begin(WLAN_SSID, WLAN_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void setup() {
  pinMode(15, OUTPUT);  // for Wio-Node
  digitalWrite(15, 1);  // for Wio-Node
  Serial.begin(115200);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  setupWiFi();
  Serial.println( milkcocoa.on(MILKCOCOA_DATASTORE, "push", onpush) );
  pinMode(MOTORPIN, OUTPUT); 
}

void loop() {
  milkcocoa.loop();
  led(255,255,255);
}
```

## まとめ
複数同時にクラッカーを鳴らすとさらに盛り上がることを確認できた。(外国人の方にもウケました！)
みなさまの盛り上がりに少しでも貢献できれば幸いです。良きパリピライフを！！

[![スクリーンショット 2018-03-14 21.06.35.png](https://qiita-image-store.s3.amazonaws.com/0/72479/ae66898c-cc03-9189-8650-4f55c7b86507.png)]
(https://youtu.be/tpOUzTTVZyg)