ワットメーターシールドV2の作り方

ワットメーターシールドV2の作り方

クランプ式電流センサーを使用したarduino電力計シールドです

AC100Vを使用するので感電に注意して下さい
よほど運が悪くない限り人間は死んだりしませんがAC100V回路をarduinoにショートさせるとUSB経由でパソコンが死にます

・arduinoシールドなのでarduinoも必要です
・センサーは別売です
  100V機器の電力を計測する場合はセンサーが1個必要
  分電盤に取り付けて家全体で使っている電力を計測する場合はセンサーが2個必要
・計測可能な電力はセンサー1個あたり2500Wまでです。それ以上の電力を計測したい場合は抵抗を1本交換する必要があります
・AC100Vに繋いで使いますがこのシールドは電圧を計測していません
 電圧は実効値100Vのサインカーブであると仮定し(実際には実効値も波形も微妙に異なります)、その位相のみを検知することで消費電力を求めています
・プログラムはサンプルです。使う環境に合わせて修正が必要です。
 標準状態ではLCD上段にセンサーCT1の電力計測結果を下段にセンサーCT2の計測結果を表示します


2013-03-29

部品は以下の物に変更しました

R0026745.jpg

白文字液晶はバックライトが点灯していないと文字が読めないので通常の黒文字タイプに変更しました。これに伴い取付ネジやソケットも変更されています

R0024008.jpg

10μFの積層セラミックコンデンサは青い物から黄色い物に変更しました

R0026778.jpg

R20が追加されました。これを取り付けると液晶のバックライトが点灯します。バックライトが不要な場合は取り付けません

この写真と部品表を頼りに組み立てて下さい。裏側に配置されている部品はありません。部品面のベタパターンは5Vです。裏面のベタパターンはGNDです。点線より右側はAC100V回路です。感電に注意して下さい

R0017046.jpg

部品表

buhinhyo1.png

半固定抵抗は液晶のコントラスト調整用です。回さないと液晶に何も表示されないことがあります

R0017052.jpg

100V機器の電力を測定するときはこのような延長コードを作ってコードの片方をクランプで銜えます。
ゼロクロス検出回路は電流が少ししか流れないので細い電線が使えます。但し細いコードは被服が薄く電線が露出しやすいことに注意して下さい。
太い電線は丈夫ですがarduinoが太い電線に振り回される事に注意して下さい。太い電線を使うときは確実に絶縁をしてください。

R0017055.jpg

分電盤に取り付けるときは赤線と黒線をセンサーでクランプします。2つのセンサーで計測した電力を合算した物が全消費電力になります。クランプする電線を間違えても非接触なので壊れることはありませんが正しい値を表示できません。

R0016891.jpg

回路図。解説付きの回路図はワットメーターシールドV1の作り方を見て下さい。ゼロクロス検出回路(位相検出回路)以外は全く同じです。ゼロクロス検出回路の解説はありません。動作を確認したい場合は下にLTspiceの回路図を添付してあるので各部の電圧などを見て下さい。

schv2_rev1.PNG

------------------------------
 ポート番号解説
------------------------------

センサーCT1用
 Digital 3,2
   レンジ切り替え 電流計測にR1を使うとき D2=HIGH D3=LOW R3を使うとき D2=LOW D3=HIGH にする
   R1,R3の抵抗値を変更すると計測可能な電流値を変更出来る
   抵抗値を小さくするとより大きな電流を計測出来るようになるが精度が落ちる。抵抗を大きくするとその逆になる
 Analog 4
   電流電圧変換回路の出力。
   測定対象物に電流が流れていない時は約2.5Vになる。この電圧を軸に出力が振れる。
   AC100V機器であれば約2.5Vを軸とした交流信号になる
   サンプルプログラムでは1サイクルの平均値から約2.5Vの軸電圧を求めているがセンサーに電流が流れていない時の計測値をEEPROMに記憶する方が望ましい
   2つの回路は全く同じ物であるが部品のばらつきなどにより軸電圧は僅かに異なる

