第16回 IoT×プログラミング教育
ウェアラブル端末を作ります。16回目にしてようやくIoTです。
手を振るとブラウザ上で雪が降る仕組みを作ります。
ウォッチを作る
足立区のイベントでもらったパラスポーツ応援リングに、前回作ったブレッドボードを巻きつけます。
もっと小さくして、ただのリングにしたかったのですが、大きくなって時計のようになってしまいました。
バッテリーも邪魔です。
・・・まあ、最初のIoT体験としてはこれで良いでしょう。
1回振ると、1つ雪が降る
腕を1回振ると、ブラウザ上で1回雪が振る仕組みを作ります。
「ESPr Developer」をサーバーとし、腕を振った回数を取得できるようにします。
雪を降らすまでの大まかな流れは、
傾斜センサーが傾き取得
↓
LEDが光ると同時に、傾いた回数をカウント
↓
傾いた回数を0.5秒ごとにサーバーがJSONP出力
↑
ブラウザからAjaxでJSONP取得
↓
傾いた回数が増えていたら、増えた数だけ雪を降らす
「ESPr Developer」側のプログラム
世の中に出して良いプログラムなのか迷うほど、正攻法とは思えないやり方ですが、「ESPr Developer」に書き込んだプログラムを掲載します。
/* ESPr Developerを使ったWi-Fi接続コードは、下記をサイトのものを使わせて頂きました。ESPr Developer ( ESP-WROOM-02 開発ボード )の使い方をザッと紹介*/ #include <ESP8266WiFi.h> #define PIN 13 const char* ssid = "※自分のWi-FiのID※"; const char* password = "※自分のWi-Fiパスワード※"; WiFiServer server(80); WiFiClient client; int val = 0; //アナログ入力値 int count = 0; //振った回数 int interval = 0; boolean shake = false; void setup(){ pinMode(PIN, OUTPUT); #ifndef __AVR_ATtiny85__ #endif Serial.begin(115200); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); server.begin(); // Print the IP address Serial.println(WiFi.localIP()); } void loop(){ val = analogRead(0); if(val > 800){ //傾き無し digitalWrite(PIN,LOW); shake = false; }else if(shake == false){ //傾き初回 digitalWrite(PIN,HIGH); count++; shake = true; }else{ //傾き中 digitalWrite(PIN,LOW); } delay(50); interval++; if(interval > 10){ //50m秒×10(=500m秒)ごとに Ini_HTTP_Response(); //HTTPレスポンス実行 interval = 0; } } void Ini_HTTP_Response() { client = server.available(); delay(1); String req; while(client){ if(client.available()){ req = client.readStringUntil('\n'); Serial.println(req); if (req.indexOf("GET / HTTP") >= 0 || req.indexOf("GET /?callback") >= 0 || req.indexOf("GET /favicon") >= 0){ Serial.println(req); while(req.indexOf("\r") != 0){ req = client.readStringUntil('\n'); Serial.println(req); } req = ""; delay(10); //JSONP書き出し client.print("callback({\"Shake\":"); client.print(count); client.print("});"); delay(1); client.stop(); Serial.println("\nGET HTTP client stop--------------------"); req = ""; } } } }
これで、「ESPr Developer」と同一ネットワーク上にあるPCやスマホのブラウザで、JSONPを取得できるようになります。
Serial.println(ssid);により、シリアルモニタにIPアドレスが書き出されるので、それをブラウザ側でも使います。
ブラウザ側のプログラム
次にブラウザで表示するHTMLを作ります。
ローカルサーバーでもレンタルサーバーでも良いので、やりやすいところにHTMLを置きます。
HTML(CSSとJS込)は以下です。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>距離計測結果</title> <script src="//ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <style type="text/css"> body { background: #000; color: #FFF; overflow:hidden; } #output { font-size: 100px; } .snow { position: absolute; border-radius: 50%; } .snow.layer0 { width: 50px; height: 50px; background-color: hsla(0,0%,100%,0.8); animation: fall 2s linear; } .snow.layer1 { width: 40px; height: 40px; background-color: hsla(0,0%,100%,0.6); animation: fall 3s linear } .snow.layer2 { width: 30px; height: 30px; background-color: hsla(0,0%,100%,0.4); animation: fall 4s linear; } @keyframes fall { 0% { margin-top: 0; } 100% { margin-top: 1200px; } } </style> </head> <body> <div id="wrap"> <div id="output"></div> </div> <script type="text/javascript"> var count = 0, oldCount = 0, snowCount = 0, init = function(){ setInterval(function(){ $.ajax({ type: 'GET', url: 'http://192.168.179.2', dataType: 'jsonp', jsonpCallback: 'callback', success: function(json){ oldCount = count; count = json.Shake; if(count > oldCount){ $("#output").text(count); snowCount = count - oldCount; for(var i = 0; i < snowCount; i++){ $("#wrap").append('<div class="snow layer' + Math.floor( Math.random() * 3 ) + '" style="left:' + Math.floor( Math.random() * 101 ) + '%; top:-' + (Math.floor( Math.random() * 101 ) + 50) + 'px"></div>'); } } } }); },1000); } init(); </script> </body> </html>
Ajaxで取得するURLは、Arduinoシリアルモニタで確認したIPアドレスを指定します。
JSONPで、クロスドメインの壁を超えていますが、こんなやり方でよいのでしょうか・・・。
雪を降らそう
ブラウザをフルスクリーンにして、雪降るウォッチを振ってみます。
左上の数字は降った(振った)回数です。
たまに動作が安定しないので、そういう時は「ESPr Developer」のリセットボタンを押してやり直します。
子供の食いつきはなかなか
IoT体験として、子供の食いつきは良かったです。
有り余る子供のエネルギーに、パソコンが連動するのが良いです。
今回は深い理由もなく、雪を降らせましたが、別途IoT観戦で使えないか研究中です。
多分「ESPr Developer」をサーバーとするやり方は限界があるので、別の方法も考えていきます。