C言語でEV3開発(23)
モーターの性能確認

2021年2月6日

どもです。
今回は、EV3に付属しているモーター(Lモーター/Mモーター)の性能について調べてみたので、その結果についてのエントリです。

0.動機

これまで、EV3のモーターを色々動かしてきましたが、その中で「Mモーターの出力が50%前後以上にならない」ということが起きています。
そこで、手元にあるEV3のモーターが、本当に公開されている仕様を満たしているのか否かを確認してみることにしました。

1.公開されている仕様

「LEGO MINDOSTORMS EV3 Hardware Development Kit」によれば、各モーターの仕様は下記の通りです。

Lモーター 175 RPM
60 mA
Mモーター 260 RPM
80 mA

特に負荷をかけずにモーターを回転させた際の出力/動作が、上記の仕様を満たしているのかを確認します。

2.検証環境と方法

検証は、下記の環境で実施します。

CPU i7-3770K
3.50GHz
メモリ 16.0GB
OS Windows7 Professional SP1
64bit
Ev3 OS TOPPERS EV3RT
Beta-7-release

3.検証用アプリケーション
検証のためのアプリケーションの機能は、以下の非常にシンプルなものです。

  • メインのタスク
    • ポートなど、各種の初期化と、周期タスクの開始と停止
  • 100msec定周期タスク
    • そのときのモーター出力とモーター角の取得と、ログファイルへの出力
  • 1sec定周期タスク
    • モーター出力値の決定と設定
    • モーター出力は、「0%」から開始して「100%」まで「5%」ごとに変化
    • 「100%」に到達した後は、「-100%」まで「5%」ごとに変化
    • 「-100%」に到達した後は、「0%」まで「5%」ごとに変化

実際の検証用アプリケーションのコードは、下記の通りです。

/**
 * This application tests motor output.
 */
#include "ev3api.h"
#include "app.h"

#define MSG_BUF_SIZE    (64)

const motor_port_t motor_port = EV3_PORT_A;

int motor_power_output = 0;
int motor_power_current = 0;
int motor_counts_current = 0;
int motor_power_output_change = 0;
int cyc_task_1sec_count = 0;
int cyc_task_100msec_count = 0;
//const char *logging_file_name = "Log.csv";

FILE *logging_file = NULL;
const char *logging_file_name_list[10] = {
    "Log_001.csv", "Log_002.csv", "Log_003.csv", "Log_004.csv", "Log_005.csv",
    "Log_006.csv", "Log_007.csv", "Log_008.csv", "Log_009.csv", "Log_010.csv"
    };
char msg_buf[MSG_BUF_SIZE];
/**
 * @biref   Main task of this application.
 *          Initializes parameters, configures device,
 *          creates log file, and starts periodic tasks.
 *          The started tasks will be stopped after a
 *          concrete time passed.
 */
void main_task(intptr_t unused)
{
    int index = 0;
    const char *logging_file_name = NULL;

    //Initialize
    ev3_lcd_set_font(EV3_FONT_SMALL);
    ev3_lcd_draw_string("STARTING", 0, 0);
    ev3_motor_config(motor_port, LARGE_MOTOR);

    for (index = 0; index < 10; index++) {
        logging_file_name = logging_file_name_list[index];
        logging_file = fopen(logging_file_name, "w");
        fprintf(logging_file, "CNT,TARGET,CURRENT,COUNTS\n");

        //Reset paraemters.
        motor_power_output = 0;
        motor_power_current = 0;
        motor_counts_current = 0;
        motor_power_output_change = 5;

        cyc_task_100msec_count = 0;
        cyc_task_1sec_count = 0;

        ev3_motor_reset_counts(motor_port);

        sprintf((char *)&msg_buf[0], "RUNNING:%s", logging_file_name);
        ev3_lcd_draw_string((char *)&msg_buf[0], 0, 0);

        ev3_sta_cyc(CYC_TASK_10MS);
        ev3_sta_cyc(CYC_TASK_1SEC);
        tslp_tsk(85000);

        ev3_stp_cyc(CYC_TASK_10MS);
        ev3_stp_cyc(CYC_TASK_1SEC);

        fclose(logging_file);
        ev3_lcd_draw_string("FINISHED", 0, 0);
    }
}

/**
 * @brief   Periodic task called each 10 mseconds.
 */
void cyc_task_100msec(intptr_t unused)
{
    motor_power_current = ev3_motor_get_power(motor_port);
    motor_counts_current = ev3_motor_get_counts(motor_port);

    if (cyc_task_100msec_count <= 800) {
        fprintf(logging_file, "%d,%d,%d,%d\n", 
            cyc_task_100msec_count,
            motor_power_output,
            motor_power_current,
            motor_counts_current);
    }
    cyc_task_100msec_count++;
}

/**
 * @brief   Periodic task called each 1 sencond.
 */
void cyc_task_1sec(intptr_t unused)
{
    if (100 == motor_power_output) {
        motor_power_output_change = -5;
    }
    if (-100 == motor_power_output) {
        motor_power_output_change = 5;
    }

    motor_power_output += motor_power_output_change;
    if (cyc_task_1sec_count <= 80) {
        ev3_motor_set_power(motor_port, motor_power_output);
    } else {
        ev3_motor_set_power(motor_port, 0);
    }

    cyc_task_1sec_count++;
}

4.実行結果

上記のアプリケーションを実行、その10回の試行の結果の平均値(出力指定値と動作値)をグラフ化した図が、下記の通りです。

Mモーターの平均値(1)
Mモーターの平均値(2)
Lモーターの平均値
このグラフを見て分かる通り、M-モーターの出力指示値が50%以上/-50%以下になったくらいから、モーター出力値が変化しなくなっています。
そこで、このときのモーターの回転数を確認します。
確認した結果のグラフは、数の通りです。

Mモーターの回転数の平均値(1)
Mモーターの回転数の平均値(2)

このグラフから見ると、モーターの回転数は、おおよそ150RPM/-150RPMです。
これは、M-モーターの仕様に記載された値に非常に近い値です。
そのため、これは正常な値であると考えられます。
また、違う見方をすると、モーターの出力値が100%になった場合、単純計算でモーターの回転数は300RPM程度になります。
これは、仕様の内容とかけ離れた値になります。

次にL-モーターの動きを見ます。
モーターの出力値指示値を、出力値が追従しています。
また、モーターの回転数については、おおよそ200RPMであり、これは仕様に記載された値と一致しません。
Lモーターの回転数の平均値

5.確認結果の考察

TOPPERS のAPIでは、モーターの出力は、「-100%」から「100%」の範囲で出力を指定できます。
しかし、この範囲での出力の指定は、実際のモーターの出力の割合とは一致しません。
現状、モーターの出力を制御するためのAPIは限られています。
そのため、「APIで指定した出力と実際の出力は必ずしも一致しない」ということを念頭において、APIを使用する必要がありそうです。

6.公開しています

今回のエントリーで作成したコード、およびテストデータについては、GitHubで公開しています。
以上、今回はEV3のモーターの出力について確認しました。
次は…何をしよう?

ではっ!