電力量計の計量パルスをArduinoで読む(割込み版)
電力量計の話の続きです。一つ前の記事でArduinoから電力の測定結果を読むプログラムを作りましたが、このプログラムで残念な点は、デ-ターはアラゴの円板の穴を検出したタイミングで出力されるということです。つまり電力の大きさによってデーターが出力される間隔が変化します。
これでも、人間が値を読む場合はあまり問題は無いと思います。でもデーターをファイルに落としてPCでグラフ化して分析したい、などという場合は、一定の時間間隔のデーターでないと使い難いです。
この対策として、タイマー割り込み(MsTimer2)を使って測定間隔を一定にするようにしました。あと、せっかくなので、円板の穴の検出も割り込みで行うようにしました。こうしておけば、後で別の機能を追加するのが楽になるはずです。
▼回路図

円板の回転検出の表示用のLED(D1)をハードで点灯させるようにしました。同じことを割込みで動くプログラムでやろうとすると、ちょっとやっかいです。
それと、C2はノイズ対策用に入れています。パルスの検出を割り込みでやっているので、ノイズが入ると誤動作するので注意が必要です。あと、回路図にはうまく表現出来ませんが、アナログ回路部分のノイズ対策はしっかりやる必要があります。
▼プログラム
これ、二種類の割り込みを使っているので Arduino のプログラムとしてはちょっと高級な部類に入ると思います。でも、10行くらいの小さな関数の組み合わせで出来ているので、判り易いのではないかと思います。
▼出力例-1 (開始時)

開始直後の出力です。穴の数(HoleCnt)が2にならないと電力が計算できないので、最初はゼロになっています。
▼出力例-2 (測定中)

電力測定中のリストです。左から開始からの秒数、穴のカウント数、電力(W)、電力量(Wh)が表示されています。なお、電力の値は、円板から次のパルスが来るまで同じ値が連続して出力されます。
◆まとめ
これで電力量計の測定結果が使い易いデーターとして取得出来るようになりました。
この話はこれで終わりにしようかと思ったのですが、測定結果をSDカードに保存すると使い勝手がもっと良くなりそうです。以前気圧ロガーを作った時にSDカードを使いましたが、それ以来ずっとSDカードを使うプログラムを作っていません。
そんなことで、久しぶりにSDカードへのデーターの記録をやってみたいと思います。ヤフオクで1500円で落とした電力量計ですが、これをネタにずいぶん楽しんでいるのですが、まだまだ遊べそうです。
これでも、人間が値を読む場合はあまり問題は無いと思います。でもデーターをファイルに落としてPCでグラフ化して分析したい、などという場合は、一定の時間間隔のデーターでないと使い難いです。
この対策として、タイマー割り込み(MsTimer2)を使って測定間隔を一定にするようにしました。あと、せっかくなので、円板の穴の検出も割り込みで行うようにしました。こうしておけば、後で別の機能を追加するのが楽になるはずです。
▼回路図

