2016b/Member

概要

今回の課題は書道ロボットである.

一般的なローバーにペンをつけただけでは,H/Wは簡単でもS/Wで困難を極めるので,縦軸を動くロボットと横軸を動くロボット,そしてペンの昇降装置をつくり,それぞれに役割を分担させることにした.こうすることでコーディングが簡単になる.

加えて,このタイプのロボットであれば(理論上は)描画する線の角度なども,バッテリーの電圧に依存することなく常に一定になる(但し最終的な文字の大きさは変化する).

ハードウェアについて

完成したロボット

もともとは自動車工場などで稼働しているような「アームロボット」型のものを作る予定だっただが,部品点数の少なさやS/Wが複雑になりすぎることが判明したので断念した.

かわって,冒頭で記した通り,縦軸(以降Y軸と呼ぶ)を動くローバーロボットに高架を接続し,その上に,横軸(以降X軸と呼ぶ)を動くローバーロボットを走らせる.そのローバーロボットにペンの昇降を制御するアームを取り付け,Y軸移動,X軸移動,ペンの昇降をそれぞれ独立して制御するようにした.

Y軸制御ロボット

Y軸制御ロボット

写真の通り,基本的なローバーロボットに高架を接続したものである.

ローバーロボット本体に関しては途中で曲がらずに,できるかぎり直線的に移動する必要があり,また,高架にアーム付きローバーロボット(重い)が乗ることを考え,できるだけ安定する必要がある.そのためにホイールスペースをできるだけ長くとった.

また,ローバーロボットと反対側を支える支柱はできるだけ滑らかに動作し,引っかかることのないようにしなければならなかったため,あえてタイヤ(ゴム)を外したが,あまり改善されなかった.

高架部分は長いブロックを使用し,重さに耐えられるようにした.途中つなぎ目部分で段差があるが,動作に支障はなかった.

X軸制御/ペン昇降ロボット

X軸制御/ペン昇降ロボット

基本的なローバーロボットであるが,車輪の幅が高架の幅と一致するようになっている.また,動作時の振動や通信ケーブルのねじれによって脱輪することのないように,ロボット下側にガイドを取り付けた.

ガイド

Y軸制御ロボットを作った段階で部品が不足していたため,アーム部分の取り付けにはかなり無理をしている(ただし動作に支障はなかった).

当初は,ペンの昇降は"4211510"と呼ばれる部品(ねじ状の部品)を使い,エレベーターのように行う予定であったが,部品の不足と重量の問題で断念し,かわりにモーターにペンを取り付けるだけのシンプルな構成にした.これによって部品を大幅に節約できるが,ペン先を紙面に対して垂直に当てられないため,ペンを降ろす際の力加減によっては,これが動作時の微妙なずれの原因となるようである.これはS/Wによるキャリブレーションで解決している.

ソフトウェアについて

課題では「7画以上の漢字」を書く必要があるが,H/Wの仕様上斜めに線を描くことが難しい(実際に試したが無視できないほどの誤差が生じてしまった)ので,極力水平・垂直な線の多い文字を選ぶ必要がある.今回は「車」「豆」という文字を選んだ.

以下がそのコード(「車」)である.結果はこちらを参照.

//OUT_A -> Y軸移動(縦)
//OUT_B -> X軸移動(横)
//OUT_C -> Z軸移動(ペン)

#define MP_XY 20				//モーターの強さは20に固定
#define MP_Z 10					//ただしペンの昇降は弱めにする

sub X_ML(int time)				//X軸左方向
{
	OnRev(OUT_B,MP_XY);
	Wait(time);
	Off(OUT_ABC);Wait(1000);
}

sub X_MR(int time)				//X軸右方向
{
	OnFwd(OUT_B,MP_XY);
	Wait(time);
	Off(OUT_ABC);Wait(1000);
}

sub Y_UP(int time)				//Y軸上方向
{
	OnRev(OUT_A,MP_XY);Wait(time);
	Off(OUT_ABC);Wait(1000);
}

sub Y_DWN(int time)				//Y軸下方向
{
	OnFwd(OUT_A,MP_XY);Wait(time);
	Off(OUT_ABC);Wait(1000);
}

sub Z_UP()					//ペンをあげる
{
	RotateMotor(OUT_C,MP_Z,-20);
	Off(OUT_ABC);Wait(1000);
}