センサーCT2用
 Analog 0,1
   レンジ切り替え 電流計測にR2を使うとき A0=HIGH A1=LOW R4を使うとき A0=LOW A1=HIGH にする
 Analog 2
   電流電圧変換回路の出力

共通
 Analog 5
   ブザー用 ON/OFFを繰り返さないと鳴りません HIGHにしたままにしないで下さい
 Analog 3
   基準電圧 ここは2.495Vになる(若干誤差有り。テスターで実測すると良い)
 Digital 4
   ゼロクロス検出回路の出力。AC100Vの電圧がゼロになる瞬間だけHIGHになる

ソースの解説
0001  //----------------------------------------------------------------- 2013-03-29 ------------
0002 // 電力計 サンプルスケッチ
0003 //-------------------------------------------------------- written by iizuka --------------
0004 #include <LiquidCrystal.h>
0005
0006 //---------------- 環境により変更する項目 -------------------------------------------
0007 #define FREQ 50 // 50Hz
0008 // #define FREQ 60 // 60Hz
0009 #define CT_TURN 3000 // CTセンサーのコイル巻き数 CTL-10-CLS は 3000巻き
0010 #define CH1_R_LOW_RESOLUTION 200 // 回路図のR1=200Ω 抵抗は出力が振り切れない範囲で大きい方が計測精度が良い
0011 #define CH1_R_HIGH_RESOLUTION 3000 // 回路図のR3=3kΩ 実際の抵抗は誤差があるのでテスターで実測して
0012 #define CH2_R_LOW_RESOLUTION 200 // 回路図のR2=200Ω この値を変更すると精度が向上する
0013 #define CH2_R_HIGH_RESOLUTION 3000 // 回路図のR4=3kΩ
0014 #define SAMPLES 120 // 1サイクル(1/50秒)に何回サンプリングするか
0015 // 大きいほど精度が高く計測できるが大きすぎるとA/D変換の速度が間に合わない 150あたりが限界
0016
0017 //---------------- 配線を変更したら変更する項目 -------------------------------------------
0018 #define PORT_CH1_RANGE_SELECT_HIGH_RESOLUTION 3 // Port Digital 3
0019 #define PORT_CH1_RANGE_SELECT_LOW_RESOLUTION 2 // Port Digital 2
0020 #define PORT_CH2_RANGE_SELECT_HIGH_RESOLUTION 15 // Port Analog 1
0021 #define PORT_CH2_RANGE_SELECT_LOW_RESOLUTION 14 // Port Analog 0
0022
0023 #define PORT_ZERO_CROSS 4 // Port Digital 4
0024 #define PORT_CH1 18 // Port Analog 4
0025 #define PORT_CH2 16 // Port Analog 2
0026 #define PORT_REF 17 // Port Analog 3
0027 #define PORT_BUZZER 19 // Port Analog 5
0028 #define PORT_LED 13 // Port Digital 13
0029
0030 LiquidCrystal lcd(5,6,7,8,9,10);
0031
0032 //---------------- 回路定数など -----------------------------------------------------------
0033 #define SELECT HIGH
0034 #define NOT_SELECT LOW
0035
0036 #define HIGH_RESOLUTION 0
0037 #define LOW_RESOLUTION 1
0038
0039 #define REF_VOLTS 2.495 // TL431 Typ 2.495V
0040 #define PERIOD (1000000/FREQ/SAMPLES) // microsec
0041 const float pi = 3.141592;
0042
0043 int out_volts[SAMPLES]; // 電流->電圧変換回路の出力の計測値
0044 int ac100_sin_volts[SAMPLES]; // AC100V サインカーブ
0045 int ref_volts_10bit; // TL431リファレンス電圧のA/D RAW値
0046
0047 //------------------------------------------------------------------------------------------
0048 // AC100Vサイン波形の生成
0049 // 1/4サイクルでもよいがメモリー不足ではないので1サイクル分生成している
0050 //------------------------------------------------------------------------------------------
0051 void generate_ac100v_sine_curve()
0052 {
0053 for( int time_index = 0 ; time_index < SAMPLES ; time_index++ ) {
0054 ac100_sin_volts[time_index] = abs(sin( ( 2 * pi ) / SAMPLES * time_index )) * sqrt(2) * 100;
0055 }
0056 }
0057
0058 //------------------------------------------------------------------------------------------
0059 // 10ビットの計測値を電流値[mA]に換算する
0060 //
0061 // INPUUT:
0062 // volt -> 計測対象機器の10ビット計測値
0063 // ref_volt -> TL431のA/D計測値
0064 // R_range -> 計測レンジ
0065 //------------------------------------------------------------------------------------------
0066 float convert_10bit_to_milli_amp( int volt, int ref_volt, int R_range )
0067 {
0068 return ((float)volt * REF_VOLTS * CT_TURN) / ((float)ref_volt * (float)R_range);
0069 }
0070
0071 //------------------------------------------------------------------------------------------
0072 // 1サイクルぶんをサンプリングする
0073 //
0074 // INPUT:
0075 // port -> arduinoアナログポート番号
0076 // range -> HIGH_RESOLUSION / LOW_RESOLUTION
0077 //------------------------------------------------------------------------------------------
0078 void ad_get( int port, int range )
0079 {
0080 long time_next_period;
0081 long period = PERIOD;
0082
0083 if( range == HIGH_RESOLUTION ) {
0084 if( port == PORT_CH1 ) {
0085 digitalWrite( PORT_CH1_RANGE_SELECT_HIGH_RESOLUTION, SELECT );
0086 digitalWrite( PORT_CH1_RANGE_SELECT_LOW_RESOLUTION, NOT_SELECT );
0087 } else { // PORT_CH2
0088 digitalWrite( PORT_CH2_RANGE_SELECT_HIGH_RESOLUTION, SELECT );
0089 digitalWrite( PORT_CH2_RANGE_SELECT_LOW_RESOLUTION, NOT_SELECT );
0090 }
0091 } else { // LOW_RESOLUTION
0092 if( port == PORT_CH1 ) {
0093 digitalWrite( PORT_CH1_RANGE_SELECT_HIGH_RESOLUTION, NOT_SELECT );
0094 digitalWrite( PORT_CH1_RANGE_SELECT_LOW_RESOLUTION, SELECT );
0095 } else { // PORT_CH2
0096 digitalWrite( PORT_CH2_RANGE_SELECT_HIGH_RESOLUTION, NOT_SELECT );
0097 digitalWrite( PORT_CH2_RANGE_SELECT_LOW_RESOLUTION, SELECT );
0098 }
0099 }
0100 delay(1); // デジタル回路が動くと電圧が変動したりするので1ms程度待っている。たぶん効果はほとんど無い。気分の問題。
0101
0102 while(digitalRead(PORT_ZERO_CROSS) == LOW ) {} // AC100Vの電圧がゼロになるまで待つ
0103 time_next_period = micros();
0104 for( int time_index = 0 ; time_index < SAMPLES ; time_index++ ) {
0105 out_volts[time_index] = analogRead( port );
0106 time_next_period += period;
0107 while( micros() < time_next_period ) {
0108 // digitalWrite( PORT_LED, HIGH ); // LEDが点灯しないならA/D変換速度が間に合っていないのでサンプル数を小さくすること
0109 }
0110 }
0111 }
0112
0113 //------------------------------------------------------------------------------------------
0114 // リファレンス電圧のA/D変換10ビット値を得る
0115 // 1回A/D変換すれば済むが、A/Dの揺らぎを考慮し10回取得して平均値を求めている
0116 // INPUT:
0117 // port -> arduinoアナログポート番号 = TL431出力
0118 //------------------------------------------------------------------------------------------
0119 float get_ref_volt( int port )
0120 {
0121 int total = 0;
0122
0123 for( int t = 0 ; t < 10 ; t++ ) {
0124 delay(1);
0125 total += analogRead( port );
0126 }
0127
0128 return (float)total / 10;
0129 }
0130
0131 //------------------------------------------------------------------------------------------
0132 // 計測値のオフセット値を求める
0133 // 機器の電流波形は正負均等に触れると見なし、平均値をオフセットとする 値は 大体 512 になる
0134 //------------------------------------------------------------------------------------------
0135 float calc_offset()
0136 {
0137 long total = 0;
0138
0139 for(int time_index = 0 ; time_index < SAMPLES ; time_index++ ) {
0140 total += (long)out_volts[time_index];
0141 }
0142
0143 return (float)total / SAMPLES;
0144 }
0145
0146 //------------------------------------------------------------------------------------------
0147 // 1ビットあたりの電流値[mA]を求める
0148 //
0149 // INPUT:
0150 // range -> HIGH_RESOLUSION / LOW_RESOLUTION
0151 //------------------------------------------------------------------------------------------
0152 float get_amp_div( int port, int range )
0153 {
0154 if( range == HIGH_RESOLUTION ) {
0155 if( port = PORT_CH1 ) {
0156 return (REF_VOLTS * CT_TURN) / ((float)ref_volts_10bit * CH1_R_HIGH_RESOLUTION) * 1000;
0157 } else { // CH2
0158 return (REF_VOLTS * CT_TURN) / ((float)ref_volts_10bit * CH2_R_HIGH_RESOLUTION) * 1000;
0159 }
0160 } else { // LOW_RESOLUTION
0161 if( port = PORT_CH1 ) {
0162 return (REF_VOLTS * CT_TURN) / ((float)ref_volts_10bit * CH1_R_LOW_RESOLUTION) * 1000;
0163 } else { // CH2
0164 return (REF_VOLTS * CT_TURN) / ((float)ref_volts_10bit * CH2_R_LOW_RESOLUTION) * 1000;
0165 }
0166 }
0167 }
0168
0169 //------------------------------------------------------------------------------------------
0170 // ブザーを0.2秒鳴らす
0171 //------------------------------------------------------------------------------------------
0172 void beep()
0173 {
0174 for( int i = 0 ; i < 100 ; i++ ) {
0175 digitalWrite( PORT_BUZZER, HIGH );
0176 delay(1);
0177 digitalWrite( PORT_BUZZER, LOW );
0178 delay(1);
0179 }
0180 }
0181
0182 //------------------------------------------------------------------------------------------
0183 // 消費電力の計算 ゼロクロス点からサンプリングされた波形であることを前提として電力を計算する
0184 //------------------------------------------------------------------------------------------
0185 float calc_watt_zc( int port, int range )
0186 {
0187 float offset;
0188 float total;
0189 float temp_volt;
0190 float amp_div;
0191
0192 offset = calc_offset();
0193
0194 amp_div = get_amp_div( port, range );
0195 total = 0.0;
0196 for( int time_index ; time_index < SAMPLES ; time_index++ ) { // 1サイクルぶん電力を積算
0197 temp_volt = abs((float)out_volts[time_index] - offset);
0198 total += (temp_volt * amp_div * (float)ac100_sin_volts[ time_index ] / 1000);
0199 }
0200
0201 return total / SAMPLES;
0202 }
0203
0204 //------------------------------------------------------------------------------------------
0205 // arduino setup
0206 //------------------------------------------------------------------------------------------
0207 void setup()
0208 {
0209 pinMode(PORT_CH1_RANGE_SELECT_HIGH_RESOLUTION, OUTPUT);
0210 pinMode(PORT_CH1_RANGE_SELECT_LOW_RESOLUTION, OUTPUT);
0211 pinMode(PORT_CH2_RANGE_SELECT_HIGH_RESOLUTION, OUTPUT);
0212 pinMode(PORT_CH2_RANGE_SELECT_LOW_RESOLUTION, OUTPUT);
0213
0214 pinMode(PORT_LED, OUTPUT);
0215 pinMode(PORT_BUZZER, OUTPUT);
0216
0217 digitalWrite( PORT_CH1_RANGE_SELECT_HIGH_RESOLUTION, NOT_SELECT );
0218 digitalWrite( PORT_CH1_RANGE_SELECT_LOW_RESOLUTION, SELECT );
0219 digitalWrite( PORT_CH2_RANGE_SELECT_HIGH_RESOLUTION, NOT_SELECT );
0220 digitalWrite( PORT_CH2_RANGE_SELECT_LOW_RESOLUTION, SELECT );
0221
0222 lcd.begin(8, 2);
0223 lcd.println("WatMeter");
0224 lcd.setCursor(0,1);
0225 lcd.println("Sample 2");
0226
0227 generate_ac100v_sine_curve();
0228 ref_volts_10bit = get_ref_volt( PORT_REF );
0229
0230 beep();
0231 delay(500);
0232 }
0233
0234
0235 //------------------------------------------------------------------------------------------
0236 // arduino loop
0237 //------------------------------------------------------------------------------------------
0238 void loop()
0239 {
0240 float watt_ch1;
0241 float watt_ch2;
0242
0243 ad_get( PORT_CH1, LOW_RESOLUTION );
0244 watt_ch1 = calc_watt_zc( PORT_CH1, LOW_RESOLUTION );
0245 ad_get( PORT_CH2, LOW_RESOLUTION );
0246 watt_ch2 = calc_watt_zc( PORT_CH2, LOW_RESOLUTION );
0247
0248 lcd.clear();
0249 lcd.print( "C1 " );
0250 lcd.print( (int)watt_ch1 );
0251 lcd.print( "W" );
0252 lcd.setCursor(0,1);
0253 lcd.print( "C2 " );
0254 lcd.print( (int)watt_ch2 );
0255 lcd.print( "W" );
0256 delay(300);
0257 }
0258
0259 //------------------------------------------------------------------ E N D ------------------
0260
行番号
解説
全体
自動レンジ切り替え機能はありません 正負均等に電流が流れないと正しい値を表示できないので電源が半波整流回路になっている機器の消費電力は計測出来ません(市販の電機製品には殆ど無いはずです) AC100Vに繋がないと動きません。このサンプルはゼロクロス信号が来るのを永久に待ってしまいます。
7-8行目
60Hzの地域は変更が必要
9行目
センサーを変更したらここを修正。センサーに依存しているのは巻き数だけしか無い
10-13行目
抵抗には誤差があるので抵抗値を実測した値を入れると計測精度が向上する
サンプルスケッチなど
ファイル ファイルタイプ 添付ファイルの解説
wattkitV2_ino.zip arduino サンプルスケッチ。 2013-11-08 バグがあったので修正しました。 上のリストはad_get関数にバグ有ります
ctrange.zip EXCEL 電流計測レンジを変更したときはこれを参考にR1,R2,R3,R4の値を変更する
センサーにも計測限界があるのでセンサーのデータシートも参照すること
CTL-10-CLSなら10mA~80Aが計測可能範囲
OpenOffice.calc でも開けます
zerocross6_LTC.zip LTspice ゼロクロス検出回路 LTspiceIV用
ご参考
ファイル ファイルタイプ 添付ファイルの解説
watt2FPCB_V2_EAGLE.zip EAGLE EAGLE V4.16回路図&基板レイアウト (これは旧販売ロットの物です日本国内で16ピンの液晶が入手しにくいのでそのままにしてあります)

