아두이노에서 서보모터를 사용할 때에는 보통 <Servo.h>라는 헤더파일을 사용합니다.
<Servo.h>에 있는 servo.write() 함수는 서보모터를 구동시킬 때 사용됩니다.
하지만 servo.write() 함수는 외부인터럽트 안에서는 동작을 하지 않는다는 문제점이 있습니다.
오늘은 외부인터럽트 안에서 서보모터를 구동시키는 방법을 알아보겠습니다.
button, servo motor, led를 그림과 같이 연결해 줍니다.
※문제점 : <servo.h>사용 시 인터럽트에서 서보모터가 동작하지 않음
▽예상 동작 : 버튼을 누르면 인터럽트가 호출되어 인터럽트 안에 있는 led가 켜지고, 서보모터가 동작합니다.
그러나, 실제 동작을 시켜보면 인터럽트가 정상적으로 호출되어 led는 켜지지만,
인터럽트가 정상적으로 호출되어도 서보모터는 동작하지 않습니다.
#include <Servo.h>
Servo servo1;
int led=5;
int interruptpin=2;
void setup()
{
servo1.attach(3); //서보모터 신호선
pinMode(interruptpin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptpin),moter,LOW);
pinMode(led, OUTPUT); //led 출력선
Serial.begin(9600);
}
void loop()
{
servo1.write(90); //버튼을 안 눌렀을 때 모터 정지
digitalWrite(led, LOW); //버튼 안 눌렀을 때 led OFF
}
void moter() //인터럽트 호출됐을 때(버튼 눌렀을 때) 실행
{
Serial.println("intterupt");
servo1.write(83); //버튼 누르면 모터 동작
}
※해결책
인터럽트 발생 시 사용할 motor(), servoPulse()함수를 사용자 지정함수로 만들어 주었습니다.
servoPulse()에서 angle값을 pwm값으로 변환해주어 모터 구동에 사용합니다.
예상동작 : 버튼을 누르면 led가 켜짐과 동시에 인터럽트가 발생되어 motor()를 호출하고, motor()에서 servoPulse()를 호출하여 각도로 서보모터를 제어합니다. 버튼에서 손을 떼면 led가 꺼짐과 동시에 servo motor도 정지합니다.
int servo = 3;
int button = 2;
int angle;
int pwm;
int led=5;
void setup()
{
pinMode(servo, OUTPUT);
pinMode(button, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2),motor,LOW);
Serial.begin(9600);
}
void loop ()
{
servoPulse(servo, 90); //버튼을 안 눌렀을 때 모터 정지
digitalWrite(led, LOW); //버튼 안 눌렀을 때 led OFF
}
void motor() //인터럽트 호출됐을 때(버튼 눌렀을 때) 실행
{
servoPulse(servo, 80); //버튼 누르면 모터 동작
digitalWrite(led, HIGH); //버튼 누르면 led on
}
void servoPulse (int servo, int angle) //서보모터 구동하기 위한 함수
{
pwm = (angle*11) + 500; // Convert angle to microseconds
digitalWrite(servo, HIGH);
delayMicroseconds(pwm);
digitalWrite(servo, LOW);
delay(50);
}
인터럽트가 호출되었을 때 led와 servomotor모두 정상적으로 동작합니다.
........
시제품 제작 문의