【Python】ロボットアームをラズパイで制御してみた

必要なもの

パーツ

部品名用途
Raspberry Pi 3 model B+
https://amzn.to/2JP3w1l
サーボモータの制御
MCP3008
https://amzn.to/30093Ie
アナログ入力
可変抵抗 ✖ 3
https://amzn.to/30ehjAw
サーボモータのコントローラ
ロボットアーム
https://amzn.to/30flZ9r
三軸のトルクの大きいものを選ぶ

※ロボットアームですが、AliExpressというサイトから買ったほうがお得なので、ぜひ興味のある方はそちらを検討されるのがよいかも知れません。しかし、中国から発送されるので、到着までに1週間以上かかります。

金額

ラズパイをお持ちの方なら部品だけで5千円を切るので、自分で3Dプリンタを買ってロボットアームを作るよりも、購入したほうが金額としては安く作れると思います。

組み立て

ロボットアーム

ロボットアームは未完成の状態で送られてきます。

  • サーボモータ ✖ 3
  • ロボットアームの骨格
  • ねじ類

サーボモータ( mg996r )

仕様

トルク   9.4 kgf·cm (4.8 V ), 11 kgf·cm (6 V)

動作電圧 4.8 ~ 7.2 V

動作電流  500 ~ 900 mA (6Vの時)

過負荷電流 2.5A (6V)

PWM信号:周期 50ms

デューティー比 2 ~ 12 %

角度   0 ~ 180 °

データシート より引用

電源が5V以上で、電流がラズパイの許容電流を超えるので、外部電源として単三電池 ✖ 4 で 6 V の電源に接続しました。

ロボットアームの外観

回路

可変抵抗のつまみを回すことによって制御することを目指すので、可変抵抗の真ん中のピンをA/DコンバータであるMCP3008のチャンネルに入力している。

ソースコード

PWMはソフトウェアPWMを利用した。物を挟むことのできる先端のサーボモータだけは他と違い 0 ~ 180 ° まで回すことができないので、丁度よいデューティー比を自分で測定した。

デューティー比
アームが開いているとき7.8%
アームが閉じているとき12%
import RPi.GPIO as GPIO
from gpiozero import MCP3008
import sys
import time
import numpy as np

Vref = 3.33

# MCP3008から入力値を読み取る関数
def analog_read(channel):
    pot = MCP3008(channel)
    volt = pot.value * Vref
    return volt

# 0~3.3Vの値をデューティー比の 2~12%に変換する関数
def mortor_signal(volt):
    sig = []
    #head mortor
    sig.append ( round( ((7.8 - 12.0) / 3.3 ) * volt[0] + 12.0, 1) )
    #middle mortor
    sig.append ( round( ((2.0 - 12.0) / 3.3 ) * volt[1] + 12.0, 1) )
    #botom mortor
    sig.append ( round( ((2.0 - 12.0) / 3.3 ) * volt[2] + 12.0, 1) )

    return sig      # 2 ~ 12 %

#startup
GPIO.setmode(GPIO.BCM)
GPIO.setup(2, GPIO.OUT)
GPIO.setup(3, GPIO.OUT)
GPIO.setup(4, GPIO.OUT)

servo1 = GPIO.PWM(2, 50)
servo2 = GPIO.PWM(3, 50)
servo3 = GPIO.PWM(4, 50)

servo1.start(0)
servo2.start(0)
servo3.start(0)

#一つ前の信号を格納
old_sig = [0, 0, 0]

if __name__== "__main__":
    try:
        while True:
            three_volt = []
            duty_sig = []
            
            filtered_duty_sig = []
            for i in range(3):
                volt = analog_read(i+1)
                three_volt.append(volt)
                time.sleep(0.01)

            print(three_volt)

            duty_sig = mortor_signal(three_volt)

            print(duty_sig)
            if duty_sig[0] != old_sig[0]:
                servo1.ChangeDutyCycle(duty_sig[0])
            if duty_sig[1] != old_sig[1]:
                servo2.ChangeDutyCycle(duty_sig[1])
            if duty_sig[2] != old_sig[2]:
                servo3.ChangeDutyCycle(duty_sig[2])

            old_sig = duty_sig.copy()
            
            time.sleep(0.1)
            
    except KeyboardInterrupt:
        servo.stop()
        GPIO.cleanup()
        sys.exit(0)

完成品

完成品はYoutubeで公開しています。

※2020/3/6 追記

ロボットアーム企画第二弾が完成しました!!

今度は,AI画像認識で制御しました.一段とグレードアップしたので,ぜひ見て下さい!