用途
伺服馬達(servo motor),可用於遙控模型汽車或機械手臂的轉向, 所以又常稱為RC伺服機(RC Servo)、伺服馬達舵機。
伺服馬達內含直流馬達、齒輪箱、軸柄、以及控制電路, 可透過訊號控制軸柄角度, 大都是0到180度, 不同廠牌型號會有不同的範圍. 經由齒輪箱降速後, 變成適當可用的轉速, 提供更高的扭轉力.
一般伺服馬達有三條線,電源(紅色)、接地(黑或棕色)、訊號線(橘). 透過訊號線傳送PWM脈衝控制軸柄的停止位置旋轉角度,脈衝波必須達到50Hz, 也就是每20ms發送一次脈衝. 而脈衝持續供電狀態下的時間長短便代表了馬達該將軸柄轉到什麼位置.
本章節使用Tower Pro SG90這個Servo進行實驗, 其規格為 0.5ms代表0度, 2.4ms代表 180度, 不在此範圍的脈衝寬度將會造成馬達燒毀.
不同廠牌型號的伺服馬達可允許旋轉的角度各不相同,請詳查產品規格書
型號規格
型號 : Tower Pro SG90
重量:9g
尺寸:23*12.2*29mm
工作電壓:4.8V
轉矩:1.8kg-cm,當工作電壓為4.8V時
運轉速度:0.1秒 ∕ 60度 ,當工作電壓為4.8V時
脈衝寬度範圍:500~2400µs
死頻帶寬度(dead band width):10µs
接線
SG90的黑色線為接地, 需接到樹莓派實体編號的第6支接腳, 紅色線需輸入5V的電壓, 所以需接樹莓派的實体編號第2支接腳, 橘色線為控制線, 接GPIO 1之接腳
極限值
SG90的脈衝寬大於一般的伺服馬達. 所以網路上有人說, 這樣子的話, 角度會大於180度, 但也有人說大於180度是錯誤的.
但經本人實驗, value最小值為54, 最大值是280, 總共有227個值, 中間值為167. 然後再由量角器實際測量 SG90的最大旋轉角度也在226度.
以上, 經由實際測量, SG90的最大角度的確會到226度. 所以凡事還是要自已用心觀查求證.
嗯, SG90是目前試過蠻精準的元件, 可以給個讚
程式
找遍了網路上所有的資源, 幾乎找不到使用Java撰寫伺服馬達的程式, 後來經歷馬達燒掉的危險, 終於試出如下的程式碼了.
首先將SG90的頻率控制在192Hz,然後將Range 設為2000,
再將值控制在50~240之間, 就會由 50/2000~240/2000 = 2.5%~12%之間
package servotest; import com.pi4j.wiringpi.Gpio; import com.pi4j.wiringpi.GpioInterrupt; public class ServoTest { static boolean closeFlag=false; public static void main(String[] args){ int start=54; int end=280; int init=start; Gpio.wiringPiSetup(); Gpio.pinMode(1, Gpio.PWM_OUTPUT); Gpio.pwmSetMode(Gpio.PWM_MODE_MS); Gpio.pwmSetRange(2000); Gpio.pwmSetClock(192); Thread thread=new Thread(()->{ int angle=init; int dir=1; int speed=1; int interval=100; while(true){ Gpio.pwmWrite(1, angle); try {Thread.sleep(interval);} catch (InterruptedException ex) {} angle+=dir * speed; System.out.printf(String.format("angle= %d\n", angle)); if(angle>=end || angle<=start)dir=-1*dir; } }); thread.start(); Gpio.pinMode(0, Gpio.INPUT); GpioInterrupt.addListener((event)->{ System.out.println("Raspberry Pi PIN [" + event.getPin() +"] is in STATE [" + event.getState() + "]"); switch(event.getPin()){ case 0: closeFlag=true; thread.interrupt(); break; } }); GpioInterrupt.enablePinStateChangeCallback(0); while(!closeFlag){ try {Thread.sleep(500);} catch (InterruptedException ex) {} } GpioInterrupt.disablePinStateChangeCallback(0); Gpio.pinMode(1, Gpio.PUD_OFF); Gpio.pwmWrite(1, 0); } }