まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:obniz

タイトルの通りです。obniz に赤外線人感センサー(HC-SR501)をつなげて人の存在を確認し、なんらかの変化があった場合にその結果をクラウド上の Google スプレッドシートに送信する、という仕組みを作ってみました。必要な設定やコードはこちらからも公開しています:
https://github.com/dotnsf/obniz_sensor_gas


Google スプレッドシートを複数人で共有しておけば人感センサーのセンシング結果を複数の人で共有することができます。今回の例ではそこまで実装していませんが、センシング結果にセンサーの ID を含めるようにすれば、複数のセンサーからの結果を一枚のスプレッドシートにまとめることもでき、またスプレッドシート側でピボットして確認したり、グラフ化などの視覚化も容易にできるようになります。

この仕組みはもともとこちらの動画で紹介されていたものを参考にしています。この動画ではラズベリーパイと HC-SR501 を接続して、ラズベリーパイのコマンドでセンシングを実現しています。また最終的にはそのコマンドを cron に登録する形で永続処理化まで実現されているようでした:
RaspberryPIでIoT簡単入門!クラウド対応人数カウントを作る!

2021052502


これを参考にラズベリーパイを obniz に置き換えて GPIO に接続し、ラズベリーパイのコマンドではなく、obniz のウェブページの JavaScript でセンシングし、その結果を Google スプレッドシートに向けて JavaScript で(jQuery で) POST する、となるように書き換えました。

以下、その準備段階も含めた実現の手順を紹介します(ハードウェアは持っていない場合は購入の必要があります)。

【入手するハードウェア】
obniz 本体
人感センサー(HC-SR501)
ジャンパケーブル(オス-メス)3本

【用意するソフトウェア】
・Google スプレッドシート(Google Drive から作成)


【準備作業】
人感センサーによるセンシングを行うための準備作業は以下の大きく以下3つの作業を行います:
1 スプレッドシート側の準備
2 obniz と HC-SR501 の接続
3 センシングを実行する HTML / Javascript コードの用意


1 スプレッドシート側の準備

まず Google スプレッドシートを1つ新規に作成します:
2021052601


スプレッドシートのメニューから ツール - スクリプトエディタ を選択します:
2021052602


コード画面が表示されるので、デフォルトで用意されているスクリプトをすべて消し、代わりに以下のコード(後述のデータ送信を受けて、シート内に日付時刻と送信データ内容を追加するコード)をコピー&ペーストします:
function doPost(e) {
  SpreadsheetApp.getActive().getActiveSheet().appendRow(
    [new Date(),e.postData.contents]
  );
  
  var output = ContentService.createTextOutput("ok");
  output.setMimeType(ContentService.MimeType.TEXT);
  return output;
}
2021052603



メニューから 公開 - ウェブアプリケーションとして導入 を選択します:
2021052604


プロジェクト名を聞かれたら適当に入力して OK をクリックしてください:
2021052605


続けてデプロイ設定画面になります。バージョンは "New" の "1" 、アプリケーションの実行者は自分のメールアドレスを指定、そしてアクセスできる人として "Anyone, even anonymous" を選択して deploy ボタンをクリックします:
2021052606


アプリケーションの認証が必要なので「許可を確認」をクリックします:
2021052607


ちょっとびっくりするような画面になりますがエラーではないので続けます。詳細を表示して、安全ではないページに移動します:
2021052608


作成したプロジェクトにアクセスの許可を与えるため、「許可」ボタンをクリックします:
2021052601


デプロイが行われ、最後に URL が含まれる画面になります。この URL はこの後必要になるので、メモしておきます。OK を押してダイアログを閉じます:
2021052602


これでスプレッドシートの最低限の準備はできました。必要であればスプレッドシートの名称を変更したり、他の人と共有しておいてください:
2021052603


2 obniz と HC-SR501 の接続

まず以下の作業をする前に obniz の電源を OFF にしてください。以下の作業は obniz の電源が OFF になっている状態で行ってください。

HC-SR501 には3本の接続コネクタピンがあります。接続コネクタ部分が左側にくるように向きを調整した時のピンを上から0、1、2とみなします。また obniz も同様に GPIO が下側にくるように向きを調整した時のコネクタを左から0、1、2、・・・とみなすことにします:
2021052601


この状態でジャンパケーブルを使って、0と0、1と1、2と2をそれぞれ接続します。ここまでできると写真のような状態になります:
D95C6870-EBAC-4D5B-88BB-F8F5F48F9D7F


これで obniz と HC-SR501 が接続できました。この後、obniz の電源を ON にすると HC-SR501 でセンシングできるようになり、センシングした結果を obniz から取得することができるようになりました。


3 センシングを実行する HTML / Javascript コードの用意

最後に実際にセンサーで人の存在を確認し、その結果を取得して、(上述で準備した)スプレッドシートに記録する、というプログラムを作ります。

