[[2013b/Member/dyuma/Mission2]] #contents *注意 [#vcc93610] ※コンパイルは通っていますが、実機で動かしたわけではありません。~ うまく動く保証はどこにもありません。~ [[michaegonのプログラム>2013b/Member/michaegon/Mission2]]のほうがよほどいいです。 *プログラム [#tb1ebc02] #ref(2013b/Member/dyuma/Mission2/program/Screenshot_2014-02-03_14-23-20.png,480x360); 緑、青、赤の順にこなします。 **メインマシンのプログラム [#u493d425] #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(); } メインは簡潔にかかれています。~ たったこれだけです。~ **サブマシンのプログラム [#w53019be] #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); } } } メインのプログラムは、通信された時にどう返すかのみ書かれています。~ それ以外は必要ありませんので。 *最後に [#ta279b59] 結果的に使われることのなかったプログラムですが、メインの方はそこそこ上手く書けていると思います。~ サブの方は空白も多く、実際に機体を見ながら、試しながら書く前提で書いたので、こんな感じになっています。~ まだまだ直すべき点は多いと思います。~ 今後の課題にしたいです。