ELEGOO:Lesson 31,32,33 Stepper Motor

Lesson 31 Stepper Motor

いよいよ、最後のカテゴリ。ステッピングモータ(英語だと Stepper Motor になるのかな)です。

ステッピングモータ本体と、ステッピングモータコントローラ基板。

ステッピングモータとサーボモータ、似てる気がするけど、何が違うのか。

正直、まだズバっと説明できません。モーター内のコイルの状態を自分で制御して、軸を回転させるのがステッピングモータで、制御用のコントローラも必要。そういう細かい制御は考えずに、与えられた入力にあわせた角度に回転して停止するのがサーボモータ、ぐらいの理解です。

360度連続回転可能なサーボ(ローテーションサーボ)というのあるみたいですね。


コントロールモジュールを用いて制御します。ドライバーチップは ULN2003。モジュール基板にはLEDが4つ付いてて、ステッピングモータの動作状態を表示します。

ステッピングモータは、内部にコイルが4つ入っていて、これに電流を流したり流さなかったりすることで、回転を発生させています。コントロール基板の4つのLEDで、それぞれのコイルの状態を表示してます。

プログラムは、Steppter ライブラリを使ってます。ino側では、ライブラリ呼んでるだけです。

#include <Stepper.h>
const int stepsPerRevolution = 2048; // change this to fit the number of steps per revolution
const int rolePerMinute = 15; // Adjustable range of 28BYJ-48 stepper is 0~17 rpm
// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);
void setup() {
  myStepper.setSpeed(rolePerMinute);
  // initialize the serial port:
  Serial.begin(9600);
}
void loop() {
  // step one revolution in one direction:
  Serial.println("clockwise");
  myStepper.step(stepsPerRevolution);
  delay(500);
  // step one revolution in the other direction:
  Serial.println("counterclockwise");
  myStepper.step(-stepsPerRevolution);
  delay(500);
}

定数として以下を定義。

const int stepsPerRevolution = 2048;
const int rolePerMinute = 15;

最初に、ライブラリの初期化

Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);

このライブラリは、ステッピングモータの信号が5つ、4つ、2つに対応してます。

2つの場合の初期化

Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2)

4つの場合の初期化

Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2,int motor_pin_3, int motor_pin_4)

5つの場合の初期化

Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2,int motor_pin_3, int motor_pin_4,int motor_pin_5)

今回は4つですね。1回転のステップ数と、接続してる4つのピン番号を指定します。

Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);

例だと、10と9が逆ですね…。なんでだ?
気になったので、順番を入れ替えて、

Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);

これも試してみたのですが、こちらの場合は回転しませんでした。うーん?ピンの順番と指定順は異なっている…?

setSpeedで 回転スピードの設定

myStepper.setSpeed(rolePerMinute);

rolePerMinute = 15なので、1分間に 15回転の速度。

ライブラリ内の関数 setSpeed では、全体のステップ数と、回転速度を元に、

void Stepper::setSpeed(long whatSpeed)
{
  this->step_delay = 60L * 1000L * 1000L / this->number_of_steps / whatSpeed;
}

最低回転単位時間(動かした後の待ち時間)を決めてます。

動かすときには step を呼び出します。

myStepper.step(stepsPerRevolution);

これで、指定したステップ数、回転します。内部的には、最低回転単位時間ごとに1ステップ回転して、指定したステップ数を回転終わるまでループします。

回転が分かりやすいように、回転軸にキャップかぶせてみました。

では、回転!

回転!0.5秒待ち。反転!


Lesson 32 Controlling Stepper Motor With Remote

IR receiver と組み合わせて、リモコンでステッピングモータをコントロール。

リモコンは Lesson 14 ですでに使ってますね。今回は単にそれらの組み合わせです。

「VOL+」押すと時計方向、「VOL-」押すと反時計方向に回転します。


Lesson 33 Controlling Stepper Motor With Rotary Encoder

ラスト!ロータリーエンコーダでのコントロールです。

ロータリーエンコーダは、回転入力と押し込み入力が可能です。

const int PinCLK=2; // Generating interrupts using CLK signal
const int PinDT=3; // Reading DT signal
const int PinSW=4; // Reading Push Button switch

ピン2 がクロック入力(回転したらクロック発生)
ピン3 が回転方向の入力
ピン4 が押し込み入力です。

ロータリーエンコーダの回転は、割り込み処理で取得します。

attachInterrupt (0,isr,FALLING); // interrupt 0 always connected to pin 2 on Arduino UNO

回転を検出した時に isr () が呼び出されます。

最後の最後で割り込み処理 attachInterrupt がいきなり登場してきましたね。

Arduino 日本語リファレンス:attachInterrupt(interrupt, function, mode)
http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=3069

パラメータは以下の通り。

interrupt: 割り込み番号
function: 割り込み発生時に呼び出す関数
mode: 割り込みを発生させるトリガ
LOW ピンがLOWのとき発生
CHANGE ピンの状態が変化したときに発生
RISING ピンの状態がLOWからHIGHに変わったときに発生
FALLING ピンの状態がHIGHからLOWに変わったときに発生

どのピンでどの割込み番号が発生するかは、Arduinoの種類によって変わってきます

Mega2560 の場合は、以下の通り。

ピン2:割り込み番号 0
ピン3:割り込み番号 1
ピン21:割り込み番号 2
ピン20:割り込み番号 3
ピン19:割り込み番号 4
ピン18:割り込み番号 5

2番(クロックのピン)がHIGH から LOW になったとき、つまり、ロータリーエンコーダ回転操作をしたときに割り込み0が発生して isr () が呼び出されます。

void isr () {
  delay(4); // delay for Debouncing
  if (digitalRead(PinCLK))
    rotationdirection= digitalRead(PinDT);
  else
    rotationdirection= !digitalRead(PinDT);
  TurnDetected = true;
}

回転方向を PinDT で判定。PinCLKの値で向きを逆にしてる?これはちょっと後で調べます…。

回転を検出したら、検出した方向にステッピングモータを50ステップ回転。

押し込みはデジタル値で判定可能。

if (!(digitalRead(PinSW))) { // check if button is pressed
  if (RotaryPosition == 0) { // check if button was already pressed
  } else {
    small_stepper.step(-(RotaryPosition*50));
    RotaryPosition=0; // Reset position to ZERO
  }
}

押し込まれたら、ステッピングモータの位置を回転してた分だけ戻します。

ロータリエンコーダを回すと、ステッピングモータも回転!


ついに!ELEGOO Lesson、全部完了しました!やりとげました!

1年近くかかってしまいましたが…。