printfデバッグで原因が判って問題は解決しましたが、制御ループが正確なタイミングで実行されていないと制御が不安定になる原因になりますので、タイマ割り込みと制御ループの実行間隔を調べて見ました。
(4)のtimeに表示されている数値は1ms毎の割り込み関数でインクリメントされているので正確に増えていますが実際には消去関数は130mS程度割り込みを禁止しているのでその間は実際の周期は狂っているはずです。
そこで今度はタイマーRFを使って割り込み関数の起動タイミングを調べてみます。
init()の最後に次の処理を追加してタイマRFを20MHz/32のクロックでインクリメントします。
本当ならばもっときりの良いクロックを使いたかったのですが空いているタイマーの制約上このようなクロックを使うことになりました。
/* タイマ 時間 計測 */ trfcr0 = 0x05; /* f32 フリーランカウント開始 */
タイマRFが0-0xFFFFまでカウントアップする時間は 約(1/9.5)秒、およそ0.1秒です。
次のようにタイマ関数の先頭にprintf文を入れてタイマRFの値を表示してみます。
/************************************************************************/ /* タイマRB 割り込み処理 */ /************************************************************************/ #pragma interrupt /B intTRB(vect=24) void intTRB( void ) { static int line_no; /* 行番号 */ unsigned int i; asm(" fset I "); /* タイマRB以上の割り込み許可 */ #ifdef DEBUG printf("%04X\n",trf); // TRF 表示 20/32 MHzクロック #endif uTimer1ms++; // 時間計測用タイマ cnt0++; cnt1++; cnt2++; cnt_lcd++; check_sen_cnt++; check_enc_cnt++; ...
実行結果は次のようになります
これをグラフ表示で見ると次のように周期的に間隔が乱れているのが判ります。
間隔の乱れているところを拡大してみると次のようになっています。
縦軸がタイマの値で横軸はデータの数です、タイマの値は16bitで65535を超えると0に戻るためノコギリ波のような形になります、真ん中の大きい段がDataFlashの消去で割り込みが止まっている時でおよそ(57+105×n)mS止まっています。
ここで57mSはグラフから読み取れる値で、105mSはTRFがタイムアウトする時間です。
DataFlash消去中はデータも出力されないためその間に何度TRFがタイムアウトしているかはわかりません。
止まっている時間を正確に知りたければ例えば10KHzクロックでカウントアップするタイマがあれば6.5秒までは測れることになります。
手がかりとしてdata_flash_lib.cのソースに次のような記述があります。
/************************************************************************/ /* モジュール名 blockEraseDataFlash */ /* 処理概要 ブロックイレーズ */ /* 引数 unsinged int アドレス */ /* 戻り値 1:エラーなし 0:エラーあり */ /* メモ 実測で135ms程度 */ /************************************************************************/ int blockEraseDataFlash( unsigned int address ) { volatile int ret = 1; volatile int block; block = checkBlockAddress( address ); if( block == -1 ) return 0; asm( "FCLR I" ); /* 全体の割り込み禁止 */ ...
これを考慮すれば n=1で 162mSの間割り込みが止まっていると考えるのが妥当でしょう。
両側の小さい段は書き込みの時で書き込みの時も割り込み禁止期間があり数ミリ秒は割り込みが止まるようです。
マイコンカーラリーではロボットが高速走行します。
例えば2m/秒の速度で走っているとすれば2mm / 1msの間隔で制御をしていますが、162mS制御不能になればその間に 2mm × 162 = 324mm 進んでしまうことになります。
カーブ等で324mmの間制御が止まればコースアウトは確実です。
次にメインループの先頭にtrfを表示するprintfを入れてメインループの実行間隔も確認してみます。
while( 1 ) { // デバッグ表示 #ifdef DEBUG printf("%04X\n",trf); // TRF 表示 20/32 MHzクロック #endif // LCD表示、パラメータ設定処理 lcdProcess(); ...
結果のグラフ表示は次のようになりました
当然ですがこちらも同じように制御周期が乱れています。
拡大してみます。
メインループの周期はノコギリ波の周期とその間のデータ数から求められます。
ノコギリ波の1周期は105msでその間におよそ120のデータが出力されていますから、105/120=約0.9msとほぼ割り込みと同じ周期でメインループが繰り返されていることがわかります。。