はじめに
ここでは,EEZYbotARM mk1のロボットアーム本体だけではなく、オプションパーツのスロープを使ってみます.
目次へ戻るには ここ をクリック
※本ページは実験のテキストです.
概要
前回はシリアル通信でEEZYbotARM mk1を動かしました.
今回は、EEZYbotARM mk1の公式オプションであるスロープ(ramp=坂)とボールを追加して動かします.
前回のシリアル通信のプログラムに書き加える形で,システム全体を動かしてみましょう.
スロープ部品
スロープとボールは,下の図のような部品です.
次の参考動画のように動作します,
参考動画:https://clipchamp.com/watch/EfhEGhqDTrg
ボールが上から転がってくるとスピードが出すぎて飛び出してしまうため,
サーボモータで作られたゲートで一旦ボールを受け止めて,その後でゲートを開いてゆっくりと送り出すためです.
ゲートのサーボをPCA9685ボードに挿す
0~3番のピンは既にEEZYbotARMに使われているので,ゲートのサーボのコネクタは4番以降のピンに挿します.
ピンの色に注意して差し込んでください.
この記事中では,10番のピンに差し込みました.
スケッチを書き込む
前回のserial2servo.ino
に,更に書き加える形でプログラムを追加します.
完成すると,以下のようなプログラムになります.
前回の違いを出すために,ファイル名は serial2servo_2.ino
としました。
このプログラムは10番ピンに追加する形で書いているので,違うピンに挿した人はそれに合わせてください.
// ライブラリの読み込み
#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
キーを送信すると,ニュートラル位置に戻ります.
以下の図のようにプログラムしてあるわけです.
プログラム解説
それではプログラムを解説していきます.
準備
前回のプログラムserial2servo.ino
と異なる部分だけ抜き出して解説します.
#define SERVO10_GATE 10
int sv10 = 1500;
ゲートのサーボを10番ピンに挿したため,
#defineとグローバル変数を追加しました.
初期化関数
次は初期化関数です.
こちらも,前回のプログラムと異なる部分だけ解説します.
// 初期姿勢をセット
Servo.writeMicroseconds(SERVO10_GATE, sv10);
10番ピンのゲートの出力だけ書き加えました.
ループ関数
次はループ関数です.
// ループ関数
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
キーのみで,リンクやハンドは自分で書き加える必要がありました.
今回のプログラムは,すべてのサーボを書いてあります.
課題
キーボード入力をして,
- ゲートを閉じる
- ボールをつまみに行く
- ボールをつまむ
- リリースポイントまで移動
- ボールを離す
- ゲートを開く
をやってみましょう.
まとめ
今回は,シリアル通信を使ってEEZYbotARM mk1とスロープを動かせるようにプログラムしてみました.
おわりに
これでシリアル通信での動作は完了です.
次回は予め与えた数値で動かすチャレンジをしてみます.
目次 へ戻って次の作業を行ってください。