C言語でEV3開発(13)
opOUTPUT_STEP_SPEEDコマンド

2021年1月30日

どもです。
今回のエントリーは、モーターを動かすコマンドである
「opOUTPUT_STEP_SPEED」コマンドについて書きます。

1.opOUTPUT_STEP_SPEEDコマンド

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

バイト
インデックス
内容
1 コマンドコード opOUTPUT_TIME_SPEED(0xAF)
2 チャンネル
3 スピード -100~100(%)
4 Time1
スピードに達するまでに回転する時間
0~4294967295(ミリ秒)
5 Time2
スピードで動作する時間
0~4294967295(ミリ秒)
6 Time3
スピードが0になるまでに要する時間
0~4294967295(ミリ秒)
7 ブレーキ 0=ブレーキをかけない
1=ブレーキをかける

このコマンドでは、コマンド名が似ていることもそうですが、コマンドフォーマット自体も「opOUTPUT_STEP_POWER」コマンドに似ています。
なお、基本的な動作は、opOUTPUT_STEP_POWERコマンドと同様で、Step1~Step3に設定したそれぞれの「角度」だけモーターが回転します。
すなわち、コマンドの動作が完了した際には、Step1~Step3に設定した値の分だけモーターが回転しています。
なお、単位は「°」です。
「rad(ラジアン)」ではないので、注意が必要です。

2.サンプルコード

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

#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_STEP_SPEEDコマンドを実行する。                        */
/*                                                                           */
/*===========================================================================*/
int StepSpeed(
        UBYTE ch,
        UBYTE speed,
        UWORD step1,
        UWORD step2,
        UWORD step3,
        UBYTE brake) {
    int ret;
    size_t size;
    STEPSPEED stepSpeed = { 0 };
    stepSpeed.Cmd = opOUTPUT_STEP_SPEED;
    stepSpeed.Nos = ch;
    stepSpeed.Speed = speed;
    stepSpeed.Step1 = step1;
    stepSpeed.Step2 = step2;
    stepSpeed.Step3 = step3;
    stepSpeed.Brake = brake;
    size = sizeof(stepSpeed);
    ret = write(motor_fp, (void *)&stepSpeed, size);

    return ret;
}

/*****************************************************************************/
/*                                                                           */
/*  メイン関数                                                               */
/*                                                                           */
/*****************************************************************************/
int main() {
    UBYTE speed = 100;
    UWORD step1 = 720;
    UWORD step2 = 3600;
    UWORD step3 = 720;
    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);
    //	opOUTPUT_STARTコマンドは、実効しない。
    //MotorStart(CH_D);
    StepSpeed(CH_D, speed, step1, step2, step3, brake);
    sleep(5);

    MotorStop(CH_D);

    ProgramStop();

    close(motor_fp);
    exit(0);
}

動かしてみた

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

見てわかるように、モーターは最初ゆっくり動き始め、その後だんだんゆっくりになり、最終的に停止します。

4. コマンドの注意点

このコマンドを使用する際には、opOUTPUT_STEP_POWERのときと同様の注意点があります。
すなわち、回転方向はPowerの値で決定し、この値に負数を指定した場合には、モーターは逆方向に回転します。
たとえば、「-100」を指定した場合には、「出力100%、回転方向は逆」として認識されてしまいます。

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

次に、StepNに設定する値です。
ます、Step1には、必ず値を設定しなければなりません。
Step1に値を設定しなかった場合、モーターはきちんと動作しないようです。(というか、しませんでした。)
Step2、およびStep3ですが、Step1が設定してあれば、特に設定する必要はないようです。(実際に、値を設定しなくても、モーターは動作しました。)

また、次に記載する点がopOUTPUT_STEP_POWERコマンドと大きな違いです。
すなわち、コマンド実行前にopOUTPUT_STARTコマンドを実行する必要がありません。
いきなりopOUTPUT_STEP_SPEEDコマンドを実行した場合でも、モーターが動作します。

4.まとめ

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