記念すべき(?)400回目の原稿を、〆切を2日過ぎた土曜の朝に書いている体たらくでまことに情けない限りです。ま、担当者は朝までカラオケして遊んでたみたいだし、いいか。今後もよろしくお願いいたします。

一応データをArduinoで取れるようになったので、ではこれをどう処理するかと言う話。Tweet-a-wattの場合、クライアントの側(つまりKILL A WATTの側)は、XBeeを使って1ms毎に電圧と電流の値を取得、これをそのままサーバー(つまりZigBeeを受信できる機能を持ったPC)側に転送する。サーバー側はこれを17サンプルごとにまとめて、ここから電圧と電流値を計算するという方法になっている。なんで17サンプルか? というと、オリジナルはアメリカの120V 60Hzの電源を想定したものだからで、60HzのACの場合16.6msで1周期が完了する。このあたりの話はこちらに詳しいのだが、英語でもあるのでちょっとかいつまんで説明する。

たとえば日本の電源電圧の場合、電圧は100Vで、東日本は50Hz、西日本は60Hzということになっている。実際には電圧の供給状態とか屋内配線の状態、負荷のかかり方などで変動するのだが、理想的な電圧状況にあるとすれば、電圧はグラフ1(東日本)もしくはグラフ2(西日本)の様に変動する。電圧がピークで100Vを超えているのだが、これが正常である。ACの場合は正弦波で送られてくるので、ピークは平均電圧の√2倍(≒1.414倍)グラフ1を平均化すると丁度100Vになる筈だ。

で、グラフ1・2は試しに0.25ms毎にプロットしたものだが、これを1ms毎にするとどうなるか? というのがグラフ3・4である。表1は、実際に取得した値を表形式にしたものだが、50Hzならば20個、60Hzなら17個の値をそれぞれ抜き出し、絶対値を取った上で平均すると、50Hzの場合で89.3V、60Hzで88.3Vといった値が算出できる。

■表1
Time(ms) Voltage(50Hz) Voltage(60Hz)
0 0.0 0.0
1 43.7 52.1
2 83.1 96.8
3 114.4 128.0
4 134.5 141.1
5 141.4 134.5
6 134.5 109.0
7 114.4 68.1
8 83.1 17.7
9 43.7 -35.2
10 0.0 -83.1
11 -43.7 -119.4
12 -83.1 -138.9
13 -114.4 -138.9
14 -134.5 -119.4
15 -141.4 -83.1
16 -134.5 -35.2
17 -114.4 17.7
18 -83.1 68.1
19 -43.7 109.0
20 0.0 134.5
21 43.7 141.1
22 83.1 128.0
23 114.4 96.8
24 134.5 52.1
25 141.4 0.0

「100Vにならないじゃないか」というご指摘はごもっともであるが、これはサンプリング間隔が長いほど誤差が出る事は避けられない。ためしに0.25ms毎のサンプリングにすると、50Hzの場合で90.0V、60Hzの場合で89.6Vまで値が上がる。もっとも、ここからの上がり方は非常にゆるやかで、たとえば0.1ms毎にサンプリングするとどうなるかをシミュレーションしてみたら、50Hzの場合は90.0Vのまま(正確に言えば0.25msで89.98V→0.1msで90.03V)、60Hzの場合は89.9Vになったが、せいぜいがその程度。逆に2msとかにすると著しく落ちるので、1msというTweet-a-wattの設定は案外良いバランスなのではないか、と思う。

ちなみに今は電圧の話をしたが、電流も同じように正弦波の形で変動するので、やはり同じように定期的にサンプリングをし、絶対値を取った上で平均値を算出するといった形で電流の値を計算することになる。

理屈で言えば、これをArduinoなりPCなりで実行することで電流と電圧の値が算出できることになるのだが、実はこの前にもうひとつやるべきことがある。ちょっと下のようなSketchを実行してみた。前回のList 1と似ているが、今度はあらかじめ用意した100個のバッファにまとめてデータを格納する様にしており、100個分のデータを1ms間隔でまとめて取得、それを後でガバっと表示する様に作り変えた。これを走らせてSerial Consoleを開き、取得したデータをグラフにまとめたのがグラフ5である。今はまだワットチェッカー自体をACに繋いだだけで、ワットチェッカーには何も繋いでいないので、電圧は出ている(ワットチェッカーには101.3Vと表示された)が、電流値は0である。この状態で測定を行うと、Voltの方は確かに正弦波で振動しており、一方Ampのほうは一定値になっていることが分かるが、ただし値そのものは0ではなく、ある程度オフセットを付けた値になっている。Tweet-a-wattのほうではこのオフセットを"DC Bias"と呼び、ソースを見ると固定値として取得した値から抜くような処理になっている。このオフセット値だが計算は簡単で、最大値と最小値をそれぞれ求め、この中間値に最小値を足したものとなる。Volの場合はMax:523、Min:131でDC Biasは327、Ampの場合はMax:492、Min:489でDC Biasは491(正確には490.5だが四捨五入した)となる。DC Biasを抜いた後のデータはグラフ6の様になる。

(続く)

List 1:

#define  VOLTPIN 0
#define  AMPPIN  1

int  volt[100], amp[100];

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  int lpCnt;
  for(lpCnt=0;lpCnt<100;lpCnt++)
  {
    volt[lpCnt] = analogRead(VOLTPIN);
    amp[lpCnt] = analogRead(AMPPIN);
    delay(1);
  }

  for(lpCnt=0;lpCnt<100;lpCnt++)
  {
    Serial.print(lpCnt);
    Serial.print(":");
    Serial.print(volt[lpCnt]);
    Serial.print(":");
    Serial.println(amp[lpCnt]);
  }
  delay(1000);
}