🐡

C言語でのモーター制御

に公開

概要

C言語でモーターの制御をしたいと思っているのですが、効率的なデザインパターンがありそうなので記事にしました。一応Arduinoを想定して書いています。

ソースコード

ヘッダーファイル
https://github.com/begengineer/modanC/blob/main/manyMotor/motor.h
プログラムファイル
https://github.com/begengineer/modanC/blob/main/manyMotor/motor.c

コード説明

  1. モーター構造体を作成
    モーターの構造体を作成します。
    ピン設定や現在の状態、動かし方を定義する関数ポインタなどを設定します。ここで関数ポインタの引数に自分の構造体を渡してあげると構造体で設定したピンの項目をそのまま使用できるので個別制御の場面で便利だと思います。
// モーター構造体
typedef struct{
    const uint8_t dirPin;
    const uint8_t pwmPin;
    const uint8_t drivePin1;
    const uint8_t drivePin2;

    // 現在の状態
    MTRState currntState;

    // 重要なのはここ。状態と関数を列挙体を用いて紐づけてあげる
    void (*stateProcs[3])(MotorS *motor);

    // 現在の速度
    uint8_t currntduty;
} MotorS;
  1. モーターを動作させる関数を定義する
    今回だと停止、前進、後進ができる関数を作成します。(今回は作成していません)
  2. 制御するモーターの個数だけモーター構造体を定義する
    このように配列で定義して、enumで宣言したモーターの順番で定義すると便利かもしれません。
    今回のコードで一番便利なのはここだと思っています。構造体でモーターの定義をすると複数のモーターを一元管理できます。
MotorS motors[MOTOR_NUM] = {
    { .dirPin = 1,.pwmPin = 5,.drivePin1 = 9,.drivePin2 = 13,.currntState = STOP,.currntduty = 0},
    { .dirPin = 2,.pwmPin = 6,.drivePin1 = 10,.drivePin2 = 14,.currntState = STOP,.currntduty = 0},
    { .dirPin = 3,.pwmPin = 7,.drivePin1 = 11,.drivePin2 = 15,.currntState = STOP,.currntduty = 0},
    { .dirPin = 4,.pwmPin = 8,.drivePin1 = 12,.drivePin2 = 16,.currntState = STOP,.currntduty = 0},
};
  1. 初期化:ピンの設定を初期化する
    3で設定したピン情報を実際のハードウェア設定に反映させます。
    この時に動かし方を定義した関数を適応してあげます。
void initMTR(){
    for(int i = 0;i < MOTOR_NUM;i++){
        pinMode(motors[i].dirPin, OUTPUT);
        pinMode(motors[i].pwmPin, OUTPUT);
        pinMode(motors[i].drivePin1, OUTPUT);
        pinMode(motors[i].drivePin2, OUTPUT);

        // 状態テーブル
        motors[i].stateProcs[STOP]     = motorStop;
        motors[i].stateProcs[FORWARD]  = motorForward;
        motors[i].stateProcs[BACKWARD] = motorBackward;
    }
  1. 駆動させてみる。
    このようにプログラムファイルでモーターの構造体を宣言してあげると使用者側からは動かしたいモーターとそのモーターの動かし方だけを気にすれば良いのでプログラム作成が楽になると思います。
// モーター駆動処理
bool motorDrive(MTRTYPE motortype,MTRState wantstate){
    motors[motortype].stateProcs[wantstate](&motors[motortype]);
    // 状態を更新
    motors[motortype].currntState = wantstate;
    // 戻り値を返す
    return true;
}

まとめ

このように構造体と関数ポインタを用いるとモーターの管理が楽になると思いました。
次はこのモーターをどうやって動かすかを状態遷移テーブルを用いて実装してみたいです。

Discussion