LoginSignup
0
0

EEZYbotARMにrampユニットとサーボを追加して動かす

Last updated at Posted at 2023-05-18

はじめに

ここでは,EEZYbotARM mk1のロボットアーム本体だけではなく、オプションパーツのスロープを使ってみます.

目次へ戻るには ここ をクリック

※本ページは実験のテキストです.

概要

前回はシリアル通信でEEZYbotARM mk1を動かしました.

今回は、EEZYbotARM mk1の公式オプションであるスロープ(ramp=坂)とボールを追加して動かします.

前回のシリアル通信のプログラムに書き加える形で,システム全体を動かしてみましょう.

スロープ部品

スロープとボールは,下の図のような部品です.

image.png

次の参考動画のように動作します,

 参考動画:https://clipchamp.com/watch/EfhEGhqDTrg

ボールが上から転がってくるとスピードが出すぎて飛び出してしまうため,
サーボモータで作られたゲートで一旦ボールを受け止めて,その後でゲートを開いてゆっくりと送り出すためです.

ゲートのサーボをPCA9685ボードに挿す

0~3番のピンは既にEEZYbotARMに使われているので,ゲートのサーボのコネクタは4番以降のピンに挿します.
ピンの色に注意して差し込んでください.

この記事中では,10番のピンに差し込みました.

image.png

スケッチを書き込む

前回のserial2servo.inoに,更に書き加える形でプログラムを追加します.

完成すると,以下のようなプログラムになります.
前回の違いを出すために,ファイル名は serial2servo_2.ino としました。
このプログラムは10番ピンに追加する形で書いているので,違うピンに挿した人はそれに合わせてください.

serial2servo_2.ino
// ライブラリの読み込み
#include <Wire.h>                     // I2C通信
#include <Adafruit_PWMServoDriver.h>  // PCA9685でサーボを動かす

// サーボのパルス幅(μs)
#define SERVO_MIN   800   // 最小パルス幅
#define SERVO_CENT 1500   // ニュートラル(センター)
#define SERVO_MAX  2200   // 最大パルス幅

// ロボットアームのピン番号
#define SERVO0_YAW    0
#define SERVO1_LINK1  1
#define SERVO2_LINK2  2
#define SERVO3_HAND   3
#define SERVO10_GATE  10

// サーボ制御クラスの作成
Adafruit_PWMServoDriver Servo = Adafruit_PWMServoDriver(0x40);  // PCA9685のI2Cアドレスは0x40番地

// サーボに出力するマイクロ秒の値を格納する変数
int sv0 = 1500; // 初期値は1500us
int sv1 = 1500;
int sv2 = 1500;
int sv3 = 1500;
int sv10 = 1500;

// 初期化関数
void setup() {
  Serial.begin( 9600 );     // シリアル通信を初期化する。通信速度は9600bps

  // PWMドライバを初期化する
  Servo.begin();

  // PWM周波数を50Hzに設定する(デフォルト値)
  Servo.setPWMFreq(50);

  // 1秒待機する
  delay(1000);

  // 初期姿勢をセット
  Servo.writeMicroseconds(SERVO0_YAW,   sv0);
  Servo.writeMicroseconds(SERVO1_LINK1, sv1);
  Servo.writeMicroseconds(SERVO2_LINK2, sv2);
  Servo.writeMicroseconds(SERVO3_HAND,  sv3);
  Servo.writeMicroseconds(SERVO10_GATE,  sv10);

  Serial.println( "Hello Arduino!" );   // 最初に1回だけメッセージを表示する
}

