ArduinoでNXTのモーターを制御する


Arduinoで回転数を指定して回転できるモーターを使いたかったので、ロータリーエンコーダを内蔵しているNXTのモーターについて調べました。ここでは調べた内容と、実際に動かせるコードを記します。

使用している物

  • SainSmart MEGA2560 互換ボード R3 (ArduinoMegaの互換機)
  • NXTモーター
  • NXT用コネクタケーブル
  • TA7291P(モータードライバIC)

ピン配置

NXT用の端子の黒い膜を剥くと上の写真のように白、黒、赤、緑、黄、青の線が見えます。NXTのモーターにつなげた時、それぞれの役割は次のようになります。

記号 説明
白  MA0 モーター出力1
黒  MA1 モーター出力2
赤  GND ロータリーエンコーダー用ICのGND
緑  POWERMA ロータリーエンコーダー用ICの電源
黄  TACHOA0 ロータリーエンコーダー1
青  TACHOA1 ロータリーエンコーダー2

ロータリーエンコーダ―について

黄、青の線からは、その時点でのロータリーエンコーダ―の状態に応じて、0,1の信号が出ています。...→00→01→11→10→00→01→...のように、回転するごとに順に信号が出るようになっています。これはモーターの中に発光ダイオードとフォトトランジスタがあり、その間に一定の間隔で穴の開いた円盤が挟まれていて、それがモーターと一緒に回りフォトトランジスタに光が入る、入らないが繰り返されることで信号になっているようです。ロータリーエンコーダ― 仕組みなどで調べれば、分かりやすく詳しい解説と図が出てきます。
このロータリーエンコーダは、どちらの線の信号が変わるかによって前転、後転を見分けることができるようですが、今回は回転方向は一定のものとしているのでどちらかが変わったら1、両方が変わったら2、回転した(その回転角の大きさは調べていないのでわかりません)としてプログラムを作りました。

回路

 白と黒の線をモータードライバICであるTA7291Pの2,10ピンにそれぞれ繋ぎました。後は赤、緑の線をArduinoのGND,5Vにそれぞれ繋ぎ、黄、青を任意のデジタルピンに繋げば、動作します。TA7219Pについては、Arduino TA7291Pなどと調べれば詳しく書かれています。

プログラム

motorRotation関数でNXTのモーターを動かします。この関数の中のfor文で、ロータリーエンコーダ―をgetAngle関数で読み取って値を加算していき、指定した値以上になった時にモーターを止めるようにしています。PWMのピン以外はどのピンを用いても大丈夫です。

NXT_motor.ino
//モータードライバーICのピン
#define IN1_PIN 12
#define IN2_PIN 13
//PWMで速さを変更する
#define VREF_PIN 11
//ロータリーエンコーダ―
#define TACHOA0_PIN 14
#define TACHOA1_PIN 15

//任意の大きさ回転する
void motorRotation(int angle);
//ロータリーエンコーダ―を読み取る
int getAngle();
//一つ前のループでのロータリーエンコーダーの状態を入れておく
int past_state[2];

void setup() {
  pinMode(IN1_PIN, OUTPUT);
  pinMode(IN2_PIN, OUTPUT);
  pinMode(TACHOA0_PIN, INPUT);
  pinMode(TACHOA1_PIN, INPUT);
}

void loop() {
  motorRotation(1000);
  delay(1000);
}

void motorRotation(int angle) {
  int now_angle;
  //状態を今のものに更新しておく
  past_state[0] = digitalRead(TACHOA0_PIN);
  past_state[1] = digitalRead(TACHOA1_PIN);
  //モーター駆動開始
  digitalWrite(IN1_PIN, HIGH);
  digitalWrite(IN2_PIN, LOW);
  analogWrite(VREF_PIN, 125);
  //指定された回数まで回転する
  for(now_angle = 0; now_angle <= angle; now_angle += getAngle());
  //ブレーキ
  digitalWrite(IN1_PIN, HIGH);
  digitalWrite(IN2_PIN, HIGH);
  analogWrite(VREF_PIN, 0);
}

int getAngle() {
  //今のロータリーエンコーダ―の状態を入れる
  int now_state[2]; 
  //加算する値を入れる
  int return_value = 0;
  //値を読み取る
  now_state[0] = digitalRead(TACHOA0_PIN);
  now_state[1] = digitalRead(TACHOA1_PIN);
  //前回の情報と比較して返す値を決める
  for(int i = 0; i < 2; i++) {
    //値が違えば動いているので、加算する値を増やす
    if(now_state[i] != past_state[i]) {
      return_value++;
    }
    //情報を更新する
    past_state[i] = now_state[i];
  }
  return return_value;
}

正常に動いていれば一度タイヤを手で止めても回り続けるので、それで確認できると思います。

最後に

NXTの部品もそれぞれの線が何に当たるかが分かればArduinoでも使えことるとが確認できたので、NXTのセンサーなども使ってみたいなぁと思ってます。

参考