用途
步進馬達可以控制比較精密的動作, 例如4相步進馬達, 可以把一圈360度分為2048 or 4096 個等分, 程式碼可以精密的控制馬達轉動等分.
步進馬達定位較精確, 可使用1000rpm以內的速度運轉, 適合動作頻繁與距離短的應用, 比如自動門的開啟. 步進馬達通常搭配控制晶片, 程式比較容易設計, 以下使用整合ULN2003晶片的控制模組, 可連接步進馬達的插座、指示燈號與連接到Raspberry Pi的針腳‧
至於伺服馬達, 也可精確的控制馬達定位角度, 反應速度比步進馬達快, 運轉的扭力也較大, 但轉向只能在0-180度之間, 通常適用於方向機之類的應用.
照片
28BYJ-48 會附有一個控制板, 控制板的編號為 ULN2003. 透過控制板就可以容易的控制步進馬達. 請注意, UL2003的電源可使用5V 及12V. 而本版本的右邊是+ 極, 左邊是 – 極.
小編曾參照網路上的接法, 將正反極接反而無法運轉, 還好沒有燒掉.
規格
28BYJ-48的規格如下
Rated voltage : 5VDC
Number of Phase : 4 相
Speed Variation Ratio : 1/64
Stride Angle : 5.625° /64
Frequency : 100Hz
DC resistance : 50Ω±7%(25℃)
Idle In-traction Frequency : > 600Hz
Idle Out-traction Frequency : > 1000Hz
In-traction Torque >34.3mN.m(120Hz)
Self-positioning Torque >34.3mN.m
Friction torque : 600-1200 gf.cm
Pull in torque : 300 gf.cm
Insulated resistance >10MΩ(500V)
Insulated electricity power :600VAC/1mA/1s
Insulation grade :A
Rise in Temperature <40K(120Hz)
Noise <35dB(120Hz,No load,10cm)
Model : 28BYJ-48
28BYJ-48 是四相 5線的規格
運作方式
下圖為四相圖面, 所謂四相是指有四個定子, 也就是四組線圈. 而下圖的激磁方式為一次激發一組線圈, 稱為一相激磁.
1. 先激發北方的線圈, 把轉子的N極吸到北方.
2. 激發西方的線圈, 把轉子的N極及到西方.
3. 激發南方的線圈, 把轉子的N極及到南方.
4. 激發東方的線圈, 把轉子的N極及到東方.
此種方式電力消耗小, 缺點是振動大, 轉距小.
一相激磁
二相激磁
二相激磁是一次激發二組線圈, 如下圖. 此種方式振動小、轉距大
半相激磁
先激發北方, 再激發北/西, 然後西, 西/南, 南, 南/東, 東, 東/北
角度控制
上述不論是一相激磁, 二相激磁, 還是一/二相激磁(半相), 不是四個方向, 頂多也才八個方向而以. 那如何控制在精準的其他角度呢.
原來是每次送一個脈衝, 就改變一個基本步進角, 然後停住.
一相激磁, 二相激磁
先看一下官方原文的說法
There are 32 steps per revolution on my sample motor, and inside is a 1/64 reduction gear set. Gear reduction is actually : (32/9)/(22/11)x(26/9)x(31/10)=63.683950617, This means is that there are really 32*63.683950617 steps per revolution = 2037.88641975 ~ 2038 steps!
上述說明, 在一相激磁或二相激磁時, 轉子每轉一圈是32步(齒), 也就是每一次脈衝, 就會轉1齒, 需要32次脈衝才會轉一圈. 但裏面有一個減速齒輪組, 是1:64的比率. 也就是說轉子轉64圈, 輸出軸心才會轉一圈.
說的更白話一點, 也就是輸出軸心轉一圈, 轉子需轉64圈, 而轉子一圈為32步, 所以轉子64圈就是 64*32=2048步, 所以輸出軸心一圈就是 2048步.
由上換算出基本步進角為 : 360/2048=0.17578125°
半相激磁
半相激磁時, 轉子一圈是64步(齒), 再套上 1:64的減速齒輪組, 因此輸出軸心轉一圈是 64*64=4096步
由上算出基本步進角為 360/4096 = 0.087890625°.
ps. 但更精細的規格是, 減速齒輪組其實是 (32/9)/(22/11)/(26/9)/(31/10)=63.683950617, 也就是轉子跟傳輸軸比為 1:63.683950617, 所以傳輸軸的正確步數為 2038步及4075步
接線
簡易程式
Pi4J提供GpioStepperMotorComponent 類別, 是控制步進馬達是最方便的作法。GpioStepperMotorComponent類別包裝在 pi4j-device.jar中, 所除了加入pi4j-core.jar外,也要加入pi4j-device.jar.
請注意, 經本人測試, 使用一相或二相激磁, 就是約2048步, 使用 一/二相激磁, 就是4096步.
在半相之下, 使用setStepsPerRevolution(4096), motor.rotate(0.25)則會轉 1/4圈(90度), 但若設為 setStepsPerRevolution(2048), 則rotate(0.25)僅會轉 45 度.
setSetpInterval
Motor物件需設定 setStepInterval()方法, 也就是每走一步後, 要停留的時間, 本人測試, 只要低於 1.5ms, 就不會動, 甚至可能會燒掉. 其實設定停留時間是可以指定nano second的, 如下
motor.setStepInterval(1, 500000);
另外 setStepInterval() 是相當不精準的. 一來這是使用C語言 delay的方式來延遲, 本身就受執行緒條件限制, 所以很不精準. 二來是馬達每走一步也要時間, 但行進的時間並未算入, 所以千萬別用這個裝置來製作時鐘.
底下程式, 會讓步進馬達正向轉二圈, 然後再反向轉二圈
package steppermotor;
import com.pi4j.component.motor.impl.GpioStepperMotorComponent;
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;
public class StepperMotor {
//一相激磁
public static final byte[] SINGLE_STEP = {
(byte) 0b0001,
(byte) 0b0010,
(byte) 0b0100,
(byte) 0b1000 };
//二相激磁
public static final byte[] DOUBLE_STEP = {
(byte) 0b0011,
(byte) 0b0110,
(byte) 0b1100,
(byte) 0b1001 };
//半相激磁
public static final byte[] HALF_STEP = {
(byte) 0b0001,
(byte) 0b0011,
(byte) 0b0010,
(byte) 0b0110,
(byte) 0b0100,
(byte) 0b1100,
(byte) 0b1000,
(byte) 0b1001 };
// 4-Step sequence: 32 * 63.68395 = 2037.8864 (2038)
public static final int STEPS_PER_REV = 2038;
public static void main(String[] args) {
System.out.println("StepperMotorDemo01 Start...");
final GpioController gpio = GpioFactory.getInstance();
// 建立控制步進馬達的GPIO輸出物件
final GpioPinDigitalOutput[] pins = {
gpio.provisionDigitalOutputPin(RaspiPin.GPIO_02, PinState.LOW),
gpio.provisionDigitalOutputPin(RaspiPin.GPIO_03, PinState.LOW),
gpio.provisionDigitalOutputPin(RaspiPin.GPIO_04, PinState.LOW),
gpio.provisionDigitalOutputPin(RaspiPin.GPIO_05, PinState.LOW)};
// 結束時把輸出針腳設定為低電壓
gpio.setShutdownOptions(true, PinState.LOW, pins);
// 建立步進馬達物件
GpioStepperMotorComponent motor =
new GpioStepperMotorComponent(pins);
// 設定每一步的間隔時間
motor.setStepInterval(2);
// 設定運作模式
motor.setStepSequence(SINGLE_STEP);
motor.setStepsPerRevolution(STEPS_PER_REV);
while(true){
// 正向轉一圈
motor.rotate(1);
delay(50);
// 反向轉一圈
motor.rotate(-1);
delay(50);
}
}
private static double angleToRev(int angle) {
return angle / 360.0;
}
private static void delay(int ms) {
try {Thread.sleep(ms);}
catch (InterruptedException e) {}
}
}
精準控制
指定角度
底下是在4096半相激磁時, 每次進1度的用法
motor.rotate(-1/360.0);
try {Thread.sleep(300);} catch (InterruptedException ex) {}
指定步數
底下是在4096半相激磁時, 每次進1步的用法
motor.step(-1);
try {Thread.sleep(300);} catch (InterruptedException ex) {}
另外還有 motor.forward(), motor.reverse();
自動門程式
底下程式, 使用超音波測距模組, 偵測若有人接近, 就啟動步進馬達開啟自動門. 若人離開, 就關閉自動門
下面程式碼有個特性, 假設開門跟關門, 輸出軸心要轉1.5圈才會全開跟全關. 所以在一開始的1.0圈要快速開啟, 但後面剩於的0.5圈為了防止撞擊力道太大, 又分為二部份, 前面0.25圈開始減速, 最後0.25圈速度更底.
那程式碼就可以寫成如下
motor.setStepInterval(2); motor.rotate(-1.0); motor.setStepInterval(3); motor.rotate(-0.25); motor.setStepInterval(5); motor.rotate(-0.25); motor.setStepInterval(2); motor.rotate(1.0); motor.setStepInterval(3); motor.rotate(0.25); motor.setStepInterval(5); motor.rotate(0.25);