#はじめに
ロボットアームキットを組立てて動かしてみました。
GUIを作って簡単に動かせるようにしました。
#構成
・ロボットアームキット
DiyStudio 6自由度ロボットアームDIYキット
・PCA9685
HiLetgo PCA9685
・外部電源
SUCCUL ACアダプター 5V 4A
Kabenjee DC電源コネクタ ジャック コネクタ
・Arduino
ELEGOO Arduino用UNO R3スターターキット
ELEGOO 120pcs多色デュポンワイヤー
#組立、配線
ロボットアームの組立ては同封の説明書を参考に組み立てます。
(組み立てる時はサーボモータの原点位置を把握して、動かしたときに干渉しないように注意します。)
サーボモータ、PCA9685、Arduinoの配線はこちらの方を参考にさせてもらいました。
サーボモータドライバ(PCA9685)とArduinoを用いて複数(12個)のサーボモータ(mg996r)を動かす
#プログラム
・動作環境
Windows10 Home
Python 3.7.2
Arduino IDE 1.8.13
Arduino Uno R3
・Arduino
Arduinoに書き込むコードはこちらの方を参考にしました。
Arduinoで複数のサーボを動かす(PCA9685)
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
#define MIN 150
#define MAX 600
Adafruit_PWMServoDriver PWM_SERVO = Adafruit_PWMServoDriver(0x40);
void setup() {
Serial.begin(9600);
PWM_SERVO.begin();
PWM_SERVO.setPWMFreq(50);
}
void loop() {
if(Serial.available()> 1){
int SERVO_NUMBER;
int SERVO_ANGLE;
SERVO_NUMBER = Serial.read();
if(SERVO_NUMBER > 199){
SERVO_ANGLE = Serial.read();
if(SERVO_NUMBER==200){SERVO_MOVE(0, SERVO_ANGLE);}
if(SERVO_NUMBER==201){SERVO_MOVE(1, SERVO_ANGLE);}
if(SERVO_NUMBER==202){SERVO_MOVE(2, SERVO_ANGLE);}
if(SERVO_NUMBER==203){SERVO_MOVE(3, SERVO_ANGLE);}
if(SERVO_NUMBER==204){SERVO_MOVE(4, SERVO_ANGLE);}
if(SERVO_NUMBER==205){SERVO_MOVE(5, SERVO_ANGLE);}
}
delay(200);
}
}
void SERVO_MOVE(int ch, int ang){
ang = map(ang, 0, 180, MIN, MAX);
PWM_SERVO.setPWM(ch, 0, ang);
}
・Python
GUIの作成にはtkinterを利用しました。
arduinoとはシリアル通信を利用します。pyserialをpipでインストールします。
pipの使い方
pyserial 3.5
pythonコード
import tkinter as tk
import serial, time
from functools import partial
# シリアル通信準備
print("Open Port")
ser =serial.Serial("COM3", 9600)
time.sleep(1.5)
# ウィンドウの作成
body = tk.Tk()
body.title("robot_control_GUI")
body.geometry("700x550")
#servo_0--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
# 上2ボタンの押したときの動作
x_position_servo_0 = 60
def botan_up_2(servo_num):
if int(label_servo_0_angle["text"]) < 170:
#ラベルの値を取得してint型に変換して、+10して返す
label_servo_0_angle["text"] = int(label_servo_0_angle["text"]) + 10
servo_move(servo_num,int(label_servo_0_angle["text"]))
# 上2ボタンの作成
bota_up_2 = tk.Button(text ='▲▲',width = 7,height = 3,command = partial(botan_up_2,0))
bota_up_2.place(x=x_position_servo_0,y=0)
# 上1ボタンの押したときの動作
def botan_up(servo_num):
if int(label_servo_0_angle["text"]) < 179:
#ラベルの値を取得してint型に変換して、+1して返す
label_servo_0_angle["text"] = int(label_servo_0_angle["text"]) + 1
servo_move(servo_num,int(label_servo_0_angle["text"]))
# 上1ボタンの作成
bota_up = tk.Button(text ='▲',width = 7,height = 3,command = partial(botan_up,0))
bota_up.place(x=x_position_servo_0,y=60)
# 下1ボタンの押したときの動作
def botan_down(servo_num):
if int(label_servo_0_angle["text"]) > 0:
#ラベルの値を取得してint型に変換して、-1して返す
label_servo_0_angle["text"] = int(label_servo_0_angle["text"]) - 1
servo_move(servo_num,int(label_servo_0_angle["text"]))
# 下1ボタンの作成
bota_down = tk.Button(text ='▼',width = 7,height = 3,command = partial(botan_down,0))
bota_down.place(x=x_position_servo_0,y=120)
# 下2ボタンの押したときの動作
def botan_down_2(servo_num):
if int(label_servo_0_angle["text"]) > 10:
#ラベルの値を取得してint型に変換して、-10して返す
label_servo_0_angle["text"] = int(label_servo_0_angle["text"]) - 10
servo_move(servo_num,int(label_servo_0_angle["text"]))
# 下2ボタンの作成
bota_down_2 = tk.Button(text ='▼▼',width = 7,height = 3,command = partial(botan_down_2,0))
bota_down_2.place(x=x_position_servo_0,y=180)
# 「servo_0」の角度の表示
label_servo_0_angle = tk.Label(text="90", borderwidth=2, relief="sunken")
label_servo_0_angle.place(x=x_position_servo_0, y=240, width=60, height=20)
# 「servo_0」ラベルの作成
label_servo_0 = tk.Label(text="servo_0")
label_servo_0.place(x=x_position_servo_0,y=260)
#----------------------------------------------------------------------------------------------------------
#servo_1----------------------------------------------------------------------------------------------------------
# 上2ボタンの押したときの動作
x_position_servo_1 = 150
def botan_up_2(servo_num):
if int(label_servo_1_angle["text"]) < 170:
#ラベルの値を取得してint型に変換して、+10して返す
label_servo_1_angle["text"] = int(label_servo_1_angle["text"]) + 10
servo_move(servo_num,int(label_servo_1_angle["text"]))
# 上2ボタンの作成
bota_up_2 = tk.Button(text ='▲▲',width = 7,height = 3,command = partial(botan_up_2,1))
bota_up_2.place(x=x_position_servo_1,y=0)
# 上1ボタンの押したときの動作
def botan_up(servo_num):
if int(label_servo_1_angle["text"]) < 179:
#ラベルの値を取得してint型に変換して、+1して返す
label_servo_1_angle["text"] = int(label_servo_1_angle["text"]) + 1
servo_move(servo_num,int(label_servo_1_angle["text"]))
# 上1ボタンの作成
bota_up = tk.Button(text ='▲',width = 7,height = 3,command = partial(botan_up,1))
bota_up.place(x=x_position_servo_1,y=60)
# 下1ボタンの押したときの動作
def botan_down(servo_num):
if int(label_servo_1_angle["text"]) > 0:
#ラベルの値を取得してint型に変換して、-1して返す
label_servo_1_angle["text"] = int(label_servo_1_angle["text"]) - 1
servo_move(servo_num,int(label_servo_1_angle["text"]))
# 下1ボタンの作成
bota_down = tk.Button(text ='▼',width = 7,height = 3,command = partial(botan_down,1))
bota_down.place(x=x_position_servo_1,y=120)
# 下2ボタンの押したときの動作
def botan_down_2(servo_num):
if int(label_servo_1_angle["text"]) > 10:
#ラベルの値を取得してint型に変換して、-10して返す
label_servo_1_angle["text"] = int(label_servo_1_angle["text"]) - 10
servo_move(servo_num,int(label_servo_1_angle["text"]))
# 下2ボタンの作成
bota_down_2 = tk.Button(text ='▼▼',width = 7,height = 3,command = partial(botan_down_2,1))
bota_down_2.place(x=x_position_servo_1,y=180)
# 「servo_1」の角度の表示
label_servo_1_angle = tk.Label(text="90", borderwidth=2, relief="sunken")
label_servo_1_angle.place(x=x_position_servo_1, y=240, width=60, height=20)
# 「servo_1」ラベルの作成
label_servo_1 = tk.Label(text="servo_1")
label_servo_1.place(x=x_position_servo_1,y=260)
#----------------------------------------------------------------------------------------------------------
#servo_2----------------------------------------------------------------------------------------------------------
# 上2ボタンの押したときの動作
x_position_servo_2 = 240
def botan_up_2(servo_num):
if int(label_servo_2_angle["text"]) < 170:
#ラベルの値を取得してint型に変換して、+10して返す
label_servo_2_angle["text"] = int(label_servo_2_angle["text"]) + 10
servo_move(servo_num,int(label_servo_2_angle["text"]))
# 上2ボタンの作成
bota_up_2 = tk.Button(text ='▲▲',width = 7,height = 3,command = partial(botan_up_2,2))
bota_up_2.place(x=x_position_servo_2,y=0)
# 上1ボタンの押したときの動作
def botan_up(servo_num):
if int(label_servo_2_angle["text"]) < 179:
#ラベルの値を取得してint型に変換して、+1して返す
label_servo_2_angle["text"] = int(label_servo_2_angle["text"]) + 1
servo_move(servo_num,int(label_servo_2_angle["text"]))
# 上1ボタンの作成
bota_up = tk.Button(text ='▲',width = 7,height = 3,command = partial(botan_up,2))
bota_up.place(x=x_position_servo_2,y=60)
# 下1ボタンの押したときの動作
def botan_down(servo_num):
if int(label_servo_2_angle["text"]) > 0:
#ラベルの値を取得してint型に変換して、-1して返す
label_servo_2_angle["text"] = int(label_servo_2_angle["text"]) - 1
servo_move(servo_num,int(label_servo_2_angle["text"]))
# 下1ボタンの作成
bota_down = tk.Button(text ='▼',width = 7,height = 3,command = partial(botan_down,2))
bota_down.place(x=x_position_servo_2,y=120)
# 下2ボタンの押したときの動作
def botan_down_2(servo_num):
if int(label_servo_2_angle["text"]) > 10:
#ラベルの値を取得してint型に変換して、-10して返す
label_servo_2_angle["text"] = int(label_servo_2_angle["text"]) - 10
servo_move(servo_num,int(label_servo_2_angle["text"]))
# 下2ボタンの作成
bota_down_2 = tk.Button(text ='▼▼',width = 7,height = 3,command = partial(botan_down_2,2))
bota_down_2.place(x=x_position_servo_2,y=180)
# 「servo_2」の角度の表示
label_servo_2_angle = tk.Label(text="90", borderwidth=2, relief="sunken")
label_servo_2_angle.place(x=x_position_servo_2, y=240, width=60, height=20)
# 「servo_2」ラベルの作成
label_servo_2 = tk.Label(text="servo_2")
label_servo_2.place(x=x_position_servo_2,y=260)
#----------------------------------------------------------------------------------------------------------
#servo_3----------------------------------------------------------------------------------------------------------
# 上2ボタンの押したときの動作
x_position_servo_3 = 330
def botan_up_2(servo_num):
if int(label_servo_3_angle["text"]) < 170:
#ラベルの値を取得してint型に変換して、+10して返す
label_servo_3_angle["text"] = int(label_servo_3_angle["text"]) + 10
servo_move(servo_num,int(label_servo_3_angle["text"]))
# 上2ボタンの作成
bota_up_2 = tk.Button(text ='▲▲',width = 7,height = 3,command = partial(botan_up_2,3))
bota_up_2.place(x=x_position_servo_3,y=0)
# 上1ボタンの押したときの動作
def botan_up(servo_num):
if int(label_servo_3_angle["text"]) < 179:
#ラベルの値を取得してint型に変換して、+1して返す
label_servo_3_angle["text"] = int(label_servo_3_angle["text"]) + 1
servo_move(servo_num,int(label_servo_3_angle["text"]))
# 上1ボタンの作成
bota_up = tk.Button(text ='▲',width = 7,height = 3,command = partial(botan_up,3))
bota_up.place(x=x_position_servo_3,y=60)
# 下1ボタンの押したときの動作
def botan_down(servo_num):
if int(label_servo_3_angle["text"]) > 0:
#ラベルの値を取得してint型に変換して、-1して返す
label_servo_3_angle["text"] = int(label_servo_3_angle["text"]) - 1
servo_move(servo_num,int(label_servo_3_angle["text"]))
# 下1ボタンの作成
bota_down = tk.Button(text ='▼',width = 7,height = 3,command = partial(botan_down,3))
bota_down.place(x=x_position_servo_3,y=120)
# 下2ボタンの押したときの動作
def botan_down_2(servo_num):
if int(label_servo_3_angle["text"]) > 10:
#ラベルの値を取得してint型に変換して、-10して返す
label_servo_3_angle["text"] = int(label_servo_3_angle["text"]) - 10
servo_move(servo_num,int(label_servo_3_angle["text"]))
# 下2ボタンの作成
bota_down_2 = tk.Button(text ='▼▼',width = 7,height = 3,command = partial(botan_down_2,3))
bota_down_2.place(x=x_position_servo_3,y=180)
# 「servo_3」の角度の表示
label_servo_3_angle = tk.Label(text="90", borderwidth=2, relief="sunken")
label_servo_3_angle.place(x=x_position_servo_3, y=240, width=60, height=20)
# 「servo_3」ラベルの作成
label_servo_3 = tk.Label(text="servo_3")
label_servo_3.place(x=x_position_servo_3,y=260)
#----------------------------------------------------------------------------------------------------------
#servo_4----------------------------------------------------------------------------------------------------------
# 上2ボタンの押したときの動作
x_position_servo_4 = 420
def botan_up_2(servo_num):
if int(label_servo_4_angle["text"]) < 170:
#ラベルの値を取得してint型に変換して、+10して返す
label_servo_4_angle["text"] = int(label_servo_4_angle["text"]) + 10
servo_move(servo_num,int(label_servo_4_angle["text"]))
# 上2ボタンの作成
bota_up_2 = tk.Button(text ='▲▲',width = 7,height = 3,command = partial(botan_up_2,4))
bota_up_2.place(x=x_position_servo_4,y=0)
# 上1ボタンの押したときの動作
def botan_up(servo_num):
if int(label_servo_4_angle["text"]) < 179:
#ラベルの値を取得してint型に変換して、+1して返す
label_servo_4_angle["text"] = int(label_servo_4_angle["text"]) + 1
servo_move(servo_num,int(label_servo_4_angle["text"]))
# 上1ボタンの作成
bota_up = tk.Button(text ='▲',width = 7,height = 3,command = partial(botan_up,4))
bota_up.place(x=x_position_servo_4,y=60)
# 下1ボタンの押したときの動作
def botan_down(servo_num):
if int(label_servo_4_angle["text"]) > 0:
#ラベルの値を取得してint型に変換して、-1して返す
label_servo_4_angle["text"] = int(label_servo_4_angle["text"]) - 1
servo_move(servo_num,int(label_servo_4_angle["text"]))
# 下1ボタンの作成
bota_down = tk.Button(text ='▼',width = 7,height = 3,command = partial(botan_down,4))
bota_down.place(x=x_position_servo_4,y=120)
# 下2ボタンの押したときの動作
def botan_down_2(servo_num):
if int(label_servo_4_angle["text"]) > 10:
#ラベルの値を取得してint型に変換して、-10して返す
label_servo_4_angle["text"] = int(label_servo_4_angle["text"]) - 10
servo_move(servo_num,int(label_servo_4_angle["text"]))
# 下2ボタンの作成
bota_down_2 = tk.Button(text ='▼▼',width = 7,height = 3,command = partial(botan_down_2,4))
bota_down_2.place(x=x_position_servo_4,y=180)
# 「servo_4」の角度の表示
label_servo_4_angle = tk.Label(text="90", borderwidth=2, relief="sunken")
label_servo_4_angle.place(x=x_position_servo_4, y=240, width=60, height=20)
# 「servo_4」ラベルの作成
label_servo_4 = tk.Label(text="servo_4")
label_servo_4.place(x=x_position_servo_4,y=260)
#----------------------------------------------------------------------------------------------------------
#servo_5----------------------------------------------------------------------------------------------------------
# 上2ボタンの押したときの動作
x_position_servo_5 = 510
def botan_up_2(servo_num):
if int(label_servo_5_angle["text"]) < 50:
#ラベルの値を取得してint型に変換して、+10して返す
label_servo_5_angle["text"] = int(label_servo_5_angle["text"]) + 10
servo_move(servo_num,int(label_servo_5_angle["text"]))
# 上2ボタンの作成
bota_up_2 = tk.Button(text ='▲▲',width = 7,height = 3,command = partial(botan_up_2,5))
bota_up_2.place(x=x_position_servo_5,y=0)
# 上1ボタンの押したときの動作
def botan_up(servo_num):
if int(label_servo_5_angle["text"]) < 59:
#ラベルの値を取得してint型に変換して、+1して返す
label_servo_5_angle["text"] = int(label_servo_5_angle["text"]) + 1
servo_move(servo_num,int(label_servo_5_angle["text"]))
# 上1ボタンの作成
bota_up = tk.Button(text ='▲',width = 7,height = 3,command = partial(botan_up,5))
bota_up.place(x=x_position_servo_5,y=60)
# 下1ボタンの押したときの動作
def botan_down(servo_num):
if int(label_servo_5_angle["text"]) > 0:
#ラベルの値を取得してint型に変換して、-1して返す
label_servo_5_angle["text"] = int(label_servo_5_angle["text"]) - 1
servo_move(servo_num,int(label_servo_5_angle["text"]))
# 下1ボタンの作成
bota_down = tk.Button(text ='▼',width = 7,height = 3,command = partial(botan_down,5))
bota_down.place(x=x_position_servo_5,y=120)
# 下2ボタンの押したときの動作
def botan_down_2(servo_num):
if int(label_servo_5_angle["text"]) > 10:
#ラベルの値を取得してint型に変換して、-10して返す
label_servo_5_angle["text"] = int(label_servo_5_angle["text"]) - 10
servo_move(servo_num,int(label_servo_5_angle["text"]))
# 下2ボタンの作成
bota_down_2 = tk.Button(text ='▼▼',width = 7,height = 3,command = partial(botan_down_2,5))
bota_down_2.place(x=x_position_servo_5,y=180)
# 「servo_5」の角度の表示
label_servo_5_angle = tk.Label(text="0", borderwidth=2, relief="sunken")
label_servo_5_angle.place(x=x_position_servo_5, y=240, width=60, height=20)
# 「servo_5」ラベルの作成
label_servo_5 = tk.Label(text="servo_5")
label_servo_5.place(x=x_position_servo_5,y=260)
#----------------------------------------------------------------------------------------------------------
def servo_move(servo_num,servo_angle):
#servoは200からカウントすることとする
#サーボ番号と角度がバッティングすることはない
count_servo = 200 + servo_num
servo_id = (count_servo).to_bytes(1, 'big')
servo_angle = (servo_angle).to_bytes(1, 'big')
ser.write(servo_id)
ser.write(servo_angle)
#実行内容記述_終了-----------------------------------------------------
# イベントループ
body.mainloop()
print("Close Port")
ser.close()
ボタンを押したときの移動量
button | angle |
---|---|
▲▲ | +10 |
▲ | +1 |
▼ | -1 |
▼▼ | -10 |
各サーボの角度
servo | min | max | default |
---|---|---|---|
servo_0 | 0 | 179 | 90 |
servo_1 | 0 | 179 | 90 |
servo_2 | 0 | 179 | 90 |
servo_3 | 0 | 179 | 90 |
servo_4 | 0 | 179 | 90 |
servo_5 | 0 | 59 | 0 |
#終わりに
GUIから動かしている記事が少なかったので、やってみました。
GUIで動かせると直感的に操作できるので、簡単に動かせるようになりました。
#参考
arduino ide ポートの指定
Arduinoライブラリのインストール
arduino Adafruit_PWMServoDriver