sub Z_DWN()					//ペンをおろす
{
	RotateMotor(OUT_C,MP_Z,20);
	Off(OUT_ABC);Wait(1000);
}

task main()
{
	
	/*
	"Z_DWN()"から"Z_UP()"までの動作で線を描画する.
	それ以外の動作は移動のみで,実際に描画はしない.
	
	ペン先を紙面に当てた状態で実行すること.
	*/
	
	Z_UP();
	
	Z_DWN();X_MR(1000);Z_UP();
	
	Y_DWN(200);
	
	Z_DWN();X_ML(1000);Y_DWN(600);Z_UP();
	
	Y_UP(600);X_MR(1000);
	
	Z_DWN();Y_DWN(600);Z_UP();
		
	Y_UP(400);
	
	Z_DWN();X_ML(1200);Z_UP();
		
	Y_DWN(400);
	
	Z_DWN();X_MR(1200);Z_UP();
	
	Y_DWN(300);
		
	Z_DWN();X_ML(1200);Z_UP();
	
	Y_UP(1500);X_MR(600);
	
	Z_DWN();Y_DWN(1600);Z_UP();
}

モーターの対応

//OUT_A -> Y軸移動(縦)
//OUT_B -> X軸移動(横)
//OUT_C -> Z軸移動(ペン)

これは,それぞれの出力が対応するモーターを示している(コメント).

モーターのトルクを定義

#define MP_XY 20				//モーターの強さは20に固定
#define MP_Z 10					//ただしペンの昇降は弱めにする

これは,モーターのトルクをマクロ置換している(MP=Moter Power).

H/Wの動作,特に,ペンの昇降についてはゆっくりと行わないと誤差の原因となる.X軸制御/ペン昇降ロボットについては,あまり高速に動作させると高架から脱輪することもあった.

各種動作の定義

sub X_ML(int time)				//X軸左方向
{
	OnRev(OUT_B,MP_XY);
	Wait(time);
	Off(OUT_ABC);Wait(1000);
}

sub X_MR(int time)				//X軸右方向
{
	OnFwd(OUT_B,MP_XY);
	Wait(time);
	Off(OUT_ABC);Wait(1000);
}

これは,X軸方向の移動をsubroutineとして定義したものである.

動作時間(=移動距離)を引数としている.動作後には1秒間静止するようにしている.これは,振動によるズレを防ぐためである.

以下も同様

sub Y_UP(int time)				//Y軸上方向
{
	OnRev(OUT_A,MP_XY);Wait(time);
	Off(OUT_ABC);Wait(1000);
}

sub Y_DWN(int time)				//Y軸下方向
{
	OnFwd(OUT_A,MP_XY);Wait(time);
	Off(OUT_ABC);Wait(1000);
}

sub Z_UP()					//ペンをあげる
{
	RotateMotor(OUT_C,MP_Z,-20);
	Off(OUT_ABC);Wait(1000);
}

sub Z_DWN()					//ペンをおろす
{
	RotateMotor(OUT_C,MP_Z,20);
	Off(OUT_ABC);Wait(1000);
}

ペンの昇降についてはOnFwd(OnRev)ではなく,回転の角度を指定できるRotateMotorを使用した.

task main()

task main()
{
	
	/*
	"Z_DWN()"から"Z_UP()"までの動作で線を描画する.
	それ以外の動作は移動のみで,実際に描画はしない.
	
	ペン先を紙面に当てた状態で実行すること.
	*/
	
	Z_UP();
	
	Z_DWN();X_MR(1000);Z_UP();
	
	Y_DWN(200);
	
	Z_DWN();X_ML(1000);Y_DWN(600);Z_UP();
	
	Y_UP(600);X_MR(1000);
	
	Z_DWN();Y_DWN(600);Z_UP();
		
	Y_UP(400);
	
	Z_DWN();X_ML(1200);Z_UP();
		
	Y_DWN(400);
	
	Z_DWN();X_MR(1200);Z_UP();
	
	Y_DWN(300);
		
	Z_DWN();X_ML(1200);Z_UP();
	
	Y_UP(1500);X_MR(600);
	
	Z_DWN();Y_DWN(1600);Z_UP();
}

最初はペン先を紙面に当てた状態にしておく.これは,線を描く際に確実にペン先を紙面に当てるためである.プログラムを実行すると同時にペン先は指定した角度(20度)上昇する.

