MTM07で出展したArduino Megaの話も今回で最後である。さて、前回のList 2のSketchをロードした後で、Windows側のプログラムを立ち上げる(コードが未完成なので、今回はWindows側のソースは無しである)。で、実際に実行してみると、うまくデータが取れる場合(Photo01)と取れない場合(Photo02)が出てきた。頻度で言えば、表示のインターバルを2秒程度にすると、概ね5割程度の確率でデータが取れるが、1秒以下の頻度にするとかなりの確率でデータが取れない。
で、ためしにArduino IDEのSerial Monitorを使うとこんな結果になる(Photo03)。一応毎回数字はちゃんと流れてくるのだが、まず9桁目のサンプル数が30を超えている事になる。これは明らかにおかしい。というのは、前回のグラフ5からも判るとおり、ノーウェイトでひたすらサンプリングだけを行っても、一周期あたりのサンプリングは30回が限界である。ましてや前回のList 2から判るとおり、実際にSketchの内容は、
(1) 8ポート(4台のワットメーター×(電圧と電流))にanalogRead()
(2) 1台目の電圧と電流がどちらも0か判断
(3) 波形のどの位置のデータをサンプリングしているかを判断
(4) 8つのデータについて加算
を行っているから、サンプリング間隔はもっと少なくないとおかしい。ためしに前回のList 1に、上の4つの処理を擬似的に追加したSketch(List 1)を実施してみたところ、グラフ1の様な結果が得られた。ノーウェイトでも1周期あたり22サンプルが限界で、とても34サンプルなどには行き着かない。
このあと幾つかテストコードを書いて振る舞いを調べたのだが、「これだ」という確たる証拠はつかめなかった。ただ、振る舞いに関する大雑把な仮説は見つかった。要するに前回のList 2のSketchを実際にぶん回すと、Arduino MEGAの処理が間に合わずにどこかで飽和するようだ。これはどういうことかというと、今回のList 1の場合は50サンプル×8chで合計400回のサンプリングをした後でシリアルに結果を送って1秒ウェイトするので、結果的に400回のサンプリング毎にちょっと時間を置くことになり、結果フルスピードでぶん回しても余裕でこなせるのだが、前回のSketchだと切れ目無くサンプリングを行っていることになる(1周期分のサンプリングの後で結果をまとめるが、その後も電圧の正負の反転を確認するために定期的にサンプリングが続く)ため、長時間連続稼働だとどこかで飽和する事になる。この飽和をしている間はサンプリングを含めた動作がどっかで止まってしまい、結果的に2周期分以上の波形をサンプリングする事になるため、トータルとしてのサンプル数が34とか異様に多くなるものと考えられる。しかも、この飽和中は通信もとまるので、CPU側にはデータ無しと認識され、電圧/電流が0とレポートされる事になる。
で、これはArduino全般というよりも、Arduino MEGAに負荷の高い処理をやらせたのがどうもまずかった気がする。というのは、ためしに測定するワットメーターを1台に減らすように前回のList 2を書き換えて走らせても、やはりサンプル数が多すぎるとレポートされる(本来なら60サンプル/周期程度が上限なのに、結果は100サンプル位取れたとされる)上、通信途絶の状況も変わらなかったからだ。こうした事柄はArduino UNOでは発生しておらず、Arduino MEGAを酷使したのが悪かったのではないかと判断される。
ということであれば、やはりArduino MEGAを使って複数のワットメーターをまとめてサンプリングというのが無茶、という話でやはりArduino UNOを使って1台のワットメーターの値をサンプリングする程度で収めておくほうが無難、という判断ができる。そんなわけで次回からは改めてArduino Unoに戻し、ちゃんとデータのサンプリングができるシステムを完成させることにしたい。
List 1:
#define VOL1PIN 0
#define AMP1PIN 1
#define VOL2PIN 2
#define AMP2PIN 3
#define VOL3PIN 4
#define AMP3PIN 5
#define VOL4PIN 6
#define AMP4PIN 7
#define BUFSIZE 50
#define VOL1BIAS 483
#define AMP1BIAS 495
#define VOL2BIAS 484
#define AMP2BIAS 497
#define VOL3BIAS 480
#define AMP3BIAS 487
#define VOL4BIAS 483
#define AMP4BIAS 476
long vol0[BUFSIZE], amp0[BUFSIZE];
long vol1[BUFSIZE], amp1[BUFSIZE];
long vol2[BUFSIZE], amp2[BUFSIZE];
long vol3[BUFSIZE], amp3[BUFSIZE];
void setup()
{
Serial.begin(9600);
}
void loop()
{
int lpCnt;
long vol1Sum, vol2Sum, vol3Sum, vol4Sum;
long amp1Sum, amp2Sum, amp3Sum, amp4Sum;
long vol1Act;
int flag;
flag = 0;
vol1Sum = vol2Sum = vol3Sum = vol4Sum = 0;
amp1Sum = amp2Sum = amp3Sum = amp4Sum = 0;
for(lpCnt=0;lpCnt < BUFSIZE;lpCnt++)
{
vol0[lpCnt] = analogRead(VOL1PIN);
amp0[lpCnt] = analogRead(AMP1PIN);
vol1[lpCnt] = analogRead(VOL2PIN);
amp1[lpCnt] = analogRead(AMP2PIN);
vol2[lpCnt] = analogRead(VOL3PIN);
amp2[lpCnt] = analogRead(AMP3PIN);
vol3[lpCnt] = analogRead(VOL4PIN);
amp3[lpCnt] = analogRead(AMP4PIN);
// delayMicroseconds(1);
/* 両方0なら0としてBreak; */
if (!(vol1[lpCnt]||amp1[lpCnt]))
{
vol1Sum = vol2Sum = vol3Sum = vol4Sum = 0;
amp1Sum = amp2Sum = amp3Sum = amp4Sum = 0;
}
/* flagの値を判断 */
vol1Act = vol0[lpCnt]-VOL1BIAS;
if ((flag==2)&&(vol1Act>0))
flag=0; /* データサンプリング開始 */
else if ((flag==0)&&(vol1Act<0))
flag++; /* 一度目の値の符号反転 */
else if((flag==1)&&(vol1Act>0))
flag++; /* 二度目の値の符号反転 */
/* 取得した値を加算 */
if(flag!=2)
{
vol1Sum += abs(vol1Act);
amp1Sum += abs(amp0[lpCnt]-AMP1BIAS);
vol2Sum += abs(vol1[lpCnt]-VOL2BIAS);
amp2Sum += abs(amp1[lpCnt]-AMP2BIAS);
vol3Sum += abs(vol2[lpCnt]-VOL3BIAS);
amp3Sum += abs(amp2[lpCnt]-AMP3BIAS);
vol4Sum += abs(vol3[lpCnt]-VOL4BIAS);
amp4Sum += abs(amp3[lpCnt]-AMP4BIAS);
}
}
for(lpCnt=0;lpCnt < BUFSIZE;lpCnt++)
{
Serial.print(lpCnt);
Serial.print(":");
Serial.print(vol0[lpCnt]);
Serial.print(":");
Serial.print(amp0[lpCnt]);
Serial.print(":");
Serial.print(vol1[lpCnt]);
Serial.print(":");
Serial.print(amp1[lpCnt]);
Serial.print(":");
Serial.print(vol2[lpCnt]);
Serial.print(":");
Serial.print(amp2[lpCnt]);
Serial.print(":");
Serial.print(vol3[lpCnt]);
Serial.print(":");
Serial.println(amp3[lpCnt]);
}
Serial.print(vol1Sum);
Serial.print(":");
Serial.print(amp1Sum);
Serial.print(":");
Serial.print(vol2Sum);
Serial.print(":");
Serial.print(amp2Sum);
Serial.print(":");
Serial.print(vol3Sum);
Serial.print(":");
Serial.print(amp3Sum);
Serial.print(":");
Serial.print(vol4Sum);
Serial.print(":");
Serial.println(amp4Sum);
delay(1000);
}