まず,モーターで走るロボットを作成します。

RCX本体にモーターを2つ取り付け,それぞれがタイヤを回すようにします。

裏から見るとこのようになります。 このロボットを3秒間前進させ,その後同じ時間だけ後退するプログラムを作ってみます。RCXCCを起動して,File(ファイル)メニューからNewを選び次のように入力しました。(この時点では,IRタワーでパソコンとRCXを繋いでおく必要はありません。)


4-1.プログラムを作成・転送する手順

 コードの内容を説明する前に,プログラムを作成しRCXにダウンロードする手順について説明しておきましょう。新規にプログラムを作成する場合は,FileメニューからNewを選び,プログラムを記述します。既存のプログラム(以前に作成したプログラム)に追加・変更を加える場合は,FileメニューからOpenでプログラムを選択します。

 もちろん,その前にどんなプログラムを作成するか,つまりロボットをどのように動かすかを考えておく必要がありますね。この考える作業のことを設計作業と言います。企業で使うような大きなシステム(プログラムの集まり)ではもちろんのことですが,どんな小さなプログラムでも事前に設計をすることは大切です。結果として,プログラムの作成に費やす時間が短くなります。頭の中で考えるだけでなく,設計書として紙に残しておくほうがいいでしょう(もちろんにパソコンにデータとして残しておくのも良い方法です)。

 プログラムの編集が終わったら,コンパイルを行います。CompileメニューからCompile(コンパイル)を選択しコンパイル(翻訳)を行います。もし,この時点でプログラムにミスがあればコンパイル・エラーが表示されます。

 line 6: Error: prase errorと表示されています。OnRev(OUT_A+OUT_C)の行がセミコロン(;)で終わっていないことが原因で次の行(Line 6) の Wait(300); が正しく判断できない(5行の続きとして判断すると間違いである)ためエラーと表示されています。

 コンパイル・エラーが1つも表示されていない状態になればOK,つまりコンパイル・アップです。Fileメニューからsaveを選び,名前を付けて保存しておきましょう。今回はmotor1と名前をつけました。拡張子はnqcになります。このプログラムのフルネームはmotor1.nqcです。ファイル名には,そのプログラムが何をするプログラムなのか,またはどういう種類のプログラムなのかを表す名前をつけます。拡張子はプログラムの分類に使用されます。nqcという拡張子の付いたファイルはNQCのソース・プログラムであると人間が見て判別できるだけでなく,WindowsOSもNQCのプログラムであると理解できるのです。

 コンパイルエラーがなくなったら,RCXにプログラムをダウンロードできます。まず,IRタワーをパソコンのシリアル・ポート(Com1,Com2,…)に接続します。組み立てたロボットをIRタワーの前に置き,赤外線ポート同士を向かい合わせます。5cm程度の距離に置きましょう。RCXの電源スイッチ(赤いスイッチ)を押したら,RCXCCのtool(ツール)メニューからFind RCXを選択します。

OKをクリックするとRCXをFindして(見つけて)くれます。これで,いよいよプログラムをダウンロードできます。CompileメニューからDownloadを選びます。ダウンロードが完了するとRCXからそれを知らせる音がなります。Runスイッチ(緑のスイッチ)を押してロボットを走らせてみましょう。3秒間前進した後,バックして戻ってきましたね。


4-2.プログラムの解説

 motor1.nqc

 task main()
 {
  OnFwd(OUT_A+OUT_C);
  Wait(300);
  OnRev(OUT_A+OUT_C);
  Wait(300);
  Off(OUT_A+OUT_C);
 }

 task(タスク)は仕事という意味です。nqcでは複数のタスクを定義してRCXに実行させる仕事を記述していきます。今回のプログラムは最初のプログラムですので,タスクは1つだけです。mainという名前のタスクは必ず必要で,処理の実行はmainタスクから始まります。

 {  と } にはさまれた中にステートメントを記述していきます。順に見ていきましょう。
 OnFwdはモーターを前進方向に設定し,オンにします。( ) の中にモーターを繋いだ出力ポート(A,B,C)を指定します。+ で連結して複数のモーターを同時に指定することができます。OnFwdは複合命令です。出力をオンするにOn命令と,前進方向に設定するFwd命令の組み合わせです。

 Fwd(OUT_A+ OUT_C);
 On(OUT_A+ OUT_C);

 と2行で分けて書くのと同じ意味です。

 RCXには出力ポートが3つあります。A,B,Cとラベルが付いている3つの黒い正方形(2ポッチ×2ポッチ)のブロックです。それぞれの出力ポートをOUT_A, OUT_B, OUT_Cと指定します。
 On(OUT_A+ OUT_C);は

 On(OUT_A);
 On(OUT_C);