-------------------------------------------
グラフ表示プログラム
-------------------------------------------

-----------------
 Watt Loggerの仕様
-----------------
・ハードウェアは現時点の全てのワットメーターシールドV1,2,3に対応
・センサーは1つでも2つでも使用可能
・V1はハードウェアの仕様から皮相電力(ボルトアンペア)のみ計測可能
・V2,V3は有効電力(普通のワット)、皮相電力(ボルトアンペア)、力率が計測可能
 AC100Vに接続しないと皮相電力のみ計測される。AC100Vに接続しているときはブザーが3回鳴る
・V1,V2の液晶には計測値が表示されるのでパソコンに繋がなくても使用可能
 但しレンジが高精度モードになっているので200W程度が計測限界
・V2の液晶に表示される値はAC100に繋いでいると有効電力、繋がないと皮相電力を表示する
・電流検出抵抗を交換すればレンジを変更出来る
 但しソフトの仕様上計測可能な最大電流は65A(厳密には65536mAつまり16ビット)
・V3はメモリーを内蔵しているのでWindowsを休止モードにしても記録は続けられる
 最大65536秒間(18時間)休止モードに出来る。
 プログラムを終了すれば記録は終了するので記録中にWindowsをシャットダウンすると記録はそこで終了してしまう

-----------------
 ソフトの使い方概要
