mBlock & Arduino(16)控制步進馬達


步進馬達這東西的學問真不少,就結論而言,控制步進馬達最好的方式,就是找到與手邊步進馬達可以配合的程式庫來使用。Arduino IDE 不是有 Stepper 程式庫可以使用嗎?嗯!它是可以用一些步進馬達上,不過,不見得能完全發揮步進馬達應有的控制能力,控制某些馬達則會有些問題,正巧,我手上這顆 28BYJ-48 5V DC 就是!… XD

認識步進馬達

在 Arduino 官方網站的 Arduino - Stepper 文件中,談到了步進馬達的兩個基本分類:單極步進馬達(Unipolar Stepper)與雙極步進馬達(Bipolar Stepper)。那麼就從這兩個分類開始認識!

單極步進馬達是提供單一方向的電流來驅動馬達,例如:

單極步進馬達

在上圖中,可以看到線圈各有一個共同接點,通常接電源,只要改變其他接點的電壓訊號,就可以產生電流,而電流都是固定的方向,而由於有四個線圈,這樣的馬達被稱為四相(Phase)馬達。

雙極步進馬達的電流則是雙向的,例如:

雙極步進馬達

這類馬達在驅動時,需要改變電流的方向來達到不同激磁的效果,而由於有兩個線圈,這樣的馬達被稱為二相馬達。

馬達的相數除了二向、四相之外,還有單相、三相、五相等,這是為了達到不同程度的控制,馬達的控制是運用電流通過線圈會產生磁場,並與另一永久磁鐵產生作用,來達到轉動的效果,以四相步進馬達為例:

一相激磁

如果做為定子的線圈激磁後,面對轉子一面是 S 極,就會吸引轉子的 N 極,只要依順序對各相線圈激磁,就會產生轉動效果,像上面這種一次激磁一個線圈的方式,稱為一相激磁,因為每次只激磁一個線圈,電力消耗小,不過缺點是振動大、轉距小。

常見的激磁方式是二相激磁,顧名思義,一次激磁兩相,由於有兩相用以吸引住轉子,因此振動小、轉距大:

二相激磁

也有一相、二相輪流激磁,稱為一/二相激磁,順序其實就是上面兩張圖的結合:

一/二相激磁

可以看出這種激磁方式,每次轉動的角度為一相或二相激磁的一半,可以得到更精確的控制。

步進馬達控制電路

步進馬達需要比較高的電壓或電流驅動,在 Arduino 官方網站的 Arduino - Stepper 文件中,有 Unipolar SteppersBipolar Steppers 兩個頁面,介紹了如何連接出能驅動步進馬達的電路,分別有可以接成兩個控制腳位與四個控制腳位的方式。

其中會用到的 IC 是達靈頓陣列(Darlington Array),如先前〈mBlock & Arduino(15)認識電晶體與繼電器〉談到的,若想運用電晶體提供更大的電流來驅動馬達,可以使用兩個或多個電晶體的組合,達靈頓陣列中有多組達靈頓電路,以 ULN2003APG 來說,裏頭有七組達靈頓電路。

如果不想那麼麻煩地自己接電路,那麼可以依使用的步進馬達來搭配現成的步進馬達驅動模組:

步進馬達驅動模組

這個步進馬達驅動模組,左上四個腳位可以接到 Arduino 的數位輸出腳位,下方有 +、- 兩個腳位,分別接 Vcc 與 GND,右上白色插槽用來連接我手邊這顆五線四相的 28BYJ-48 5V DC,上圖步進馬達驅動模組中的 ULN2003APG,可搭配 28BYJ-48 5V DC 這個步進馬達:

28BYJ-48 5V DC 步進馬達

28BYJ-48 5V DC 這個步進馬達,其中紅線是接 5V 電源,各線的連接是:

28BYJ-48 5V DC 步進馬達

