しかも、色々な周期で色々やりたいときなどは、Delayなどを使って時間を調整するのは結構大変だ。
タイマ割り込みは標準だと使えない。
ということで、4種類の周期で任意の処理をするためのスケッチを描いてみた。
オシロスコープなどで確かめていない為、本当に一定の周期で実行されているかは保証できないが、LEDを光らせてみた感じではなんとなく良さそうだ。
また、micros();で時刻を取得する際に、Arduino内部のカウンタがオーバーフローした時などはおかしなタイミング生成がされる場合がある。
そのうち対策する予定です。
あと、ひとつの周期の処理は16msec以内に終わらせないと、次の周期の処理がずれていきます。
以下、スケッチ。
/*
* 一定の周期(64msec, 128msec, 512msec, 1024msec, 4096ms)で特定の処理を
* 行うためのフレームワーク?
*
* 以下の各関数が各周期毎に実行される。
* execute64msTask() -> 64msec毎に実行
* execute128msTask() -> 128msec毎に実行
* execute512msTask() -> 512msec毎に実行
* execute1024msTask() -> 1024msec毎に実行
* execute4096msTask() -> 4096msec毎に実行
*
* 各々の関数内に任意の処理を記述するだけで良い。
* 但し、各周期の処理は16msec以内に終わるものとする。
* 今後のバージョンアップにより、32msecに伸びる可能性有り。
*/
/* タスクID定義 */
const byte TASK_ID_64MS = 1;
const byte TASK_ID_128MS = 2;
const byte TASK_ID_512MS = 3;
const byte TASK_ID_1024MS = 4;
const byte TASK_ID_4096MS = 5;
/* 現在のタスクインデックス 0-255を繰り返す.*/
byte taskIndex = 0;
/*
* タスクIDのテーブル. taskIndexから次に実行すべきタスクを決定する.
* 読みやすさの為、値をベタ書き.
*/
const byte taskIdTbl[] =
{
/*1 4 8 12 16 */
1, 2, 3, 4, 1, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0,
1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0,
1, 2, 3, 5, 1, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0,
1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0,
1, 2, 3, 4, 1, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0,
1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0,
1, 2, 3, 0, 1, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0,
1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0,
1, 2, 3, 4, 1, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0,
1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0,
1, 2, 3, 0, 1, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0,
1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0,
1, 2, 3, 4, 1, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0,
1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0,
1, 2, 3, 0, 1, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0,
1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0,};
unsigned long taskStartTime = 0; /* タスク開始時刻 */
unsigned long taskEndTime = 0; /* タスク終了時刻 */
int taskDelay = 0; /* 次の周期までの待ち時間 */
unsigned long BASE_DELAY = 16000; /* 基本となるタスク実行周期 16ms */
unsigned int ledStat = 0; /* LEDの状態. サンプル用. */
void setup(){
/* LED サンプル用 */
pinMode(13, OUTPUT);
}
void loop(){
/* タスク実行時間計測の為、時刻をキャプチャ */
taskStartTime = micros();
/* 該当する周期のタスクを実行. */
switch( taskIdTbl[taskIndex] ){
case TASK_ID_64MS:
execute64msTask();
break;
case TASK_ID_128MS:
execute128msTask();
break;
case TASK_ID_512MS:
execute512msTask();
break;
case TASK_ID_1024MS:
execute1024msTask();
break;
case TASK_ID_4096MS:
execute4096msTask();
break;
default:
break;
}
/* タスクインデックスをインクリメント */
taskIndex = taskIndex + 1;
/* タスク完了時刻をキャプチャ */
taskEndTime = micros();
taskDelay = BASE_DELAY - (taskEndTime - taskStartTime);
if( taskDelay >= 0 ){
/*
* delayMicrosecondsは16383マイクロ秒以内の値を
* を指定したとき、正確に動作する.
*/
delayMicroseconds(taskDelay);
}
}
/* 64msec毎に起動する関数 */
void execute64msTask(){
}
/* 128msec毎に起動する関数 */
void execute128msTask(){
}
/* 512msec毎に起動する関数 */
void execute512msTask(){
}
/* 1024msec毎に起動する関数 */
void execute1024msTask(){
if( getLedStat() ){
digitalWrite(13,HIGH);
}
else{
digitalWrite(13,LOW);
}
}
/* 4096msec毎に起動する関数 */
void execute4096msTask(){
}
/* LED状態切替 サンプル用*/
boolean getLedStat(){
boolean ret = false;
if( ( ledStat % 2 ) == 0 ){
ret = true;
}
ledStat = ledStat + 1;
return ret;
}
0 件のコメント:
コメントを投稿