測定部、表示部、と作ってきたRaspberry Piによる自宅用電力ロガー作成。3回目の今回、Raspberry Piの本設置と設定を行いひとまずの完成となります。
1.測定部
電力をラズパイにて測る基本的仕組みは下記記事の通り。
あれから本設置に向けて以下を変更しています
- 回路部をユニバーサル基板で作り直し
- 入力を2chに増設(ch0:200V機器,ch1:暖房ボイラー)
- DHT11用ヘッダピン追加
基板レイアウトはギュッとつめてもう2ch分くらいは追加できるようにスペースを残しました。あとはこれを上にクリップ留め。
思いつきで温湿度センサDHT11用のGPIO5も基板に引っ張ってきました。Vcc,GNDは共用できるのでケーブル周りがすっきりします。これで消費電力の記録と合わせて温湿度もグラフ化できます。
電力測定
rubyで書いた電力測定のプログラムも2ch化しました。
”x.xx,y.yy”(x=0ch,y=1ch)というフォーマットで出力します。
require "pi_piper" RESOLUTION_AT_12BIT = 0b111111111111.to_f.freeze #Power Factor pf = 1.1 #Vref:MCP3208 Refarence voltage ( pin 13) v_ref = 3.3 #Register rl = 1000 #Coupling constant kt = 0.98 #coil turn turn = 3000 #Sampling time ( Number / sleep time * 2(ch) ) sampling = 20 #init totpow0 = 0 totpow1 = 0 read_ch = 0 count = sampling * 2 PiPiper::Spi.begin do |spi| while count > 0 do case read_ch when 0 then _, center, last = spi.write [0b00000110, 0b00000000, 0b00000000] when 1 then _, center, last = spi.write [0b00000110, 0b01000000, 0b00000000] end center = center & 0b00001111 center = center << 8 value = center + last eo = ( ( value / RESOLUTION_AT_12BIT ) * v_ref ).round(4) io = ( eo / ( rl.to_f / turn.to_f * 0.9.to_f * kt ) ).round(4) pow = ( 100 * io * pf ).round(4) case read_ch when 0 then ( totpow0 = totpow0 + pow read_ch = 1 ) when 1 then ( totpow1 = totpow1 + pow read_ch = 0 ) end count = count - 1 sleep 0.25 end puts "#{( totpow0 / sampling * 2 ).round(2)},#{( totpow1 / sampling ).round(2)}" end
0ch,1chを0.25秒おきに切り替えながら20カウント(上記では10秒)間測定し、その平均値を出力します。これはch1に接続する灯油ボイラーの消費電力が短期間でOFF/ONを繰り返すため。素直に1分に1回測定するとピークを外した際に0となってしまうのでせめてもの軽減策です。
pf=力率(Power Factor)が1を超えているのはワットチェッカーとの誤差を最終的にここで詰めているため。現実の力率が1を超えない事を考えると、むしろ大きすぎて下げる方が納得がいきそうですが果たして・・・?
温度・湿度測定
プログラムは温湿度センサDHT11をRaspberry Piに繋いでシリアル入力を学ぶ | 徒労日記にて使ったものそのまま。本当はRubyでやろうと模索したけどμsオーダーのI/O制御をRubyでどうやるか見当がつかず断念しました。(FFIを使って.cppを呼び出しているのはGitにあった)
2.表示部
作ったデータを吐き出すグラフサービス、M2Xについては下記記事に記しました。
このM2Xのフリープランのデータ送信には2.2回/分(10万回/月)までという制限があります。そのため素直にch0とch1のデータを1分おき+10分毎に温度・湿度を投げると本当プランギリギリになってしまいます。
そこで1日における使用頻度の低いch0は過去の値と比較し、値が変わった時のみ飛ばす様にcron実行用のスクリプトを書き換えました。連続データとしてみると時間軸がヘンになりますが、M2Xには「過去1日」など時間軸に沿った表示ができるため、そちらを選べばグラフはある程度の形になります。
2015/12/12 更新
#!/bin/sh if [ ! -e /dev/shm/ch1.txt ]; then echo 0.0 > /dev/shm/ch1.txt echo 0.0 > /dev/shm/ch0.txt fi epower=$(ruby /usr/local/etc/piper/epower.rb) #echo epower= $epower # # Chanel 1 = boiler power # ch1=$( echo $epower | cut -f2 -d',') ch1_bef=`cat /dev/shm/ch1.txt` echo ch1\(bef/now\) = ${ch1_bef}/${ch1}W curl -i -X PUT http://api-m2x.att.com/v2/devices/DEVICE_ID/streams/stream_name/value -H "X-M2X-KEY: DEVICE_ID" -H "Content-Type: application/json" -d "{ \"value\": \"$ch1_bef\" }" echo $ch1 > /dev/shm/ch1.txt # # Chanel 0 = 200V power # *200V is not uploaded if there is no change # ch0=$( echo $epower | cut -f1 -d',') ch0_bef=$(cat /dev/shm/ch0.txt) echo ch0\(bef/now\) = ${ch0_bef}/${ch0}W if [ $ch0_bef != 0.0 -o $ch0_bef != $ch0 ] ; then curl -i -X PUT http://api-m2x.att.com/v2/devices/DEVICE_ID/streams/stream_name/value -H "X-M2X-KEY: DEVICE_ID" -H "Content-Type: application/json" -d "{ \"value\": \"$ch0_bef\" }" fi echo $ch0 > /dev/shm/ch0.txt
ただ目下の問題として、同じ値(大抵0W)が続いた後にいきなり最高出力で使われるとグラフが大きな右肩上がりになり、実際と乖離するという事が分かりました。過去に1分戻って0Wを書き込めればいいんですがそうもいかず現在思案中。
このスクリプトをCrontabに
* * * * * /usr/local/etc/epower2m2x.sh 2>&1 | logger -t epower2m2x -p local0.info
と書いて1分ごとに実行するよう設定しました。
2015/12/12 追記
過去には戻れないので、プロットするデータを1分前のデータに変更しました。
最初の測定で両chとも結果をRAMDISKの/dev/shmへ保存します。その次の測定では前回と今回の結果と比較し、差異が出た場合は前回の値をM2Xへ書き込みます。これにより変更直前(1分前)のデータがプロットされるため、0WからxxxWへの変化でも上昇度合いが正確にプロットされる様になりました。また値が正の場合は無条件で書き込むため、同じ値が続いた場合もプロットされます。
3.設置
灯油ボイラーはコンセントを短い延長ケーブルに接続しそこをクランプ。これはch1へ。
Raspberry Piは脱衣所上についてるブレーカーボックスのそばに設置しました。そこから赤いラベルの「単相200V」ブレーカーに向かってCTL-10を伸ばします。これをch0へ。
他の100Vと違い、この200Vブレーカーだけ線間電圧が200V。本来は白-黒間(L1-L2間)それぞれを測って合算するのがベターですが、センサーが足りないので片側に出た電圧を単純に2倍して200Vの消費電力としています。力率もわからないのであくまで簡易という事で。200VはIHクッキングヒーターとエアコンのみが利用しています。
というわけで同時に4つのデータをプロットしつづけるロガーが完成しました。
ch0のデータについてはもうちょっとうまい方法を考えてみようと思います。→文中に追記しました