2013b/Member/dyuma/Mission2

注意

※コンパイルは通っていますが、実機で動かしたわけではありません。
うまく動く保証はどこにもありません。
michaegonのプログラムのほうがよほどいいです。

プログラム

Screenshot_2014-02-03_14-23-20.png

緑、青、赤の順にこなします。

メインマシンのプログラム

#define sikiiti 50
#define BMAX 500
#define go_left OnFwd(OUT_C,30);OnFwd(OUT_B,-20);
#define go_right OnFwd(OUT_C,-20);OnFwd(OUT_B,30);
#define go_straight OnFwd(OUT_BC,15);
#define turn_right OnFwd(OUT_C,-10);OnFwd(OUT_B,10);
#define turn_left OnFwd(OUT_C,10);OnFwd(OUT_B,-10);
#define back_left OnFwd(OUT_C,-30);OnFwd(OUT_B,20);
#define back_right OnFwd(OUT_C,20);OnFwd(OUT_B,-30);
#define back_straight OnFwd(OUT_BC,-15);
#define STOP Off(OUT_BC);Wait(1000);
#define P 10
#define MODOSHITIME 300
#define TEST 11
#define CONNx 5
#define CONNy 1
#define MODOSHITIME 300
#define KICK 12
#define FINISH 13
#define KANOKI 14

大量にdefineされていますけど、上半分程は僕がnxcプログラムを書くときにテンプレとして置いているものなので、使わなかったものも多いです。
いちいち定義を書かずとも、ある程度は指定できるのがいいです。

int count[3]={0,0,0};

今回はカウンターは配列形式にしています。
白ければcount[0]を+1、黒ければcount[1]を+1、交差点と判定されればcount[2]を+1します。

void TSUSHIN(int x){
	int msg1=0;
	STOP;
	SendRemoteNumber(CONNx,MAILBOX1,x);
	while(msg1==0){
		ReceiveRemoteNumber(MAILBOX1,true,msg1);
		Wait(1);
	}
}

通信用のプログラムを別に置いています。
こうすることで、いちいちややこしい送信文、受信文を書かなくてもいいようにしました。

void START(){
	TSUSHIN(TEST);
	while(SENSOR_1>sikiiti){
		go_straight;
	}
	while(SENSOR_1<sikiiti){
		turn_right;
	}
}

スタート時の動作です。
通信テストを行い、ライントレースに行くまでの動作が書かれています。

int iscan(){
	if(SENSOR_2<15){
                 return 1;
}else{
                 return 0;
}
}

缶があれば1を、なければ0を返す関数です。

void kick(){
	while(SENSOR_2>10){
		go_straight;
	}
	TSUSHIN(KICK);
}

もし缶があれば、近づいた上で、キックしろという命令を送ります。

void LAPfinish(){
	back_straight;
	Wait(500);
	TSUSHIN(KANOKI);
	int msg1=0;
	while(msg1==0){
		ReceiveRemoteNumber(MAILBOX1,true,msg1);
		Wait(1);
	}
	back_straight;
	Wait(2000);
}

各LAPの終了行動、つまり缶を立てる時の動作が書かれています。

void line_trace(int t){
	int MEIDO=SENSOR_1-sikiiti;
	if(t==3||t==4){
		OnFwd(OUT_C,P+MEIDO);OnFwd(OUT_B,P-MEIDO);
	}else{
		OnFwd(OUT_C,P-MEIDO);OnFwd(OUT_B,P+MEIDO);
	}
	if(0<MEIDO){
		count[0]=0;
		count[1]++;
	}else{
		count[0]++;
		count[1]=0;
	}
	if(count[0]>50){
		count[0]=0;
		count[1]=0;
		count[2]++;
		if(t==1){
			turn_left;
			Wait(MODOSHITIME);
			go_straight;
			Wait(2000);
		}else if(t==2){
			turn_left;
			Wait(2000);
		}
	}
}

ライントレースについて書かれています。
ここでは光センサーの値により、各モーターをどの速度で回すか指定しています。
課題1のような二段階、さらには6段階などより、格段に多くの段階になっています。
もしうまくいかなければ、課題1が終わったあとで書いた6段階、それでもうまく行かなければ課題1のときの二段階のライントレースに差し替えることもできます。

