🦾

Adeeptロボットアームキットを動かした

2022/01/22に公開1

Adeeptロボットアームキットを購入したので、自分用のセットアップの備忘録です。
ついでに、コントローラからの制御を行ったので、その紹介もします。

🏁デモ

きっかけ

Amazonを物色していたら、下記の商品を見つけました。

https://www.amazon.co.jp/gp/product/B086BR2J6H/ref=ox_sc_act_title_1?smid=A392L2974KVICD&psc=1

このへんの商品は、取説などが不親切な場合が多いのですが、
リンクを見る限りドキュメントが充実しているようでしたので購入しました。

資料 - 公式

https://www.adeept.com/learn/detail-31.html

↑ページに、ドキュメントおよびサンプルプログラムが配置されています。

また、組み立ての動画がYoutubeに投稿されています。

https://www.youtube.com/watch?v=JgC8sg4C1Ks

補足

本製品は、2つの組み立て方があります。
マニュアルのPDF上では、"Play1"と"Play2"で表記されています。

  • Play1
    • 3軸で動作
    • ペンを固定し、動作をさせることを想定
  • Play2
    • 5軸で動作
    • アームを制御できる状態

以降、やったことを記載します。

💻セットアップ

組み立て

https://www.youtube.com/watch?v=JgC8sg4C1Ks

↑の動画を見ながら、組み立てを行いました。

作業時に感じたことは以下です。

  • キャプションで指定されているネジと同封のネジとで異なる箇所がある
    • M2.6とM2.5の違いや数が間違っている箇所がありました
    • 動画でどの部品を使っているかを確認しながら、つくりました
  • 電池が18650型の電池だった
    • 3.7Vの18650電池x2を想定されています
    • (ドキュメントより)入力電圧は、6-24Vとなっています
    • ACアダプタから電圧を入力するようにしました
  • 組み立ての途中に電源をいれる必要がある
    • 付属のArduino互換ボードにはテスト用のプログラムが書かれている
    • サーボモータが90度になるようにPWM制御をしている(90度が基準)
  • 動画は全部見なくてよい
    • 動画は、Play1とPlay2の両方が含まれる
    • 今回は、Play1(ペンタイプ)を想定しているため、~13:00ぐらいで終わります

動作の確認

基板に搭載されているアナログメータより、各軸の制御が確認できます。

GUI制御のサンプルプログラムを動かす

https://www.adeept.com/learn/tutorial-410.html

の内容になります。

上記のページのポイントを記載します。

  • ロボットアーム側
    • Arduino基板側には、ArduinoIDEを経由してblock_py.inoを書き込む
  • ホストPC側
    • Pythonプログラム - ./websocket/servosGUI.pyを実行する
    • 下記のGUIが表示される
    • COMポートを指定し、接続する
    • D1/D2/D3のスライドバーを変更すると、各軸が動作する

以上が、サンプルプログラムを動かすまでのセットアップです。

🕹ジョイスティックから制御する

サンプルプログラムには、不要な部分が多いため、
制御の部分だけを整理する上で、ジョイスティックから制御するコードを書きました。

構成

  • ①操作
    • 利用者は、🕹を操作する
    • ラズパイにてキーイベントを取得する
  • ②通信
    • キーイベントに応じて、角度コマンドを送信
  • ③ペン操作
    • 角度コマンドを受信し、各軸を制御

🕹の仕様

🕹は、ロジクールのUSBコントローラを使用しました。

https://www.amazon.co.jp/gp/product/B00CDG799E/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&th=1

各スイッチの割り当ては以下としました。

スイッチ名 制御軸 動作 備考
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 ロボットアーム制御モジュール サンプルプログラムに付属
sample.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()

補足 - ジョイスティック制御の説明

ラズパイからのコントローラの制御については、

https://zenn.dev/kotaproj/books/raspberrypi-tips/viewer/460_kiso_js

にまとめてありますので参考にしてください。

実行例

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

うまく操作すれば、下記の動作となります。

https://twitter.com/tw_kotatu/status/1482500637229469696

さいごに

簡単なコマンドで動作することができるため、使えそうな気はします。
ただ、速い動作をさせると、アーム自体に揺れがあります。
精密な動作を実施するには、固定方法や制御プログラムを検討しないと厳しいという感想です。

ラズパイの活用方法を

https://zenn.dev/kotaproj/books/raspberrypi-tips

としてまとめ中です。

GitHubで編集を提案

Discussion

らいんはるとらいんはると

バッジって、現金じゃないんですよねぇ🍵😅✨
いやぁ、こういう内容あるから、SNSも、止められないですなぁ😏☕🌃❤🎶✨