製作動機
我が家のリビングに設置された「予定通知ロボット」
M5Stackに加えてBlynkというアプリで連携すれば、スマホからリビングにある通知ロボット(M5Stack)との情報連携が簡単にできます。しかし、欠点としては、「常にスマホが必要となる事」です。
例えば、子供にスマホを奪われている時であったり、自分以外の人に操作してもらう場合などでスマホを渡せない状況もあったりします。
それが特に露見したのは、2019/5に参加したMaker Faire Kyoto でした。
この時は、もともと展示説明員として当てにしていた妻が、なんと足の骨を折ってしまい、外出そのものが困難になってしまいました。
私一人で2日間、ブースを回せる自信がなかったため、ちょうど我が家で使っていた分身ロボットOriHimeを駆使して、
妻に自宅から遠隔説明員として参加してもらう事でヘルプに入って貰いました。
しかし、ここにきて課題なのは、会場から妻への簡易的な連絡手段。
OriHimeは自宅のタブレットから映像/音声で通信するイメージなのですが、
朝から夕方まで常にタブレットを見続ける事は出来ないので、
用事のある時やブースにお客さんが来た時に応対してもらう様にしました。
そんなガヤガヤした会場から自宅へ簡単に呼び出し通知を行う仕組みが必要でした。
(OriHimeからの呼びかけだとガヤガヤ音等でかき消される事もあったので)
Blynkを使ってスマホアプリ上に呼び出しボタンを作ろうとしたけど、さすがに自分のスマホを公共の場に置きっぱなしにできないなぁ、と悩んでいたら…
Blynkにデバイスブリッジ機能がある事Blynkにデバイスブリッジ機能がある事Blynkにデバイスブリッジ機能がある事を見つけました!
これを使えば、会場のM5Stackから、自宅リビングにあるM5Stack間へ呼び出し通知が出来る
と思い、製作に取り掛かりました。
完成動画
OriHimeに搭載したM5Stackからの自宅リビングにあるM5Stackへ通知
ケガで外出不可の妻に #MFKyoto2019 での展示サポートをお願いすべく、分身ロボット #OriHime を活用した遠隔説明員のチャレンジ検討
— おぎ-モトキ (@ogimotoki) 2019年5月2日
会場から妻本体@自宅を呼出す機能を #M5Stack +Blynk で実現。会場にいる分身の名札ボタンを押せば、自宅リビングに音声お知らせが届くよ#家族のためのモノづくり pic.twitter.com/vjskbzAkim
実験的には同じ室内ですが、当然ながらOriHime+M5Stackを宅外に持っていっても同様に、
宅内のM5Stackに通知ができます
ブロック構成
本システムの簡易ブロック図は以下です。
すごくシンプルなんです!
それぞれのM5Stackが WIfiを介して外部ネットワークと繋がる環境であれば、Blynkサーバーを介して情報を伝送してくれるイメージです!
しかし、Blynk内のプロジェクトは「1プロジェクト1デバイス」の様で、2つのデバイスをBlynk上で連携させるにはもう一工夫必要。
そこで活躍するのが「Bridgeウィジット」です。
このウィジェットはどうやら「プロジェクト間の通信をBridgeする」イメージの様ですので、2つのデバイス用に割り当てたBlynkプロジェクト間を本ウィジェットで繋げてやります!
ソフトウェア(
前文でも書いた通り、2つのプロジェクトを作成します。
今回は『 auth_orihime(ロボット側)』 と 『 auth_living (リビング設置側)』の2種類を用意しています。
Blynkアプリ設定
プロジェクト間での通信をしたい側にBridgeウィジェットを配置します。
今回は、auth_orihimeからの一方向通信のため、auth_orihime側にBridgeウィジェットを置きます。
画面上に置くだけで特にアプリ上からは設定不要です。(auth_living側は特にアプリでの設定不要)
送信側(OriHime呼び出し側) Arduinoコード
ロボット側のコードは、
「M5Stackのボタンが押されたらauth_livingプロジェクトのV3ピンをHに上げる」
内容になります。
#include <M5Stack.h> #include <WiFi.h> #include <WiFiClient.h> #include "time.h" #include <BlynkSimpleEsp32.h> #define BLYNK_PRINT Serial // Audio speaker #include "AudioFileSourceSD.h" #include "AudioFileSourceID3.h" #include "AudioOutputI2S.h" #include "AudioGeneratorWAV.h" AudioGeneratorWAV *wav; AudioFileSourceSD *file; AudioOutputI2S *out; AudioFileSourceID3 *id3; const char* auth_orihime = "7xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; //OriHime側(call側)Blynkアプリ Auth コード const char* auth_living = "4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; //リビング側(receive側) Auth コード const char* ssid = "xxxxxxxxxxxxxxxxxxxxxxx"; //ポケットWifi等のSSID const char* password = "xxxxxxxxxxxxxxxxxxxxxx"; // ポケットWIfi等のSSIDパスワード // Bridge widget on virtual pin 0 WidgetBridge bridge1(V0); // OriHime側BlynkアプリのV0を使用 void setup() { M5.begin(); Serial.begin(115200); // M5Stackによる名札機能 M5.Lcd.fillScreen(BLACK); M5.Lcd.drawJpgFile(SD, "/okan.jpg"); // M5Stackによるスピーカ再生機能設定 out = new AudioOutputI2S(0,1); out->SetOutputModeMono(true); out->SetGain(0.8); wav = new AudioGeneratorWAV(); // Blink起動 Blynk.begin(auth_orihime, ssid, password ); // OriHime側Blynkサーバーと通信 } int nafuda_num = 0; bool display_flag = 0; int orihime_num = 0; void loop() { // Blynk更新 Blynk.run(); M5.update(); if(M5.BtnB.wasPressed()){ M5.Lcd.drawJpgFile(SD, "/call_real.jpg"); Serial.println("本体を呼び出し中"); //本体呼び出し音を再生 file = new AudioFileSourceSD("/call_real.wav"); wav = new AudioGeneratorWAV(); wav->begin(file, out); while(wav->isRunning()){ if (!wav->loop()) wav->stop(); } // リビング bridge1.virtualWrite(3, HIGH); //リビング側(receive側) のV3ピンをHに Serial.printf("V3 : H"); delay(1000); bridge1.virtualWrite(3, LOW); //リビング側(receive側) のV3ピンをLに Serial.printf("V3 : L"); delay(5000); display_flag = 1; } } BLYNK_CONNECTED() { bridge1.setAuthToken(auth_living); // リビング側Blynkサーバーと通信 }
受信側(リビング通知側) Arduinoコード
リビング側のコードは、
『V3ピンがHighに上がったらお知らせ映像&音声を再生する』
だけのコードを実装します。
#include <M5Stack.h> #include <WiFi.h> #include <WiFiClient.h> #include <HTTPClient.h> #include "time.h" // Audio speaker #include "AudioFileSourceSD.h" #include "AudioFileSourceID3.h" #include "AudioOutputI2S.h" #include "AudioGeneratorWAV.h" AudioGeneratorWAV *wav; AudioFileSourceSD *file; AudioOutputI2S *out; AudioFileSourceID3 *id3; #include <BlynkSimpleEsp32.h> #define BLYNK_PRINT Serial const char* auth_living = "4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; //リビング側(receive側) Auth コード const char* ssid = "xxxxxxxxxxxxxxxxxxxxxxx"; //自宅Wifi等のSSID const char* password = "xxxxxxxxxxxxxxxxxxxxxx"; // 自宅WIfi等のSSIDパスワード void setup(){ M5.begin(); Serial.begin(115200); delay(10); // WiFi設定 Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } //WAVの場合 out = new AudioOutputI2S(0,1); out->SetOutputModeMono(true); out->SetGain(0.8); wav = new AudioGeneratorWAV(); // Blink起動 Blynk.begin(auth_living, ssid, password ); } void loop(){ // Blynk更新 Blynk.run(); } // BLYNKサーバーからお父さん呼び出し通知(v3)を受けた場合 BLYNK_WRITE(V3){ int val = param[0].asInt(); if(val == 1){ display_information("calll_orihime"); delay(3000); view_change = 1; } } void display_information(String str){ M5.Lcd.drawJpgFile(SD, String("/" + str + ".jpg").c_str()); file = new AudioFileSourceSD(String("/" + str + ".wav").c_str()); wav = new AudioGeneratorWAV(); wav->begin(file, out); while(wav->isRunning()){ if (!wav->loop()) wav->stop(); } }