ロボット

RaspberryPiと3Dプリンターで作るロボットアーム完成編

今回は、前回までに作成したロボットアームの部品を組み合わせてロボットアームを完成させていきます。結果としてロボットアームの作成は失敗でした。ここまで頑張ってきたので、途中まで完成したロボットアームと、それを動かすコードを紹介していこうと思います。

ロボットアームを完成させていく

上の1枚目の写真が途中まで組み立てたロボットアームです。この後に2枚目の写真の部品を取り付けたのですが、先端部分が重すぎたのでサーボモータが支えきれずに倒れてしまいました。

完璧な設計ミスです。途中から少し気づいていましたが、物を掴む部品がでかすぎます。それ以外にも土台の部分をもっと強固に作って、全体を見た時に三角形になるのが理想なのかと思います。

折角、ここまで作ったので1枚目の写真までのロボットアームを動かすコードを書いていこうと思います。

コードを書いてみる

ロボットアームを動かす実験用のプログラムです。コードの一部が改行されて、見にくくなっていますので、コードの右上に別ウィンドでコードが見れるようになります。また、githubにコードをアップしていますので、見てみてください。

https://github.com/eskmoguran/robot-arm/blob/master/Mark001.py#L57

#ロボットアームの実験機Mark001です

import time
import Adafruit_PCA9685
import configparser
import sys

class Mark001:

	def __init__(self):
		#設定ファイルより各関節の現在位置を取得する
		self.config = configparser.ConfigParser()
		self.config.read("./config/position.conf","UTF-8")
		self.channel00 = self.config.get("channel0","now")
		self.channel01 = self.config.get("channel1","now")
		self.channel02 = self.config.get("channel2","now")

		#PCA9685ドライブを準備する
		self.pwm = Adafruit_PCA9685.PCA9685()
		self.pwm.set_pwm_freq(60)

	def readConfigFile(self,channel):
		#現在位置の読み込み
		return int(self.config.get(channel,"now"))

	def writeConfigFile(self,value,channel):
		#現在位置の書き込み
		self.config.set(channel,"now",str(value))
		with open("./config/position.conf","w") as configfile:
			self.config.write(configfile)

	def angleDecomposition(self,angle):
		#90度=375 0度=150 180度=600
		#1度あたり2.5
		#例: angle=60 150+60x2.5=300
		value = 150+int(angle)*2.5
		return value

	def selectChannel(self,channel):
		#チャンネルの実際の番号(整数)を返します
		if channel == "channel0":
			result = 0
		elif channel == "channel1":
			result = 1
		else:
			result = 2
		return result


	def moveServo(self,angle,channel):
		#実際にサーボモータを動かします
		print("サーボモータを動かします")
		servo = self.selectChannel(channel)
		value = self.readConfigFile(channel)
		if self.readConfigFile(channel) < self.angleDecomposition(angle):
			for i in range(int((self.angleDecomposition(angle)-self.readConfigFile(channel))/2)):
				value += 2
				self.pwm.set_pwm(servo,0,value)
				i += 1
				time.sleep(0.002)
		else:
			for i in range(int((self.readConfigFile(channel)-self.angleDecomposition(angle))/2)):
				value -= 2
				self.pwm.set_pwm(servo,0,value)
				i += 1
				time.sleep(0.002)
		print("現在位置を記録しています:"+str(self.angleDecomposition(angle)))
		self.writeConfigFile(int(self.angleDecomposition(angle)),channel)

if __name__ == "__main__":
	mark = Mark001()
	while True:
		print("動かしたいサーボモータのチャンネルを選択してください")
		print("channel0,channel1,channel2")
		print("channel: ")
		channel = input()
		print("channel0の角度を入力してください")
		print("0-180度で入力してください")
		print("angle: ")
		angle = input()
		if angle == "stop":
			break
		elif 0<=int(angle) and int(angle)<=180:
			mark.moveServo(int(angle),str(channel))
			print(type(angle))
		else:
			print("角度を入力するか、stopで終了してください")

上のコードを軽く説明していきます。前回テストを行った時と一緒でpythonで作成しました。

[def __init__(self)]

コンストラクタです。インスタンスを作成時に初めに呼び出されます。configファイルからサーボモータの現在の角度を取得します。設定ファイルは別のconfigフォルダにあります。次にPCA9685ドライブを準備する

[channel0]
now = 175

[channel1]
now = 175

[channel2]
now = 600

[def readConfigFile(self,channel)]

引数で受け取ったサーボモータのチャンネルの現在の角度を設定ファイルから取得します。

[def writeConfigFile(self,value,channel)]

引数で受け取ったサーボモータのチャンネルの現在の角度(value)を設定ファイルに書き込みます。

[def angleDecomposition(self,angle)]

引数で受け取った 角度をサーボモータを動かすように変換します。

[def selectChannel(self,channel)]

引数で受け取ったサーボモータのチャンネルの番号を文字列”channel~”に変換します。
これは設定ファイルの読み書きに使用します。

[def moveServo(self,angle,channel)]

実際にサーボモータを動かすメインの処理を書いています。引数で受け取ったチャンネルのサーボモータを、同じく引数で受け取った角度の分動かします。角度はPCA9685のライブラリで解釈できる値に変換します。変換が終わったら現在位置と比較して処理を分岐させます。このままだとサーボモータを急激に動くので、ループを使って小刻みに動かすようにします。動かし終わったら新たな現在位置を設定ファイルに書き込みます。

[if __name__ == “__main__“]

コマンドラインから動かしたいサーボモータをのチャンネルと角度を入力すると動きます。

反省点

完璧に設計ミスでした。設計する前にしっかりと他の人が作成したロボットアームを関節するべきでした。また、サーボモータが支えきれる重さを計測もするべきでした。

しかし、色々反省点を挙げてみて振り返ってみると、実際に作ったからこそ気づけたと思います。今回は失敗しましたが、またいつかリベンジしようと思います。

次は何を作りましょうかー