Arduino筆記(15):控制伺服馬達 Servo

先前寫的一篇文章:「Arduino筆記(八):控制步進馬達」,說明如何使用Arduino 的 Stepper 函式庫,控制步進馬達的正反轉。這篇文章要來實做一下伺服馬達的功能?同樣都是馬達,步進馬達和伺服馬達有和不同?同樣都可控制正轉反轉以及轉速,簡單的說最大的差別在於伺服馬達有回饋反授的機制,會將訊號傳回給驅動器;而步進馬達不會回傳訊號,這就是最大的不同。也因為這個回饋反授機制,讓伺服馬達轉動時的精確度較高,不會有失步的狀況。以下就來看看如何透過 Arduino 控制伺服馬達。

Adruino 開發板提供的電壓是 5V,如果供給 MG996R伺服馬達使用,在空轉情況下應該沒有問題,但如果接有其他電子零件,可能就會不夠,建議再加額外的電源給伺服馬達,本篇也會說明外接電力的方式。


[Servo Library]

•  attach(pin, min, max) :連接伺服馬達的控制線給 Arduino 的一個 Pin 腳
  pin : 在早期的 Arduino 只能指定 Pin 9 跟 Pin 10
  min (選項) : 對應於伺服上的最小 ( 0度) 角度的脈衝寬度 (以微秒為單位),預設為 544
  max (選項) : 對應於伺服上的最大 (180度) 角度的脈衝寬度 (微秒),預設為 2400
•  write(angle) :將值寫到伺服機相對應的控制軸
  angle: 寫到伺服機的值,從 0 到 180
•  read():讀取目前的伺服機值

[材料]

  • Arduino Uno x 1
  • 伺服馬達 (型號 MG996R) x1
  • 連接線 x 3條
     MG996R  伺服馬達規格
  • 角度:180度 (對應的角度是-90度~+90度)
  • 扭力:11KG 大扭力舵機/金屬齒輪伺服器
  • 產品淨重: 55g
  • 產品拉力: 9.4kg/cm(4.8V ), 11kg/cm(6V)
  • 反應速度: 0.17sec/60degree(4.8v) 0.14sec/60degree(6v)
  • 工作電壓: 4.8-7.2V
  • 齒輪形式: 金屬齒輪


[接線圖一:讓伺服馬達正反轉] 

• MG996R連接線路

MG996RArduino
橘色線 PWMPin 9
紅色線 V+5V
棕色線 GNDGND


• MG996R 直接連接接 Arduino 電源

• MG996R 外接電源,再連接 Arduino


[程式一]

#include <Servo.h>

Servo myservo;  // 建立一個 servo 物件,最多可建立 12個 servo

int pos = 0;    // 設定 Servo 位置的變數

void setup() {
  myservo.attach(9);  // 將 servo 物件連接到 pin 9
}

void loop() {
  // 正轉 180度,從 0 度旋轉到 180 度,每次 1 度
  for (pos = 0; pos <= 180; pos += 1)  
  {     
    myservo.write(pos);    // 告訴 servo 走到 'pos' 的位置
    delay(15);        // 等待 15ms 讓 servo 走到指定位置
  }

  // 反轉 180度,從 180 度旋轉到 0 度,每次 1 度 
  for (pos = 180; pos >= 0; pos -= 1) 
  { 
    myservo.write(pos);   // 告訴 servo 走到 'pos' 的位置

    delay(15);   // 等待 15ms 讓 servo 走到指定位置
  }
}


[接線圖二:利用電阻控制伺服機] 


• MG996R及電阻連接線路
MG996RArduino可變電阻
棕色線 GNDGNDPin 1
紅色線 V+5VPin 3
橘色線 PWMPin 9-
-Pin A2Pin 2


[程式二]


#include <Servo.h>
Servo myservo;   // 建立一個 servo 物件,最多可建立 12個 servo

int r1_pin = 2;  // 可變電阻連接的 pin 腳
int r1_val;      // 從可變電阻來的數值 

void setup() 
{ 
  myservo.attach(9);  // 將 servo 物件連接到 pin 9
} 

void loop() 
{ 
  // 從可變電阻讀取類比數值 (介於 0 跟 1023) 
  r1_val = analogRead(r1_pin);  

  // 將類比值轉換為 servo 可讀取的範圍值(介於0 跟 180)      
  r1_val = map(r1_val, 0, 1023, 0, 179);  
  myservo.write(r1_val);   // 設定 servo 位置 
  delay(15);               // 等待 15ms 讓 servo 走到指定位置
} 


