"ตัวอย่างการควบคุม RC Servo Motor ด้วย Arduino"
RC Servo Motor รุ่นที่มีจำหน่าย:
Servo
เป็นคำศัพท์ที่ใช้กันทั่วไปในระบบควบคุมอัตโนมัติ มาจากภาษาละตินคำว่า
Sevus หมายถึง “ทาส” (Slave) ในเชิงความหมายของ Servo Motor ก็คือ Motor
ที่เราสามารถสั่งงานหรือตั้งค่า แล้วตัว Motor
จะหมุนไปยังตำแหน่งองศาที่เราสั่งได้เองอย่างถูกต้อง
โดยใช้การควบคุมแบบป้อนกลับ (Feedback Control) ในบทความนี้จะกล่าวถึง RC
Servo Motor ซึ่งนิยมนำมาใช้ในเครื่องเล่นที่บังคับด้วยคลื่นวิทยุ (RC = Radio - Controlled) เช่น เรือบังคับวิทยุ รถบังคับวิทยุ เฮลิคอปเตอร์บังคับวิทยุ เป็นต้น
Feedback Control
คือ
ระบบควบคุมที่มีการวัดค่าเอาต์พุตของระบบนำมาเปรียบเทียบกับค่าอินพุตเพื่อ
ควบคุมและปรับแต่งให้ค่าเอาต์พุตของระบบให้มีค่า เท่ากับ หรือ
ใกล้เคียงกับค่าอินพุต ส่วนประกอบภายนอก RC Servo Motor
- Case ตัวถัง หรือ กรอบของตัว Servo Motor
- Mounting Tab ส่วนจับยึดตัว Servo กับชิ้นงาน
- Output Shaft เพลาส่งกำลัง
- Servo Horns ส่วนเชื่อมต่อกับ Output shaft เพื่อสร้างกลไกล
-
Cable สายเชื่อมต่อเพื่อ จ่ายไฟฟ้า และ ควบคุม Servo Motor
จะประกอบด้วยสายไฟ 3 เส้น และ ใน RC Servo Motor
จะมีสีของสายแตกต่างกันไปดังนี้
o สายสีแดง คือ ไฟเลี้ยง (4.8-6V)
o สายสีดำ หรือ น้ำตาล คือ กราวด์
o สายสีเหลือง (ส้ม ขาว หรือฟ้า) คือ สายส่งสัญญาณพัลซ์ควบคุม (3-5V)
- Connector จุดเชื่อมต่อสายไฟ
ส่วนประกอบภายใน RC Servo Motor
Ref: www.pololu.com
1. Motor เป็นส่วนของตัวมอเตอร์
2. Gear Train หรือ Gearbox เป็นชุดเกียร์ทดแรง
3. Position Sensor เป็นเซ็นเซอร์ตรวจจับตำแหน่งเพื่อหาค่าองศาในการหมุน
4. Electronic Control System เป็นส่วนที่ควบคุมและประมวลผล
Servo Motor Block Diagram
หลักการทำงานของ RC Servo Motor
เมื่อจ่ายสัญญาณพัลซ์เข้ามายัง RC Servo Motor ส่วนวงจรควบคุม
(Electronic Control System) ภายใน Servo
จะทำการอ่านและประมวลผลค่าความกว้างของสัญญาณพัลซ์ที่ส่งเข้ามาเพื่อแปลค่า
เป็นตำแหน่งองศาที่ต้องการให้ Motor หมุนเคลื่อนที่ไปยังตำแหน่งนั้น
แล้วส่งคำสั่งไปทำการควบคุมให้ Motor หมุนไปยังตำแหน่งที่ต้องการ โดยมี
Position Sensor เป็นตัวเซ็นเซอร์คอยวัดค่ามุมที่ Motor กำลังหมุน เป็น
Feedback
กลับมาให้วงจรควบคุมเปรียบเทียบกับค่าอินพุตเพื่อควบคุมให้ได้ตำแหน่งที่
ต้องการอย่างถูกต้องแม่นยำ
สัญญาณ RC ในรูปแบบ PWM
ตัว RC Servo Motor ออกแบบมาใช้สำหรับรับคำสั่งจาก Remote
Control ที่ใช้ควบคุมของเล่นด้วยสัญญาณวิทยุต่างๆ เช่น เครื่องบินบังคับ
รถบังบังคับ เรือบังคับ เป็นต้น ซึ่ง Remote
จำพวกนี้ที่ภาครับจะแปลงความถี่วิทยุออกมาในรูปแบบสัญญาณ PWM (Pulse Width
Modulation)
มุม
หรือองศาจะขึ้นอยู่กับความกว้างของสัญญาณพัลซ์
ซึ่งโดยส่วนมากความกว้างของพัลซ์ที่ใช้ใน RC Servo Motor จะอยู่ในช่วง 1-2
ms หรือ 0.5-2.5 ms
ยกตัวอย่างเช่นหากกำหนดความกว้างของสัญญาณพัลซ์ไว้ที่ 1 ms ตัว
Servo Motor จะหมุนไปทางด้ายซ้ายจนสุด
ในทางกลับกันหากกำหนดความกว้างของสัญญาณพัลซ์ไว้ที่ 2 ms ตัว Servo Motor
จะหมุนไปยังตำแหน่งขวาสุด แต่หากกำหนดความกว้างของสัญญาณพัลซ์ไว้ที่ 1.5 ms
ตัว Servo Motor ก็จะหมุนมาอยู่ที่ตำแหน่งตรงกลางพอดี
ดังนั้นสามารถกำหนดองศาการหมุนของ RC Servo Motor
ได้โดยการเทียบค่า เช่น RC Servo Motor สามารถหมุนได้ 180 องศา โดยที่ 0
องศาใช้ความกว้างพัลซ์เท่ากับ 1000 us ที่ 180 องศาความกว้างพัลซ์เท่ากับ
2000 us เพราะฉะนั้นค่าที่เปลี่ยนไป 1 องศาจะใช้ความกว้างพัลซ์ต่างกัน
(2000-1000)/180 เท่ากับ 5.55 us
จากการหาค่าความกว้างพัลซ์ที่มุม 1 องศาข้างต้น หากต้องกำหนดให้
RC Servo Motor หมุนไปที่มุม 45 องศาจะหาค่าพัลซ์ที่ต้องการได้จาก 5.55 x
45 เท่ากับ 249.75 us แต่ที่มุม 0 องศาเราเริ่มที่ความกว้างพัลซ์ 1ms หรือ
1000 us เพราะฉะนั้นความกว้างพัลซ์ที่ใช้กำหนดให้ RC Servo Motor หมุนไปที่
45 องศา คือ 1000 + 249.75 เท่ากับประมาณ 1250 us
วิธีควบคุม RC Servo Motor ด้วย Arduino Arduino มีไลบรารี่สำหรับสั่งงาน RC Servo Motor มาให้ใช้งานอยู่แล้วเป็นฟังก์ชั่นสำเร็จรูปและใช้งานได้ง่าย ในหน้าเว็บไซต์ http://arduino.cc/en/reference/servo
ได้ให้ข้อมูลไว้ว่า Servo Library ของ Arduino สามารถสั่งงาน RC Servo
Motor ได้ทั้งแบบหมุนไป-กลับได้ 0-180 องศา
(ที่กล่าวถึงตามตัวอย่างข้างต้น)
และแบบต่อเนื่องที่หมุนครบรอบได้เรียกว่าเป็น Continuous Rotation Servo
(ซึ่งในช่วงท้ายบทความจะกล่าวถึงเพิ่มเติม) โดยสามารถรองรับการเชื่อมต่อ RC
Servo Motor ได้ถึง 12 ตัวกับบอร์ด Arduino UNO และรองรับสูงสุดถึง 48
ตัวหากใช้บอร์ด Arduino Mega ฟังก์ชั่นภายใน Servo Library- attach()- write()- writeMicroseconds()- read()- attached()- detach()attach()Description คือฟังก์ชั่นที่ใช้ในการกำหนดขาสัญญาณที่ Servo Motor ต่อกับ Arduino และกำหนดความกว้างของพัลซ์ที่ 0 องศาและ 180 องศา Syntax Servo.attach(pin) Servo.attach(pin,min,max)Parameters Pin: คือ ขาสัญญาณของ Arduino ที่ใช้เชื่อมต่อกับ Servo Motor
Min: คือ ความกว้างของพัลซ์ที่ 0 องศาของ Servo
ตัวที่ใช้ในหน่วยไมโครวินาที (us)
โดยปกติแล้วหากไม่มีการตั้งค่าโปรแกรมจะกำหนดค่าไว้ที่ 544 us
Max: คือ ความกว้างของพัลซ์ที่ 180 องศาของ Servo
ตัวที่ใช้ในหน่วยไมโครวินาที (us)
โดยปกติแล้วหากไม่มีการตั้งค่าโปรแกรมจะกำหนดค่าไว้ที่ 2400 usWrite()Description
คือฟังก์ชั่นที่ใช้ควบคุมตำแหน่งที่ต้องการให้ Servo Motor
หมุนไปยังองศาที่กำหนดสามารถกำหนดเป็นค่าองศาได้เลย คือ 0-180 องศา แต่ใน
Servo Motor ที่เป็น Full Rotation คำสั่ง write
จะเป็นการกำหนดความเร็วในการหมุน โดย ค่าเท่ากับ 90 คือคำสั่งให้ Servo Motor หยุดหมุน ค่าเท่ากับ 0 คือการหมุนด้วยความเร็วสูงสุดในทิศทางหนึ่ง ค่าเท่ากับ 180 คือการหมุนด้วยความเร็วสูงสุดในทิศทางตรงกันข้ามSyntax servo.write(angle)Parameters
Angle: คือมุมที่ต้องการให้ RC Servo Motor แบบ 0-180 องศาหมุนไป
แต่หากเป็น RC Servo Motor แบบ Full Rotation ค่า Angle คือ
การกำหนดความเร็วและทิศทางในการหมุนwriteMicroseconds()Description
คือฟังก์ชั่นที่ใช้ควบคุมตำแหน่งที่ให้ Servo Motor
หมุนไปยังตำแหน่งองศาที่กำหนดโดยกำหนดเป็นค่าความกว้างของพัลซ์ในหน่วย us
ซึ่งปกติแล้ว RC Servo Motor จะใช้ความกว้างของพัลซ์อยู่ที่ 1000-2000 us
ตามที่ได้กล่าวไปข้างต้นแล้ว แต่ RC Servo Motor
บางรุ่นหรือบางยี่ห้อไม่ได้ใช้
ช่วงความกว้างของพัลซ์ตามที่ได้กล่าวเอาไว้นี้ อาจจะใช้ช่วง 700-2300
แทนก็สามารถใช้ฟังก์ชั่น writeMicroseconds
นี้เพื่อกำหนดความกว้างพัลซ์ได้เอง การ
ใช้ฟังก์ชั่น writeMicroseconds สามารถกำหนดค่าได้อิสระ ตรงนี้
”ต้องระวังในการใช้งาน” หากสั่งงาน RC Servo Motor (แบบ 0 - 180 องศา)
จนหมุนไปเกินจุดสิ้นสุดคือเกินทั้งฝั่ง 0 หรือ 180 องศา
จะทำให้เกิดเสียงครางดังจากการหมุนไปต่อไม่ได้และมอเตอร์จะกินกระแสสูงขึ้น
ด้วยในเวลาเดียวกันนั้น ซึ่งอาจทำให้ RC Servo Motor เกิดความเสียหายได้Syntax servo.writeMicroseconds(uS)Parameters uS: คือค่าความกว้างของพัลซ์ที่ต้องการกำหนดในหน่วยไมโครวินาที (โดยตัวแปร int)read()Description
คือฟังก์ชั่นอ่านค่าองศาที่สั่งเข้าไปด้วยฟังก์ชั่น write()
เพื่อให้รู้ว่าตำแหน่งองศาสุดท้ายที่เราสั่งเข้าไปนั้นมีค่าเท่าไหร่ซึ่งค่า
ที่อ่านออกมานั้นจะมีค่าอยู่ในช่วง 0 - 180 Syntax servo.read()Parameters ไม่มี: จะ Return ค่า 0-180attached()Description คือฟังก์ชั่นตรวจสอบว่า Servo ที่เราต้องการใช้กำลังต่ออยู่กับขสัญญาณของ Arduino หรือไม่Syntax servo.attached()Parameters
ไม่มี: จะ Return ค่า True ออกมา หาก Servo Motor
เชื่อมต่ออยู่กับ Arduino แต่ถ้าหาก Return
ออกมาเป็นค่าอื่นถือว่าไม่เชื่อมต่อdetach()Description คือฟังก์ชั่นคืนสถานะของขาที่เรากำหนดให้เป็นขาควบคุม Servo Motor ด้วยคำสั่ง attached() ให้กลับคือสู่การใช่งานปกติSyntax servo.detach()Parameters ไม่มี
ตัวอย่างการเชื่อมต่อ RC Servo Motor เข้ากับบอร์ด Arduino
โค้ดตัวอย่างการควบคุมตำแหน่ง RC Servo Motor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#include <Servo.h>
Servo myservo;
void setup()
{
myservo.attach(9);
}
void loop()
{ myservo.write(0);
delay(1000);
myservo.write(90);
delay(1000);
myservo.write(180);
delay(1000);
}
|
ผลการทำงานของโค้ด
myservo.write(0);
delay(1000);
Servo Motor จะหมุนไปที่ตำแหน่ง 0 องศา และ หยุดเป็นเวลา 1 วินาที
myservo.write(90);
delay(1000);
Servo Motor จะหมุนไปที่ตำแหน่ง 90 องศา และ หยุดเป็นเวลา 1 วินาที
myservo.write(90);
delay(1000);
Servo Motor จะหมุนไปที่ตำแหน่ง 180 องศา และ หยุดเป็นเวลา 1 วินาที
จากนั้นจะหมุนกลับไปที่ตำแหน่ง 0 องศา และวนรอบไปเช่นนี้เรื่อยๆ
โค้ดตัวอย่างการควบคุมตำแหน่ง RC Servo Motor แบบ Sweep
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#include <Servo.h>
Servo myservo;
int pos = 0;
void setup(){
myservo.attach(9);
}
void loop(){
for (pos = 0; pos < 180; pos += 1)
{
myservo.write(pos);
delay(15);
}
for (pos = 180; pos>=1; pos-=1)
{
myservo.write(pos);
delay(15);
}
}
|
ผลการทำงานของโค้ด
for(pos = 0; pos < 180; pos += 1){myservo.write(pos);delay(15);}
ลูป for กำหนดให้ค่า pos มีค่าเท่ากับ 0 และทุกๆ
การทำงานคำสั่งภายใน for loop ค่า pos จะเพิ่มค่าขึ้น 1 ค่า จนจนถึง 180
ก็จะหลุดออกจาก loop
ภายใน loop for คำสั่ง myservo.write(pos); ก็คือการกำหนดให้
Servo Motor หมุนไปยังตำแหน่ง มุมตามค่าในตัวแปร pos และหน่วงเวลา 15ms
ด้วยคำสั่ง delay(15); ดังนั้น Servo Motor จะค่อยๆ หมุนอย่างช้าๆ
จากตำแหน่ง 0 องศาไปที่ 180 องศา
for(pos = 180; pos>=1; pos-=1) { myservo.write(pos); delay(15); }
ใน loop for ที่สองนี้จะทำงานเช่นเดียวกับใน loop for
แรกเพียงแต่เปลี่ยนค่าเริ่มต้นจาก 180 เป็น 0 และลดลงค่าลง 1 ค่าทุกๆ
การทำงาน 1 รอบ ส่งผลให้ Servo Motor จะหมุนจากตำแหน่งมุม 180 องศา
ไปยังมุม 0 องศาอย่างช้าๆ
!!! ทดลองเพิ่มค่าในคำสั่ง delay() ให้มากขึ้นจะพบว่า Servo
Motor จะหมุนช้าลงและในทางกลับกันหากลดค่าใน delay() ลงจะพบว่า Servo Motor
จะหมุนเร็วขึ้น
ตัวอย่างการควบคุมตำแหน่ง RC Servo Motor โดยใช้ Potentiometer
โค้ดตัวอย่างการควบคุมตำแหน่ง RC Servo Motor โดยใช้ Potentiometer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#include <Servo.h>
Servo myservo;
int potpin = 0;
int val;
void setup(){
myservo.attach(9);
}
void loop(){
val = analogRead(potpin);
val = map(val, 0, 1023, 0, 179);
myservo.write(val);
delay(15);
}
|
ผลการทำงานของโค้ด
val = analogRead(potpin); อ่านค่า Analog จาก Potentiometer ที่ต่ออยู่ที่ขา A0 เก็บไว้ในตัวแปร valval = map(val, 0, 1023, 0, 179);
เนื่องจาก ADC ภายใน Arduino เป็น ADC ขนาด 10-bit จึงอ่านค่า
Analog ได้ตั้งแต่ 0 – 1023 แต่ RC Servo Motor สามารถหมุนได้เพียงแค่
1-180 องศา จึงต้องใช้ Function map เพื่อทำการสเกลค่าลงจาก 0-1023 เป็น
0-179 แล้วนำไปเก็บไว้ในตัวแปร val myservo.write(val); เมื่อสเกลค่า จาก 0-1023 ลงเหลือ 0-179 แล้วก็นำมาสั่งให้ Servo Motor หมุนไปยังตำแหน่งในค่าตัวแปร valdelay(15); หน่วงเวลา 15 msผลของการทำงานทำให้สามารถปรับตำแหน่งองศาของ Servo Motor ได้โดยการหมุนปรับค่า Potentiometer
Continuous Rotation Servo
Continuous Rotation Servo คือ RC Servo Motor แบบที่สามารถหมุนได้ 360 องศา
ส่วนประกอบภายนอกนั้นจะมีหน้าตาคล้ายกับ RC Servo Motor แบบที่หมุนได้ 180
องศา เพียงแต่จะมี Potentiometer เพื่อใช้สำหรับปรับ ตำแหน่ง Center Stop
Adjust ของตัว Servo
ลักษณะการใช้งาน RC Servo Motor ชนิดนี้จะแตกต่างจากการใช้งาน RC
Servo Motor แบบ 180 องศาตรงที่ Servo
ชนิดนี้จะใช้ความกว้างของสัญญาณพัลซ์ในการกำหนดความเร็วและทิศทางในการหมุน
ไม่ได้ใช้เพื่อกำหนดมุมจึงไม่สามารถกำหนดให้ Motor
หมุนไปยังตำแหน่งมุมต่างๆ ตามความต้องการได้
สัญญาณความกว้างของพัลซ์ที่ใช้ควบคุมจะอยู่ในช่วง 1000-2000 us
แต่จะมีความแตกในความหมายของแต่ละความกว้างของพัลซ์ดังนี้
ความกว้าง 1000 us หมายถึงการหมุนไปทางซ้ายด้วยความเร็วสูงสุดที่ Servo Motor จะหมุนได้
ความกว้าง 1500 us หมายถึงการสั่งให้ Servo Motor หยุดหมุน
ความกว้าง 2000 us หมายถึงการหมุนไปทางขวาด้วยความเร็วสูงสุดที่ Servo Motor จะหมุนได้
การ Calibrate Center Stop
ในการใช้งาน Continuous Rotation Servo
เมื่อซื้อมาใหม่หรือใช้งานไปสักระยะหนึ่งจุด Center Stop
อาจมีการคลาดเคลื่อนได้ ซึ่งแม้เราสั่งให้สัญญาณพัลซ์มีความกว้างเท่ากับ
1500 us ไป Continuous rotation servo ก็จะไม่หยุดหมุน
เราจึงต้องปรับตั้งค่า Center Stop ดังนี้
- ต่อ Continuous rotation servo เข้ากับ Arduino
- เขียนโปรแกรมจ่ายความกว้างพัลซ์ 1500 us ให้กับ Servo Motor
#include <Servo.h>Servo myServo;void setup() { myServo.attach(9); myServo.writeMicroseconds(1500); // Stop }
-
เมื่อรันโปรแกรมจ่ายความกว้างพัลซ์ 1500 us แล้ว Servo Motor ไม่หยุดหมุน
ให้ใช้ไขควงขนาดเล็กหมุนปรับ Center Stop Adjust จน Servo Motor หยุดหมุน
การควบคุม Continuous Rotation Servo โดยใช้ Potentiometer ปรับความเร็วและทิศทางการหมุน
โค้ดตัวอย่างการควบคุม Continuous Rotation Servo โดยใช้ Potentiometer
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#include <Servo.h>
Servo myservo;
int potpin = 0;
int val;
void setup(){
myservo.attach(9);
}
void loop(){
val = analogRead(potpin);
val = map(val, 0, 1023, 0, 179);
myservo.write(val);
delay(15);
}
|
!!! โค้ดเหมือนกับตัวอย่าง RC Servo Motor โดยใช้ Potentiometer แต่ผลการทำงานจะแตกต่างกัน
ผลการทำงานของ Code
val = analogRead(potpin);
อ่านค่า Analog จาก Potentiometer ที่ต่ออยู่ที่ขา A0 เก็บไว้ในตัวแปร val
val = map(val, 0, 1023, 0, 179);
เนื่องจาก ADC ภายใน Arduino เป็น ADC ขนาด 10-bit จึงอ่านค่า
Analog ได้ตั้งแต่ 0-1023 แต่ Continuous Rotation Servo รับค่าได้ในช่วง
1-180 จึงต้องใช้ Function map เพื่อสเกลค่าจาก 0-1023 เป็น 0-179
แล้วนำไปเก็บไว้ในตัวแปร val
myservo.write(val);
เมื่อสเกลค่า จาก 0-1023 ลงเหลือ 0-179 แล้วก็นำมาสั่งให้ Servo
Motor หมุนในความเร็วและ ทิศทางตามค่าความกว้างของพัลซ์ที่จ่ายออกไป
delay(15);
หน่วงเวลา 15 ms
ผลของการทำงานในโค้ดนี้จะเห็นได้ว่า หากปรับ Potentiometer
ไปทางด้านใดด้านหนึ่งจนสุด Continuous Rotation Servo
จะหมุนในทิศทางหนึ่งด้วยความเร็วสูงสุดและเมื่อเราค่อยๆ ปรับ Potentiometer
กลับมาให้มาอยู่ในตำแหน่งกึ่งกลาง Servo Motor
จะค่อยหมุนช้าลงแต่ยังหมุนในทิศทางเดิม และจะหยุดสนิทหากเราปรับ
Potentiometer มาที่ตำแหน่งกึ่งกลางพอดี เมื่อปรับ Potentiometer เกินกว่า
ครึ่งหนึ่งในทิศตรงกันข้าม Servo Motor จะเปลี่ยนทิศการหมุน
แต่จะหมุนอย่างช้าๆ และจะค่อยๆหมุนเร็วขึ้นเมื่อเราปรับ Potentiometer
มากขึ้น