まず obniz の開発者コンソールにログインします:
https://obniz.io/ja/console


画面左の「リポジトリ」から「新規作成」を選択します:
2021052604


新しいプログラムのダイアログが表示されます。タイプは「WebApp」、アクセスレベルは「公開」を選択し、適当なファイル名を付けて「作成」します:
2021052605


サンプルページの HTML がエディタ内に表示されます:
2021052606


この HTML をすべて消して、以下の内容をコピー&ペーストします:
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    <script src="https://unpkg.com/obniz@3.8.0/obniz.js"></script>
  </head>
  <body>
    <h1>人感センサー</h1>
    <div id="obniz-debug"></div>

    <script>
      var obniz = new Obniz("OBNIZ-ID");
      var sensor = null;
      const url = "https://script.google.com/macros/s/xxxxxxxxxx-xxxxxxxxxx/exec";//GASのウェブアプリケーションのURLを指定してください

      obniz.onconnect = async function () {
        sensor = obniz.wired( "Keyestudio_PIR", { signal:1, vcc:0, gnd:2 } );
        console.log( sensor );
        sensor.onchange = function( v ){
          console.log( v );
          $.post( url, { value: v } )
            .done( function( data ){ console.dir( data ); } );
        };
      };
    </script>
  </body>
</html>
2021052607


12 行目と 14 行目は変更が必要です。12 行目の new Obniz( "OBNIZ-ID" ); となっている OBNIZ-ID の部分は自分が使っている obniz の ID (電源を入れた時に画面に表示される nnnn-nnnn 形式の8桁数字)に置き換えてください。 また 14 行目の url の値は上述の作業1の最後、スプレッドシートに権限を与えた際に取得した URL 文字列に置き換えてください。

なお、17 行目で obniz と人感センサーをソフトウェア的に接続しています。上述の 0-0, 1-1, 2-2 と物理的に繋いだ作業の意味(0 が vcc 、1 がシグナル、2 がアース)を指定しています。

ここまでの変更ができたら準備はすべて完了です。


【センシング実行】
まず obniz と、obniz に接続された HC-SR501 に電源を入れます。obniz にマイクロ USB ケーブルを接続して、WiFi に接続してください。成功すると以下のように obniz ID とその QR コードが表示される画面になります:
2021052601


そして obniz コンソール画面右上の「実行」ボタンをクリックします:
2021052607


すると以下のような画面になります。緑の帯が出ていれば obniz は WiFi を経由してインターネット接続ができていることを意味しています(緑にならず、赤くなっている場合は WiFi 接続に失敗しているなど、インターネットに接続できていないことを意味しているので修正が必要です):
2021052602


この時に人感センサー近くで人が行ったり来たりして、人が存在していたりいなかったりするような状況になると、その変化を人感センサーが感知してスプレッドシートにその変化の様子が送信されます。スプレッドシートは以下のような感じになり、変化を検知する度に一行ずつ増えていきます:
2021052603

↑左が検知の日付時刻、右は value=true が人を感知した時、value=false は検知していた人がいなくなったことを検知したことを意味しています。

なお、このスプレッドシートは手動で情報を消さない限りはずっと情報が「追加」されます。一度リセットしたい場合は該当シート内に書かれた部分を手動で全選択して DELETE してください。


動作確認ができたら、いったん「終了」ボタンを押してセンシングを終了します:
2021052602


【センシングの自動化設定】
とりあえず人感センサーとしての挙動は確認できました。最後にこの仕組を(わざわざウェブページを開いて「実行」ボタンを押さなくても、電源に接続しただけで実行できるように)自動実行する方法を紹介します。

改めて obniz 開発者コンソールに戻り、左側のメニューから「サーバーレスイベント」を選んで「新規作成」します:
2021052601


適当な名前(図では「人感センサー」)を入力し、「トリガー」には obniz Hardware Event を選択後に対象 obniz id を選択して online イベントを、「実行するアプリケーション」にはリポジトリ内の HTML を選択後に先程作成した HTML を、それぞれ選択します。最後に「作成」ボタンをクリックします:
2021052602


これで対象 obniz がオンラインになったタイミングで対象 HTML ページが実行されるので、自動起動に近い処理が実現できました。いったん obniz の電源を OFF にしてから ON にするなどして、再度センシングできているかどうか(スプレッドシートに情報が追加されるかどうか)を確認してください:
2021052603


肝心のセンサー精度などはまだちゃんと測定できていない(苦笑)のと、実際には HC-SR501 についているネジでそのあたりの調整もできるようですがまだしていない(苦笑)ので、実際のところどの程度現実的に役立つものなのか、まだわかっていないところもありますが、(ラズベリーパイや)obniz があるとこんなことも簡単に作れちゃうんですね。単にセンシングするだけでなく、取得した内容をインターネット上に記録して共有するところまでできている点がポイント高いと思っています。




