こんちは、ナナです。
マイコン入門編も終わりに差し掛かってきました。最後の仕上げとなるシステムを統括するMAINモジュールの構築が記事の内容です。
本記事では次の疑問点を解消する内容となっています。
では、ライントレースカーを完成させましょう。
ライントレースカーシステムにおけるMAINモジュールの役割
本章までで必要となるデバイスドライバのモジュール達が完成しました。
ここまでMAINモジュールはデバイスドライバモジュールの動作を検査するために利用してきましたが、これは本来の役割ではありません。
MAINモジュールの本来の役割は本システム全体の指揮を執るアプリケーションとして動作することです。目的のシステムを動かすために部下となるデバイスドライバに指示を出しながらミッションを遂行するのです。
では今回のライントレースカーシステムの動作仕様から見ていきましょう。
ライントレースカーの動作仕様
ライントレースカーに対する動作仕様を決定します。
動作仕様項目
- 電源を入れるとオレンジとグリーンLEDを点灯状態とする。
- 電源投入直後はモーター動作は停止とする。
- スイッチをユーザーが押すことでスピーカーから1秒間隔で「ド・レ・ミ」の3音を順番に出力する。
- 「ド・レ・ミ」の出力が終わり次第、P制御による走行を開始する。
- 走行中は1秒間隔で両LEDを点灯/消灯を繰り返す。
- 走行中の光センサ値はシリアル通信で常にパソコンに送信し続ける。出力書式は「SEN:%d\n」とする。
- 電源を切るまでは走り続ける。
課題:ライントレースカーシステムを管理するMAINモジュールを作ろう
課題1
課題内容
MAINモジュールから各デバイスドライバモジュールを呼び出し、目的のライントレースカーシステムを構築せよ。
main.c
//------------------------------------------------
// 概 要:エントリーポイント
//------------------------------------------------
void main(void)
{
// システム初期化処理
main_init();
while(1)
{
}
}
課題が完成したらビルドを行いビュートローバー上で動作させ、期待動作通りに動くことを確認せよ。
期待動作
動作仕様項目の従い動作することを確認する。
起動時の実施すべき処理をシーケンス図で表現すると次のとおりである。この図を参考に起動時処理を行うとよい。
起動処理シーケンス
走行処理シーケンス
main.c
//------------------------------------------------
// 概 要:エントリーポイント
//------------------------------------------------
void main(void)
{
int ledFlg = 0; // 0:消灯 1:点灯
unsigned long time; // LED点滅用の時刻管理
// システム初期化処理
main_init();
// 起動時LED点灯処理
Led_setLight(D_LED_KIND_ORANGE, D_LED_LIGHT_ON);
Led_setLight(D_LED_KIND_GREEN, D_LED_LIGHT_ON);
// 走行前準備処理
while (1)
{
if (Sw_getPressed() == D_SW_PRESSED_ON)
{
int scale;
// ド・レ・ミの3音を1秒毎に出力
for (scale = E_SPK_SCALE_DO ; scale <= E_SPK_SCALE_MI ; scale++)
{
Spk_start(scale);
Timer_waitTime(1000);
}
Spk_stop();
break;
}
}
// 時刻初期化
time = Timer_getTime();
// 走行処理
while (1)
{
unsigned short sen1;
unsigned short sen2;
// P制御走行開始
Lsen_getSensor(&sen1, &sen2);
Motor_runPcon(sen1);
// シリアルへセンサ値送信
sprintf(gMainSciString, "SEN:%d\n", sen1);
Sci_putString(gMainSciString);
// 1秒毎のLED点滅制御
if (time + 1000 < Timer_getTime())
{
if (ledFlg == 0)
{
Led_setLight(D_LED_KIND_ORANGE, D_LED_LIGHT_ON);
Led_setLight(D_LED_KIND_GREEN, D_LED_LIGHT_ON);
ledFlg = 1;
}
else
{
Led_setLight(D_LED_KIND_ORANGE, D_LED_LIGHT_OFF);
Led_setLight(D_LED_KIND_GREEN, D_LED_LIGHT_OFF);
ledFlg = 0;
}
// 時刻更新
time = Timer_getTime();
}
}
}
全体で70行程のプログラムであるが、各デバイスドライバのインターフェースを適宜呼び出すことで割と簡単に作ることができる。
Q&A:アプリケーション作成においてよくある質問
はい。ソフトウェア開発を仕事にする方は特に学んだ方がよいでしょう。
UMLにはシーケンス図以外にもたくさんの図が規定されています。一度にすべてを覚えて使いこなすのは難しため、まずはよく使う図から覚えていくとよいです。シーケンス図はモジュール分割を行うシステムでは非常によく使われます。
上から下に時間が流れ、左から右へインターフェースの呼び出しが流れるように書きます。