// ループ関数
void loop() {
  char key;     // 受信データを格納するchar型の変数

  // 受信データがあった時だけ、サーボの変数の値を変える
  if ( Serial.available() ) {       // 受信データがあるか?
    key = Serial.read();            // 1文字だけ読み込む

    // keyの文字に応じて、行う処理を切り替える
    switch ( key ) {
      // 土台の操作
      // qキーが押された時の処理
      case 'q':        sv0 += 100;        break;
      // aキーが押された時の処理
      case 'a':        sv0 = 1500;        break;
      // zキーが押された時の処理
      case 'z':        sv0 -= 100;        break;

      // リンク1操作
      // wキーが押された時の処理
      case 'w':        sv1 += 100;        break;
      // sキーが押された時の処理
      case 's':        sv1 = 1500;        break;
      // xキーが押された時の処理
      case 'x':        sv1 -= 100;        break;

      // リンク2操作
      // eキーが押された時の処理
      case 'e':        sv2 += 100;        break;
      // dキーが押された時の処理
      case 'd':        sv2 = 1500;        break;
      // cキーが押された時の処理
      case 'c':        sv2 -= 100;        break;

      // ハンド操作
      // rキーが押された時の処理
      case 'r':        sv3 += 100;        break;
      // fキーが押された時の処理
      case 'f':        sv3 = 1500;        break;
      // vキーが押された時の処理
      case 'v':        sv3 -= 100;        break;

      // ゲート操作
      // tキーが押された時の処理
      case 't':        sv10 += 100;        break;
      // gキーが押された時の処理
      case 'g':        sv10 = 1500;        break;
      // bキーが押された時の処理
      case 'b':        sv10 -= 100;        break;

      // 上記以外の場合の処理(何もしない)
      default:
        break;
    } //switch文の末尾

    // 上限・下限のソフトウェアリミットはswitch文の外に出してプログラムを読みやすくした
    if ( sv0 > SERVO_MAX ) sv0 = SERVO_MAX;
    if ( sv0 < SERVO_MIN ) sv0 = SERVO_MIN;

    if ( sv1 > SERVO_MAX ) sv1 = SERVO_MAX;
    if ( sv1 < SERVO_MIN ) sv1 = SERVO_MIN;

    if ( sv2 > SERVO_MAX ) sv2 = SERVO_MAX;
    if ( sv2 < SERVO_MIN ) sv2 = SERVO_MIN;

    if ( sv3 > SERVO_MAX ) sv3 = SERVO_MAX;
    if ( sv3 < SERVO_MIN ) sv3 = SERVO_MIN;

    if ( sv10 > SERVO_MAX ) sv10 = SERVO_MAX;
    if ( sv10 < SERVO_MIN ) sv10 = SERVO_MIN;

    // サーボに出力
    Servo.writeMicroseconds(SERVO0_YAW,   sv0);
    Servo.writeMicroseconds(SERVO1_LINK1, sv1);
    Servo.writeMicroseconds(SERVO2_LINK2, sv2);
    Servo.writeMicroseconds(SERVO3_HAND,  sv3);
    Servo.writeMicroseconds(SERVO10_GATE, sv10);

    // シリアルモニタに現在の出力値を表示
    Serial.print( sv0 );
    Serial.print("\t");
    Serial.print( sv1 );
    Serial.print("\t");
    Serial.print( sv2 );
    Serial.print("\t");
    Serial.print( sv3 );
    Serial.print("\t");
    Serial.println( sv10 );
  } //if文の末尾
}

動作テスト

Arduinoに書き込みが終わると,ロボットアームに力が入って動きます.
最初は全てのサーボがニュートラル位置(1500マイクロ秒)です.

もし,ロボットアームが変な姿勢になっていたら,サーボがズレているかもしれないので,担当の先生に申し出てください.

シリアルターミナルで,tキーを入力して[送信]してください.
ゲートが少し動いたでしょうか.

bキーを送信すると,逆方向に回ります.

gキーを送信すると,ニュートラル位置に戻ります.

以下の図のようにプログラムしてあるわけです.

image.png

プログラム解説

それではプログラムを解説していきます.

準備

前回のプログラムserial2servo.inoと異なる部分だけ抜き出して解説します.

#defineとグローバル変数の追加
#define SERVO10_GATE  10

int sv10 = 1500;

ゲートのサーボを10番ピンに挿したため,
#defineとグローバル変数を追加しました.

初期化関数

次は初期化関数です.
こちらも,前回のプログラムと異なる部分だけ解説します.

setup関数から抜粋
  // 初期姿勢をセット
  Servo.writeMicroseconds(SERVO10_GATE,  sv10);

10番ピンのゲートの出力だけ書き加えました.

ループ関数

次はループ関数です.