void LAP(int x){
	if(x==1){
		while(SENSOR_1<sikiiti){
			turn_right;
		}
		count[2]=0;
		while(count[2]<7){
			line_trace(1);
			if(iscan()==1){
				kick();
			}
		}
		do{
			Wait(200);
			go_straight;
		}while(SENSOR_1>sikiiti);
		LAPfinish();
		while(SENSOR_1>sikiiti){
			go_left;
		}
	}else if(x==2){
		count[2]=0;
		while(count[2]<3){
			line_trace(0);
			if(iscan()==1){
				kick();
			}
		}
		while(count[2]<7){
			line_trace(1);
			if(iscan()==1){
				kick();
			}
		}
		while(count[2]<9){
			line_trace(0);
			if(iscan()==1){
				kick();
			}
		}
		LAPfinish();
		while(SENSOR_1>sikiiti){
			go_right;
		}
	}
}	

非常にめんどくさく書かれていますが、通過した交差点の数でいまどこにいるかを把握し、それに対応した行動を行っていくプログラムです。
もしこのプログラムを調整することがあるならば、最も調整が必要と思われる部分の一つです。

void LAST_ACTION(){
	go_straight;
	Wait(5000);
	STOP;
	TSUSHIN(FINISH);
}

最終行動が書かれています。

task main(){
	SetSensorLight(S1);
	SetSensorLowspeed(S2);
	START();
	LAP(1);
	LAP(2);
	LAST_ACTION();
}		

メインは簡潔にかかれています。
たったこれだけです。

サブマシンのプログラム

#define turn_left OnFwd(OUT_C,10);OnFwd(OUT_B,-10);
#define back_left OnFwd(OUT_C,-30);OnFwd(OUT_B,20);
#define back_right OnFwd(OUT_C,20);OnFwd(OUT_B,-30);
#define back_straight OnFwd(OUT_CB,-15);
#define STOP Off(OUT_BC);Wait(1000);
#define P 10
#define MODOSHITIME 300
#define TEST 11
#define CONNx 5
#define CONNy 1
#define MODOSHITIME 300
#define KICK 12
#define FINISH 13
#define KANOKI 14

defineはメインと変わってません。

inline void SHIME(){

}

inline void TATE(){

}

inline void HANASU(){

}

この辺はまだ空白です。
SHIMEで「閉めて」、TATEで「立てて」、HANASUで「離し」ます。
最終的には消す予定ではありました、というのは同じようなものをmichaegonが書いていましたので。

inline void CANOKI(){
	SHIME();
	TATE();
	HANASU();
}

わかりやすいようにこう書いてはいますが、michaegonのプログラムをそのまま持ってくる、うまく行かなければその場で合ったものを書く予定でした。

inline void OTO(){
	
}

inline void KERI(){

}

最後の行動が終了した時の音をだすOTO「音」と、缶を叩き込むKERI「蹴り」をここで書く予定でした。
michaegonのプログラムをそのまま持ってくるなり、その場で書くなりする予定でした。

task main(){
	while(true){
		int msg1=0;
		while(msg1==0){
			ReceiveRemoteNumber(MAILBOX1,true,msg1);
			Wait(1);
		}
		if(msg1==TEST){
			SendRemoteNumber(CONNy,MAILBOX1,TEST);
		}else if(msg1==KICK){
			KERI();
			SendRemoteNumber(CONNy,MAILBOX1,KICK);
		}else if(msg1==FINISH){
			OTO();
			break;
		}else if(msg1==KANOKI){
			CANOKI();
			SendRemoteNumber(CONNy,MAILBOX1,KANOKI);
		}
	}
}

メインのプログラムは、通信された時にどう返すかのみ書かれています。
それ以外は必要ありませんので。

最後に

結果的に使われることのなかったプログラムですが、メインの方はそこそこ上手く書けていると思います。
サブの方は空白も多く、実際に機体を見ながら、試しながら書く前提で書いたので、こんな感じになっています。
まだまだ直すべき点は多いと思います。
今後の課題にしたいです。


添付ファイル: fileScreenshot_2014-02-03_14-23-20.png 295件 [詳細]

トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2014-02-06 (木) 02:45:40