コスパ最強!?ロボットアームの作り方_その⑤_プログラム

このサイトはアフィリエイト広告を含みます
IT・ブログ

プログラムについて

それでは最後にプログラムの説明をします。

最初に断って置きますと今回紹介するプログラムは完璧なものではなく、多々改善の余地があります。

具体的には、サーボモーターを速度制御ができるようにしたり、逆運動学を利用して、より直感的に動かせるようにしたり、やれることは沢山あります。

しかし、そういった部分はより高度な機能になるのと、追加したい機能が人によって違うと思うので、この記事では、基礎的な所にとどめたいと思います。

それでも下記記事で紹介した動作はちゃんとできるので、参考にしていただけると幸いです。

コスパ最強!? ロボットアームの作り方_その①
自作ロボットアームの紹介本格的なロボットアームが欲しい!制御方法を勉強してみたい!と思っても産業用のロボットアームは、個人で扱うには高額な商品です。しかし、今は便利な時代になったもので、学習用のものであれば、そこそこ本格的なロボットアームが...

もしかしたら今後アップグレードしたコードを追加するかもしれませんので、ご了承ください。

操作方法について

動画でもご紹介しましたが、このロボットアームはPS4のコントローラーで操作します。

下記手順で操作できるようにプログラムを作っていますので、参考にしてください。

プログラムのソースコードは記事の後半に載せています。

PS4コントローラーとArduinoのリンク

PS4コントローラーとArduinoのはBluetoothで通信をしています。

通信を始めるには、PS4コントローラーのSHAREボタンとPSボタンを長押ししてください。

PS4コントローラーは、リンク中に青色で点滅し、通信が始まると青色で光ります。

ジョイスティックの動作

このプログラムでは、ジョイステックの操作によって、サーボモーター1から4を動かします。

ジョイスティックとサーボモーターの対応は画像のとおりです。

LRボタンの動作

ロボットアームのハンド部分は、LRボタンで動かします。

L1、R1ボタンが、手首部分を45度ずつ回転操作で、L2、R2ボタンがハンドの開閉操作です。

リセットボタン

ロボットアームを終了させる際は、コントローラーのOPTIONSボタンを押してください。

ロボットアームが初期位置に戻り、Bluetooth通信が終了します。

初期位置について

安全のため、電源を入れる際は、ロボットアームが下記画像の姿勢になるようにしてください。

電源投入時にロボットアームが初期位置へ動くため、その他の状態から始めると大暴れする可能性があります。

ライブラリについて

このプログラムで使用するライブラリは下記のとおりです。

  • Bluetooth通信用ライブラリ
  • モータードライバー用ライブラリ

ライブラリのダウンロード

Bluetooth通信用ライブラリのライブラリは下記からダウンロードできます。

GitHub - felis/USB_Host_Shield_2.0: Revision 2.0 of USB Host Library for Arduino.
Revision 2.0 of USB Host Library for Arduino. Contribute to felis/USB_Host_Shield_2.0 development by creating an account...

モータードライバー用のライブラリは下記からダウンロードできます。

403- 現在メンテナンス中です。

ライブラリのインストール

ダウンロード後は、画像のように

スケッチ → ライブラリをインクルード → .zip形式のライブラリをインストール

で先ほどダウンロードしたzipファイルを選択してください。

ソースコード

Arduinoのソースコードは下記になります。

//-----PS4 Bluetooth通信用設定
#include <PS4BT.h>
#include <usbhub.h>

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>

USB Usb;
BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so

/* You can create the instance of the PS4BT class in two ways */
PS4BT PS4(&Btd, PAIR);

bool printAngle, printTouch;
uint8_t oldL2Value, oldR2Value;
//-----PS4 Bluetooth通信end

//-----サーボ制御用設定
#include <PCA9685.h> //PCA9685用ヘッダーファイル
PCA9685 pwm = PCA9685(0x40);    //PCA9685のアドレス指定

//-----各変数の設定
#define SERVOMIN 150            //最小パルス幅 
#define SERVOMAX 500            //最大パルス幅
#define servo_01 0              //サーボ1のピンの設定
#define servo_02 1              //サーボ2のピンの設定
#define servo_03 2              //サーボ3のピンの設定
#define servo_04 3              //サーボ4のピンの設定
#define servo_05 4              //サーボ5のピンの設定
#define servo_06 5              //サーボ6のピンの設定

