我的部落格中有一篇被瀏覽次數很高的文章,是有關於伺服馬達的控制(Arduino筆記(15):控制伺服馬達 SERVO),那是說明單一個伺服馬達的控制,可外接電源使用 Arduino PWM的接腳來控制。如果要控制兩個伺服馬達,可用L293D或L298P直流電機驅動模組,如果要控制4個伺服馬達,可用CNC步進馬達控制驅動板,搭配 A4988或DRV8825;如果要控制4個伺服馬達,可用3D控制板套件,搭配 A4988或DRV8825。
如果超過上述的電機數量,就要改用PCA9685,PCA9685是一款16通道(可連接16個電機)12位 PWM I2C總線控制的伺服電機驅動模組,這個模組可以很容易地連接Arduino或樹莓派,並可以用簡易的程式來控制單個或多個伺服電機,如雙足或六足機器人等,或任何您想要的東西。
伺服馬達有三根電線從背面伸出,通常是橙色,紅色和棕色,但可能因伺服馬達而異。一條提供正電壓(+5 V,通常是紅色),黑色線接地,第三條橙色線提供PWM信號控制用,作為告訴電動機它應該旋轉哪個角度。
一般舵機大多使用50HZ的控制頻率,脈寬為0.5ms ~2.5ms,12位元解析度(4096),相關精度計算如下:
此功能可用於調節 PWM 的頻率,這個頻率確定IC每秒產生多少個完整「脈衝」。也就是頻率決定了每個脈衝從開始到結束的持續時間有多長,同時考慮了脈衝的高段和低段。
頻率在 PWM 中很重要,因為在很小的佔空比下將頻率設置得太高會引起問題,因為信號的「上升時間」(從0V變為VCC所需的時間)可能比信號的上升時間更長。信號處於活動狀態,PWM 輸出將變得平滑,甚至可能無法達到 VCC,而導致許多問題。
on:信號從低到高轉變時的標記(介於0..4095之間)
off:信號從高電平轉換為低電平時的標記(介於0..4095之間)
此功能設置特定通道上PWM 脈衝的高電位開始和結束。您可以在信號開啟和關閉之間的0到4095之間指定「刻度」值。通道值是指定16個 PWM 輸出中的哪一個。
如果超過上述的電機數量,就要改用PCA9685,PCA9685是一款16通道(可連接16個電機)12位 PWM I2C總線控制的伺服電機驅動模組,這個模組可以很容易地連接Arduino或樹莓派,並可以用簡易的程式來控制單個或多個伺服電機,如雙足或六足機器人等,或任何您想要的東西。
伺服馬達有三根電線從背面伸出,通常是橙色,紅色和棕色,但可能因伺服馬達而異。一條提供正電壓(+5 V,通常是紅色),黑色線接地,第三條橙色線提供PWM信號控制用,作為告訴電動機它應該旋轉哪個角度。
一般舵機大多使用50HZ的控制頻率,脈寬為0.5ms ~2.5ms,12位元解析度(4096),相關精度計算如下:
- PWM週期: 1/50 sec = 0.02s = 20ms = 20000us
- 時間解析度:20000 us / 4096 = 4.88us
- 最大與最小脈寬時間差:2.5ms - 0.5ms = 2ms = 2000us
- 最大脈寬時間可分的份數:2000us / 4.88us = 410
- 0-180度的舵機,角度解析度:180度 / 410 = 0.439度
[安裝Adafruit-PWM-Servo-Driver-Library]
本實作需要安裝以下程式庫:- adafruit /Adafruit-PWM-Servo-Driver-Library
程式庫(Library)安裝方法請參考另一篇文章: Arduino筆記:安裝 Arduino IDE 程式庫(Library)。
[Adafruit_PWMServoDriver函式庫]
瞭解上述這些概念後,我使用Adafruit 的 PWM Servo Device函式庫的函式來驅動伺服電機,這些驅動程序使用I2C進行通信,需要2個接腳(SDA、SCL)。以下是函式庫的用法說明:- setPWMFreq(freq)
此功能可用於調節 PWM 的頻率,這個頻率確定IC每秒產生多少個完整「脈衝」。也就是頻率決定了每個脈衝從開始到結束的持續時間有多長,同時考慮了脈衝的高段和低段。
頻率在 PWM 中很重要,因為在很小的佔空比下將頻率設置得太高會引起問題,因為信號的「上升時間」(從0V變為VCC所需的時間)可能比信號的上升時間更長。信號處於活動狀態,PWM 輸出將變得平滑,甚至可能無法達到 VCC,而導致許多問題。
- setPWM(channel, on, off)
on:信號從低到高轉變時的標記(介於0..4095之間)
off:信號從高電平轉換為低電平時的標記(介於0..4095之間)
此功能設置特定通道上PWM 脈衝的高電位開始和結束。您可以在信號開啟和關閉之間的0到4095之間指定「刻度」值。通道值是指定16個 PWM 輸出中的哪一個。
[接線圖]
PCA9685 | Arduino UNO |
---|---|
VCC | 5V |
GND | GND |
SDA | A4(SDA) |
SCL | A5(SCL) |
[程式]
以下程式以搖桿左右及上下控制伺服馬達的正轉或反轉,並判斷搖桿的X軸或Y軸是否移動來設定伺服馬達的位置。#include <Wire.h> #include <Adafruit_PWMServoDriver.h> // 呼叫伺服驅動程式函數,預設I2C位址為 0x40 Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); #define MIN_PULSE_WIDTH 544 #define MAX_PULSE_WIDTH 2400 #define FREQUENCY 50 // 定義伺服機使用的輸出Port int motorA = 0; #define JoyX A0 // 搖桿 X 軸的接腳連接 Uno A0 #define JoyY A1 // 搖桿 Y 軸的接腳連接 Uno A1 void setup() { Serial.begin(9600); Serial.println("16 channel PWM test!"); pwm.begin(); pwm.setPWMFreq(FREQUENCY); // This is the maximum PWM frequency } void loop() { int valX = analogRead(JoyX); // Read current value of Joystick 1 X axis int valY = analogRead(JoyY); // Read current value of Joystick 1 Y axis int pulse_wide, pulse_width; // 判斷搖桿X軸是否移動 if (valX < 490 || valX > 510){ // 將搖桿讀取的值轉換為高低脈衝間的對應值 pulse_wide = map(valX, 0, 1023, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH); } // 判斷搖桿Y軸是否移動 if (valY < 490 || valY > 510){ // 將搖桿讀取的值轉換為高低脈衝間的對應值 pulse_wide = map(valY, 0, 1023, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH); } // 轉換脈衝寬度 pulse_width = int(float(pulse_wide) / 1000000 * FREQUENCY * 4096); Serial.print(pulse_wide); Serial.print(" "); Serial.println(pulse_width); // 讓伺服馬達移動到該位置 pwm.setPWM(motorA, 0, pulse_width); }
[結果]
[參考資料]
- DroneBot Workshop:Using Servo Motors with the Arduino
- Sunfounder:PCA9685 16 Channel 12 Bit PWM Servo Driver
張貼留言