スマートメータを自作した話

12/24 この記事は おうちハック Advent Calendar 2015 の24日目の記事です。

3日連続で鍵の話題が続いているのを中断するのは心苦しいのですがスマートメーターの話です。

はじめに

昨年、3人でシェアハウスしていたのですが電気代が3万円を超え、24時間1000W位上の電気を使っている状態になっていました。 漏電、盗電、メータの故障、電気代が折半なのをいいことにビットコインを掘ってる人がいる等の可能性が出てきたので、スマートメータを設置し電気使用量を可視化しました。

結果的に理由はわからずじまいのままシェアハウスは解散し、パーツだけ手元にあった状態で放置されてましたが、調度良い機会だったので再設置し記事にしました。

用意するもの

作成

スマートメーター仕組みとしては配電盤に電流センサを設置しマイコンで取得、サーバに送信し蓄積・可視化するだけです。

配電盤の近くにはコンセントは無いため、長期間電池駆動可能な無線マイコンのTWE-Liteを選択しました。 TWE-LITEは、

  • 省電力: 間欠1秒モードの場合単3電池2本で1年以上保つ
  • プログラム不要: 親機子機で通信する分には電源を入れるだけでOK

等と今回の案件にぴったりでした。

ただし、クランプ型電流センサの出力は交流なので、間欠動作では1秒間に何度もサンプリングして実効値を算出する方法が使えないません。 そこで平均値整流型電流変換回路を使います。

適当にブレッドボードに回路を組んで完成。 ADコンバータが余ってもったいないのでLM61を挿してます。 f:id:YarmUI:20151223210526j:plain

配電盤に設置します。 f:id:YarmUI:20151224205827j:plain

PCに親機であるToCoStickを接続し、こんな感じのルビースクリプトを書いてデータを取得します。

require 'serialport'
dev = '/dev/tty.usbserial-AHXKQMRT'

sp = SerialPort.new(dev, 115200, 8, 1, SerialPort::NONE)
loop do
  l = sp.gets.chomp
  next if l[0] != ":" || l.size != 49
  l = l[1, 48]

  chk = l.scan(/.{1,2}/).map{|e| e.hex}.inject(:+) & 0xff
  next unless chk.zero?
  src       = l[0, 2]  # print "  src       = 0x%02x" % l[0]
  src_long  = l[10, 8] # print "  src long  = 0x%08x" % ladr
  command   = l[2, 2]  # print "  command   = 0x%02x (data arrival)" % l[1]
  dst       = l[18,2]  # print "  dst       = 0x%02x" % l[9]
  pktid     = l[4, 2]  # print "  pktid     = 0x%02x" % l[2]
  prtcl_ver = l[6, 2]  # print "  prtcl ver = 0x%02x" % l[3]
  lqi       = l[8, 2]  # print "  LQI       = %d / %.2f [dbm]" % (l[4], (7*l[4]-1970)/20.)
  timestamp = l[20, 4].to_i(16)
  vlt       = l[26, 4].to_i(16)
  dibm      = l[32, 2].to_i(16)
  dibm_chg  = l[34, 2].to_i(16)
  er        = l[44, 2].to_i(16)

  di     = []
  di_chg = []
  4.times do |i|
    di[i]     = dibm     & 0x1
    di_chg[i] = dibm_chg & 0x1
    dibm     >>= 1
    dibm_chg >>= 1
  end
  ad = []
  4.times do |i|
    av = l[i*2 + 36, 2].to_i(16)
    next ad[i] = nil if av == 0xFF
    ad[i] = (av*4 + (er & 0x3))*4
    er >>= 2
  end
  puts "#{Time.now}\t#{(ad[0]+ad[1])*2.7}w\t#{(ad[2]-600)/10}"
end

公式で公開されているPythonスクリプトを参考にしました。ADコンバータの値だけ取得すればよいのですが、取れる値全部変換しています。

可視化

本職がウエッブエンジニアなのではやりのfluentd+elasticsearch+kibana4を使います。 上記ルビースクリプトにfluentd-loggerを追加、ログとしてfluentdに垂れ流すだけで簡単に可視化できます。 qiita.com セットアップはここなどを参考にしてください。

完成したダッシュボードがこちらになります f:id:YarmUI:20151224213638p:plain

去年設置していた旧版ですが、kibana3のほうがダッシュボードはかっこいいです・・・ f:id:YarmUI:20151224213803g:plain (gif画像です、クリックで動きます)

課題と今後

  • 電流値なので正確な電力は測れない。精度が欲しい場合はコンセント経由で電圧も取得する必要がある。
  • 電波垂れ流しなので、ご近所にTWE−LITE使ってる人がいると電気使用量が筒抜けになる。(TWE-Liteは通信を暗号化する機能もあるけど面倒だった)
  • データ量が1秒に1件と多いのでnorikraを使って1分に1件に減らしたい。
  • ついでにnorikra使ってブレーカ落ちる警告を出したい。

おわりに

以上、スマートメータを自作した話でした。スマートメータを設置して驚いたのは、この時間のエアコンをつけた、ケトルを使った等の電気に伴う行動があとから結構分かるということでした。 ブログを書くのが久しぶりすぎてひどい文章だと思いますが、読んでくれた方はありがとうございました。

明日の最終日は@massa142さんの「皆さんの投稿を参考にして1週間でおうちを快適にしてみる」です。 メリークリスマス!!!