double arg_01 = 90;             // サーボの角度
double arg_02 = 180;            // サーボの角度
double arg_03 = 135;            // サーボの角度
double arg_04 = 135;            // サーボの角度
double arg_05 = 90;             // サーボの角度
double arg_06 = 90;             // サーボの角度
 
int X_POS_L = 128;              // LスティックのX軸方向の読み取り値
int Y_POS_L = 128;              // LスティックのY軸方向の読み取り値
int X_POS_R = 128;              // RスティックのX軸方向の読み取り値
int Y_POS_R = 128;              // RスティックのY軸方向の読み取り値

int GRIP_servo5 = 128;          // サーボ5の入力(L1,R1)
int GRIP_L2 = 128;              // アームのグリップ部 閉まる方向
int GRIP_R2 = 128;              // アームのグリップ部 開く方向

int i = 0;
int arg_x = 0;
//-----サーボ制御end


//-----初期設定
void setup() {
 pwm.begin();                   //初期設定 (アドレス0x40用)
 pwm.setPWMFreq(50);            //PWM周期を50Hzに設定 (アドレス0x40用)        

 initial_position();  //ポジション初期化

  //-----PS4 Bluetooth通信
   Serial.begin(115200);        // シリアル通信の開始
#if !defined(__MIPSEL__)
  // Wait for serial port to connect - used on Leonardo, 
  // Teensy and other boards with built-in USB CDC serial connection
  while (!Serial);              
#endif
  if (Usb.Init() == -1) {
    Serial.print(F("\r\nOSC did not start"));
    while (1);                  // Halt
  }
  Serial.print(F("\r\nPS4 Bluetooth Library Started"));
  //-----PS4 Bluetooth通信
}

//-----メインループ
void loop() {
  //-----PS4 Bluetooth通信
  Usb.Task();
  if (PS4.connected()) {
    
    //-----L1、R1の入力値を200 or 0に変換
    if (PS4.getButtonClick(L1))
      GRIP_servo5 = 200;
    if (PS4.getButtonClick(R1))
      GRIP_servo5 = 0;

    //-----6回に1回コントローラーのアナログ入力を取得する(過敏に反応しすぎるため)
    if(i == 0){
      //ボタンの入力を取得
      X_POS_L = PS4.getAnalogHat(LeftHatX);  // LスティックのX軸方向のアナログ値を読み取る
      Y_POS_L = PS4.getAnalogHat(LeftHatY);  // LスティックのY軸方向のアナログ値を読み取る
      X_POS_R = PS4.getAnalogHat(RightHatX); // RスティックのX軸方向のアナログ値を読み取る
      Y_POS_R = PS4.getAnalogHat(RightHatY); // RスティックのY軸方向のアナログ値を読み取る

      GRIP_L2 = PS4.getAnalogButton(L2);     // L2のアナログ値を読み取る
      GRIP_R2 = PS4.getAnalogButton(R2);     // R2のアナログ値を読み取る
    }

    //-----オプションボタンが押されたら通信終了_Aruduinoリセット
    if (PS4.getButtonClick(OPTIONS)) {
      Serial.print(F("\r\nOptions"));
      PS4.disconnect();           //Bluetooth通信を遮断

      /*Arduinoリセット時にサーボ2が暴れる可能性があるので、
        5回に分けて初期位置に戻す*/
      arg_x = (180 - arg_02)/5;
      for(int i=0; i < 5; i++){
          arg_02 += arg_x; 
          servo_write(servo_02, arg_02);
          delay(500); 
      }
      
      software_reset();         //Arduinoリセット
    }

    i = i + 1;

    if(i == 5){
      i = 0;
    }
  }

  //-----PS4 Bluetooth通信

    
  //-----サーボモーター用にコントローラー入力→角度_変換
  arg_01 = arg_01 + convert_01(X_POS_L, arg_01);
  arg_02 = arg_02 + convert_02(Y_POS_L, arg_02);
  arg_03 = arg_03 + convert_03(Y_POS_R, arg_03);
  arg_04 = arg_04 + convert_03(X_POS_R, arg_04);
  arg_05 = arg_05 + 20 * convert_01(GRIP_servo5, arg_05); //2度×20=40度ずつ制御
  arg_06 = arg_06 + convert_04(GRIP_L2, GRIP_R2, arg_06);


  //-----サーボ制御(関数呼び出し)
  servo_write(servo_01, arg_01);
  servo_write(servo_02, arg_02);
  servo_write(servo_03, arg_03);
  servo_write(servo_04, arg_04);
  servo_write(servo_05, arg_05);
  servo_write(servo_06, arg_06);


  //-----入力リセット
  X_POS_L = 128;      // LスティックのX軸方向の読み取り値
  Y_POS_L = 128;      // LスティックのY軸方向の読み取り値
  X_POS_R = 128;      // RスティックのX軸方向の読み取り値
  Y_POS_R = 128;      // RスティックのY軸方向の読み取り値

  GRIP_L2 = 128;      // アームのグリップ部 閉まる方向
  GRIP_R2 = 128;      // アームのグリップ部 開く方向
  GRIP_servo5 = 128;  //サーボ5

}
//-----メインループend