-----------------
・プログラムのインストールはダウンロード解凍して wattmeterM.exe を適当なフォルダーに置くだけ
 arduinoスケッチはV1,V2,V3共通になっているので修正が必要。以下の2カ所
  1.ハードウェアのバージョン
  2.50Hz,60Hzの設定
 V3の受信機用スケッチはそのまま無修正で使用する
・●RECボタンで計測値が記録開始される。ボタンの色が赤くなるのでそれとわかる。
 再度押すと記録終了。記録中で無くても計測されたデータで常にグラフは更新される
・ファイルはプログラムのあるフォルダーの\dataディレクトリーに作成される
 ファイル名は日時から自動生成される
・保存したファイルは「ファイル」メニューから開くことが出来る
 ファイル形式はCSVなのでEXCEL等でグラフ化することも可能
 Arduinoが繋がっていなくてもファイルの参照だけは出来る
・計測器は自動的にソフトが見つけてくれる
 見つからなかったときはソフトを再度起動してみる
 それでも見つからないときは接続を再確認
・グラフの範囲をドラッグするとその部分が拡大される
 縮小はグラフのスクロールバーの左にあるボタンを押す
・PAUSEにチェックを付けると表示が止まる
 プログラム上は「表示を止める」のでは無く「受信した計測データを捨てる」という処理になっている
