今まで作っていた NXT のプログラムはすべて main タスクだけで
した。関数をいくつか作りましたが、それらもタスクとしてはすべ
て main タスクの配下にあります。
今回は、main タスクとは別のタスクを作ってみましょう。
NXC では、タスクは最大で 255 個まで作れます。
■ 動きながら音を鳴らす
これは、「動く」タスクと、「音を鳴らす」タスクの 2 つを作り、
これらのタスクを main タスクから起動します。
これらの動きを、main タスクだけのシングルタスクで実現するの
は無理があります。
まあ、モーター自体はタスクがスリープしている間は動き続けるの
でいいとして、トーンを鳴らすスリープとタイミングを計るのは無
理があります。
これらは、別タスクとして動かすことで、スムーズに無理なく 2
つの動作を実現できるのです。
今回は、それぞれのタスクを無限ループするようにしているので、
止めるときは NTX の停止ボタンで止めます。
□ #include "Music01.nxc" // 音楽関係のマクロ // (1)
前回の周波数等はマクロの定数としてヘッダーファイルに入れてお
きます。
□ task playing() // (2)
タスク playing の定義です。task キーワードを使います。関数と
同じように、使う前に定義しておく必要があります。
□ task moving() // (3)
タスク moving の定義です。
□ Precedes(playing, moving); // (4)
playing, moving タスクを起動します。
□ Precedes 関数
---
Precedes(task1, task2, ..., taskN) Function
指定されたタスクの実行をスケジュールします。
例:
Precedes(moving, drawing, playing);
---
■ タッチセンサーで、演奏したり止めたりする
つぎに、タッチセンサーをスイッチ代わりにして、タッチするたび
に演奏したり止めたりするようにしてみましょう。
ただし、これだと、NBC の stopthread 文でエラーになる。なぜ?
★
---
# Error: Invalid opcode: stopthread
File "C:_docsLegoBricx_NXCMovingAndPlaying02.nxc" ; line
2482
# stopthread playing
---
□ bool isPlay; // 演奏中かどうか // (1)
演奏中かどうかを表すフラグをグローバル変数として定義する。
□ task touching() // (2)
タッチセンサーのタスク。
演奏中のときにタッチされれば演奏を止め、演奏していないときに
タッチされると演奏を開始する。
□ if (isPlay) { //(3)
演奏中かどうかを判断。
□ StopTask(playing); // (4)
□ StartTask(playing); // (5)
playing タスクの終了、開始。
□ StartTask 関数
---
StartTask(task) Function
指定されたタスクを開始する。
例:
StartTask(sound); // start the sound task
---
□ StopTask 関数
---
StopTask(task) Function
指定されたタスクを停止する。
例:
StopTask(sound); // stop the sound task
---
■ しょうがないので、少し仕様を変えて、タッチセンサーが押さ
れたら、演奏を開始するようにした。
以上
した。関数をいくつか作りましたが、それらもタスクとしてはすべ
て main タスクの配下にあります。
今回は、main タスクとは別のタスクを作ってみましょう。
NXC では、タスクは最大で 255 個まで作れます。
■ 動きながら音を鳴らす
これは、「動く」タスクと、「音を鳴らす」タスクの 2 つを作り、
これらのタスクを main タスクから起動します。
これらの動きを、main タスクだけのシングルタスクで実現するの
は無理があります。
まあ、モーター自体はタスクがスリープしている間は動き続けるの
でいいとして、トーンを鳴らすスリープとタイミングを計るのは無
理があります。
これらは、別タスクとして動かすことで、スムーズに無理なく 2
つの動作を実現できるのです。
今回は、それぞれのタスクを無限ループするようにしているので、
止めるときは NTX の停止ボタンで止めます。
--- /** * MovingAndPlaying01.nxc * 「トライボット」使用 * 1秒間前進し、その後1秒間停止、1秒間後退する。 * その間に音を鳴らす。 * @author maruno * @version 1.0, 2008-01-12 * @since 1.0 */ #include "NXCDefs.h" #include "Music01.nxc" // 音楽関係のマクロ // (1) /** * 音楽再生タスク */ task playing() // (2) { while (true) { PLAY_TONE(FR_C6, NOTE_MINIM, 2, false, INTERVAL); PLAY_TONE(FR_C5, NOTE_QUAVER, 2, false, INTERVAL); PLAY_TONE(FR_C4, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_C5, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_AS6, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_AS6, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_AS6, NOTE_CROTCHET, 2, false, INTERVAL + NOTE_CROTCHET); PLAY_TONE(FR_DS5, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_DS5, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_DS5, NOTE_CROTCHET, 2, false, INTERVAL + NOTE_CROTCHET); } } /** * 移動タスク */ task moving() // (3) { while (true) { OnFwd(OUT_BC, 75); Wait(500); Off(OUT_BC); Wait(500); OnRev(OUT_BC, 75); Wait(500); Off(OUT_BC); } } /** * メインタスク */ task main() { Precedes(playing, moving); // (4) } ---
□ #include "Music01.nxc" // 音楽関係のマクロ // (1)
前回の周波数等はマクロの定数としてヘッダーファイルに入れてお
きます。
□ task playing() // (2)
タスク playing の定義です。task キーワードを使います。関数と
同じように、使う前に定義しておく必要があります。
□ task moving() // (3)
タスク moving の定義です。
□ Precedes(playing, moving); // (4)
playing, moving タスクを起動します。
□ Precedes 関数
---
Precedes(task1, task2, ..., taskN) Function
指定されたタスクの実行をスケジュールします。
例:
Precedes(moving, drawing, playing);
---
--- #ifndef MUSIC01_H_ #define MUSIC01_H_ /** * Music01.ncx * 音楽関係のマクロ定義 * @author maruno * @version 1.0, 2008-01-12 * @since 1.0 */ /* * 音符を演奏する時間(ミリ秒) */ #define NOTE_SEMIBREVE 1200 // 全音符 #define NOTE_MINIM (NOTE_SEMIBREVE / 2) // 二分音符 #define NOTE_CROTCHET (NOTE_MINIM / 2) // 四分音符 #define NOTE_QUAVER (NOTE_CROTCHET / 2) // 八分音符 /* * 周波数 */ #define FR_B3 247 #define FR_B4 494 #define FR_B5 988 #define FR_B6 1976 #define FR_B7 3951 #define FR_B8 7902 #define FR_AS3 233 #define FR_AS4 466 #define FR_AS5 932 #define FR_AS6 1865 #define FR_AS7 3729 #define FR_AS8 7458 #define FR_A3 220 #define FR_A4 440 #define FR_A5 880 #define FR_A6 1760 #define FR_A7 3520 #define FR_A8 7040 #define FR_A9 14080 #define FR_GS4 415 #define FR_GS5 831 #define FR_GS6 1661 #define FR_GS7 3322 #define FR_GS8 6644 #define FR_GS9 13288 #define FR_G4 392 #define FR_G5 784 #define FR_G6 1568 #define FR_G7 3136 #define FR_G8 6272 #define FR_G9 12544 #define FR_FS4 370 #define FR_FS5 740 #define FR_FS6 1480 #define FR_FS7 2960 #define FR_FS8 5920 #define FR_FS9 11840 #define FR_F4 349 #define FR_F5 698 #define FR_F6 1397 #define FR_F7 2794 #define FR_F8 5588 #define FR_F9 11176 #define FR_E4 330 #define FR_E5 659 #define FR_E6 1319 #define FR_E7 2637 #define FR_E8 5274 #define FR_E9 10548 #define FR_DS4 311 #define FR_DS5 622 #define FR_DS6 1245 #define FR_DS7 2489 #define FR_DS8 4978 #define FR_DS9 9956 #define FR_D4 294 #define FR_D5 587 #define FR_D6 1175 #define FR_D7 2349 #define FR_D8 4699 #define FR_D9 9398 #define FR_CS4 277 #define FR_CS5 554 #define FR_CS6 1109 #define FR_CS7 2217 #define FR_CS8 4435 #define FR_CS9 8870 #define FR_C4 262 #define FR_C5 523 #define FR_C6 1047 #define FR_C7 2093 #define FR_C8 4186 #define FR_C9 8372 /* * 音符間の間隔(ミリ秒) */ #define INTERVAL 100 /** * トーンを鳴らすマクロ * @param frequency 周波数 * @param duration 持続時間(ミリ秒) * @param volume 音量 * @param bLoop 繰り返すか * @param interval 間隔時間(ミリ秒) */ #define PLAY_TONE(frequency, duration, volume, bLoop, interval) do { PlayToneEx((frequency), (duration), (volume), (bLoop)); Wait((duration)+(interval)); } while(false) #endif ---
■ タッチセンサーで、演奏したり止めたりする
つぎに、タッチセンサーをスイッチ代わりにして、タッチするたび
に演奏したり止めたりするようにしてみましょう。
ただし、これだと、NBC の stopthread 文でエラーになる。なぜ?
★
---
# Error: Invalid opcode: stopthread
File "C:_docsLegoBricx_NXCMovingAndPlaying02.nxc" ; line
2482
# stopthread playing
---
--- /** * MovingAndPlaying02.nxc * 「トライボット」使用 * 1秒間前進し、その後1秒間停止、1秒間後退する。 * その間に演奏する。このとき、タッチセンサーが押されたら、演奏したり、止めたりする。 * @author maruno * @version 1.0, 2008-01-12 * @since 1.0 */ #include "NXCDefs.h" #include "Music01.nxc" // 音楽関係のマクロ #include "SensorFuncs02.nxc" // センサー関係 bool isPlay; // 演奏中かどうか // (1) /** * 音楽再生タスク */ task playing() { while (true) { PLAY_TONE(FR_C6, NOTE_MINIM, 2, false, INTERVAL); PLAY_TONE(FR_C5, NOTE_QUAVER, 2, false, INTERVAL); PLAY_TONE(FR_C4, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_C5, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_AS6, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_AS6, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_AS6, NOTE_CROTCHET, 2, false, INTERVAL + NOTE_CROTCHET); PLAY_TONE(FR_DS5, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_DS5, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_DS5, NOTE_CROTCHET, 2, false, INTERVAL + NOTE_CROTCHET); } } /** * 移動タスク */ task moving() { while (true) { OnFwd(OUT_BC, 75); Wait(500); Off(OUT_BC); Wait(500); OnRev(OUT_BC, 75); Wait(500); Off(OUT_BC); } } /** * タッチセンサータスク */ task touching() // (2) { while (true) { if (SENSOR_1 == 1) { if (isPlay) { //(3) StopTask(playing); // (4) isPlay = false; } else { StartTask(playing); // (5) isPlay = true; } } } } /** * メインタスク */ task main() { // センサーの設定 SetSensors(MASK_S1); // タスクの開始 Precedes(moving, touching); } ---
□ bool isPlay; // 演奏中かどうか // (1)
演奏中かどうかを表すフラグをグローバル変数として定義する。
□ task touching() // (2)
タッチセンサーのタスク。
演奏中のときにタッチされれば演奏を止め、演奏していないときに
タッチされると演奏を開始する。
□ if (isPlay) { //(3)
演奏中かどうかを判断。
□ StopTask(playing); // (4)
□ StartTask(playing); // (5)
playing タスクの終了、開始。
□ StartTask 関数
---
StartTask(task) Function
指定されたタスクを開始する。
例:
StartTask(sound); // start the sound task
---
□ StopTask 関数
---
StopTask(task) Function
指定されたタスクを停止する。
例:
StopTask(sound); // stop the sound task
---
■ しょうがないので、少し仕様を変えて、タッチセンサーが押さ
れたら、演奏を開始するようにした。
--- /** * MovingAndPlaying03.nxc * 「トライボット」使用 * 1秒間前進し、その後1秒間停止、1秒間後退する。 * その間に演奏する。このとき、タッチセンサーが押されたら、演奏を開始する。 * @author maruno * @version 1.0, 2008-01-14 * @since 1.0 */ #include "NXCDefs.h" #include "Music01.nxc" // 音楽関係のマクロ #include "SensorFuncs02.nxc" // センサー関係 /** * 音楽再生タスク */ task playing() { PLAY_TONE(FR_C6, NOTE_MINIM, 2, false, INTERVAL); PLAY_TONE(FR_C5, NOTE_QUAVER, 2, false, INTERVAL); PLAY_TONE(FR_C4, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_C5, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_AS6, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_AS6, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_AS6, NOTE_CROTCHET, 2, false, INTERVAL + NOTE_CROTCHET); PLAY_TONE(FR_DS5, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_DS5, NOTE_CROTCHET, 2, false, INTERVAL); PLAY_TONE(FR_DS5, NOTE_CROTCHET, 2, false, INTERVAL + NOTE_CROTCHET); } /** * 移動タスク */ task moving() { while (true) { OnFwd(OUT_BC, 75); Wait(500); Off(OUT_BC); Wait(500); OnRev(OUT_BC, 75); Wait(500); Off(OUT_BC); } } /** * タッチセンサータスク * タッチされたら、演奏タスクを開始 */ task touching() { while (true) { if (SENSOR_1 == 1) { StartTask(playing); } } } /** * メインタスク */ task main() { // センサーの設定 SetSensors(MASK_S1); // タスクの開始 Precedes(moving, touching); } ---
以上
※コメント投稿者のブログIDはブログ作成者のみに通知されます