/////-----ここから下は呼び出し用の関数-----/////

//サーボ出力用_サーボ番号、角度→出力_関数
void servo_write(int ch, int ang){ //動かすサーボチャンネルと角度を指定

 //角度(0~180)をPWMのパルス幅(150~500)に変換
  ang = map(ang, 0, 180, SERVOMIN, SERVOMAX); 
  pwm.setPWM(ch, 0, ang);
}

//-----サーボ位置初期化用関数
void initial_position(){ //動かすサーボチャンネルと角度を指定

  arg_01 = 90;    // サーボの角度
  arg_02 = 180;   // サーボの角度
  arg_03 = 135;   // サーボの角度
  arg_04 = 135;   // サーボの角度
  arg_05 = 90;    // サーボの角度
  arg_06 = 90;    // サーボの角度

  //サーボ出力
  servo_write(servo_01, arg_01);
  delay(500); 
  servo_write(servo_02, arg_02);
  delay(500); 
  servo_write(servo_03, arg_03);
  delay(500); 
  servo_write(servo_04, arg_04);
  delay(500); 
  servo_write(servo_05, arg_05);
  delay(500); 
  servo_write(servo_06, arg_06);
  delay(500); 
}

//-----リセット用関数
void software_reset() {
  asm volatile ("  jmp 0");  
} 

//-----サーボ1、サーボ5用_コントローラー入力→角度_変換関数
int convert_01(int input_x, int arg_x){
  if(arg_x == 170 && input_x > 190){      //サーボ角度制御、170度以下
    return 0;
  }
  else if (arg_x == 10 && input_x < 65){  //サーボ角度制御、10度以上
    return 0;
  } 
  else if(input_x > 190){     //2度ずつ増加
    return 2;
  } 
  else if(input_x < 65){      //2度ずつ減少
    return -2;
  }
  else{
    return 0;
  }
}

//-----サーボ2用_コントローラー入力→角度_変換関数
int convert_02(int input_x, int arg_x){
  if(arg_x == 180 && input_x > 190){      //サーボ角度制御、180度以下
    return 0;
  }
  else if (arg_x == 45 && input_x < 65){  //サーボ角度制御、45度以上
    return 0;
  } 
  else if(input_x > 190){     //1度ずつ増加
    return 1;
  } 
  else if(input_x < 65){      //1度ずつ減少
    return -1;
  }
  else{
    return 0;
  }
}

//-----サーボ3、サーボ4用_コントローラー入力→角度_変換関数
int convert_03(int input_x, int arg_x){
  if(arg_x == 135 && input_x < 65){        //サーボ角度制御、135度以下
    return 0;
  }
  else if (arg_x == 45 && input_x > 190){  //サーボ角度制御、45度以上
    return 0;
  } 
  else if(input_x > 190){     //1度ずつ減少
    return -1;
  } 
  else if(input_x < 65){      //1度ずつ増加
    return 1;
  }
  else{
    return 0;
  }
}

//サーボ6用_コントローラー入力→角度_変換関数
int convert_04(int input_L, int input_R, int arg_x){
  if(arg_x == 90 && input_L > 190){        //サーボ角度制御、90度以下
    return 0;
  }
  else if (arg_x == 20 && input_R > 190){  //サーボ角度制御、20度以上
    return 0;
  }
  else if(input_L > 190 && input_R > 190){  //L2、R2同時押しは無効化
    return 0;
  }
  else if(input_L > 190){     //5度ずつ増加
    return 5;
  } 
  else if(input_R > 190){     //5度ずつ減少
    return -5;
  }
  else{
    return 0;
  }
}

Arduinoの動かし方から学びたい方へ

