Adeeptロボットアームキットを動かした
Adeeptロボットアームキットを購入したので、自分用のセットアップの備忘録です。
ついでに、コントローラからの制御を行ったので、その紹介もします。
🏁デモ
きっかけ
Amazonを物色していたら、下記の商品を見つけました。
このへんの商品は、取説などが不親切な場合が多いのですが、
リンクを見る限りドキュメントが充実しているようでしたので購入しました。
資料 - 公式
↑ページに、ドキュメントおよびサンプルプログラムが配置されています。
また、組み立ての動画がYoutubeに投稿されています。
補足
本製品は、2つの組み立て方があります。
マニュアルのPDF上では、"Play1"と"Play2"で表記されています。
- Play1
- 3軸で動作
- ペンを固定し、動作をさせることを想定
- Play2
- 5軸で動作
- アームを制御できる状態
以降、やったことを記載します。
💻セットアップ
組み立て
↑の動画を見ながら、組み立てを行いました。
作業時に感じたことは以下です。
- キャプションで指定されているネジと同封のネジとで異なる箇所がある
- M2.6とM2.5の違いや数が間違っている箇所がありました
- 動画でどの部品を使っているかを確認しながら、つくりました
- 電池が18650型の電池だった
- 3.7Vの18650電池x2を想定されています
- (ドキュメントより)入力電圧は、6-24Vとなっています
- ACアダプタから電圧を入力するようにしました
- 組み立ての途中に電源をいれる必要がある
- 付属のArduino互換ボードにはテスト用のプログラムが書かれている
- サーボモータが90度になるようにPWM制御をしている(90度が基準)
- 動画は全部見なくてよい
- 動画は、Play1とPlay2の両方が含まれる
- 今回は、Play1(ペンタイプ)を想定しているため、~13:00ぐらいで終わります
動作の確認
基板に搭載されているアナログメータより、各軸の制御が確認できます。
GUI制御のサンプルプログラムを動かす
の内容になります。
上記のページのポイントを記載します。
- ロボットアーム側
- Arduino基板側には、ArduinoIDEを経由してblock_py.inoを書き込む
- ホストPC側
- Pythonプログラム - ./websocket/servosGUI.pyを実行する
- 下記のGUIが表示される
- COMポートを指定し、接続する
- D1/D2/D3のスライドバーを変更すると、各軸が動作する
以上が、サンプルプログラムを動かすまでのセットアップです。
🕹ジョイスティックから制御する
サンプルプログラムには、不要な部分が多いため、
制御の部分だけを整理する上で、ジョイスティックから制御するコードを書きました。
構成
- ①操作
- 利用者は、🕹を操作する
- ラズパイにてキーイベントを取得する
- ②通信
- キーイベントに応じて、角度コマンドを送信
- ③ペン操作
- 角度コマンドを受信し、各軸を制御
🕹の仕様
🕹は、ロジクールのUSBコントローラを使用しました。
各スイッチの割り当ては以下としました。
スイッチ名 | 制御軸 | 動作 | 備考 |
---|---|---|---|
Aボタン | A1 | 現在位置から+10度 | - |
Bボタン | A1 | 現在位置から-10度 | - |
Yボタン | A2 | 現在位置から+10度 | - |
Xボタン | A2 | 現在位置から-10度 | - |
Lボタン | A0 | 現在位置から+10度 | - |
Rボタン | A0 | 現在位置から-10度 | - |
アナログスティック-右 | A0 | 0 - 180度で絶対値指定 | ニュートラルが90度 |
アナログ-LT | A2 | 90 - 180度で絶対値指定 | ニュートラルが90度 |
アナログ-RT | A1 | 0 - 90度で絶対値指定 | ニュートラルが90度 |
上記以外のボタンは、未使用です。
コード
Arduino側
サンプルと同じ、block_py.inoを使用します。
コードに変更はありません。
ラズパイ側
ファイル構成は以下です。
ファイル | 内容 | 備考 |
---|---|---|
sample.py | メインプログラム | 🕹のイベント処理 |
Adeept.py | ロボットアーム制御モジュール | サンプルプログラムに付属 |
import json
from json.tool import main
import os
import time
import struct
import Adeept
# device file
COM_NAME = "/dev/ttyUSB0"
DEVICE_PATH = "/dev/input/js0"
EVENT_FORMAT = "LhBB"
EVENT_SIZE = struct.calcsize(EVENT_FORMAT)
def main():
# 初期化
com = COM_NAME
Adeept.com_init(com, 115200, 1)
Adeept.wiat_connect()
Adeept.three_function("'servo_attach'", 0, 9)
Adeept.three_function("'servo_attach'", 1, 6)
Adeept.three_function("'servo_attach'", 2, 5)
Adeept.three_function("'servo_attach'", 3, 3)
Adeept.three_function("'servo_attach'", 4, 11)
print(com + ':Succes')
time.sleep(0.5)
# 角度の計算
lambda_ana2deg_a0 = lambda val : 180 - (90 * (val + 32767)//0x8000)
lambda_ana2deg_a1 = lambda val : 90 - 90 * (val + 32767)//0xFFFF
lambda_ana2deg_a2 = lambda val : 180 - (90 - 90 * (val + 32767)//0xFFFF)
last_a0_deg = 90
last_a1_deg = 90
last_a2_deg = 90
with open(DEVICE_PATH, "rb") as device:
while True:
event = device.read(EVENT_SIZE)
if event is not None:
(js_time, js_val, js_type, js_num) = struct.unpack(EVENT_FORMAT, event)
print( "{0}, {1}, {2}, {3}".format( js_time, js_val, js_type, js_num ) )
# analog - RT
if js_type == 2 and js_num == 5:
deg = lambda_ana2deg_a1(js_val)
if last_a1_deg != deg:
Adeept.three_function("'servo_write'", 1, deg)
last_a1_deg = deg
# analog - LT
if js_type == 2 and js_num == 2:
deg = lambda_ana2deg_a2(js_val)
if last_a2_deg != deg:
Adeept.three_function("'servo_write'", 2, deg)
last_a2_deg = deg
# analog - right
if js_type == 2 and js_num == 3:
deg = lambda_ana2deg_a0(js_val)
if last_a0_deg != deg:
Adeept.three_function("'servo_write'", 0, deg)
last_a0_deg = deg
# B Button
if js_val == 1 and js_type == 1 and js_num == 1:
deg = 0 if last_a1_deg < 10 else last_a1_deg - 10
if last_a1_deg != deg:
Adeept.three_function("'servo_write'", 1, deg)
last_a1_deg = deg
# A Button
if js_val == 1 and js_type == 1 and js_num == 0:
deg = 180 if last_a1_deg > 170 else last_a1_deg + 10
if last_a1_deg != deg:
Adeept.three_function("'servo_write'", 1, deg)
last_a1_deg = deg
# Y Button
if js_val == 1 and js_type == 1 and js_num == 3:
deg = 180 if last_a2_deg > 170 else last_a2_deg + 10
if last_a2_deg != deg:
Adeept.three_function("'servo_write'", 2, deg)
last_a2_deg = deg
# X Button
if js_val == 1 and js_type == 1 and js_num == 2:
deg = 0 if last_a2_deg < 10 else last_a2_deg - 10
if last_a2_deg != deg:
Adeept.three_function("'servo_write'", 2, deg)
last_a2_deg = deg
# L Button
if js_val == 1 and js_type == 1 and js_num == 4:
deg = 180 if last_a0_deg > 170 else last_a0_deg + 10
if last_a0_deg != deg:
Adeept.three_function("'servo_write'", 0, deg)
last_a0_deg = deg
# R Button
if js_val == 1 and js_type == 1 and js_num == 5:
deg = 0 if last_a0_deg < 10 else last_a0_deg - 10
if last_a0_deg != deg:
Adeept.three_function("'servo_write'", 0, deg)
last_a0_deg = deg
return
if __name__ == "__main__":
main()
補足 - ジョイスティック制御の説明
ラズパイからのコントローラの制御については、
にまとめてありますので参考にしてください。
実行例
joystickのイベントを表示しています。
(env) $ python sample.py
/dev/ttyUSB0:Succes
44966390, 0, 129, 0
44966390, 0, 129, 1
44966390, 0, 129, 2
44966390, 0, 129, 3
44966390, 0, 129, 4
44966390, 0, 129, 5
44966390, 0, 129, 6
44966390, 0, 129, 7
44966390, 0, 129, 8
44966390, 0, 129, 9
44966390, 0, 129, 10
44966390, 0, 130, 0
44966390, -2, 130, 1
44966390, -32767, 130, 2
44966390, 0, 130, 3
44966390, -2, 130, 4
44966390, -32767, 130, 5
44966390, 0, 130, 6
44966390, 0, 130, 7
44966400, -3628, 2, 3
44966400, 0, 2, 3
44972100, 2331, 2, 3
44972110, 3626, 2, 3
44972120, 4921, 2, 3
44972130, 6475, 2, 3
44972130, 8029, 2, 3
44972140, 9583, 2, 3
44972150, 10878, 2, 3
44972160, 11656, 2, 3
44972160, 12433, 2, 3
44972170, 12692, 2, 3
44972180, 12951, 2, 3
44972190, 13210, 2, 3
44972250, 10101, 2, 3
44972250, 8547, 2, 3
44972260, 6993, 2, 3
44972270, 5439, 2, 3
44972270, 3626, 2, 3
44972280, 2072, 2, 3
44972290, 518, 2, 3
44972300, 0, 2, 3
うまく操作すれば、下記の動作となります。
さいごに
簡単なコマンドで動作することができるため、使えそうな気はします。
ただ、速い動作をさせると、アーム自体に揺れがあります。
精密な動作を実施するには、固定方法や制御プログラムを検討しないと厳しいという感想です。
ラズパイの活用方法を
としてまとめ中です。
Discussion
バッジって、現金じゃないんですよねぇ🍵😅✨
いやぁ、こういう内容あるから、SNSも、止められないですなぁ😏☕🌃❤🎶✨