Arduino 伺服 馬達 抖動

這一篇介紹伺服馬達,以Tower Pro(輝盛)的小型伺服馬達SG90為例,價格便宜,在拍賣網站上大約80元,可作為初步練習之用。

我的板子是Arduino Uno R3,Arduino軟體開發環境是1.0.5版。

Arduino 伺服 馬達 抖動

伺服馬達(servo motor),因常用於遙控模型飛機,所以又常稱為RC伺服機(RC Servo,Radio Control Servo,Remote Control Servo)、伺服馬達舵機。

伺服馬達裡含有直流馬達、齒輪箱、軸柄、以及控制電路,我們可透過訊號控制軸柄的停止角度,大概都是0到180度,但不同廠牌型號會有不同的範圍;經由齒輪箱降速後,變成適當可用的轉速,並且提供更高的轉矩(扭轉力)。

另外還有能連續轉動的伺服馬達,有些出廠時便能連續轉動,有些則是玩家自己動手改造,這種馬達透過訊號可控制轉動的速度。

一般伺服馬達有三條線,電源(紅色)、接地(黑或棕色)、訊號線(白、黃、橘、藍,甚至是黑色)。透過訊號線傳送PWM脈波來控制軸柄的停止位置旋轉角度,這個訊號脈波必須每秒重複50次(也就是50Hz),而脈衝持續時間長短便代表了馬達該將軸柄轉到什麼位置,範圍從1.0ms到2.0ms(millisecond,毫秒,千分之一秒),若想置中則是1.5ms;也可將1.0ms當做角度0度,那麼1.5ms會是90度,2.0ms則是轉到底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

從中我們可知,可允許的脈衝範圍是500~2400µs,也就是0.5~2.4ms,比剛剛說的一般範圍還要寬,也就代表這個伺服馬達能旋轉的角度更大。另外有項值得一提的數據是死頻帶寬度,意思是說,因為訊號可能不穩上下起伏,當這一次脈衝寬度與上一次相差不超過死頻帶寬度時,伺服馬達便不會動作。

硬體線路很簡單,因為只有一個伺服馬達,我直接由Arduino的5V腳位供電。若想使用超過兩個,則應以另外的電源供電,而且要記得共同接地。

電路圖如下,除了電源5V與接地外,訊號線接往Arduino的數位腳位9。

Arduino 伺服 馬達 抖動

照片如下,Tower Pro SG90的三條線顏色分別是黃、紅、棕,對應訊號、電源、接地。

Arduino內建操控伺服馬達的程式庫,已經將零零總總的東西通通包起來,使用方法非常簡單,讓我們能以非常簡單的方式操控伺服馬達的旋轉角度。因為需使用PWM,所以會影響原本的PWM腳位,使用此程式庫時,數位腳位9與10便無法輸出PWM,不管有無接伺服馬達,於是我們通常也會將伺服馬達的訊號線接在數位腳位9或10。

接下來是軟體的部份,先讓伺服馬達來回旋轉吧。

#include <Servo.h>

Servo myservo; // 建立Servo物件,控制伺服馬達

void setup()
{
  myservo.attach(9); // 連接數位腳位9,伺服馬達的訊號線
}

void loop()
{
  for(int i = 0; i <= 180; i+=1){
    myservo.write(i); // 使用write,傳入角度,從0度轉到180度
    delay(20);
  }
  for(int i = 180; i >= 0; i-=1){
    myservo.write(i);// 使用write,傳入角度,從180度轉到0度
    delay(20);
  }
}

不過Servo預設的脈衝寬度範圍是544到2400µs,跟SG90的500到2400差了一些些,我們可修正此點。

#include <Servo.h>

Servo myservo;

void setup()
{

  myservo.attach(9, 500, 2400); // 修正脈衝寬度範圍
  myservo.write(90); // 一開始先置中90度
  delay(3000);
}

void loop()
{
  for(int i = 500; i <= 2400; i+=100){
    myservo.writeMicroseconds(i); // 直接以脈衝寬度控制

    delay(300);
  }
  for(int i = 2400; i >= 500; i-=100){
    myservo.writeMicroseconds(i);

    delay(300);
  }
}

要注意的是,必須查詢伺服馬達的規格表,查知正確的脈衝寬度範圍,使用writeMicroseconds時也要小心,不可傳入超出範圍的值,否則會損壞伺服馬達

Servo程式庫中,還有read()可用,但只是讀取上次傳入write()的值;還有detach(),呼叫後伺服馬達就不動了,也就可以使用腳位9的PWM功能。

參考資料:

  • Arduino官方文件Servo library。
  • Cooper Maa的Arduino 筆記 – Lab16 使用可變電阻控制伺服馬達、Lab17 使用光敏電阻控制 Servo。
  • Instructables的Tower Pro SG 90 Micro Servo Hack,修改SG90,讓它能連續旋轉。
  • Adafruit Learning System的About Servos and Feedback,有四條線的伺服馬達,可測量並讀取伺服馬達的旋轉位置,甚至將它當做輸入裝置。

