プログラムと電子工作の置き場、たまにコラム

日々のスニペットやMaker's系のプログラムを置いてきます。

Raspberry Piで温度センサー。部屋の気温を取得しよう

温度センサーを使って部屋の温度を取得してみましょう。

この記事を書いているのは冬なので今日は何度まで下がるのか等々、温度(気温)というのは人の生活において最も大切な指標の一つですね。今回はそんな気温をセンサーで取得してみましょう。

このグラフは21度に設定されたエアコンを入れてからの20分間の温度推移です。
f:id:yuriai0001:20131223190351j:plain
21度に向けて数値が上昇していってます。
f:id:yuriai0001:20131223234245p:plain

キットを購入していただいてる方は、温度センサーとセラミックコンデンサーを準備してください。

f:id:yuriai0001:20140513202451p:plain
回路そのものは、CDSの項目とほぼ同じです。
温度センサーは逆向きに取り付けないよう注意してください。また温度センサーの後ろにセラミックコンデンサーを取り付けます。温度センサーの両脇の足の後ろに取り付けます。このコンデンサーには極性はないのでどちら向きでも結構です。


コードもCDSで明るさを取得した際のものを流用すればいいのですが、今回の最終的な単位は℃なので返ってきたvalueの数値をもとにして変換する必要があります。温度センサーの仕様として電圧範囲は100mVから1.75V、0℃の時には500mVの出力電圧で温度の係数は10.0mV/℃つまり1℃につき10mV出力電圧が変化します。アナログセンサーとして利用しているMCP3002に関しては10bit(1024)ですので、

require 'pi_piper'
loop do
  value = 0
  PiPiper::Spi.begin do |spi|
    raw = spi.write [0b01101000,0]
    value = ((raw[0]<<8) + raw[1]) & 0x03FF
  end
  volt = (value * 3300)/1024
  degree = (volt - 500)/10
  puts degree
  sleep(1)
end

実行すると1秒ごとに現在の温度が表示されます。
この温度センサーは個体によって最大±4℃の精度と温度センサーとしてどうなんだというくらいに、大幅にずれる可能性があるみたいです。その場合には+25℃を基準にしてソフトウェアによる校正を入れてみてください。私がいくつか試した結果では、ほぼ問題なく21℃を示していました。結果をfloatで求めたい場合などは、ずれを均一化するため平均で数値を出すなどの工夫が必要になると思います。

部屋の温度はcsvで出力して表計算ソフトウェアで編集するのもよいでしょう。
CSVについての詳細はcodezineの記事が役に立ちます。
CSVファイルフォーマットの解説:CodeZine(コードジン)

Raspberry Piの入門本ではwebブラウザ経由で現在の温度や過去の温度をグラフで確認するというようなサンプルが多いので、ここでもやってみましょう。ただ、インターネット経由となるとその他多くの作業が必要になるため今回はLocalの範囲内とします。

webアプリのフレームワークといえばRuby on Railsですが、小さなアプリの場合はsinatraが適しているように思います。まずはチュートリアルに従ってHello Worldをやってみましょう。やり方は公式サイトに掲載されています。
http://www.sinatrarb.com/intro-ja.html
以下のコードを書いて

# myapp.rb
require 'sinatra'
get '/' do
  'Hello world!'
end

gemをインストールしましょう。
gem install sinatra
そして実行。
ruby myapp.rb

webブラウザを起動してアドレスバーに下記を入力すると、
http://localhost:4567

Hello world!と出力されてると思います。


さて、グラフの描写にはJavaScriptを使用したいと思います。ネットで調べて見たところ、Chart.jsが良さそうな感じです。
http://www.chartjs.org/


サンプルコードをそのまま使用しましたのでチグハグですが(時間あるときに修正します)。
sinatraのマニュアルに従いviewsというフォルダにindex.erbファイルを置きます。
index.erb

<!doctype html>
<html>
<head>
  <title>Line Chart</title>
  <script src="../Chart.js"></script>
  <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.js"></script>
  <meta name = "viewport" content = "initial-scale = 1, user-scalable = no">
</head>
<body>
<input type="button" id="synch" value="load">
<div id="container">
<canvas id="canvas" height="450" width="600"></canvas>
</div>

<script>
$(function () {
     $('#synch').click(function () {
         $.ajax({
             type: 'GET',
             url: 'http://localhost:4567/graph',
             dataType: 'json',
             success: function (json) {
                 var ary = json;
                 var xaxis = [];
                 var yaxis = [];
                 for (var i = 0, l = ary.length; i < l; i++) {
                     if (i % 2 == 0) {
                         xaxis.push(ary[i]);
                     } else {
                         yaxis.push(ary[i]);
                     }
                 }
                 var lineChartData = {
                     labels: xaxis,
                     datasets: [{
                             fillColor: "rgba(220,220,220,0.5)",
                             strokeColor: "rgba(220,220,220,1)",
                             pointColor: "rgba(220,220,220,1)",
                             pointStrokeColor: "#fff",
                             data: yaxis
                         },

                     ]
                 }

                 var myLine = new Chart(document.getElementById("canvas").getContext("2d")).Line(lineChartData);

             },
             error: function () {
                 $('#container').append('<p>' + 'Error! something is wrong.' + '<p>');
             }
         })
     })
 })
</script>
</body>
</html>
require 'sinatra'
require 'sinatra/reloader'
require 'sinatra/contrib/all'
require 'csv'
require 'json'

def file_convert
  datatime=""
  CSV.foreach("./temp.csv","r") do |data|
     datatime = data
  end
  return datatime
end

get '/' do
  erb :index
end

get '/graph' do
 @message = "Hello Graph Page"
 content_type :json
  data = file_convert
  data.to_json
end

実行する前に、
gem install sinatra-contrib
をしてください。

アプリケーションを起動したら、
http://localhost:4567/にアクセスします。ボタンを押すとAjaxを使った通信によってcsvファイルに保存されている時間と温度がグラフ表示される仕組みです。
http://localhost:4567/graphにアクセスするとjson形式で値が出力されます。
f:id:yuriai0001:20140107182301p:plain
動くことには動きました。グラフのデザインを設定するにはオプションを設定する必要があります。
Chart jsのドキュメントを見て、ひとまず必要最低限のデザイン設定をしました。
http://www.chartjs.org/docs/
f:id:yuriai0001:20140128142443j:plain

[補足]
このマニュアルを公開してから随分と月日が経ちました。IoTがバズワードからようやく実際に利活用される段階まできている気がします。最近はIoTのバックエンド周りをサポートしてくれるサービスがちらほら出てきます。以下のリンク先をもその1つです。これを使えば、自前でネットワークの問題を解決する必要がなくなります。また視覚化も簡単ですね。
blog.mlkcca.com


以上で、キットの内容はすべてとなります。
パーツとして使いましたデータシート一覧が必要な場合はメールにてお問い合わせください。

またお時間があれば、番外編として圧電スピーカーで音階を奏でるもご覧ください。