と書くところを + で複数のポートをまとめて指定しています。

OnRevはOnFwdと同様に,出力をオンにするOn命令と,後退方向に設定するRev命令の組み合わせです。

 Rev(OUT_A+ OUT_C);
 On(OUT_A+ OUT_C);

と同じ意味です。 Off命令は出力をオフにし,モーターを止めます。Offでモーターを止めるとロボットはピタッと止まります。急ブレーキをかけたような感じです。ゆるやかに止めたい場合もあります。そのためにはFloat命令を使います。


 Off(OUT_A+OUT_C); を Float(OUT_A+OUT_C); に変更するとロボットはゆっくりと止まるようになります。

 このプログラムの中でわかりにくい箇所はWait(300)でしょう。かっこの中に指定した数値はティック値というコンピュータ内部の時間の単位です。1ティック = 1/100 秒ですから,300ティック= 3 秒です。さて,問題はWait(ウェイト)の意味です。Wait = 『待つ』と解釈すると,じっとしているようなイメージになりますね。「走っているのに,じっとしている」となぞなぞのようになってしまいます。Waitは現在の状態を指定された時間『保つ』と解釈して下さい。

 出力ポートに対する他の命令を紹介します。

Toggle(出力ポート)  

 Toggleは,出力を逆転させます。ボタンが一つのスイッチのような命令です。回転方向を現在の方向の逆にします。
 例えば,motor1.nqc の OnRev(OUT_A+OUT_C); を Toggle(OUT_A+OUT_C); と置き換えることができます(動作は同じです) 。

 OnFwd(OUT_A+OUT_C);
 Wait(300);
 Toggle(OUT_A+OUT_C);
 Wait(300);
 Off(OUT_A+OUT_C);

OnFor(出力ポート,時間)

 OnForは指定した時間,出力をオンにします。時間はティック値で指定します。
 motor1.nqc を OnFor を使って書き換えると以下のようになります。

 Fwd(OUT_A+OUT_C);
 OnFor(OUT_A+OUT_C,300);
 Rev(OUT_A+OUT_C)
 OnFor(OUT_A+OUT_C,300);

SetPower (出力ポート,速度)

 SetPowerは出力の大きさを指定します。通常はモーターを出力ポートに接続していますので,回転速度を指定することになります。0~7の値を設定できます。
 下記のプログラムは,1秒ごとに速度を変えます(加速していきます)。

 motor2.nqc

 task main()
 {
  SetPower(OUT_A+OUT_C,0);
  OnFwd(OUT_A+OUT_C);
  Wait(100);
  SetPower(OUT_A+OUT_C,4);
  Wait(100);
  SetPower(OUT_A+OUT_C,7);
  Wait(100);
  Off(OUT_A+OUT_C);
 }

 定数を使って速度を指定することもできます。OUT_LOW,OUT_HALF,OUT_FULLの3つの定数が用意されています。

   例 SetPower(OUT_A+OUT_C,OUT_HALF);

SetOutput(出力ポート,モード)

 SetOutputは出力ポートのモードを設定します。モードには,定数OUT_ON,OUT_OFF,OUT_FLOATのいずれかを指定します。On,Off,Float命令と同じ意味です。

SetDirection(出力ポート,回転方向)

 SetDirectionは回転方向をOUT_FWD,OUT_REVなどの定数で指定します。Fwd,Rev命令と同じ意味です。

方向を変える

 モーターの回転方向を変えることで,ロボットの進行方向を変えることができます。次のプログラムでは,ロボットは1秒間前進した後,左折し,また1秒間前進します。

 motor3.nqc

 #define MOVE_TIME 100
 #define TURN_TIME 10
 task main()
 {
  SetPower(OUT_A+OUT_C,OUT_HALF);
  OnFwd(OUT_A+OUT_C);
  Wait(MOVE_TIME);
  Rev(OUT_C); 
  Wait(TURN_TIME);
  Fwd(OUT_C);
  Wait(MOVE_TIME);
  Off(OUT_A+OUT_C);
 }

  まっすぐ進む時間と曲がる時間を,それぞれMOVE_TIME,TURN_TIMEという名前で定数宣言しました。(定数もすべてグローバル定数ですから,タスクの外に定義します。)Rev(OUT_C);で出力ポートCに接続されているモーターの方向を反転させ,TURN_TIMEの時間(0.1秒)その状態を保ちます。その後Fwd(OUT_C);で回転方向を元に戻しています。
  これで,ロボットはカクッと90度左折します。(ただし,曲がる角度は床の材質や電池の状態によって異なりますので,TURN_TIMEの値を調節する必要があるかもしれません。)