#nomenubar
#navi(NQC入門)

プログラムを作成・転送してロボットを動かせるようになったら、もう少しだけ複雑なプログラムを作成してみましょう。

目次
#contents

* 3.1 少しだけ複雑に [#p2002f5f]

最初の簡単なプログラムをロボットに実行させることができたら、 次の例のような、もう少しだけ複雑なプログラムを作ってみましょう。 
以下では、前節で説明した OnFwd, Wait, Off の他にモータを逆回転をさせる OnRev, トルク(回転させる力)をかけないようにする Float を使用しています。

 task main()
 {
     OnFwd(OUT_A+OUT_C); // A と C 出力のモータを正回転
     Wait(300);
     OnRev(OUT_C);       // C 出力のモータを逆回転
                         // これで方向変換を開始する
     Wait(200);          // この時間で方向変換の角度が決まる
     OnFwd(OUT_C);       // C 出力のモータを正回転
     Wait(300);          // 再び前進
     OnRev(OUT_A+OUT_C); // 後進
     Wait(300);
     Float(OUT_A+OUT_C); // Off より滑らかに止まる
 }

モータを制御するときによく使う命令:

 On(OUT_A+OUT_C);    // A出力とC出力のモータを回転させる
 Off(OUT_A);         // A出力のモータを止める

 Off(OUT_A);         // A出力のモータを止める (止まった状態にする)

 Float(OUT_A);       // A出力のモータにトルクをかけない

 Fwd(OUT_A);         // A出力のモータの回転を正にセットする

 Rev(OUT_A);         // A出力のモータの回転の負にセットする

 Toggle(OUT_A);      // A出力のモータを反転させる

 OnFwd(OUT_A);       // A出力モータを正回転させる

 OnRev(OUT_A);       // A出力モータを負回転させる

 OnFor(OUT_A,300);   // A出力のモータを3秒間回転させる

 SetPower(OUT_A,3);  // A出力のモータの出力を3にする (0〜7まで指定できる)

最後の SetPower は、モータの出力を設定するための命令であってスピードを設定するための命令ではありません。もちろん出力が変われば多少スピードも変わりますが、基本的にはギア比を調整することでスピードの調整を行ってください。

★ 練習問題~
一辺が約50cmの正方形に沿ってロボットを動かすためのプログラムを作成しなさい。 


* 3.2 同じ動作の繰り返し [#zc495a8e]

同じ動作の繰り返しは、後で説明するように、for や while
などのループを使っても実現できますが、ここでは repeat という簡単な機能を使う方法を紹介します。

 task main()
 {
     repeat(5){
     repeat(5){                          // {}内の命令を5回繰り返す
         OnFwd(OUT_A+OUT_C); Wait(200);  // 2秒間前進
         OnRev(OUT_A+OUT_C); Wait(200);  // 2秒間後進
     }
 
     Float(OUT_A+OUT_C);                 // Off より滑らかに止まる
 }

repeat の引数(括弧の中)には繰り返す回数を指定します。
repeat の引数(括弧の中の数)には繰り返す回数を指定します。
ただしこの引数に許されるのは定数のみで、以下で登場する変数は使用できません。
この例の場合、2秒間前進して2秒間後進するという動作を5回繰り返した後
止まります。 

★ 練習問題~
前の練習問題で作成したプログラムを repeat を用いて書き直しなさい。 

* 3.3 定義された値を使う [#ibe51a97]

例えば Wait の時間を指定する時など、Waitの括弧の中に直接数字をいれずに、あらかじめ定義した「定数」を使用することで、プログラムを改良したり変更すること作業が容易になり、間違いも発見しやすくなります。
上の例では Wait の時間を指定する時など値を直接Waitの引数(Waitに渡す値)として指定しましたが、この値を頻繁に調整したい時や同じ値を何度も使いたいときには、括弧の中の値を毎回変更するのは面倒です。
このような場合、Waitの括弧の中に直接数字をいれずに、あらかじめ定義した「定数」を使用することで、プログラムを改良したり変更することが作業が容易になり、間違いも発見しやすくなります。

定数の使用例:

 #define MOVE_TIME 200
 #define MOVE_TIME 200                     // MOVE_TIMEという定数を定義(値は200)
 
 task main()
 {
     OnFwd(OUT_A+OUT_C); Wait(MOVE_TIME);  // 2秒間前進
     OnRev(OUT_A+OUT_C); Wait(MOVE_TIME);  // 2秒間後進
     Off(OUT_A+OUT_C);
 }

この例では、#define を使ってあらかじめ 200 に定義された定数 MOVE_TIME を Wait の引数に使っています。
実際には、#define で定義した定数は、コンパイル時にもとの値に置き換えられます。
このように定義した定数を使えば、動作時間などの値を変更する時でも
最初の定義だけを変更するだけで途中のプログラムは変更せずに済みます。 

ところで定数名はアルファベットと数字(ただし最初の文字には数字は使えない)とアンダースコア(_)で構成し、
少々長くなってもなるべくその定数の意味がわかるような名前を付けましょう
(文法上には x,y のような簡単なものでも構いません)。
(文法上では X,Y のような簡単なものでもかまいません)。
また、定数名は慣習的に大文字にすることが多いです
(これも文法上は小文字でも構いません)。 

ただし、以下の名前は、「予約語」として登録されていますので定数名として使ってはいけません。

|__event_src|__nolist|__res|__sensor|__taskid|__type|
|abs|acquire|asm|break|case|catch|
|const|continue|default|do|else|false|
|for|goto|if|inline|int|monitor|
|repeat|return|sign|start|stop|sub|
|switch|task|true|void|while||

★ 練習問題~
☆型に沿って動くロボットを作成しなさい。

★ 練習問題~
半径30cmの円に沿って動くロボットを作成しなさい。

★ 練習問題~
A3用紙の上にハートマークを描くロボットを作成しなさい。
ペンの装着方法にも工夫すること。

* 3.4 変数を使う [#x2096408]

今度はプログラムの実行中に値を変えることのできる「変数」を使用してみましょう。一般にプログラミングでは、変数は値を一時的に格納する箱のようなものだと考えることができます。そして変数名はその箱(変数)につけられた名前だと考えることができます。

変数名も定数名と同様アルファベットと数字(ただし最初の文字には数字は使えない)とアンダースコアで構成し、予約語以外ならどのようなものでもかまいませんが、定数名と違って小文字にするのが一般的です。もちろん変数の場合も、なるべく分かりやすい名前を選びましょう。

変数を使った例:

 int move_time ;          // move_time という整数型の変数を定義  
 int move_time ;          // move_time という整数型(integer)の変数を定義  
 
 task main()
 {
     move_time = 100 ;    // move_time に 100 を代入
     OnFwd(OUT_A+OUT_C); Wait(move_time);  // 1秒間前進 
     Off(OUT_A+OUT_C);
     Wait(move_time*2);   // 2秒間休憩
 
     repeat(10){ 
         OnFwd(OUT_A+OUT_C); Wait(move_time);   // move_time/100 秒だけ前進
         OnRev(OUT_C); Wait(80);   // 右に旋回 
         move_time = move_time + 100 ; // 繰り返すごとに move_time の値を 100 増やす
     }
     // この時点で move_time の値は 1100 になっている。         
 }

変数を定義するには変数の型を表すキーワードの後に変数名を書きます。
この例の場合は、move_time という名前の整数型(int)変数を最初に定義してあります。このように task やサブルーチン(後述)の外で定義された変数は、
グローバル変数と呼ばれ、そのプログラムのどこからでも使用できます
(これに対して個々の task やサブルーチンの中だけで定義された変数はローカル変数と呼ばれ、その task やサブルーチンの中だけで有効です。ローカル変数については、後で説明します)。
ちなみにNQCではファームウェアの制限からグローバル変数は32個まで使用することができます。

ところで、上のプログラムで最も注意して欲しいのは「=」という記号です。
この記号は、右辺の値を左辺の変数に代入するという演算子です。
つまり、 

 move_time = 100;

は、move_time という変数に 100 という値を代入するという意味です。
そして、

 move_time = move_time + 100 ;

は、もとの(右辺の) move_time という変数に 100 加えたものを新たに move_time という変数に代入するという意味です。
このように「=」は等しいという意味ではない、ということに注意してください。 

さらに、この代入の命令は、 
さらに、この代入の命令(move_time という変数の値を100増やす)は、 

 move_time += 100 ;

のように簡単な記法で書くこともできます。 

この例のように、変数を使えばプログラムの実行中に、状況にあわせて
この例のように、変数を使えばプログラムの実行中に状況にあわせて
その値を変更することができます。

足し算の他にも以下のような演算ができます。 

 -  引き算
 *  かけ算
 /  割り算
 %  割り算の余り

また += と同様に、 

 -= 
 *=
 /=

などの演算子も使えます。 

さらに特別な場合として、1 増やしたり、 1 減らしたりする場合には、 

 x++ ;  // x = x + 1 ; と同じ
 x-- ;  // x = x - 1 ; と同じ

という演算子(インクリメンタル演算子・デクリメンタル演算子)を
という演算子(インクリメンタル演算子・デクリメンタル演算子と呼ばれる)を
使うとより短く表記できます。

★ 練習問題~
渦巻状に動くロボットを作成しなさい。

* 3.5 forを使った繰り返し [#g689dc7e]

(作成中…)
同じような動作を繰り返す際に、他のプログラミング言語でもよく用いられる for について紹介しておきましょう。

 task main()
 {
     int i;                   // for ループのための変数
     int i_min=1,i_max=5;
 
     for (i=1; i<=5; i++) {   // i=1 から始めて i<=5 が成り立つ間だけ繰り返す
     for (i=i_min; i<=i_max; i++) {   // i=1 から始めて i<=5 が成り立つ間だけ繰り返す
                              // 毎回繰り返すごとに i を 1 増やす (i++)
         OnFwd(OUT_A+OUT_C); Wait(200);  // 2秒間前進
         OnRev(OUT_A+OUT_C); Wait(200);  // 2秒間後進
         OnFwd(OUT_A+OUT_C); Wait(200); 
         OnRev(OUT_A+OUT_C); Wait(200);
     }
 
     Float(OUT_A+OUT_C);                 // Off より滑らかに止まる
     Float(OUT_A+OUT_C); 
 }

repeat の場合、 繰り返し回数に指定できるのは定数だけですが、for を使ったループでは、この例のように、ループ変数の初期値(i=i_min)や条件(i<=i_max)に変数を使用することができます。
#navi(NQC入門)


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS