LoginSignup
1
0

#6 モータを動かそう【もっと!後輩たちのためのEV3rt講座】

Last updated at Posted at 2023-12-12

目次

タイトル 内容
1 はじめに 今回やることの説明
2 モータの設定 モータの設定方法について説明
3 モータを動かす系の関数 モータを動かす系の関数を紹介
4 回転角度に関わる関数 回転角度に関わる関数を紹介
5 モータ情報取得系関数 モータ情報取得系関数を紹介
6 まとめ 今回のまとめ

1. はじめに

前回まで2回に渡り、EV3rtでのプログラム開発に必要なC言語の文法を一通りおさえていきました。
今回からはいよいよ、ロボットを動かす関数(API)等を紹介していきます。

今回は、モータ系のAPIを紹介します。
モータ系のAPIの説明は以下のページに書かれています。本記事はそれをかみ砕いて、EV3ソフトでの例も交えながら紹介していきます。

EV3RT C API Reference / サーボモータ

2. モータの設定

モータを動かす前に、「どのポート」に「どのモータ」が接続されているかを設定する必要があります。
まずはこの方法から説明していきます。

EV3のモータポートについて

EV3インテリジェントブロックのモータ用のポートは、A~Dまでの4つがあります。

IMG_7146.jpg

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種類があります。

motor_type.png

こちらも、モータの種類を指定する定数が定義されています。

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ソフトではこの👇ブロックにあたります。

on.png

ER ev3_motor_set_power(motor_port_t port, int power);

関数名はev3_motor_set_powerで、その名の通りモータパワーを設定する関数です。
引数として 「ポート」「パワー」(整数値) を指定します。

使い方の例は次のOFF関数を紹介してから示します。

モータOFF 関数

モータをONする関数と対を成す存在として、モータをOFFする関数があります。
EV3ソフトではこの👇ブロックにあたります。

off.png

ER ev3_motor_stop(motor_port_t port, bool_t brake);

関数名はev3_motor_stopで、モータの回転を止める関数です。
引数として 「ポート」「ブレーキの有無」 を指定します。

EV3ソフトで表すところの「ブレーキ」を使いたい場合はtrueを、X「惰性運転」を使いたい場合はfalseを指定します。

では、以下のEV3ソフトでのプログラムブロックを、EV3rtにて表現してみます。

ex_on_off.png

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ソフトではこの👇ブロックにあたります。

degree.png

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ソフトではこの👇ブロックにあたります。

steer.png

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ソフトではこの👇ブロックにあたります。

degree_get.png

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ソフトではこの👇ブロックにあたります。

degree_reset.png

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ソフトではこの👇ブロックにあたります。

power_get.png

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 カラーセンサを使おう

1
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
1
0