帶限制和變速的伺服馬達控制

增強型掃描 (Sweep)

微控制器伺服馬達控制的常見入門工具是「掃描(Sweep)」程式。當您下載 Arduino IDE 時,會包含掃描(Sweep)程式,該程序是 Arduino 的眾多編程示例中的其中一個常見程式。此程式碼演示了 Arduino 伺服庫命令的功能,並列出了使伺服臂掃過其整個位置範圍所需的步驟。

只需一些修改和加設外部設備,使掃描(Sweep)伺服在某一設定行程範圍內基於某一可變速度移動,從而增強使其功能。此類伺服適用於許多與嗜好相關的項目,例如火車模型上橫臂設計或飛機模型上的門及起落架的精準移動。

用於限制移動和速度的步驟可通過多種方式實現,具體取決於您的編程和感測器使用的相關經驗。本範例將在標準掃描電路中添加三個電位器,並對 Arduino 編碼進行一些修改。演示的核心器件是使用 Atmega328P 微控制器(uC)的 Arduino Mini V5 (圖1)。但不會使用 uC 上所有的輸入和輸出,這樣做是為了將來加入其他更多的外圍設備。

image

設置

增強型掃描項目從安裝試驗電路板上的 uC 開始,其具有所有必需的電源和輸入/輸出連接,包括三個外部電位器輸入、一個 ON/OFF 觸摸開關輸入、LED 中心位置,以及限制指示器,驅動單個伺服的一個輸出。試驗電路板線路配置圖可參考圖2。

注意:標準跳接線套件(例如 DigiKey 「 原型開發、製程產品」網頁上的標準跳接線套件)會根據不同長度而使用不同顏色的電線,因此線路顏色可沿著線路走向而改變。文中的線路圖顯示了單色佈線,可以用散裝線軸的自訂切割線來進行佈線。

所需零件:

伺服:180度(1528-1083-ND)、觸動開關(450-1650-ND)、電位器(3310P-125-103L-ND)、Arduino Mini V5(1050-1044-ND)。二極體 - 綠色(160-1130-ND)。二極體 - 紅色(160-1127-ND)、電容(445-8571-ND)、用於Arduino編程的USB轉序列轉換器(1050-1021-ND)。 10k電阻(CF18JT10K0CT-ND)。

佈局考慮事項

典型伺服的工作電壓為 4.8 - 6.5VDC,在負載或轉向時電流可高達3安培。雖然伺服直接從 uC 接收訊號,但 Arduino Mini 板載穩壓器無法提供伺服所需的電流量。請注意,伺服電源線直接連接到 6V 電源。由於 uC 具有板載穩壓器,因此也可以在相同的 6V 電源上運行。如果伺服和 uC 在不同的電源上運行,則必須使用相同的地線,以便伺服器識別來自 uC 的訊號。本示例中的觸動開關用於通過 uC 啟動/停止伺服。

圖2 – 部份線路路徑可能會被誇大以顯示連接性

編碼(因出於教學目的而添加了大量註解)

/* 	The potentiometers are used to provide adjustable input on analog pins A0, A1, A2
The analog inputs are used for left and right limits in servo travel as well as servo travel speed.
When deactivated, the servo returns to the nearest limit position at maximum speed.
An LED on digital pin 8 indicates each crossing of the center servo position. An additional LED on pin 9 indicates the servo has reached the maximum limit. The tactile switch is pulled HIGH via a 10k resistor when not pressed. Pressing the button changes its state to LOW (direct connection to ground).	*/
/********************************* Configuration ************************************/

#include <Servo.h>					//Include the Arduino servo library
Servo wiperServo;					//Create a name for the servo

/*************************** Declare and initialize variables ****************************/

int pos; int lastPos; 					//Current position variables
int leftServo; int rightServo; 				//Desired position variables
int servoSpeed = 2;					//Set the initial servo speed

/* startAngle variable - The left and right limit potentiometers can be adjusted to add/subtract an adjustable number of degrees between zero and 90 minus the startAngle variable. With the startAngle variable set at 70, the servo will travel 70 degrees from center before the pot adjustment has any effect. If the pot is set to zero, the servo will travel 70 degrees and then reverse direction. If the pot is set to its maximum, the servo will travel the full 90 degrees and then reverse direction. If the startAngle variable is set to 50 as another example, the limit potentiometers will have 40 degrees of adjustment. The higher the variable value, the finer the potentiometer control. 
*/
int startAngle = 70;

//Designate pin 2 as an interrupt for ON/OFF control using the tactile switch
const byte interruptPin = 2;

//Set the system status flag. Also used for ON/OFF control
volatile byte flag = LOW;   		


/**************************** Setup area - Runs one time ****************************/