以降,Z_DWN()でペン先が紙面に当たり,Z_UP()でペン先が離れるわけなので,Z_DWN()からZ_UP()で挟まれた部分は実際に紙面に描画され,それ以外は描画されない,ただの移動となる(ペン先は空中を移動する).

注意する点は,特にY軸方向に描画する際に,図のように手前方向へ移動するのはOKだが,奥方向はNGである(線がかすれてしまう).

ペン先の移動

移動量が一致しないところもあるが,これは実際に紙面に描画する際のズレを考慮した結果である.

別のコード

「車」以外にも「豆」という漢字も書くことができた.結果はこちらを参照.

//OUT_A _> Y軸移動(縦)
//OUT_B _> X軸移動(横)
//OUT_C _> Z軸移動(ペン)

#define MP_XY 20				//モーターの強さは20に固定
#define MP_Z 10					//ただしペンの昇降は弱めにする

sub X_ML(int time)				//X軸左方向き
{
	OnRev(OUT_B,MP_XY);
	Wait(time);
	Off(OUT_ABC);Wait(1000);
}

sub X_MR(int time)				//X軸右方向
{
	OnFwd(OUT_B,MP_XY);
	Wait(time);
	Off(OUT_ABC);Wait(1000);
}

sub Y_UP(int time)				//Y軸上方向
{
	OnRev(OUT_A,MP_XY);Wait(time);
	Off(OUT_ABC);Wait(1000);
}

sub Y_DWN(int time)				//Y軸下方向
{
	OnFwd(OUT_A,MP_XY);Wait(time);
	Off(OUT_ABC);Wait(1000);
}

sub Z_UP()					//ペンをあげる
{
	RotateMotor(OUT_C,MP_Z,-20);
	Off(OUT_ABC);Wait(1000);
}

sub Z_DWN()					//ペンをおろす
{
	RotateMotor(OUT_C,MP_Z,20);
	Off(OUT_ABC);Wait(1000);
}

task main()
{
	/*
	"Z_DWN()"から"Z_UP()"までの動作で線を描画する.
	それ以外の動作は移動のみで,実際に描画はしない.
	
	ペン先を紙面に当てた状態で実行すること.
	*/
	
	Z_UP();
	
	Z_DWN();X_MR(1000);Z_UP();
	
	Y_DWN(300);X_ML(300);
	
	Z_DWN();X_ML(700);Y_DWN(400);X_MR(800);Z_UP();
	
	Y_UP(400);
	
	Z_DWN();Y_DWN(400);Z_UP();
	
	X_ML(600);Y_DWN(200);
	
	Z_DWN();Y_DWN(400);Z_UP();
	
	X_MR(500);Y_UP(400);
	
	Z_DWN();Y_DWN(400);Z_UP();
	
	X_ML(800);Y_DWN(200);
	
	Z_DWN();X_MR(1200);Z_UP();
}

プリンターのような動作も

インクジェットプリンターのように動作させ,文字(やイラスト)を描画することもできる.この場合,Y軸制御ロボットがプリンターの紙送り機能を,X軸制御/ペン昇降ロボットがプリンターのヘッドの役割をなす.

この場合,斜めの線や曲線を多用した文字でも容易に描写できる.

下図のように,文字を20x20のドットに分割して考える.

デザイン

以下がそのコードである.結果はこちらを参照.

//OUT_A _> Y軸移動(縦)
//OUT_B _> X軸移動(横)
//OUT_C _> Z軸移動(ペン)

#define MP_XY 20				//モーターの強さは20に固定
#define MP_Z 10					//ただしペンの昇降は弱めにする

sub X_ML(int time)				//X軸左方向に走査
{
	OnRev(OUT_B,MP_XY);
	Wait(time);
	Off(OUT_ABC);Wait(1000);
}

sub X_MR(int time)				//X軸右方向に走査
{
	OnFwd(OUT_B,MP_XY);
	Wait(time);
	Off(OUT_ABC);Wait(1000);
}

sub Y_DWN()					//Y軸方向に1単位進む
{
	OnFwd(OUT_A,MP_XY);Wait(200);
	Off(OUT_ABC);Wait(1000);
}

sub Z_UP()					//ペンをあげる
{
	RotateMotor(OUT_C,MP_Z,-20);
	Off(OUT_ABC);Wait(1000);
}