[實作結果]

[參考資料]

21 留言

  1. 作者已經移除這則留言。

    回覆刪除
  2. 作者已經移除這則留言。

    回覆刪除
  3. #include servo.h---->#include "S"ervo.h

    回覆刪除
    回覆
    1. 在編輯Html時,修改 Servo.h前後的括號改成 &lt 時,誤將S改成小寫,已經修正,謝謝您。

      刪除
  4. 哈囉 想請教一下~
    read函式可以直接讀取馬達目前的角度嗎? 還是讀取到的是前一次自己設定要擺動的角度呢?
    因為我想讓伺服馬達像風扇一樣左右擺動,並且接一個按鈕,當我按按鈕就回傳當下的角度
    不知道是否可以實現
    非常感謝!

    回覆刪除
    回覆
    1. 您好, read函式無法讀取目前伺服馬達的角度, 但是我看過有些網友對伺服馬達稍加改造後, 找到Encoder回授信號即可讀取目前位置, 詳細作法可參考其他網友的文章:http://sinocgtchen.blogspot.tw/2014/10/servo-smart-servo-servo-hacked.html

      刪除
  5. 我想請問一下 我使用你的PROGRAM 但改了用其他pin,卻無反應,我用了pin6和pin11都沒有反應,但用pin10卻有,是怎麼回事

    回覆刪除
    回覆
    1. 根據你的描述,我也不知道為何會這樣?有沒有重新Reset試看看?有沒有可能線沒接好?

      刪除
  6. 請問版主可以留下line或是fb嗎?我想請你幫些忙����

    回覆刪除
  7. 您好,因為我需要控制兩個馬達,我用兩顆獨立的可變電阻,接在麵包版上,並仿照範例程式自己宣告另一組servo去控制馬達。但轉一個可變電阻,兩個馬達都會動。另一個可變電阻則兩個都不會動。下面是我的code,想請教哪邊出了問題?
    非常感謝您!

    #include
    Servo ESC; // create servo object to control the
    Servo front_ESC;
    int potValue=0; // value from the analog pin
    int fro_potValue=0;// pin 10
    void setup() {
    // Attach the ESC on pin 9 (主軸)
    ESC.attach(9,1000,2000);
    front_ESC.attach(10,1000,2000); // (pin, min pulse width, max pulse width in microseconds) (前面馬達)
    }
    void loop() {
    //potValue = analogRead(A0);
    // potValue = map(potValue, 0, 1023, 0, 180);
    /* Serial.print("primary: ");
    Serial.print(potValue);
    Serial.print(" front: ");
    Serial.println(fro_potValue);*/
    fro_potValue = analogRead(A2); // reads the value of the potentiometer (value between 0 and 1023)
    fro_potValue = map(fro_potValue, 0, 1023, 0, 180); // scale it to use it with the servo library (value between 0 and 180)
    ESC.write(potValue); // Send the signal to the ESC
    front_ESC.write(fro_potValue);
    }

    回覆刪除
    回覆
    1. 你好,程式中少了一個analogRead()去讀另一個可變電阻的值。可是看程式應該是只有一個馬達會動,要看一下接線的方式。

      刪除
  8. 外接電源給伺服馬達的話,意思是arduino那邊只需要接橘色訊號線給arduino ?

    回覆刪除
  9. 您好 我想請問mg996 360度舵機使用時無法以別的感應器作為啟動的原因,並且loop裡頭的程式只要有讓馬達轉的不管是不是包在判斷式中他仍然會一直轉

    回覆刪除
  10. 在接線圖一中的橘色線與棕色線的功能標註說明寫反了

    回覆刪除
  11. 我想問一下怎麼控制馬達轉數謝謝

    回覆刪除
  12. 您好,想請教關於供電,我仿作了您的教學,改用XY類比搖桿+2顆MG996R
    單接USB 5V供電時,伺服機控制會不正常,而同時再加上一個9V電源雙輸入,似乎就比較正常
    但還是會發生零星的短路無法控制

    請問是漏了甚麼嗎?謝謝

    回覆刪除
    回覆
    1. 請問所謂的零星短路是指什麼?轉動可變電阻時,MG996R不會動作嗎?我覺得會不會是連接線稍有接觸不良的情況,可以再檢查看看...

      刪除
  13. 程式2
    int r1_pin = 2; // 可變電阻連接的 pin 腳
    應該改為
    int r1_pin = A2; // 可變電阻連接的 pin 腳

    回覆刪除

張貼留言

較新的 較舊