目次
章 | タイトル | 内容 |
---|---|---|
1 | はじめに | 今回やることの説明 |
2 | モータの設定 | モータの設定方法について説明 |
3 | モータを動かす系の関数 | モータを動かす系の関数を紹介 |
4 | 回転角度に関わる関数 | 回転角度に関わる関数を紹介 |
5 | モータ情報取得系関数 | モータ情報取得系関数を紹介 |
6 | まとめ | 今回のまとめ |
1. はじめに
前回まで2回に渡り、EV3rtでのプログラム開発に必要なC言語の文法を一通りおさえていきました。
今回からはいよいよ、ロボットを動かす関数(API)等を紹介していきます。
今回は、モータ系のAPIを紹介します。
モータ系のAPIの説明は以下のページに書かれています。本記事はそれをかみ砕いて、EV3ソフトでの例も交えながら紹介していきます。
EV3RT C API Reference / サーボモータ
2. モータの設定
モータを動かす前に、「どのポート」に「どのモータ」が接続されているかを設定する必要があります。
まずはこの方法から説明していきます。
EV3のモータポートについて
EV3インテリジェントブロックのモータ用のポートは、A
~D
までの4つがあります。
EV3rtには、これら4つのポートを指定するための定数が定義されています。
typedef enum {
EV3_PORT_A = 0,
EV3_PORT_B = 1,
EV3_PORT_C = 2,
EV3_PORT_D = 3,
TNUM_MOTOR_PORT = 4
} motor_port_t;
ポート | 定数 | 値 |
---|---|---|
A | EV3_PORT_A | 0 |
B | EV3_PORT_B | 1 |
C | EV3_PORT_C | 2 |
D | EV3_PORT_D | 3 |
上記の定数は「列挙型」というデータ型で定義されています。
が、細かいことは気にせず、ポートAを使用したければEV3_PORT_A
と書けばOKです。
モータの種類について
EV3のモータは「Lモータ」と「Mモータ」の2種類があります。
こちらも、モータの種類を指定する定数が定義されています。
typedef enum {
NONE_MOTOR = 0,
MEDIUM_MOTOR,
LARGE_MOTOR,
UNREGULATED_MOTOR,
TNUM_MOTOR_TYPE
} motor_type_t;
モータタイプ | 定数 | 値 |
---|---|---|
未接続 | NONE_MOTOR | 0 |
Mモータ | MEDIUM_MOTOR | 1 |
Lモータ | LARGE_MOTOR | 2 |
未調整のモータ | UNREGULATED_MOTOR | 3 |
こちらも「列挙型」により定義されていますが、Mモータを使用するときはMEDIUM_MOTOR
と、Lモータを使用するときはLARGE_MOTOR
と書けばOKです。
モータの接続設定関数
では本題のモータを設定する関数についてです。
モータ設定関数は以下のように定義されています。
ER ev3_motor_config(motor_port_t port, motor_type_t type);
まず、関数の名前はev3_motor_config
です。
引数として、 「ポート」 と 「モータタイプ」 の2つを指定します。
戻り値のデータ型は「ER」と書かれていますが、これはエラーコードを返すものです。
(実際のロボットプログラムではほぼ使用しないかと思います。以降、ER型の戻り値の説明は省略させて頂きます。必要であればご自身でAPIを確認してください。)
実際に使用するときは、以下のように記述します。
Ex 1. Lモータ2つをポートAとDに接続するとき
void main_task(intptr_t unused)
{
ev3_motor_config(EV3_PORT_A, LARGE_MOTOR);
ev3_motor_config(EV3_PORT_D, LARGE_MOTOR);
}
Ex 2. Mモータ1つをポートBに接続するとき
void main_task(intptr_t unused)
{
ev3_motor_config(EV3_PORT_B, MEDIUM_MOTOR);
}
この設定を行っておかないとモータが動きませんので、main_task
が始まったらすぐに実行するよう心がけましょう。
3. モータを動かす系の関数
では、実際にモータの動作に関わる関数を紹介していきます。
モータON 関数
まずは、モータをONする関数を紹介します。
EV3ソフトではこの👇ブロックにあたります。
ER ev3_motor_set_power(motor_port_t port, int power);
関数名はev3_motor_set_power
で、その名の通りモータパワーを設定する関数です。
引数として 「ポート」 と 「パワー」(整数値) を指定します。
使い方の例は次のOFF関数を紹介してから示します。
モータOFF 関数
モータをONする関数と対を成す存在として、モータをOFFする関数があります。
EV3ソフトではこの👇ブロックにあたります。
ER ev3_motor_stop(motor_port_t port, bool_t brake);
関数名はev3_motor_stop
で、モータの回転を止める関数です。
引数として 「ポート」 と 「ブレーキの有無」 を指定します。
EV3ソフトで表すところの☑
「ブレーキ」を使いたい場合はtrue
を、X
「惰性運転」を使いたい場合はfalse
を指定します。
では、以下のEV3ソフトでのプログラムブロックを、EV3rtにて表現してみます。
Ex 3. モータをパワー50%でONし、1秒待機して、モータをOFFする
void main_task(intptr_t unused)
{
ev3_motor_config(EV3_PORT_A, LARGE_MOTOR);
ev3_motor_config(EV3_PORT_D, LARGE_MOTOR);
ev3_motor_set_power(EV3_PORT_A, 50);
tslp_tsk(1*1000*1000);
ev3_motor_stop(EV3_PORT_A, true);
}
どちらの関数もモータを動かすときの基本となるので、マスターしておきましょう。
指定した角度だけ回転する関数
次に、指定した角度だけモータが回転する関数を紹介します。
EV3ソフトではこの👇ブロックにあたります。
ER ev3_motor_rotate(motor_port_t port, int degrees, uint32_t speed_abs, bool_t blocking);
関数名はev3_motor_rotate
で、その名の通りモータパワーを設定する関数です。
引数として 「ポート」 、 「回転角度」(整数値) 、「スピード」(正の整数値) 、 「回転完了まで待つか」 を指定します。
「スピード」は 0~100
の自然数で指定する必要があります。
回転方向については「回転角度」で指定することになります。
「回転完了まで待つか」という項目ですが、指定した角度の回転が完全に終わるまで、次の関数を実行するのを待つかどうかということです。
待つ場合はtrue
、待たない場合はfalse
を指定します。
例を交えながら説明してみましょう。
Ex 4. モータAをパワー50%で360度回し、その後にモータDをパワー50%で360度回す
void main_task(intptr_t unused)
{
//プログラムをここから書く
ev3_motor_config(EV3_PORT_A, LARGE_MOTOR);
ev3_motor_config(EV3_PORT_D, LARGE_MOTOR);
ev3_motor_rotate(EV3_PORT_A, 360, 50, true);
ev3_motor_rotate(EV3_PORT_D, 360, 50, true);
}
この例であれば、モータAが360度(つまり一周)回り切って止まった後に、モータDが回り始めます。
では、次の例はどうでしょうか。
Ex 5. モータAとDをパワー50%で360度回す
void main_task(intptr_t unused)
{
//プログラムをここから書く
ev3_motor_config(EV3_PORT_A, LARGE_MOTOR);
ev3_motor_config(EV3_PORT_D, LARGE_MOTOR);
ev3_motor_rotate(EV3_PORT_A, 360, 50, false);
ev3_motor_rotate(EV3_PORT_D, 360, 50, true);
}
Ex 4と異なるのは、ポートAのev3_motor_rotate
の一番最後の引数をtrue
からfalse
に変えたところです。
この変更により、ポートAのev3_motor_rotate
関数は、モータの回転完了を待たず、次の関数の実行に移ります。
よって、ポートAとポートDのモータが同時に回り、それぞれ360度回ったところで停止します。
上手く活用すれば、ロボットの直進動作に使えそうですね。
2つのモータでステアリング制御する関数
最後に、2つのモータをステアリングで制御する関数を紹介します。
EV3ソフトではこの👇ブロックにあたります。
ER ev3_motor_steer(motor_port_t left_motor, motor_port_t right_motor, int power, int turn_ratio);
関数名はev3_motor_steer
で、上述のとおり2つのモータをステアリングで制御する関数です。
引数として 「左モータのポート」 、 「右モータのポート」 、 「パワー」(整数値) 、 「ステアリング度合」(整数値) を指定します。
こちらに関しては「パワー」も「ステアリング度合」も-100~100
の間の整数で指定します。
Ex 6. モータAとDをパワー50%、ステアリング度合10で3秒回す
void main_task(intptr_t unused)
{
//プログラムをここから書く
ev3_motor_config(EV3_PORT_A, LARGE_MOTOR);
ev3_motor_config(EV3_PORT_D, LARGE_MOTOR);
ev3_motor_steer(EV3_PORT_A, EV3_PORT_D, 50, 10);
tslp_tsk(3*1000*1000);
ev3_motor_stop(EV3_PORT_A, true);
ev3_motor_stop(EV3_PORT_D, true);
}
このev3_motor_steer
関数を使うときの注意点として、関数自体に回転量を指定する機能がありません。
従って、上記の例のように、秒数待機をした後に、ev3_motor_stop
関数で回転を止める必要があります。
感覚的には、「ev3_motor_set_power
関数をポート2つ分一気に行えるようにしたもの」といった感じですね。
以上が、モータを動かす系の関数です。
4. 回転角度に関わる関数
EV3モータには「ロータリーエンコーダ」という回転角度を測るセンサが内蔵されています。
これにより回転角度を指定した回転命令などが出来るわけですが、一つのセンサとして値を取得することも出来ます。
回転角度を取得する
まずは、回転角度を取得してみましょう。
EV3ソフトではこの👇ブロックにあたります。
int32_t ev3_motor_get_counts(motor_port_t port);
関数名はev3_motor_get_counts
で、回転角度を取得する関数です。
引数として 「ポート」 を指定し、戻り値として 「回転角度」 が整数値で返って来ます。
使い方についてですが、例えば先ほど紹介したev3_motor_steer
関数を角度で制御しようとすると、以下のように実現できます。
Ex 7. モータAとDをパワー50%、ステアリング度合10で360度回す
void main_task(intptr_t unused)
{
//プログラムをここから書く
ev3_motor_config(EV3_PORT_A, LARGE_MOTOR);
ev3_motor_config(EV3_PORT_D, LARGE_MOTOR);
while(ev3_motor_get_counts(EV3_PORT_A) < 360){
ev3_motor_steer(EV3_PORT_A, EV3_PORT_D, 50, 10);
}
ev3_motor_stop(EV3_PORT_A, true);
ev3_motor_stop(EV3_PORT_D, true);
}
こうすると、「モータAが360度回転するまでループ」になるので、角度制御することができます。
回転角度をリセットする
先ほどから頻りに申している「回転角度」ですが、当然「基準となるポイント」があります。
通常、プログラム実行時に回転角度のリセットがかかるため、そこからの角度ということになりますが、任意のタイミングでリセットをしたい時もあるでしょう。
その時は次のコマンドでリセットすることが出来ます。
EV3ソフトではこの👇ブロックにあたります。
ER ev3_motor_reset_counts(motor_port_t port);
関数名はev3_motor_reset_counts
で、回転角度をリセットする関数です。
引数として 「ポート」 を指定します。
使い方の例として、先ほどのEx 7にリセット関数を書き足してみたいと思います。
Ex 7-1. モータAとDをパワー50%、ステアリング度合10で360度回す
void main_task(intptr_t unused)
{
//プログラムをここから書く
ev3_motor_config(EV3_PORT_A, LARGE_MOTOR);
ev3_motor_config(EV3_PORT_D, LARGE_MOTOR);
ev3_motor_reset_counts(EV3_PORT_A);
while(ev3_motor_get_counts(EV3_PORT_A) < 360){
ev3_motor_steer(EV3_PORT_A, EV3_PORT_D, 50, 10);
}
ev3_motor_stop(EV3_PORT_A, true);
ev3_motor_stop(EV3_PORT_D, true);
}
角度制御をする場合は、回転角度をリセットして基準点を設定する必要があるため、この方法を使えるようにしておきましょう。
5. モータ情報取得系関数
最後に、モータの情報を取得する関数を2つ紹介します。
モータパワーを取得する関数
現在出力されているモータパワーを取得する関数です。
EV3ソフトではこの👇ブロックにあたります。
int ev3_motor_get_power(motor_port_t port);
関数名はev3_motor_get_power
で、出力パワー値を返す関数です。
引数として 「ポート」 を指定すると、 「出力パワー値」 が戻り値として返ってきます。
ポイントとしては、「設定したパワー値」ではなく、「実際に出力されているパワー値」であるところです。
サンプルプログラムを作成してみましたので、是非実際に動かして確認してみてください。
(尚、まだ紹介していない関数等が含まれていますが、今は気にせず実行してみましょう。いずれも今後紹介予定です。)
Ex 8. モータAの実際のパワー値を確認する
void main_task(intptr_t unused)
{
//プログラムをここから書く
ev3_motor_config(EV3_PORT_A, LARGE_MOTOR);
ev3_motor_config(EV3_PORT_D, LARGE_MOTOR);
ev3_lcd_set_font(EV3_FONT_MEDIUM);
char str[8];
ev3_motor_set_power(EV3_PORT_A, 50);
while(1){
sprintf(str, "%d", ev3_motor_get_power(EV3_PORT_A));
ev3_lcd_draw_string(str, 0, 0);
}
}
モータタイプを取得する関数
以下の関数は、ev3_motor_config
関数により設定したポートに対するモータタイプを取得します。
ER_UINT ev3_motor_get_type(motor_port_t port);
使い方としては、以下のように引数に「ポート」を指定すると、戻り値としてモータタイプが返ってきます。
ev3_motor_get_type(EV3_PORT_A);
しかし、ev3_motor_config
関数により設定した情報、つまり既に自分が知っている情報なので、あまり使いどころは無いかと感じます。
(内部処理で使用されているようです。)
6. まとめ
今回はEV3のモータに関わる関数を一通り紹介しました。
ロボット開発には必要不可欠なモータを扱う関数ですので、是非マスターしましょう。
次回は、カラーセンサの使い方を紹介したいと思います。
前回: #5 C言語のキホン➁
次回: #7 カラーセンサを使おう