void setup() {
pinMode(8, OUTPUT); pinMode(9, OUTPUT);	//Set digital pins 8 and 9 as outputs

//Flash red LED 3 times to indicate uC has entered setup mode.
for (int flash = 0; flash < 3; flash++)
{
digitalWrite(8, HIGH); delay(200); digitalWrite(8, LOW); delay(200);
}

//Identify the servo signal digital pin
wiperServo.attach(10);       
                                           		
//Identify interrupt pin, function to run on interrupt, HIGH to LOW detection
attachInterrupt(digitalPinToInterrupt(interruptPin), onOff, FALLING);   

//Read the analog level of uC pin A0, convert the 12bit value to a degree range (0-90),   
rightServo = map(analogRead(A0), 0, 1023, 90, 0);

//Confine the range of servo travel to the right of center to 0-90.
rightServo = constrain(rightServo, 0, 90);

//Run the servo. The delay gives the servo time to reach its destination.
wiperServo.write(rightServo); delay(2000);

//Read the analog level of uC pin A1, convert the 12bit value to a degree range (90-180),
leftServo = map(analogRead(A1), 0, 1023, 90, 180);

//Confine the range of servo travel to the left of center to 90-180.
leftServo = constrain(leftServo, 90, 180);

//Run the servo. The delay gives the servo time to reach its destination.
wiperServo.write(leftServo); delay(2000);

//Flash an LED 3 times to indicate end of servo test.
for (int flash = 0; flash < 3; flash++)
{
digitalWrite(8, HIGH); delay(200); digitalWrite(8, LOW); delay(200);
}
//Remember the servo position as a starting point in the main program
lastPos = leftServo;

} //End of setup 

/************************* Main program - Loops continuously ***********************/

void loop() {

//Get 12bit value from speed potentiometer and map to desired output range
//Lower values of this variable cause higher servo speeds. 
servoSpeed = map(analogRead(A2), 0, 1023, 0, 20);

//Set range limits for speed - less than 2 will cause servo chatter         
servoSpeed = constrain(servoSpeed, 2, 18);               

//Turn on the green LED if leftServo value is at the center position.
if (analogRead(A1) < 25)
{
leftServo = 90;
digitalWrite(8, HIGH);
 		delay(25);
  		}
  else
 		{
    		leftServo = map(analogRead(A1), 26, 1023, 90 + startAngle, 180);
    		leftServo = constrain(leftServo, 90, 180);

//Turn on the Red LED if leftServo is approaching the maximum position.
    		if (leftServo >= 175) digitalWrite(9, HIGH);
    		else digitalWrite(9, LOW);
 		}

 	//Turn on the green LED if rightServo value is at the center position.
 if (analogRead(A0) < 25)
 		{
    		rightServo = 90;
    		digitalWrite(8, HIGH);
    		delay(25);
  		}
else
 		{
    		rightServo = map(analogRead(A0), 26, 1023, 90 - startAngle, 0);
   		rightServo = constrain(rightServo, 0, 90);

//Turn on the Red LED if rightServo is approaching the maximum position.
   		if (rightServo <= 5) digitalWrite(9, HIGH);
    		else digitalWrite(9, LOW);
  		}

//The following responds to a tactile button press (High to Low transition).
if (flag)                                                  
{
    		if (lastPos > rightServo)

			//Continuous motion loop - from right limit to left limit
    			for (pos = lastPos; pos >= rightServo; pos--)
{

//If the flag changes state (turned OFF), jump out of the loop    
if (!flag) break;                                    
   
//Run the servo motion and LED indication function
 runServo(servoSpeed);                                
 			}

if (lastPos < leftServo)
 
//Continuous motion loop - from left limit to right limit
for (pos = lastPos; pos <= leftServo; pos++) 
      			{
       			 if (!flag) break;                                    
        			runServo(servoSpeed);                                
 			 }
}

//If the flag, set by the switch, is false (OFF) enter this loop
if (!flag)                                             
{
    		if (lastPos >= 90)
    		{
//If the last position is left of center, go to the left limit
wiperServo.write(leftServo);

//Remember the current position.                        
pos = leftServo;
 		}
 else
 		{
//If the last position is right of center, go to the right limit
wiperServo.write(rightServo);
                            
//Remember the current position
 		pos = rightServo;
}
      	 }
} //End of main program

自訂函數

/*********************************** Custom Functions ******************************/
//The following function runs when a falling edge (HIGH to LOW) interrupt occurs (switch press is detected)
void onOff()                                            
{
//Toggle the flag status
flag = !flag;                                           
}

//The following function runs when servo motion is required
void runServo(int rate)                                   
{
//Send the position value to the servo
  	wiperServo.write(pos);
  	
//Remember the last position for determining which way to go home when flag is false
lastPos = pos;        
  	
//Turn ON the green LED when at center
if (pos == 90) digitalWrite(8, HIGH);	

//Turn OFF the servo center indicator when at any angle other then 90
 	if (pos != 90) digitalWrite(8, LOW);

//Stop for a moment when the servo arm reaches a limit before reversing direction.
 	if (pos == rightServo) delay(100); 
if (pos == leftServo) delay(100); 
  
//Set the speed by delaying the time between position values
delay(rate);
}

 //End of custom functions

總結

伺服馬達是功能強大且易於使用的設備,可將訊號轉換為移動。以上的編碼演示如何操作兩個簡單的變量 rightServo 和 leftServo,以使伺服電機執行許多操作,而不僅僅是簡單的掃描(Sweep)功能。可使用這兩個相同的變量輕鬆修改編碼,以執行更多可能的操作。觸動開關可以替換為可在由高至低的訊號配置下工作的任何觸發設備(例如磁性開關或具有邏輯輸出的其他感測器)。應用範圍可在很多環境下合實現。