sub Z_DWN()					//ペンをおろす
{
	RotateMotor(OUT_C,MP_Z,20);
	Off(OUT_ABC);Wait(1000);
}

task main()
{
	Z_UP();
	
	//1行目
	X_ML(2050);
	Y_DWN();
	
	//2行目	
	X_MR(150);
	Z_DWN();X_MR(1800);Z_UP();
	X_MR(100);
	Y_DWN();
	
	//3行目
	X_ML(150);
	Z_DWN();X_ML(1800);Z_UP();
	X_ML(100);
	Y_DWN();
	
	//4行目
	X_MR(50);
	Z_DWN();X_MR(200);Z_UP();
	X_MR(1400);
	Z_DWN();X_MR(200);Z_UP();
	X_MR(100);
	Y_DWN();
	
	//5行目
	X_ML(1350);
	Z_DWN();X_ML(200);Z_UP();
	X_ML(500);
	Y_DWN();
	
	//6行目
	X_MR(450);
	Z_DWN();X_MR(1100);Z_UP();
	X_MR(400);
	Y_DWN();
	
	//7行目
	X_ML(450);
	Z_DWN();X_ML(1100);Z_UP();
	X_ML(400);
	Y_DWN();
	
	//8行目
	X_MR(450);
	Z_DWN();X_MR(200);Z_UP();
	X_MR(1300);
	Y_DWN();
	
	//9行目
	X_ML(1350);
	Z_DWN();X_ML(200);Z_UP();
	X_ML(500);
	Y_DWN();
	
	//10行目
	X_MR(450);
	Z_DWN();X_MR(200);Z_UP();
	X_MR(1300);
	Y_DWN();
	
	//11行目
	X_ML(450);
	Z_DWN();X_ML(1100);Z_UP();
	X_ML(400);
	Y_DWN();
	
	//12行目
	X_MR(450);
	Z_DWN();X_MR(1100);Z_UP();
	X_MR(400);
	Y_DWN();
	
	//13行目
	X_ML(450);
	Z_DWN();X_ML(200);Z_UP();
	X_ML(700);
	Z_DWN();X_ML(200);Z_UP();
	X_ML(500);
	Y_DWN();
	
	//14行目
	X_MR(1350);
	Z_DWN();X_MR(200);Z_UP();
	X_MR(400);
	Y_DWN();
	
	//15行目
	X_ML(250);
	Z_DWN(),X_ML(1600);Z_UP();
	X_ML(200);
	Y_DWN();
	
	//16行目
	X_MR(150);
	Z_DWN(),X_MR(1600);Z_UP();
	X_MR(200);
	Y_DWN();
	
	//17行目
	X_ML(450);
	Z_DWN(),X_ML(200);Z_UP();
	X_ML(1400);
	Y_DWN();
	
	//18行目
	X_MR(750);
	Z_DWN(),X_MR(800);Z_UP();
	X_MR(400);
	Y_DWN();
	
	//19行目
	X_ML(450);
	Z_DWN(),X_ML(800);Z_UP();
	X_ML(800);
	Y_DWN();
	
	//20行目
	X_MR(1950);
}

結果

「豆」

デザイン

「車」

デザイン

「写」

デザイン

走査線の間隔が広いのでわかりにくいが,以下のように「写」と描画されている.Y軸の間隔をもっと小さくすればよいが,そこまで細かい制御はできなかった.

デザイン

感想と反省

mindstormシリーズは,実は小学生の時に使ったことがあり,簡単な茶運び人形程度のものであれば作ったことがあった.しかしその際はGUIでコードの記述を行っていたのに対し,今回はCライクな言語で記述する必要があった.GUIに比べて動作が視覚的に確認しづらいという点では苦労したが,プログラミングに対する理解が深まった.

H/Wでは,特に動作毎の微妙な誤差に悩まされたが,それも部品の調整やS/Wの調整で減らすことができた.


添付ファイル: fileFig_008.JPG 235件 [詳細] fileFig_010.JPG 257件 [詳細] fileFig_009.JPG 201件 [詳細] fileFig_007.JPG 254件 [詳細] fileFig_006.JPG 256件 [詳細] fileFig_005.JPG 290件 [詳細] fileFig_004.JPG 305件 [詳細] fileFig_003.JPG 309件 [詳細] fileFig_002.JPG 333件 [詳細] fileFig_001.JPG 366件 [詳細]

トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-11-08 (火) 18:08:37