- 追加された行はこの色です。
- 削除された行はこの色です。
[[動画はこちら:https://www.youtube.com/watch?v=vz3ReqVNWz8]]
目次
#contents
*はじめに [#u50d6f67]
今回の課題は書道ロボットで、名前の中の一文字をA4用紙の中に書くロボットを作るというものでした。僕は「谷」という漢字を書きました。&br;
はじめは左右に旋回できる基本形の車体のロボットに上下できるだけのペンを付けたもので書くつもりで作りましたが、いざ動かすと旋回したときにペンの位置がずれてしまい、綺麗な角を書くことができませんでした。その改善策として、前後に進む車体にアームを付けたものに一から作り直すことで目的の文字をかけました。
今回の課題はライントレースロボットで、図のようなコースを決められた順路を通り、途中においてあるピンポン玉をゴールまで運ぶロボットを作るというものでした。僕はC地点からA地点へ (Q交差点では直進、P三叉路では右折)を通るロボットを作りました。&br;
今回は前回と違い、本体の作成は簡単でしたが、プログラムに時間がかかりました。
#ref(./無題.png,コース)
*ロボット本体 [#i6276637]
**全体 [#r6254f2a]
#ref(./S__9723911.jpg,around,全体)
画像の様に前後に進む車体に横方向に動くアームを付けた形になっています。前後の動きがギア比を変えてもちょうどいい距離にならなかったので、車輪を大きいものから小さいものにすることで調整しました。アームにはモーターが一つ載っているため、車体が浮かないようにアームの逆側に重り用のタイヤを付けています。&br;
#ref(./S__35348483.jpg,around,全体)
基本の車の形のものにアームとセンサーを付けた形になっています。&br;
センサーが車体から遠いと一度の動作でセンサーが動く距離が大きくなり、曲がり切れないところがあったのでなるべく車体から近いところにしました。&br;
#clear
**アーム [#r7cabf87]
モーター1つが載るので、なるべく頑丈な土台の上を動くようにしました。軽量化のためになるべく少ない部品でできるようにしました。&br;
ギザギザのついたパーツによって動くようにしています。
#ref(./S__9723908.jpg,around,ペン)
#ref(./S__35348482.jpg,around,アーム)
モーター1つで開閉ができるようにしました。モーターを直接つなぐと動きが早すぎたのでギア比を考えてゆっくり動くようにしています。&br;
プログラムをこのまま送れるように送受信センサのところには棒が一本しか通らないようにしています。アームとセンサはまとめて本体から簡単に取り外しができるようにもしています。
#clear
**ペン [#w1846cc4]
ペンの上下のモジュールには苦労しました。&br;
まず、ペンの固定ですが、ちょうどアームのようなものがあったのでそれとゴムを使ってはさんで固定しました。上下の動作には図書館で借りた本に書いてあったものを少し応用して形にすることができました。
*プログラム [#k56a7f58]
//C地点からA地点へ (Q交差点では直進、P三叉路では右折)
#define turnleft OnFwd(OUT_C);OnRev(OUT_A); //左旋回
#define left OnFwd(OUT_C);Off(OUT_A); //左に曲がる
#define right OnFwd(OUT_A);Off(OUT_C); //右に曲がる
#define turnright OnFwd(OUT_A);OnRev(OUT_C); //右旋回
#define stop2sec Off(OUT_AC);Wait(200); //2秒止まる
//ライントレース用の関数
void linetrase(int t){
ClearTimer(0);
while(FastTimer(0)<t){
if(SENSOR_3<36){
turnright;
}else if(SENSOR_3<39){
right;
Wait(2);
}else{
if(SENSOR_3<47){
OnFwd(OUT_AC);
Wait(3);
}else if(SENSOR_3<50){
left;
Wait(2);
}else{
turnleft;
}
ClearTimer(0);
}
}
}
task main ()
{
SetSensor(SENSOR_3,SENSOR_LIGHT);
int count=0;
ClearTimer(1);
while(count <= 1){
linetrase(28);
if(FastTimer(1)>500||count==0){
count++;
}
ClearTimer(1);
}
stop2sec;
left;
OnFwd(OUT_B);
Wait(20);
Off(OUT_C);
Wait(100);
Off(OUT_B);
linetrase(21);
stop2sec;
linetrase(28);
Off(OUT_AC);
OnRev(OUT_A);
Wait(30);
Off(OUT_A);
OnRev(OUT_B);
Wait(50);
Off(OUT_B);
OnFwd(OUT_AC);
Wait(60);
OnRev(OUT_AC);
Wait(60);
Off(OUT_AC);
}
*説明 [#kdc3ad86]
**定義 [#uf43dbf6]
まずは以下の通り全方向に動くための定義をしました。
#define XbackYforward(t) OnRev(OUT_B);OnFwd(OUT_A);Wait(t);Off(OUT_AB); //左上
#define XbackYback(t) OnRev(OUT_AB);Wait(t);Off(OUT_AB); //左下
#define XforwardYforward(t) OnFwd(OUT_AB);Wait(t);Off(OUT_AB); //右上
#define XforwardYback(t) OnRev(OUT_A);OnFwd(OUT_B);Wait(t);Off(OUT_AC); //右下
#define turnleft OnFwd(OUT_C);OnRev(OUT_A); //左旋回
#define left OnFwd(OUT_C);Off(OUT_A); //左に曲がる
#define right OnFwd(OUT_A);Off(OUT_C); //右に曲がる
#define turnright OnFwd(OUT_A);OnRev(OUT_C); //右旋回
#define stop2sec Off(OUT_AC);Wait(200); //2秒止まる
さらに交差点で2秒止まるための定義をしました。
#define stop2sec Off(OUT_AC);Wait(200); //2秒止まる
そして、交差点までライントレースするプログラムを関数で書きました。引数を入れたかったのでサブルーチンではなく関数を使っています。引数は一度にどれだけ右に曲がったら交差点と判断するのかを入れられるようにしています。&br;
Wait関数を少し入れることでなるべく滑らかに動くようにしています。
void linetrase(int t){
ClearTimer(0);
while(FastTimer(0)<t){
if(SENSOR_3<36){
turnright;
}else if(SENSOR_3<39){
right;
Wait(2);
}else{
if(SENSOR_3<47){
OnFwd(OUT_AC);
Wait(3);
}else if(SENSOR_3<50){
left;
Wait(2);
}else{
turnleft;
}
ClearTimer(0);
}
}
}
**動作 [#e1234c3b]
#ref(./コース.png,around,right,コース)
右の図の様にライントレースしました。&br;
+右に大きく曲がる場所が交差点までに一度あるので、一度目の大きく曲がるところはスルーするようになっています。曲がる時間が長く、二度認識してしまうことがあったので、50秒以内には二度目を認識しないようにしました。
int count=0;
ClearTimer(1);
#define Yforward(t) OnFwd(OUT_A);Wait(t);Off(OUT_A); //上
#define Yback(t) OnRev(OUT_A);Wait(t);Off(OUT_A); //下
#define Xforward(t) OnFwd(OUT_B);Wait(t);Off(OUT_B); //右
#define Xback(t) OnRev(OUT_B);Wait(t);Off(OUT_B); //左
それからペンの上下の定義をしました。
#define writeon OnFwd(OUT_C);Wait(5);Off(OUT_C); //書き始め
#define writeoff OnRev(OUT_C);Wait(5);Off(OUT_C); //書き終わり
そして、この形のロボットでは横、斜め、縦の動きをすることしかできないので、マス目を意識してプログラムをするために、一辺の長さ(一辺分動く時間)を定義しました。
#define movetime 20 //一辺の長さ
**動作 [#e1234c3b]
#ref(./谷.png,around,right,書き順)
右の図の様な書き順で書きました。オレンジの部分でペンが降り、水色の部分でペンが上がります。&br;
+スタート位置から左上に1マス書き進みます。
writeon;
XbackYforward(movetime);
writeoff;
+次の書き初めの位置まで2マス移動した後、左下に1マス書き進みます。
Xback(movetime*2);
writeon;
XbackYback(movetime);
writeoff;
+2マス下に移動した後「へ」の字をかきます。
writeon;
XforwardYforward(movetime*2);
XforwardYback(movetime*2);
writeoff;
+最後に、1マス左に移動した後、「口」を書きます。
writeon;
Xback(movetime*2);
Yback(movetime*2);
Xforward(movetime*2);
Yforward(movetime*2);
writeoff;
while(count <= 1){
linetrase(28);
if(FastTimer(1)>500||count==0){
count++;
}
ClearTimer(1);
}
+2度目の大きく曲がるところを認識したら、2秒間止まってから線を越えます。そのあとはアームでピンポン玉をはさみます。
stop2sec;
left;
OnFwd(OUT_B); //アームを閉じる
Wait(20);
Off(OUT_C);
Wait(100);
Off(OUT_B);
+ライントレースを再び初めて、角を認識したら2秒間止まる。
linetrase(21);
stop2sec;
+ライントレースを再び始め、角を認識したら後ろに下がり、アームを開いてシュートする。
linetrase(28);
Off(OUT_AC);
OnRev(OUT_A); //後ろに下がる
Wait(30);
Off(OUT_A);
OnRev(OUT_B); //アームを開く
Wait(50);
Off(OUT_B);
OnFwd(OUT_AC); //シュートする
Wait(60);
OnRev(OUT_AC);
Wait(60);
Off(OUT_AC);
#clear
*結果・感想 [#rf1c4458]
#ref(./S__32784393.jpg,around,結果)
少し歪みはありますが、目的の字を書くことはできました。マス目を意識することによってだいぶ簡単にプログラムをすることができたのがとてもよかったと思いました。&br;
前回の課題の時より慣れていたためかすぐに完成させることができました。&br;
実際のロボット動きは動画にしたので見ていただきたいです。[[動画はこちら:https://www.youtube.com/watch?v=vz3ReqVNWz8]]&br;
グループで製作ということで、3人で相談しあいながらなんとか形にできたのは大きな達成感を得ることになりました。&br;
今回はアーム式だったので45°の斜め線で統一することになりましたが、SetPower関数というものがあるそうなのでそれを今度使ってみたいと思いました。&br;
おまけで、写真はありませんが、「熊」を書くプログラムも書きました。容量が大きく、defineではコンパイルができなかったので関数を使っています。最後の点3つは繰り返しを使っています。
#clear