Arduinoの動かし方等、プログラミングから学びたい方にはUdemyをおすすめします。

私も社会人になってからHTML、CSS、Javascript、PHPを勉強しましたが、その時も有料の動画受講サービスを使って学習するのが効率が良かったです。

忙しい社会人からすると動画で勉強できるのは非常にありがたいです。

Udemyのメリット

・習いごととしては価格が安い。(合宿や対面などの習いごとより安いです)

・動画で受講できるので、自分のペースで学習できる。(倍速設定もあり)

・受講期間はないため、何度でも受講できる。

・隙間時間を活用できる。

・コースごとに評価も見れるため、学習内容を信用できる。

アルディーノマイコンと電子工作入門【Udemy】

講座名 アルディーノマイコンと電子工作入門
おすすめ度 ★★★★☆ (4.5)
対象者 マイコンの初心者・入門者。電子工作の初心者・入門者。
マイコンのプログラミングをこれから始めたい人。
電子工作をこれから始めたい人。
料金 13,800円
セール時 1,600円
時間 4.5時間
学習内容 新バージョンのアルディーノIDE2.0に対応!
Arduino(アルディーノ)のマイコンボードを使って電子工作を学びます。
マイコンボードでLEDを点灯したり、センサーを使って測定したり、音を鳴らしたり、サーボモータを回したりします。

 

まとめ

以上でロボットアームの作り方解説は終了です。

冒頭でも紹介しましたが、このプログラムには改善点も多々あります。

その一つが操作が難しい点です。

改善方法としては、逆運動学を利用してより直感的に動かせるようにする方法があります。

そのため、今後このプログラムを修正するかもしれません。

その時は新しく記事を追加&解説しますね笑

ひとまずこのシリーズは終了です。

ここまで読んでくださりありがとうございました!

参考サイト

Arduinoはじめました
こんにちはせしろです。かなり久々の更新です。まぁ今後もぼちぼち更新していきます。さて、3Dプリンターも安定して使えるようになったことですし、ブログ名にもあるようにそろそろ工作をしていこうと思っている訳ですよ。で、やはりここは「ラジコン」が定
サーボモータドライバ(PCA9685)とArduinoを用いて複数(12個)のサーボモータ(mg996r)を動かす - Qiita
用いたデバイスpca9685(サーボモータドライバ)データーシートなどわかりやすい記事英語だけど詳しい・簡単にI2Cで入力しPWM出力します。単体で16個のサーボモータを、複数使うこと…

このシリーズの他の記事

この記事のシリーズ一覧
その① コスパ最強!? ロボットアームの作り方_その①
その② コスパ最強!?ロボットアームの作り方_その②__テスト回路の作り方
その③ コスパ最強!?ロボットアームの作り方_その③_機構部の組み立て方
その④ コスパ最強!?ロボットアームの作り方_その④_回路部分の作り方
その⑤ コスパ最強!?ロボットアームの作り方_その⑤_プログラム
おまけ① コスパ最強!?ロボットアームの作り方_おまけ①_プログラム更新
おまけ② コスパ最強!?ロボットアームの作り方_おまけ②_円筒座標系の逆運動学

この記事は、その⑤です。

必要な部品一覧

このロボットアームを作るのに必要な部品一覧とその役割を下記記事にまとめてみました!

ロボットアーム_部品一覧
部品一覧これから紹介するロボットアームの部品合計額は、約2万3千円です。(2022/3/27)頑丈な作りのロボットアームなので、コスパは良いと思います!学習用等にお使いください!ロボットアームの作り方はこちらの記事をご覧ください。部品表Am...
Amazonリンク購入にあたって解説
ロボットアーム在庫切れの場合はこちら
(思いのほか多くの方に購入していただいたようで
在庫切れの場合があるようです。)
Arduino 本体②’を購入の場合不要。
②’Arduino学習キット(②、⑦、⑨セット)②、⑦、⑨セット
こちらをおすすめします。
PS4 コントローラー
Arduino USB shield在庫切れの場合はこちら
USB Bluetooth アダプタ
モータードライバー
Arduino 用ワイヤーゲージ②’を購入の場合不要。
ACアダプター
モータードライバー用電源モジュール②’を購入の場合不要。
クリップ普通のクリップ1個あればOKです。
木板ホームセンターに売っているものでOKです。
30cm×20cm程度。
タッピングねじ M3×10これもホームセンターに売っているものでOKです。

コメント

タイトルとURLをコピーしました