OGIMOノート~家族のためのモノづくり~

OGIMOテックノート ~家族のためのモノづくり~

重度障害の息子を持つ父親エンジニアの備忘録。自作の電子工作おもちゃ/リハビリ器具/ロボット関係の製作記録、思った事を残していきます

Blynk(Bridge機能)で、宅外~宅内のM5Stack間で呼び出しシステムを作ってみた

f:id:motokiinfinity8:20191117191046j:plain

製作動機

我が家のリビングに設置された「予定通知ロボット」

M5Stackに加えてBlynkというアプリで連携すれば、スマホからリビングにある通知ロボット(M5Stack)との情報連携が簡単にできます。しかし、欠点としては、「常にスマホが必要となる事」です。

例えば、子供にスマホを奪われている時であったり、自分以外の人に操作してもらう場合などでスマホを渡せない状況もあったりします。

それが特に露見したのは、2019/5に参加したMaker Faire Kyoto でした。
この時は、もともと展示説明員として当てにしていた妻が、なんと足の骨を折ってしまい、外出そのものが困難になってしまいました。

私一人で2日間、ブースを回せる自信がなかったため、ちょうど我が家で使っていた分身ロボットOriHimeを駆使して、
妻に自宅から遠隔説明員として参加してもらう事でヘルプに入って貰いました。

ogimotokin.hatenablog.com


しかし、ここにきて課題なのは、会場から妻への簡易的な連絡手段
OriHimeは自宅のタブレットから映像/音声で通信するイメージなのですが、
朝から夕方まで常にタブレットを見続ける事は出来ないので、
用事のある時やブースにお客さんが来た時に応対してもらう様にしました。

そんなガヤガヤした会場から自宅へ簡単に呼び出し通知を行う仕組みが必要でした。
(OriHimeからの呼びかけだとガヤガヤ音等でかき消される事もあったので)

Blynkを使ってスマホアプリ上に呼び出しボタンを作ろうとしたけど、さすがに自分のスマホを公共の場に置きっぱなしにできないなぁ、と悩んでいたら…

Blynkにデバイスブリッジ機能がある事Blynkにデバイスブリッジ機能がある事Blynkにデバイスブリッジ機能がある事を見つけました!
これを使えば、会場のM5Stackから、自宅リビングにあるM5Stack間へ呼び出し通知が出来る

と思い、製作に取り掛かりました。

完成動画

OriHimeに搭載したM5Stackからの自宅リビングにあるM5Stackへ通知

実験的には同じ室内ですが、当然ながらOriHime+M5Stackを宅外に持っていっても同様に、
宅内のM5Stackに通知ができます

ブロック構成

本システムの簡易ブロック図は以下です。

f:id:motokiinfinity8:20191113213512j:plain

すごくシンプルなんです!
それぞれの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ウィジェットを置きます。

f:id:motokiinfinity8:20191117192220j:plain
f:id:motokiinfinity8:20191117192228j:plain

画面上に置くだけで特にアプリ上からは設定不要です。(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();
  }
}

最後に

Blynkは無料ながらも簡単にクラウド経由で宅外通信が出来るのが魅力です。
そして、今回のBridgeウィジェットでデバイス間の宅外通信が出来るなら、
例えば、実家↔自宅の簡易通信(ライフログ確認)などを簡易マイコンのみの低コストで実現できるのはとても魅力です。

また、OriHime等の遠隔コミュニケーションロボットの外付けオプション機器としてうまく使っていけそうです。

最近では Obniz OSという新たなクラウド開発ツールもでてきたので、こことの使い勝手比較もやっていきたいですね。