雪降るウォッチ

第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接続コードは、下記をサイトのものを使わせて頂きました。
https://www.mgo-tec.com/blog-entry-ss-wroom-howto01.html
*/
#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」をサーバーとするやり方は限界があるので、別の方法も考えていきます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)