円板の回転検出の表示用のLED(D1)をハードで点灯させるようにしました。同じことを割込みで動くプログラムでやろうとすると、ちょっとやっかいです。
それと、C2はノイズ対策用に入れています。パルスの検出を割り込みでやっているので、ノイズが入ると誤動作するので注意が必要です。あと、回路図にはうまく表現出来ませんが、アナログ回路部分のノイズ対策はしっかりやる必要があります。
▼プログラム
// 電力ロガー32~34行目が割り込み条件の設定です。55行目のsensInterval() がタイマー割り込み発生時の処理ルーチン。60行目のholeDetect() がアラゴの円盤の穴を検出した場合の処理ルーチンです。
// 誘導型電力量計の円盤の回転を検出して電力表示
// (回転検出と測定間隔決定に割り込みを使用)
// 2018/8/26 ラジオペンチ http://radiopench.blog96.fc2.com/
#include <MsTimer2.h>
#define holeSigPin 2
volatile unsigned long tLast; // 前回のパルス時刻(ms)
volatile unsigned long tDiff; // パルス間隔
volatile unsigned long tNow; // 現在時刻
volatile unsigned long holeCount = 0; // 穴数カウンタ
volatile unsigned long NN = 0; // 累積時間カウンタ
volatile int timeUpFlag = 0; // タイムアップフラグ
float Watt = 0.0; // 電力
float Wh = 0.0; // 積算電力量
const float SFw = 1500.0; // (ScalFactor) 電力換算係数 SFw / パルス間隔(s) = W
// 600rev/kWhで穴2個×2相合成で2400パルス/kWh → 1W = 1000*3600/2400=1500
const float SFe = 2.4; // 電力量換算係数 パルス数 * SFe = Wh
void setup() {
Serial.begin(9600);
pinMode(holeSigPin, INPUT_PULLUP); // クリーピング防止穴割り込み入力ピン
Serial.println();Serial.println("AC power logger start"); // 開始メッセージ
Serial.println("time(s), HoleCnt, Power(W), Enargy(Wh)");
// 割込み処理の設定
MsTimer2::set(1000, sensInterval); // 1000msごとにMsTimer2割込み
MsTimer2::start();
attachInterrupt(0, holeDetect, FALLING); // pin2(int0)のネガエッジで割込み
}
void loop() {
while (timeUpFlag == 0) { // タイマー割込みが入るのを待つ
}
timeUpFlag = 0;
if (holeCount >= 2) { // 2つ目以降の穴だったら電力計算
Watt = SFw / (tDiff / 1000.0); // 電力計算
Wh = (holeCount - 1) / SFe; // 累積電力量計算
}
logPrint(); // 測定結果をシリアル出力
Serial.flush(); // シリアル出力完了待ち
}
void logPrint() { // 測定結果室力
Serial.print(NN); Serial.print(", ");
Serial.print(holeCount); Serial.print(", ");
Serial.print(Watt); Serial.print(", "); Serial.println(Wh);
}
void sensInterval() { // Mstimet2の割り込み処理(タイマー割り込み)
timeUpFlag = 1; // タイムアップグフラグを立てる
NN++; // 累積時間インクリメント
}
void holeDetect() { // クリーピング防止ホール割り込み処理(ピン割り込み)
tNow = millis(); // 現在のシステム時刻取得
if ((tNow - tLast) > 30) { // 前回パルスから30ms以上経過している場合だけ計算(気休め)
tDiff = tNow - tLast; // 時間差計算 (50日でオーバーフローするので注意)
tLast = tNow; // 前回値として記録
holeCount++; // 穴数カウントアップ
}
}
これ、二種類の割り込みを使っているので Arduino のプログラムとしてはちょっと高級な部類に入ると思います。でも、10行くらいの小さな関数の組み合わせで出来ているので、判り易いのではないかと思います。
▼出力例-1 (開始時)

開始直後の出力です。穴の数(HoleCnt)が2にならないと電力が計算できないので、最初はゼロになっています。
▼出力例-2 (測定中)

電力測定中のリストです。左から開始からの秒数、穴のカウント数、電力(W)、電力量(Wh)が表示されています。なお、電力の値は、円板から次のパルスが来るまで同じ値が連続して出力されます。
◆まとめ
これで電力量計の測定結果が使い易いデーターとして取得出来るようになりました。
この話はこれで終わりにしようかと思ったのですが、測定結果をSDカードに保存すると使い勝手がもっと良くなりそうです。以前気圧ロガーを作った時にSDカードを使いましたが、それ以来ずっとSDカードを使うプログラムを作っていません。
そんなことで、久しぶりにSDカードへのデーターの記録をやってみたいと思います。ヤフオクで1500円で落とした電力量計ですが、これをネタにずいぶん楽しんでいるのですが、まだまだ遊べそうです。