loop関数
// ループ関数
void loop() {
  char key;     // 受信データを格納するchar型の変数

  // 受信データがあった時だけ、サーボの変数の値を変える
  if ( Serial.available() ) {       // 受信データがあるか?
    key = Serial.read();            // 1文字だけ読み込む

    // keyの文字に応じて、行う処理を切り替える
    switch ( key ) {
      // 土台の操作
      // qキーが押された時の処理
      case 'q':        sv0 += 100;        break;
      // aキーが押された時の処理
      case 'a':        sv0 = 1500;        break;
      // zキーが押された時の処理
      case 'z':        sv0 -= 100;        break;

      // リンク1操作
      // wキーが押された時の処理
      case 'w':        sv1 += 100;        break;
      // sキーが押された時の処理
      case 's':        sv1 = 1500;        break;
      // xキーが押された時の処理
      case 'x':        sv1 -= 100;        break;

      // リンク2操作
      // eキーが押された時の処理
      case 'e':        sv2 += 100;        break;
      // dキーが押された時の処理
      case 'd':        sv2 = 1500;        break;
      // cキーが押された時の処理
      case 'c':        sv2 -= 100;        break;

      // ハンド操作
      // rキーが押された時の処理
      case 'r':        sv3 += 100;        break;
      // fキーが押された時の処理
      case 'f':        sv3 = 1500;        break;
      // vキーが押された時の処理
      case 'v':        sv3 -= 100;        break;

      // ゲート操作
      // tキーが押された時の処理
      case 't':        sv10 += 100;        break;
      // gキーが押された時の処理
      case 'g':        sv10 = 1500;        break;
      // bキーが押された時の処理
      case 'b':        sv10 -= 100;        break;

      // 上記以外の場合の処理(何もしない)
      default:
        break;
    } //switch文の末尾

    // 上限・下限のソフトウェアリミットはswitch文の外に出してプログラムを読みやすくした
    if ( sv0 > SERVO_MAX ) sv0 = SERVO_MAX;
    if ( sv0 < SERVO_MIN ) sv0 = SERVO_MIN;

    if ( sv1 > SERVO_MAX ) sv1 = SERVO_MAX;
    if ( sv1 < SERVO_MIN ) sv1 = SERVO_MIN;

    if ( sv2 > SERVO_MAX ) sv2 = SERVO_MAX;
    if ( sv2 < SERVO_MIN ) sv2 = SERVO_MIN;

    if ( sv3 > SERVO_MAX ) sv3 = SERVO_MAX;
    if ( sv3 < SERVO_MIN ) sv3 = SERVO_MIN;

    if ( sv10 > SERVO_MAX ) sv10 = SERVO_MAX;
    if ( sv10 < SERVO_MIN ) sv10 = SERVO_MIN;

    // サーボに出力
    Servo.writeMicroseconds(SERVO0_YAW,   sv0);
    Servo.writeMicroseconds(SERVO1_LINK1, sv1);
    Servo.writeMicroseconds(SERVO2_LINK2, sv2);
    Servo.writeMicroseconds(SERVO3_HAND,  sv3);
    Servo.writeMicroseconds(SERVO10_GATE, sv10);

    // シリアルモニタに現在の出力値を表示
    Serial.print( sv0 );
    Serial.print("\t");
    Serial.print( sv1 );
    Serial.print("\t");
    Serial.print( sv2 );
    Serial.print("\t");
    Serial.print( sv3 );
    Serial.print("\t");
    Serial.println( sv10 );
  } //if文の末尾
}

前回の記事のサンプルプログラムは,土台を動かすq,a,zキーのみで,リンクやハンドは自分で書き加える必要がありました.
今回のプログラムは,すべてのサーボを書いてあります.

課題

キーボード入力をして,

  1. ゲートを閉じる
  2. ボールをつまみに行く
  3. ボールをつまむ
  4. リリースポイントまで移動
  5. ボールを離す
  6. ゲートを開く

をやってみましょう.

まとめ

今回は,シリアル通信を使ってEEZYbotARM mk1とスロープを動かせるようにプログラムしてみました.

おわりに

これでシリアル通信での動作は完了です.

次回は予め与えた数値で動かすチャレンジをしてみます.

目次 へ戻って次の作業を行ってください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0