C言語でEV3開発(12)
opOUTPUT_TIME_POWERコマンド

2021年1月30日

どもです。
今回のエントリーでは、これまた前回に引き続き、モーターを動かすためのコマンドについて書きます。
コマンドは、「opOUTPUT_TIME_POWER」です。

1.opOUTPUT_TIME_POWERコマンド

今回紹介するコマンドです。
コマンドのフォーマットは、以下の通りです。

インデックス 内容 値の範囲
1 コマンドコード opOUTPUT_TIME_POWER(0xAD)
2 チャンネル
3 パワー(Power) -100~100(%)
4 Time1 Powerに達するまでに要する時間(ミリ秒)
5 Time2 Powerで動作させる時間
6 Time3 出力を0(%)に戻すまでに要する時間
7 ブレーキ 0=ブレーキをかけない
1=ブレーキをかける

コマンドフォーマットから見て予想できるかと思いますが、このコマンドの動作と非常に似た動作、というか、ほとんど同じ動作をします。
すなわち、Time1~Time3に示した「時間」ごとにモーターを動かします。
このとき、Time1で指定した時間をかけて、Powerで指定したモーターのパワーを遷移させます。
次に、Time2で指定した時間、Powerで指定したモーターを動作させます。
最後に、Time3で指定した時間をかけて、モーターの出力を0に戻します。

2.サンプルコード

というわけで、opOUTPUT_TIME_POWERコマンドを使用してモーターを動かします。
サンプルプログラムは、以下の通りです。

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include "lms2012.h"

#define CH_A    (0x01)
#define CH_B    (0x02)
#define CH_C    (0x04)
#define CH_D    (0x08)

//   モーターのポート名
#define PWM_MOTOR_PORT_NAME ("/dev/lms_pwm")

typedef unsigned int UINT;
typedef signed int SINT;
//typedef unsigned char UBYTE;
//typedef signed int SBYTE;
typedef void VOID;

//  モーターのファイルディスクリプター
SINT motor_fp;

/*****************************************************************************/
/*                                                                           */
/*  モーターを動作させるための各種関数                                       */
/*                                                                           */
/*****************************************************************************/
/*
    * プログラムの開始
    */
int ProgramStart(void) {
    UBYTE Buf[4];
    int ret;

    Buf[0] = opPROGRAM_START;
    ret = write(motor_fp, &Buf[0], 1);

    return ret;
}

/*
    * プログラムの停止
    */
int ProgramStop(void) {
    UBYTE Buf[4];
    int ret;

    Buf[0] = opPROGRAM_STOP;
    ret = write(motor_fp, &Buf[0], 1);

    return ret;
}

/*
    * モーターの動作開始
    */
int MotorStart(UBYTE ch) {
    UBYTE Buf[4];
    int ret;

    Buf[0] = opOUTPUT_START;
    Buf[1] = ch;
    ret = write(motor_fp, &Buf[0], 2);

    return ret;
}

/*
    * モーターの動作停止
    */
int MotorStop(UBYTE ch) {
    UBYTE Buf[4];
    int ret;

    Buf[0] = opOUTPUT_STOP;
    Buf[1] = ch;
    ret = write(motor_fp, &Buf[0], 2);

    return ret;
}

/*
    * モーターのリセット
    */
int MotorReset(UBYTE ch) {
    UBYTE Buf[4];
    int ret;

    Buf[0] = opOUTPUT_RESET;
    Buf[1] = ch;
    ret = write(motor_fp, Buf, 2);

    return ret;
}

/*===========================================================================*/
/*                                                                           */
/*  今回対象のopOUTPUT_TIME_POWERコマンドを実行する                          */
/*                                                                           */
/*===========================================================================*/
int TimePower(
        UBYTE ch,
        UBYTE power,
        UWORD time1,
        UWORD time2,
        UWORD time3,
        UBYTE brake)
{
    int ret;
    size_t size;
    TIMEPOWER timePower = { 0 };

    timePower.Cmd = opOUTPUT_TIME_POWER;
    timePower.Nos = (DATA8) ch;
    timePower.Power = (DATA8) power;
    timePower.Time1 = time1;
    timePower.Time2 = time2;
    timePower.Time3 = time3;
    timePower.Brake = brake;
    size = sizeof(timePower);
    ret = write(motor_fp, (void *) &timePower, size);

    return ret;
}

/*****************************************************************************/
/*                                                                           */
/*  メイン関数                                                               */
/*                                                                           */
/*****************************************************************************/
int main() {
    UBYTE power = 100;
    UWORD time1 = 3000;
    UWORD time2 = 3000;
    UWORD time3 = 0;
    UBYTE brake = 1;

    motor_fp = open(PWM_MOTOR_PORT_NAME, O_RDWR);
    if (motor_fp < 0) {
        printf("Can not open MOTOR PORT\r\n");

        return (-1);
    }

    ProgramStart();
    ProgramStop();
    ProgramStart();

    MotorReset(CH_D);
    MotorStart(CH_D);

    TimePower(CH_D, power, time1, time2, time3, brake);
    sleep(15);

    MotorStop(CH_D);

    ProgramStop();

    close(motor_fp);
    exit(0);
}

3.動かしてみた

というわけで、実際に動かしてみた場合の動画です。

見てわかるように、モーターは最初ゆっくり動き始め、その後だんだんゆっくりになり、最終的に停止します。
コードにあわせて説明すると、モーターが動作し始めてからの最初の3秒(3000ミリ秒)間をかけて、モーターの出力を100%にします。
次の5秒(5000ミリ秒)間は、モーターを出力100%で動かします。
最後の3秒(3000ミリ秒)間で、モーターの出力を0%に遷移させています。

4.コマンドの注意点

このコマンドを使用する際には、注意点があります。
まず、回転方向の制御です。
これは、opOUTPUT_STEP_POWERの同様に、Powerで決定しています。
しかし、決定的に異なるのは、この値に負の値を設定した場合です。
opOUTPUT_STEP_POWERでは、負の値を設定しても回転方向は変化しませんでした。
しかし、opOUTPUT_TIME_POWERでは、Powerに負の値を設定した場合、回転方向が逆になります。

また、Powerに0を設定した場合です。
これは、やはり、理想的にはモーターが動作しないことです。
しかし、実際に動かしてみると、モーターは動作してしまいます。
原因は、opOUTPUT_STEP_POWERの場合同様、不明です。

次に、TimeNに設定する値です。
まず、Time1ですが、これは値を設定しない、すなわち0に設定する、ということが可能です。
0を設定した場合、いきなりPowerに設定した出力でモーターが動作します。
次に、Time2ですが、これも値を設定しない、すなわち0に設定することが可能です。
その場合には、もちろん「Powerで指定した出力で、一定時間動作する」ということはなくなります。
ただし、Time1=0、かつTime2=0、かつTime3!=0とした場合、モーターは動作しないので、注意が必要です。
最後にTime3です。
これも、値を設定しない、すなわち0を設定するということが可能です。
Time3に0を設定した場合には、Time1、Time2に対応する動作をした後、モーターが停止します。

以上、今回は、opOUTPUT_TIME_POWERコマンドについて書きました。
次回も、引き続きモーターを動作させるためのコマンドを紹介していきます。
では。