[[2017a/Member]] #contents * 課題概要 [#t0945512] 課題1は、15cm四方の中に松本での新生活を表す漢字を書くロボットを作成する課題である。 ~ 詳しくは[[課題1>2017a/Mission1]]を参照。 ** 選んだ漢字 [#uf147406] 大学生になり、自由な時間が多くなる分、自分で自分の生活を管理し律することが必要になるということで、「律」という漢字を書くことにした。 ~ 書き順は次のようにした。これは後でするプログラムの説明の時にも参考にしてほしい。 #ref(./「律」書き順.png,50%,書き順と形) * ロボット本体の説明 [#l8443962] ロボットを組み立てるときにまず考えたことは、できるだけプログラムによるモータの時間制御が行いやすい機構にするということである。 ~ そこで、旋回の動作を行わない機構を考えることにした。旋回を行わない理由としては、旋回の動作は時間の設定によって角度が決まるため、正確な時間を設定しないと線の位置がずれてしまうということ。それから、線を引くたびに旋回を行わなくてはならず、その都度時間を細かく設定しないとならないということが考えられたからである。 ~ 以上のことから直線運動のみで字を書くことのできる機構にしようと考えた。具体的にはロボットにアームを取り付け、ロボットの前後移動でY軸方向の移動を、アームの駆動でX軸方向の移動を行い字を書く機構にしている。 #ref(./ロボット全体.JPG,20%,ロボット全体) ** 車体部分 [#k0c22acf] ロボット本体は前後移動のみで良いため、モータは1個とキャタピラで走るようにした。キャタピラを選んだのは、タイヤなどよりも広く床に設置しているため、安定感があると考えたからである。 ~ 初めは振動が大きいのではないかと不安もあったが、補助輪をつけるなど調整をしたことで全く問題ないほどに振動を抑えることができた。 #ref(./キャタピラ.JPG,20%,キャタピラ部分) ** アーム・ペン保持部 [#b314981e] アーム部分は、ピニオンギアとラックを使用して駆動させている。ここでは、アームに取り付けている支えの部分とペンの駆動・保持の部分について説明していこうと思う。 *** アーム支え [#d0cd6752] 製作の途中で、アームが伸びてロボットから離れると先端の重みに耐えきれずに傾いてしまうことが分かった。そこで、ローラーを取り付けてアームを支えることで安定してアームを動かすことができるように工夫している。支えはアームの両端にそれぞれつけているが、位置関係は下の【アーム全体】の写真で見てほしい。 ~ &ref(2017a/Member/Kenty/Mission1/アーム支え1.JPG,10%,アーム全体); &ref(2017a/Member/Kenty/Mission1/アーム支え2.JPG,10%,アーム全体); *** ギア部分 [#s70f2839] ペンの上げ下げはモーターの回転をウォームギア(ギア比1:3)で減速させ、その回転をさらにプーリーで伝達させることで行っている。また、これらの機構とモーターを密集させると先ほど書いたアーム部分の傾きと安定性に影響を及ぼしてしまうように感じたため、モーターをシャフトを使って延長しながらペン保持部と反対の端に設置している。ウォームギアとプーリの部分は下の写真のようになっている。 ~ モータに関しては、【アーム全体】の写真で確認してほしい。 #ref(./ギア部.JPG,10%,ギア部分) *** ペン保持部 [#j4af1ec0] ペンはシンプルに輪ゴムで取り付けている。 #ref(./ペン保持部.JPG,30%,ペン保持部); *** アーム全体 [#w3d38c6e] &ref(2017a/Member/Kenty/Mission1/アーム.JPG,20%,アーム全体); * プログラム [#xa05481a] プログラムについては、変数宣言・マクロ・サブルーチン、メイン関数の順に説明していく。 ** 変数宣言・マクロ・サブルーチン[#f00b6555] #define UD_TIME 100 //ペンの上げ下げのための時間(1秒) int dif_y , dif_x; //現在の場所から次の場所までのX軸方向・Y軸方向の移動時間 int leng_y , leng_x; //線の長さ(時間) sub Set_RU() //ペンを書きはじめの位置にセット<右上> { OnFwd(OUT_A); Wait(dif_y); Off(OUT_A); OnFwd(OUT_C); Wait(dif_x); Off(OUT_C); } sub Set_RD() //ペンを書きはじめの位置にセット<右下> { OnRev(OUT_A); Wait(dif_y); Off(OUT_A); OnFwd(OUT_C); Wait(dif_x); Off(OUT_C); } sub Set_LU() //ペンを書きはじめの位置にセット<左上> { OnFwd(OUT_A); Wait(dif_y); Off(OUT_A); OnRev(OUT_C); Wait(dif_x); Off(OUT_C); } sub Set_LD() //ペンを書きはじめの位置にセット<左下> { OnRev(OUT_A); Wait(dif_y); Off(OUT_A); OnRev(OUT_C); Wait(dif_x); Off(OUT_C); } sub Pen_Up() //ペンを持ち上げる { OnRev(OUT_B); Wait(UD_TIME); Off(OUT_B); } sub Pen_Down() //ペンを下ろす { OnFwd(OUT_B); Wait(UD_TIME); Off(OUT_B); } sub Write_Line_Fwd() //線を引く:正方向(下→上、左→右) { OnRev(OUT_A); Wait(leng_y); Off(OUT_A); OnFwd(OUT_C); Wait(leng_x); Off(OUT_C); } sub Write_Line_Rev() //線を引く:逆方向(上→下、右→左) { OnFwd(OUT_A); Wait(leng_y); Off(OUT_A); OnRev(OUT_C); Wait(leng_x); Off(OUT_C); } グローバル変数とマクロに関しては、コメント文で説明できていると思うので省略する。 ~ サブルーチンに関しては大きく分けて3種類、全部で8個設定している。基本的にこちらもコメント文に書いてあるが、それぞれ説明していこうと思う。 *** Set_RU()・Set_RD()・Set_LU()・Set_LD() [#l97f1441] ペンを各線の書き始めの位置へ移動させる。移動する方向でそれぞれ作っており、右上・右下・左上・左下の4方向で分けている。 *** Pen_Up()・Pen_Down() [#jd6d0f1f] 名前の通りペンの上げ下げを行うためのものである。UD_TIMEを100(1秒)に設定しているので、ペンは90°ほどの角度で上げ下げを行う。 *** Write_Line_Fwd()・Write_Line_Rev() [#z6079570] 線を引くためのものである。ロボットを初めに左下においてから動作を始めるため、左下を原点と考えている。そのため「左から右」と「下から上」を正方向、「右から左」と「上から下」を逆方向としている。 ** メインタスク [#i19640ec] 当たり前のことだが、漢字(他の文字もそうだが...)を書くということは線を引くという動作を繰り返すことである。つまり、毎回行う動作は、向きの違いはあっても基本的には同じ動き(線を引く動作)である。そこで、共通している動作を繰り返すプログラムをベースとして、各線で違うもの(変数の数値や移動方向)だけ場合分けして設定できるようにした。具体的には以下のような繰り返しを行っている。 ~ ペンを持ち上げる→書き始めの位置・線の長さを指定→書き始めの位置へ移動→ペンを下ろす→線を引く(→初めに戻る) ~ 実際に使用したのは次のプログラムである。詳しい説明はプログラムの下に書く。 task main() { int str_cnt=0; //画数 int i=0; //for文用変数 /*-----1画毎ループ 10回繰り返し-----*/ for(i=1;i<11;i++){ str_cnt++; //画数+1→次の画へ /*-----ペンを持ち上げる 1・5・6画目以外-----*/ if(str_cnt!=1){ if(str_cnt!=5){ if(str_cnt!=6){ Pen_Up(); } } } /*-----0.1秒待ち-----*/ Wait(10); /*-----ペンセットの位置・線の長さを指定-----*/ if(str_cnt==1){ dif_x=20; dif_y=100; leng_x=15; leng_y=15; } else if(str_cnt==2){ dif_x=15; dif_y=0; leng_x=15; leng_y=15; } else if(str_cnt==3){ dif_x=10; dif_y=13; leng_x=0; leng_y=90; } else if(str_cnt==4){ dif_x=30; dif_y=105; leng_x=35; leng_y=0; } else if(str_cnt==5){ dif_x=0; dif_y=0; leng_x=0; leng_y=40; } else if(str_cnt==6){ dif_x=0; dif_y=0; leng_x=35; leng_y=0; } else if(str_cnt==7){ dif_x=15; dif_y=20; leng_x=60; leng_y=0; } else if(str_cnt==8){ dif_x=40; dif_y=35; leng_x=20; leng_y=0; } else if(str_cnt==9){ dif_x=35; dif_y=20; leng_x=55; leng_y=0; } else if(str_cnt==10){ dif_x=28; dif_y=100; leng_x=0; leng_y=120; } /*-----0.1秒待ち-----*/ Wait(10); /*-----ペンをセット(書き始めの位置へ移動)-----*/ if(str_cnt==1){Set_RU();} else if(str_cnt==2){Set_RD();} else if(str_cnt==3){Set_RU();} else if(str_cnt==4){Set_RU();} else if(str_cnt==7){Set_LU();} else if(str_cnt==8){Set_LD();} else if(str_cnt==9){Set_LD();} else if(str_cnt==10){Set_LU();} /*-----0.1秒待ち-----*/ Wait(10); /*-----ペンを下ろす(5・6画目はそのまま続けて書く)-----*/ if(str_cnt!=5){ if(str_cnt!=6){ Pen_Down(); } } /*-----0.1秒待ち-----*/ Wait(10); /*-----線描画(1・2画目は斜め、6画目は直線(逆方向)、それ以外は直線(正方向))-----*/ if(str_cnt==1){ OnRev(OUT_A); OnRev(OUT_C); Wait(leng_x); Off(OUT_AC); } else if(str_cnt==2){ OnRev(OUT_A); OnRev(OUT_C); Wait(leng_x); Off(OUT_AC); } else if(str_cnt==6){ Write_Line_Rev(); } else{ Write_Line_Fwd(); } /*-----0.1秒待ち-----*/ Wait(10); } //end for Pen_Up(); //最後にペンを持ち上げて終了 } //end main ~ テキストには載っていなかったが、自分で調べてfor文も使用してプログラムを作成している。for文は全体の繰り返しに使っていて、「律」は10画の漢字のため10回繰り返すようになっている。 ~ for文で1周するたびに変数“str_cnt”に+1することで画数をカウントしている。この値をif文で判断することで、変数へ入れる数値の設定や動作など各線で違う箇所を変えている。 ~ また、4・5・6画目の線はペンを上げる必要が無いのでつなげて書いている。それから、書く動作毎に0.1秒待たせているのは、動きを確認しやすくするためである。 * 考察 [#h1addc95] ** 実際にロボットで書いた漢字「律」 [#rfbb2915] #ref(./漢字「律」.JPG,20%,実際に書いた字) 全体的にはバランス良く字が書けているように思うが、行人偏の斜めの線が歪んでしまったのが何度調整しても直らずとても残念だった。ロボットの振動が完全に抑えられていないことが原因だと思う。アームの支えをさらに改良すれば良くなったかもしれない。それに加えて、X軸方向とY軸方向のモータの動きが完全に同時ではないことも原因の1つかもしれない。 ~ また、偏と旁が上下にずれてしまっているのだが、これは斜めの線の歪みと違い時間があればなんとかなったはずである。完全に時間に余裕を持って製作できなかったことが原因であり、今回の課題の1番の反省点だと思う。もっと計画的に製作を進めれば良かった... * 感想 [#cdec8edc] 課題として解決せずに残ってしまった点や反省点もいくつかあるが、課題1の製作全体で見れば良くできたと感じる。最初の課題だったからなかなかスムーズに作業を進めることができなかったが、課題はあれどもちゃんとしたロボットを製作することができたと思う。 ~ 今回の課題で製作のコツも少しずつだが分かってきたように感じる。今回学んだことを生かして【まとめ】で述べた反省点の「計画的な製作」を次の課題2では実行できるようにしたい。