・グラフをクリックするとその時点の計測値が表示される
 このときPAUSEにチェックが付いていないと送られてきたデータで上書きされてしまうので値の確認が出来ない
・最大電流はそのレンジで計測可能な最大電流値。これを超えた場合計測値は正しくない。
・グラフの右下に表示される文字はarduinoのシリアルポートから送られてくるデータをそのままの状態で表示した物

wattloggersc.png
回路図など
ファイル ファイルタイプ 添付ファイルの解説
wattmeterMexe.zip OTHER Windowsプログラムです。解凍するとEXEになります
wattkitRadioCM.zip arduino グラフ表示プログラム用のarduinoスケッチ 2013-11-08 バグがあったので修正しました
wattmeterMwinsorc.zip OTHER ソースファイル一式 Microsoft Visual Basic 2010 Express用
旧販売ロットの回路図など
ファイル ファイルタイプ 添付ファイルの解説
buhinhyo.png PNG 旧販売ロット部品表
schv2.PNG PNG 旧販売ロット回路図 新版では液晶ディスプレイが変更されている

===================================
これは旧販売ロットの説明です。現行品はメーカーで加工済みになっています
===================================
液晶ディスプレイの裏側には100Ωの抵抗を取り付けます。R9は抵抗のリード線を切った物でショートさせます

R0016841.jpg