Arduino板子是吃USB供電,當伺服馬達開始供電時,瞬間會吃掉太多電壓,導致板子供電量不足,會開啟重置機制使得供電不穩定。於是,需要電容來協助供電的穩定度。

https://learn.adafruit.com/adafruit-arduino-lesson-14-servo-motors/if-the-servo-misbehaves

用好一點的伺服馬達,便宜的穩定度不佳。官方建議是HK5298伺服馬達。但我想供電電壓的穩定度

用好一點的伺服馬達,便宜的穩定度不佳。官方建議是HK5298伺服馬達。但我想供電電壓的穩定度

Wire是Arduino裡的一個library, 他的位置在

C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\

Wire中的Receive, Send, 因為stream 的關係,對應函數已經更改為read, write

若有其他的函式的呼叫,需要注意修改。

快要完成了!

我們剛剛發給你了一封電郵。 請點擊電郵中的鏈接確認你的訂閱。

好的


很久之前做了一隻機械手臂

用的伺服馬達  一個SG90  跟 五個S03N2   結果一直無法順利控制

我用 5個可變電阻(100K) 進行來控制

一開始使用  NE555電路

控制 1 顆 伺服馬達都還很順利,隨著馬達數量提升 就會越抖動會厲害

然後根本就不受控制的自己亂跳

接著改用89S51單晶片來進行控制

直接輸出 PWM 訊號  指定角度  是可以控制的

所以覺得是可變電阻的雜訊,在電路上+一些電容

也買了比較精密一點的可變電阻 來測試,結果都沒有效果

在網路上看很多人都用 arduino 控制,所以也用了一個

結果是一樣的情形,現在又懷疑是不是電源或電流不夠
(我用5V,0.6A的變壓器接6個SERVO)
(電腦USB 透過arduino板子 輸出+5V接到可變電阻 )

網路上看了很多相關文章,大多都是控制1~2個SERVO
不然就是沒有透過可變電阻 下去控制 ,也找不出抖動的問題

機械手臂放在那兒好久了,希望有大大能夠指點迷津

Arduino 伺服 馬達 抖動

伺服馬達(Servo),對岸稱為舵機。常見於玩具、機器手臂、機器人等用途,一般型式的伺服馬達可以旋轉180度,而且可以被我們透過PWM精準的控制。Arduino Uno可以控制12個伺服馬達,而Arduino Mega則可以控制高達48個伺服馬達。伺服馬達款式型號非常多,本篇以最常見的SG90為例來進行介绍,但其實像MG995的使用基本是相同的。

SG90有3條線,分別是訊號(橘)、VCC(紅)、GND(褐),順序是固定的。這次我們把訊號線接到PIN 9,VCC接到5V,GND接到GND。

絕大多數的情況,我們都會選擇使用Arduino IDE內建的Servo函式庫來控制伺服馬達,雖然是透過PWM來控制伺服馬達,但不表示一定要用有PWM的腳位哦!但這個函式庫有個小小問題,就是除了Mega板以外,像是在Uno板上,會停用D9以及D10的PWM功能,也就是這兩個腳位使用analogWrite()時會出問題。如果是在Mega板上就換成了D11與D12。

參考官方說明:
https://www.arduino.cc/en/reference/servo

順便一提的,單顆伺服馬達在運作時,所需電流大約是300mA,所以如果你需要2顆以上的伺服馬達同時運作,這樣就要外接高電流的變壓器來供電囉,不然就會經常出現抖動的情況。

我們先來寫一個非常簡單的例子:先讓伺服馬達歸零,也就是回到0度,停1秒,再轉到90度,再停一秒,再轉到180度,然後再轉回90度、0度。

程式很簡單,只有幾行,但只要寫完,你基本上就已經學會怎麼控制伺服馬達了。

#include <Servo.h>   //載入函式庫,這是內建的,不用安裝

Servo myservo;  // 建立SERVO物件


void setup() {
  myservo.attach(9);  // 設定要將伺服馬達接到哪一個PIN腳
}

void loop() {   
  myservo.write(0);  //旋轉到0度,就是一般所說的歸零
  delay(1000);
  myservo.write(90); //旋轉到90度
  delay(1000);
  myservo.write(180); //旋轉到180度
  delay(1000);
  myservo.write(90);
  delay(1000);
}

首先要設定伺服馬達要接到哪一個PIN腳,用這行:

myservo.attach(9);

代表我們要把這個伺服馬達接到PIN 9。然後就可以控制伺服馬達的角度了。

myservo.write(0);

write()的參數可以是0-180之間,就是你想控制的角度。真的很簡單,大家可以試試!