(회전각의)제한과 변속이 가능한 서보모터 제어하기

Enhanced Sweep

마이크로컨트롤러 서보모터 제어에의 입문에는 일반적으로 “Sweep” 프로그램을 사용합니다. 아두이노 IDE를 다운로드 할 때 포함되는 아두이노 프로그래밍 예제 중 주된 것입니다. 프로그램 코드는 아두이노 서보 라이브러리 명령의 기능을 보여주며 서보 암이 전체 위치에 걸쳐 움직일 수 있는데 필요한 단계를 문서화하고 있습니다.

일부 수정과 몇 가지 외부 장치를 추가하면, 스윕 서보는 조정 가능한 이동 제한 범위 내에서 조정 가능한 속도로 이동할 수 있는 보다 유용한 장치가 될 수 있습니다. 모형 기차 레이아웃에서 건널목 차단기나 모형 항공기의 문과 랜딩 기어의 정밀한 움직임과 같은 취미와 관련된 프로젝트에 적용할 수 있는 곳이 많습니다.

제한과 속도를 결정하는데 사용되는 단계는 여러분의 프로그래밍과 센서에 대한 경험에 따라 여러 가지 방법으로 수행될 수 있습니다. 이번 예제에서는, 아두이노 코드의 몇 가지 개선과 함께 세 개의 전위차계가 표준 sweep 회로에 추가될 것입니다. 이 데모의 중심에는 Atmega328P 마이크로컨트롤러(uC)를 사용하는 아두이노 미니 V5가 있습니다, 그림 1. 향후 추가적인 주변 장치를 포용할 수 있도록 마이크로컨트롤러의 입력과 출력을 모두 사용하지는 않을 것입니다.

image

설정하기

Emhanced Sweep 프로젝트는 브레드보드에 모든 필요한 전원 및 세 개의 외부 전위차계 입력, ON/OFF용 촉각 스위치 입력, 가운데 위치와 제한된 위치를 표시하는 LED 그리고 하나의 서보모터를 구동하는 출력을 포함하는 입/출력이 연결된 마이크로컨트롤러를 장착하는 것으로 부터 시작합니다.
브레드보드의 배선도는 그림 2에 나와 있습니다.

참고: Digi-Key 시제품 제작 페이지에서 찾을 수 있는 표준 점퍼 전선 키트는 길이에 따라 색상이 지정되어 있어서 전선의 연결에 따라 전선 색상이 다를 수 있습니다. 제공된 도면에는 스풀에서 맞춰서 자른 전선을 사용함으로써 가능한 단일 색상으로의 연결을 보여주고 있습니다.

필요한 부품:

서보: 180도 (1528-1083-ND), 촉각 스위치 (450-1650-ND), 전위차계 (3310P-125-103L-ND), 아두이노 미니 V5 (1050-1044-ND), LED – 녹색 (160-1130-ND), LED – 빨간색 (160-1127-ND), 커패시터 (445-8571-ND), 아두이노 프로그래밍을 위한 USB to 시리얼 컨버터 (1050-1021-ND), 10k 저항 (CF18JT10K0CT-ND).

배치 고려 사항

일반적인 서보 모터는 4.8~6.5VDC에서 동작하며 부하 시 또는 방향 전환 시 최대 3암페어까지 소모합니다. 서보가 마이크로컨트롤러로부터 직접 신호를 받지만, 아두이노 미니에 탑재된 전압 레귤레이터는 서보가 필요로하는 전류 레벨을 제공할 수는 없습니다. 서보 전원 리드는 6V 전원 공급 장치에 직접 연결되어 있음에 주목하십시오. 마이크로컨트롤러에는 온보드 레귤레이터가 있으며, 이는 동일한 6V 전원으로부터 동작할 수 있습니다. 서보와 마이크로컨트롤러가 별개의 전원 공급 장치로부터 동작한다면, 서보가 마이크로컨트롤러에서 오는 신호를 인식하기 위해서는 공통 접지로 연결되어 있어야 합니다. 이 예제에서는 마이크로컨트롤러를 통해 서보를 시작/정지시키기 위해 촉각 스위치가 사용되었습니다.

코드(설명을 위해 주석이 많음)

/* 	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를 조작하는 방법을 보여줍니다. 이 동일한 두 변수를 사용하여 훨씬 더 많은 가능성을 만들 수 있도록 코드를 쉽게 수정할 수 있습니다. 촉각 스위치는 자기 스위치 또는 로직 출력을 가지는 다른 센서와 같이 HIGH - LOW 신호 구성으로 작동하는 어떠한 종류의 트리거 소자로도 교체될 수 있습니다. 애플리케이션은 무궁무진합니다.




영문 원본: Servomotor control with limits and variable speed