インターネット温度計

一般家庭でのIoTを考えた時に、データの流れに着目するとINとOUTがあると思う。

![IoT_Home.png](https://qiita-image-store.s3.amazonaws.com/0/104066/f93b0782-e586-3891-cc1d-942beacdda2d.png)

INは情報提供などの機能が該当し、OUTは何らかの情報共有のための機能が該当するのではないだろうか。

INのモデルとしてインターネットに接続された温度計を作ってみたいと思う。これは温度の計測は自前でおこない、ネットからその日の最高最低気温を入手して表示するような代物を考えている。

プラットフォームは以前紹介した[FreeBSD/mruby](http://qiita.com/yamori813/items/038027275d21e87388cd)とArudinoを使う。

![InterTemp.png](https://qiita-image-store.s3.amazonaws.com/0/104066/d7652d43-67fb-db45-436a-ffd3f0fe08a0.png)

mruby on FreeBSDはZRouterビルドしハードオフで購入したAR2315なジャンクルータで動いている。電波法の兼ね合いもあるのでWIFIは使わずEthernetでの接続にしている。

まずmrubyでインターネットからその日の最高最低気温を入手するコードを作ってみる。これはヤフー天気のRSSから拾ってくることにする。

```
loc = "4410"
#loc = "3530"
h = HttpRequest.new()
r = h.get("http://rss.weather.yahoo.co.jp/rss/days/"+loc+".xml");
s = r.body
pos = s.index('description')
pos = s.index('description', pos+1)
pos = s.index('description', pos+1)
pos = s.index(' - ', pos+1)
npos = s.index('℃', pos+1)
hi = s[pos+3..npos-1]
pos = s.index('/', pos+1)
npos = s.index('℃', pos+1)
lo = s[pos+1..npos-1]
p hi + " " + lo
```

mrubyには今のところxmlのパーサーが無いようなので、かなり無理矢理スクレイピングしている。これを[こらのページ](http://qiita.com/yamori813/items/1d1c40ce69fe6e60ce1c)に書いたI2Cモジュルを使いArduinoに送るコードは以下のようになる。

```
t = BsdIic.new(0)
t.write(8,0,hi.to_i)
t.write(8,1,lo.to_i)
p t.read(8,0)
```

最後の行はおまけで、Arduinoから現在気温を拾っている。

ArudinoはAitendoのびんぼうでいいので温度センサーはLM61で7セグは手元にあったTOD-5261Bという部品を使った。

![スクリーンショット（2016-02-27 9.56.18）.png](https://qiita-image-store.s3.amazonaws.com/0/104066/5687f3a7-b5a4-ed63-e393-1664b34fb0c1.png)

Arduinoのプログラムは「きむ茶工房ガレージ」さんの[I2Cのページ](http://www.geocities.jp/zattouka/GarageHouse/micon/I2C/I2C_2.htm#TEST2)と[LM61のページ](http://www.geocities.jp/zattouka/GarageHouse/micon/Arduino/Temp/Temp.htm)と「初心者だけど、一歩ずつ Arduino 超小型マイコン電子工作」さんの[7セグのページ](http://happy-arduino.blogspot.jp/2012/09/27_19.html)を参考にさせてもらった。

```
#include <MsTimer2.h>
#include <Wire.h>

//グローバル変数を宣言
int Digit1=0; //左側7セグLED表示用LED
int Digit2=0; //右側7セグLED表示用LED
int Dp;

byte dt[2] ;

int temp;
int hi, lo;

// データを受信すると処理される割込み関数
void receiveEvent(int howMany) 
{
  int count = 0;
  while(Wire.available()) {   // 書き込みの時は2バイトで読み込みの時は1バイト
    dt[count] = Wire.read();
    ++count;
  }
  if(count == 2) {
    //書き込みで1バイト目が0が最高気温,1が最低気温
    if(dt[0] == 0) {
      hi = dt[1];
    } 
    else {
      lo = dt[1];
    }
  }
}

// データ要求を受信すると処理される割込み関数
void requestEvent() 
{
  Wire.write(temp) ;   // LM61で測定した温度を送信
}

//LEDレイアウトを定義
boolean Num_Array[10][7]={
  {
    0,0,0,0,0,0,1    }
  ,{
    1,0,0,1,1,1,1    }
  ,{
    0,0,1,0,0,1,0    }
  ,{
    0,0,0,0,1,1,0    }
  ,
  {
    1,0,0,1,1,0,0    }
  ,{
    0,1,0,0,1,0,0    }
  ,{
    1,1,0,0,0,0,0    }
  ,{
    0,0,0,1,1,1,1    }
  ,
  {
    0,0,0,0,0,0,0    }
  ,{
    0,0,0,1,1,0,0    }
};

//LED表示関数を定義
void NumPrint(){
  static int DigitFlag=2; //表示している桁　1の時は左側、2の時は右側
  int Number;
  if(DigitFlag==1){
    digitalWrite(9,HIGH);
    digitalWrite(10,LOW);
    Number=Digit1;
    DigitFlag=2;
  }
  else{
    digitalWrite(9,LOW);
    digitalWrite(10,HIGH);
    Number=Digit2;
    DigitFlag=1; 
  }
  // 数字表示
  for (int w=0; w<=6; w++){
    digitalWrite(w+1,Num_Array[Number][w]);
  }
  // ドット表示
  digitalWrite(8,Dp == DigitFlag ? 0 : 1);
}

//LED2桁表示
//dotは右が１で左が2で無しが0
void NumPrintEx2(int Number, int dot){
  Digit1=Number / 10; //十の位を指定
  Digit2=Number % 10; //一の位を指定 %は余りを計算
  Dp = dot;
}

void setup(){
  //1～8番ピン　デジタル出力へセット
  for (int i=1; i<=8; i++){
    pinMode(i,OUTPUT);
  }
  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);

  MsTimer2::set(10, NumPrint); // 10ms period
  MsTimer2::start();

  Wire.begin(8) ;                    // Ｉ２Ｃの初期化、マイアドレスは８とする
  Wire.onRequest(requestEvent) ;     // 割込み関数の登録
  Wire.onReceive(receiveEvent) ;     // 割込み関数の登録
}

void loop(){
  int ans , tv ;

  ans = analogRead(0) ;              // アナログ０番ピンからセンサー値を読込む
  tv  = map(ans,0,1023,0,5000) ;     // センサー値を電圧に変換する
  temp = map(tv,300,1600,-30,100) ;  // 電圧から温度に変換する

  NumPrintEx2(temp, 0);
  delay(5000);
  NumPrintEx2(hi, 2);
  delay(5000);
  NumPrintEx2(lo, 1);
  delay(5000);
}
```

現在の気温,最高気温,最低気温の順に表示する。ドットで最低最高気温を表すようにしている。

![IMGP0152.JPG](https://qiita-image-store.s3.amazonaws.com/0/104066/5e9ffb0d-7662-6cd0-9ba2-c891e06003d0.jpeg)

ルータは3.3V系で、びんぼうでいいのは5V系なので秋月電子で購入したPCA9306を使ったレベル変換モジュールで接続しています。このモジュールにはプルアップ抵抗も入っています。

気温データをインターネットに送る事(OUT)もできますが、利用価値があるアイディアがありません。自分の部屋の温度を他人に知ってもらってもあまり嬉しくないですよね。

IoTってインターネットにつながっているかどうかは意識せずに使われるような物であるのが良いのかなとか思ったりしています。

実はこの仕組みのデータの流れは[こちら](http://techblog.yahoo.co.jp/event/hack_day_gadget1/)とほぼ同じなのですが、使っている技術がちょっと違っています。