Lego MindstormsをnxtOSEKにより自在かつ高度に制御することを
目標に、開発環境の構築を目指しています。Windows上にUNIX環境を
再現するため、Cygwinに代わりWSL(Windows
Subsystem for
Linux)を介しUbuntuを組み込むことで、Lego MindstormsNXT上で
簡単なプログラム(helloworld.c)を実行させることに成功しています。
この環境下でnxtOSEKを利用できるか、つまりNXTのアクチュエータや
センサーを制御できるか、チュートリアルに沿って作業を進めます。
|
nxtOSEKのファンクションを呼び出す前に
もう一つ簡単なプログラムを試してみます。
|
samples_cフォルダ内にtestフォルダを作成し、Makefile、
test.c、test.oilの3ファイルを以下の通り保存します。
|
|
#include "kernel.h"
#include "kernel_id.h"
#include
"ecrobot_interface.h"
DeclareTask(Task1);
void
ecrobot_device_initialize(){} //OSEK起動時の処理(何もしない)
void
ecrobot_device_terminate(){} //OSEK終了時の処理(何もしない)
void
user_1ms_isr_type2(void){}
TASK(Task1)
{
while(1){
display_clear(0);
display_goto_xy(5,3);
display_string("TASK1"); /*
メッセージを表示する */
display_update();
systick_wait_ms(1000); /*
1秒待つ */
display_clear(0);
display_goto_xy(5,5);
display_string("TASK2"); /*
メッセージを表示する */
display_update();
systick_wait_ms(1000); /*
1秒待つ */
}
TerminateTask(); //処理終了
}
|
|
test.cファイル(テキスト)の内容です。NXTのディスプレイ表示をいったん
消去(display_clear(0);)し、カーソルを(5、3)に移動(display_goto_xy(5,3);)、
"TASK1"と表示(display_string("TASK1");)して1秒間待ちます(systick
_wait_ms(1000);)。再び表示を消してからカーソルを(5、5)に移動させ、
"TASK1"と表示して1秒間待ちます。この処理を繰り返します(while(1){)。
|
|
#include "implementation.oil"
CPU ATMEL_AT91SAM7S256
{
OS LEJOS_OSEK
{
STATUS = EXTENDED;
STARTUPHOOK = FALSE;
SHUTDOWNHOOK = FALSE;
PRETASKHOOK = FALSE;
POSTTASKHOOK = FALSE;
USEGETSERVICEID = FALSE;
USEPARAMETERACCESS = FALSE;
USERESSCHEDULER = FALSE;
};
/* Definition of application
mode */
APPMODE appmode1{};
TASK Task1 /* Task1 を定義する */
{
AUTOSTART = TRUE { APPMODE =
appmode1; };
PRIORITY = 1;
ACTIVATION = 1;
SCHEDULE = FULL;
STACKSIZE = 512;
};
};
|
|
oilファイルは、テキストで記述されているオブジェクトの内容により
プログラムの実行の仕方を変えることができるそうです。拡張子の
oilはOSEK Implementation Languageの略です。実行環境が同じ
なので、前回の作業で使用したhelloworld.oilをコピーしファイル
名のみを変更してtest.oilとすることでそのまま利用できます。
|
|
#
Target specific macros
TARGET = test
# User application
source(ここにソースファイルの名前を指定する)
TARGET_SOURCES =
test.c
#
自分のフォルダから見たnxtOSEKフォルダの場所またはそのフルパスを指定する。ここでは次のフルパスを指定する。
NXTOSEK_ROOT = /nxtOSEK
# OSEK OIL
file(ここにoilファイルの名前を指定する)
TOPPERS_OSEK_OIL_SOURCE =
./test.oil
# below part should not be
modified
O_PATH ?= build
include
$(NXTOSEK_ROOT)/ecrobot/ecrobot.mak
|
|
Makefileも共通して利用できますが、TARGET、TARGET_
SOURCES、TOPPERS_OSEK_OIL_SOURCEの記述を
実行するプログラム名に一致させます。’test’に書き換えます。
|
|
include $(NXTOSEK_ROOT)/ecrobot/ecrobot.mak
↓
include $../../ecrobot/ecrobot.mak
|
|
最終行のinclude
$(NXTOSEK_ROOT)/ecrobot/ecrobot.mak中で
(NXTOSEK_ROOT)はnxtOSEKがインストールされたルート
ディレクトリを指定しているので、簡単に../..で代用させます。
|
Ubuntuを起動しtestディレクトリに移動します。dirコマンドに
よりフォルダ内のファイルを表示させると、先ほど用意した
Makefile、test.c、test.oilの各ファイルが確認できます。
|
make allコマンドによりtest.cをビルド(コンパイル)します。
エラーなく最後に実行ファイルtest.rxeが生成されています。
|
dirコマンドでもう一度フォルダ内のファイルを表示させると、
test.rxeを含む一連のビルドファイルが確認できます。
|
同じくtestフォルダをWindows上で表示させてみます。
もちろんUbuntuによる表示と全く同じファイル構成です。
|
NXTを接続した状態でsh rxeflash.shコマンドを実行し
生成された実行ファイルをNXT内のメモリに転送します。
|
NXT本体との通信にはNeXTToolが呼び出されます。
NeXTTool is terminatedと表示されているので
NXTへtest.rxeの転送は完了しているはずです。
|
NXT側でプログラムが登録
されているか確認します。
|
My Files → Software filesと
辿ると、testが格納されています。
|
testを指定して(それしか指定
できません)、実行(Run)します。
|
カーソル位置を変えながらTASK1と
TASK2が交互に表示されます。
|
チュートリアルを次の章に進め、モーターを制御してみます。
モーターはNXT本体からポートを介して外部に接続されます。
ディスプレイ表示や操作ボタン入力など標準的なデバイスと
異なり、nxtOSEKに実装されたファンクションがないと制御
できない領域です。nxtOSEKの本領を引き出しにかかります。
|
Lego Mindstorms9797に付属する
マニュアルに従い2輪走行車を組み立てます。
|
2個のモーターが左右それぞれのタイヤを
駆動します。後部に補助輪が付きます。
|
NXT本体のポートにモーターの
配線を左右とも接続します。
|
左車輪用モーターはポートCへ、右車輪用
モーターはポートBへ接続されます。
|
同じくsamples_cフォルダ内に
motor1フォルダを作成します。
|
Makefile、motor1.c、motor1.oilの
3ファイルを保存し、Makefileを編集します。
|
|
#include "kernel.h"
#include "kernel_id.h"
#include
"ecrobot_interface.h"
DeclareTask(Task1); /*
Task1を宣言 */
void
ecrobot_device_initialize(){ /* OSEK起動時の処理(モータ停止)*/
nxt_motor_set_speed(NXT_PORT_B,0,1);
nxt_motor_set_speed(NXT_PORT_C,0,1);
}
void
ecrobot_device_terminate(){ /* OSEK終了時の処理(モータ停止)*/
nxt_motor_set_speed(NXT_PORT_B,0,1);
nxt_motor_set_speed(NXT_PORT_C,0,1);
}
void
user_1ms_isr_type2(void){}
TASK(Task1)
{
//2秒前進
nxt_motor_set_speed(NXT_PORT_B,60,1);
nxt_motor_set_speed(NXT_PORT_C,60,1);
systick_wait_ms(2000);
//1秒停止
nxt_motor_set_speed(NXT_PORT_B,0,1);
nxt_motor_set_speed(NXT_PORT_C,0,1);
systick_wait_ms(1000);
//2秒後退
nxt_motor_set_speed(NXT_PORT_B,-60,1);
nxt_motor_set_speed(NXT_PORT_C,-60,1);
systick_wait_ms(2000);
//1秒停止
nxt_motor_set_speed(NXT_PORT_B,0,1);
nxt_motor_set_speed(NXT_PORT_C,0,1);
display_string("THAT'S ALL
!"); /* メッセージを表示する */
display_update();
TerminateTask(); /* 処理終了 */
}
|
|
motor1.cの内容です。左右モーターを同時に一定速度で
2秒間回転させて2輪走行車を前進させます。次に1秒間
モーターを止めて停止させ、続く2秒間でモーターを逆回転し
後退させます。モーターを制御するファンクションを使います。
|
|
nxt_motor_set_speed(NXT_PORT_X,Y,Z); の説明
・X:A・B・C
→モーターが接続されているポートをA・B・Cのいずれかから指定する。
・Y:-100~100
→モーターの出力(duty比)を指定する。-値で逆回転する。
・Z:0・1
→0(フロートモード:モーターが空転する)、1(ブレーキモード:モーターが空転しない)を指定する。
systick_wait_ms(T); の説明
→Tmsec=T/1000sec動作を待機する。
|
|
|
motor1.cで使用されているファンクションの説明です。
チュートリアルからの抜粋ですが、実際はもう少し詳しく
解説されています。出力はPWM制御されています。
|
Ubuntuを起動しmotor1ディレクトリに移動します。
Makefile、motor1.c、motor1.oilが確認できます。
|
make allコマンドによりmotor1.cをビルド(コンパイル)します。
エラーなく最後に実行ファイルmotor1.rxeが生成されています。
|
NXTを接続した状態でsh rxeflash.shコマンドを実行し
生成された実行ファイルをNXT内のメモリに転送します。
|
motor1フォルダをWindows上で表示します。
一連のビルドファイルが生成されています。
|
NXT本体にもmotor1が登録
されていることが確認できます。
|
motor1を指定して実行(Run)します。左右のモーターが音を
たてて回転し、2輪走行車が前進→停止→後退→停止します。
取りあえずnxtOSEKによりLego MindstormsNXTを制御する
基本部分の環境構築に成功したと言えるのではないでしょうか。
|
もう一つ、チュートリアルにあるnxt_motor_set_speed()を
使ったサンプルを試します。motor2フォルダを作成します。
|
Makefile、motor2.c、motor1.oilの
3ファイルを保存し、Makefileを編集します。
|
|
#include "kernel.h"
#include "kernel_id.h"
#include
"ecrobot_interface.h"
#define TURN_TIME 220 /*
回転時間を指定するマクロ */
#define MOVE_TIME 750 /*
直進時間を指定するマクロ */
#define STOP_TIME 100
DeclareTask(Task1); /*
Task1を宣言 */
void
ecrobot_device_initialize(){ /* OSEK起動時の処理(モータ停止)*/
nxt_motor_set_speed(NXT_PORT_B,0,1);
nxt_motor_set_speed(NXT_PORT_C,0,1);
}
void
ecrobot_device_terminate(){ /* OSEK終了時の処理(モータ停止)*/
nxt_motor_set_speed(NXT_PORT_B,0,1);
nxt_motor_set_speed(NXT_PORT_C,0,1);
}
void
user_1ms_isr_type2(void){}
TASK(Task1)
{
int i;
for(i=0;i<4;i++){
//直進
nxt_motor_set_speed(NXT_PORT_B,60,1);
nxt_motor_set_speed(NXT_PORT_C,60,1);
systick_wait_ms(MOVE_TIME);
//停止
nxt_motor_set_speed(NXT_PORT_B,0,1);
nxt_motor_set_speed(NXT_PORT_C,0,1);
systick_wait_ms(STOP_TIME);
//回転
nxt_motor_set_speed(NXT_PORT_B,-40,1);
nxt_motor_set_speed(NXT_PORT_C,40,1);
systick_wait_ms(TURN_TIME);
//停止
nxt_motor_set_speed(NXT_PORT_B,0,1);
nxt_motor_set_speed(NXT_PORT_C,0,1);
systick_wait_ms(STOP_TIME);
}
nxt_motor_set_speed(NXT_PORT_B,0,1);
nxt_motor_set_speed(NXT_PORT_C,0,1);
display_string("THAT'S ALL
!"); /* メッセージを表示する */
display_update();
TerminateTask(); /* 処理終了 */
}
|
|
前進→停止→回転→停止を4回繰り返し、四角形を描いて元の位置に
戻るプログラムです。回転時にはポートBに-40を指定して右タイヤを
逆回転、ポートCに40を指定して左タイヤを正回転させることで走行車を
右旋回させます。旋回角度を調整しやすくするため、前進・停止・回転の
各動作時間をマクロに定義しています。動作終了後にディスプレイに
゛THAT’S ALL!゛と表示させます。多分うまく動作するでしょう。
|
make allコマンドによりmotor2.cをビルド(コンパイル)します。
エラーなく最後に実行ファイルmotor2.rxeが生成されています。。
|
NXTを接続した状態でsh rxeflash.shコマンドを実行し
生成された実行ファイルをNXT内のメモリに転送します。
|
motor2フォルダをWindows上で表示します。
一連のビルドファイルが生成されています。
|
NXT本体にもmotor2が登録
されていることが確認できます。
|
motor2を指定して実行(Run)します。再び左右のモーターが
回転し、2輪走行車が前進→停止→回転→前進→停止を繰り
返します。残念ながら4回繰り返した結果、元の位置からかなり
ずれています。対処方法は簡単なものでして、motor2.c中に
記述されている゛#define TURN_TIME 220゛の220を変更
させるだけです。右回転が足りないので220よりも大きくします。
Lego MindstormsNXTには、何と加速度センサーやジャイロ
センサーといった高度な制御を実現するセンサーが用意されて
います。実は、これらの環境を利用してどうしても挑戦したい
課題があるのですが、その前にNXTおよびnxtOSEKの扱い
方を十分に習得しておきたいものです。続編にご期待下さい。
|
守谷工房の製作品3へ
守谷工房Topへ
|