カスタマイズネタでテトリスを扱うことがあるのですが、その時のベースに使っているのがこちらです:
https://github.com/dionyziz/canvas-tetris

Dionysis Zindros さんが HTML5 Canvas で作ったテトリスです。Canvas 、JavaScript 、そして CSS でテトリスが再現されていて、MIT ライセンスで公開されています。実際に遊ぶ時にもブラウザで index.html ファイルを開くだけ(index.html ファイルは HTTP サーバー上にアップロードされている必要はなく、ローカルファイルとして開くだけでも可)で遊べます。

一応、遊び方にも触れておきます。index.html ファイルをブラウザで開くと以下のような画面になります。この「Play」ボタンをクリックするとテトリスがスタートします:
2019061703


操作はキーボードを使います。矢印の左右でテトリミノ(ピース)を左右に移動、上矢印で回転、下矢印で強制的に下に移動します:
2019061704



といった背景もあって実際に遊ぶのはもちろん、改良する場合においても技術的&ライセンス的なハードルが低く、デモやハンズオンも含めたセミナーのネタとして重宝しています。


そんなわけで、今日のブログエントリはこのテトリスを Obniz で操作する、というカスタマイズの紹介です。


Obniz (オブナイズ)をご存じない人のために簡単に紹介しておきます。Obniz は 2017 年に Kickstarter でクラウドファンディングが開始された IoT ボードです。Arduino や Raspberry Pi(Zero) と比較しても小型で、単体ではダイヤル式のスイッチと簡単な文字が表示できるディスプレイを入出力装置として持っています。これ以外に標準で無線 LAN および Bluetooth につながることができ(そのための設定をダイヤル式スイッチで指定します)、そして 12 個の GPIO によって各種センサーやモーターを接続することができます。MicroUSB からの給電により、(単体では)最大 1.8A の電流で稼働します。

そして最大の特徴といえるのが JavaScript による API の提供です。HTML や Node.js から利用可能な JavaScript でこれらの入出力装置の状態を監視したり、値を入力/設定/出力することができます。Obniz の JavaScript そのものの紹介が本ブログエントリの目的ではないので、詳しくは公式ドキュメントを参照してください。ググればネット上にサンプルを含めた使い方がたくさん見つかりますが、要するに「ウェブ(ページ)との連携が容易なボード」なのです:
https://obniz.io/doc/root





この Obniz ボードとの連携として、ボードのダイヤルスイッチでテトリミノを動かせるように改良しました。そのコードがこちらです:
https://github.com/dotnsf/canvas-tetris


こちらのコードをダウンロード(または git clone)して、Obniz を WiFi に接続後にブラウザで index.html ファイルを開いてください。すると最初に以下のような画面になって Obniz ID の指定を促されるので所有する Obniz の ID を指定します:
2019061702


そして "Play" ボタンをクリックでゲームスタートです。ここでは Obniz のダイヤルスイッチを使って、以下のように操作することができます:
ダイヤルスイッチ操作
左に回す左移動
右に回す右移動
押し込む回転


実際に遊んでいる様子がこちらです(下手すぎるのは撮影しながらだから、です・・・):



この仕組みのすごい所は「ゲーム画面とコントローラー(Obniz)が離れていても実現できる」点です。↑の動画では Obniz のある場所でゲーム画面を開いていますが、たとえばゲーム画面は地球の裏側で見られていたり、コンサート会場の大型スクリーンなどに表示されていてもいいわけです。そんな仕組みを簡単に実現できてしまっている、という点が素晴らしいと感じてます。

ちなみにカスタマイズの肝となっている箇所のコードはこちらです。js/controller.js ファイル内に以下のコードを追加して、Obniz スイッチの変更イベントを obniz.switch.onchange でハンドリングし、その内容に応じて対応するキーが押されたようにイベントを発生させています:
  :
//. obniz
var obniz = new Obniz("XXXX-XXXX"); //. <-- Edit with your own Obniz ID
obniz.onconnect = async function(){
  obniz.display.clear();
  obniz.display.print( "Obniz TETRIS" );

  obniz.switch.onchange = function( state ){
    obniz.display.clear();
    obniz.display.print( state );

    switch( state ){
    case 'left':
      keyPress( 'left' );
      render();
      break;
    case 'right':
      keyPress( 'right' );
      render();
      break;
    case 'push':
      keyPress( 'rotate' );
      render();
      break;
    default:
    }
  }
}

この Obniz の JavaScript SDK は本当に強力で、簡単にこういうことが実現できちゃいます。LED やセンサーを繋いだり、モーターを繋いだりしなくても、手軽にこんな使い方が実現できちゃうという、このポテンシャルの高さが魅力で気に入ってます。



このページのトップヘ