如果搭配 ULN2003,要對 28BYJ-48 5V DC 步進馬達做激磁,那麼 ULN2003 的輸入腳位 4、3、2、1,提供電位以進行激磁的順序為 …

  • 一相激磁:1000-0100-0010-0001
  • 二相激磁:1100-0110-0011-1001
  • 一/二相激磁:1000-1100-0100-0110-0010-0011-0001-1001

以 mBlock 控制步進馬達

如果想要體驗一下步進馬達轉動,那麼可以簡單地如下實作,腳位 D8 到 D11 分別對應至澄、黃、粉、藍,例如一相激磁:

mBlock 控制步進馬達

執行程式之後,你可以見到步進馬達緩慢的轉動,將順序改為 S4 到 S1,就會看到馬達緩慢的逆轉,這邊沒有設任何的工作時間延遲,這是因為 mBlock 執行速度的關係,直接使用 Arduino 積木方塊,只能是這個速度了。

類似地,以下是二相激磁:

mBlock 控制步進馬達

以下是一/二相激磁:

mBlock 控制步進馬達

關於 Stepper 程式庫

如果想更進一步試試步進馬達控制,可以使用 Arduino IDE 中的 Stepper 範例,它們使用到 Arduino 的 Stepper 程式庫,不過,如果你手邊是 28BYJ-48 5V DC 步進馬達,就要注意一下了,以 stepper_oneRevolution 範例為例:

#include <Stepper.h>

const int stepsPerRevolution = 200;  
// change this to fit the number of steps per revolution
// for your motor

// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);

void setup() {
  // set the speed at 60 rpm:
  myStepper.setSpeed(60);
  // 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);
}

直接執行的話,你的馬達只會有一個方向的轉動,無法逆轉,這是因為 28BYJ-48 5V DC 的接線順序,與 Stepper 程式庫預期的不同,如果你的 28BYJ-48 5V DC 的接線順序由澄、黃、粉、藍分別是接至 D8 到 D11,那麼有兩個方式可以解決,一個方式是在 Arduino 上將 D9 與 D10 接線對調,另一個方式是在建立 Stepper 時,910 對調:

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

再來是 stepsPerRevolution 必須設定為你的馬達實際上一圈會有多少步,如果是 28BYJ-48 5V DC 的話,查詢到的規格上寫著,步進角為 5.625 / 64,因此這馬達轉一圈需要的步數是 360 / (5.625 / 64),也就是 4096 步,不過,這是一/二相激磁才會有的步數,如果你查看 Stepper 程式庫原始碼,會發現,它是採二相激磁的實作方式,因此,使用這個 Stepper 程式庫,你實際上要設的 stepsPerRevolution 必須是 2048 步。

不過,如果你改了腳位也將 stepsPerRevolution 設為 2048,步進馬達還是不會動,這是因為 Stepper 程式庫中 setSpeed 函式的關係:

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

這是以毫秒為單位來設置 step_delay,如果你設為 2048 步,那 number_of_steps 就是 2048,那麼 step_delay 就會是 29.296875 / whatSpeed,如果 whatSpeed 設為 60,那結果就會是 0.48828125,然而 step_delayunsigned long,也就是實際上結果只會儲存 0,那麼 step 函式中 millis() - this->last_step_time >= this->step_delay 該行,就會一直是成立的,也就是完全沒給工作時間,這麼一來馬達就不會動了。

因此,如果你直接使用 Stepper 程式庫,設為 2048 步之後,那麼速度就不能設太高,例如以下就可以正常正反轉了:

#include <Stepper.h>

const int stepsPerRevolution = 2048;  
// change this to fit the number of steps per revolution
// for your motor

// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);

void setup() {
  // set the speed at 60 rpm:
  myStepper.setSpeed(5);
  // 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);
}

如果你會使用 Arduino 官方語言的話,改寫 Stepper 應該不是難事,可以試著實作一/二相激磁,並令其能支援 28BYJ-48 5V DC 的 4096 步與高轉速,懶的話,網路上是也有人已經實作或改寫好的版本,不過,想要精確控制的話,重點還是在於,認識你的步進馬達與程式庫!