이 아두이노 튜토리얼에서는 아두이노로 DC 모터를 제어하는 방법을 배웁니다. DC 모터 제어의 기본 기술을 살펴보고, L298N 모터 드라이버와 아두이노 보드를 사용해 DC 모터를 제어하는 두 가지 예제를 실습합니다.
아래 비디오를 시청하거나 작성된 튜토리얼을 읽어보세요.
DC 모터 속도는 모터에 공급되는 입력 전압을 제어해 조절할 수 있으며, 가장 일반적인 방법은 PWM 신호를 사용하는 것입니다.
PWM DC 모터 제어
PWM(펄스 폭 변조)은 전원을 빠른 속도로 켜고 꺼서 전자 장치에 공급되는 전압의 평균값을 조절하는 기술입니다. 평균 전압은 듀티 사이클, 즉 한 주기 동안 신호가 ON인 시간과 OFF인 시간의 비율에 따라 달라집니다.
모터 크기에 따라 아두이노 PWM 출력을 트랜지스터 베이스나 MOSFET 게이트에 연결해 PWM 출력을 제어함으로써 모터 속도를 제어할 수 있습니다. 저전력 아두이노 PWM 신호가 MOSFET 게이트를 켜고 끄고, 이를 통해 고전력 모터가 구동됩니다.
H-브리지 DC 모터 제어
반면 회전 방향을 제어하려면 모터를 흐르는 전류 방향을 반전시키면 되며, 가장 일반적인 방법은 H-브리지를 사용하는 것입니다. H-브리지 회로는 모터를 중심으로 트랜지스터나 MOSFET 네 개가 H자 형태로 배치된 구조입니다. 특정 두 스위치를 동시에 활성화하면 전류 흐름 방향이 바뀌어 모터 회전 방향이 바뀝니다.
이 두 방법(PWM과 H-브리지)을 결합하면 DC 모터를 완벽하게 제어할 수 있습니다. 이런 기능을 가진 DC 모터 드라이버가 많으며 L298N이 그중 하나입니다.
L298N 드라이버
L298N은 듀얼 H-브리지 모터 드라이버로 두 개의 DC 모터를 동시에 속도와 방향 제어할 수 있습니다. 이 모듈은 5~35V 전압의 DC 모터를 구동할 수 있으며 최대 2A의 피크 전류를 지원합니다.
L298N 모듈의 핀아웃을 자세히 살펴보고 작동 원리를 설명하겠습니다. 모듈에는 모터 A, B용 두 개의 스크류 터미널 블록과 그라운드 핀, 모터용 VCC, 5V 핀(입력 또는 출력 가능)용 스크류 터미널 블록이 하나 더 있습니다.
이것은 모터 VCC에 사용되는 전압에 따라 다릅니다. 모듈에 내장된 5V 레귤레이터는 점퍼로 활성화/비활성화할 수 있습니다. 모터 공급 전압이 12V 이하이면 5V 레귤레이터를 활성화해 5V 핀을 출력으로 사용해 아두이노 보드에 전원을 공급할 수 있습니다. 하지만 모터 전압이 12V보다 높으면 점퍼를 제거해야 합니다. 그렇지 않으면 높은 전압이 내장 5V 레귤레이터를 손상시킬 수 있습니다. 이 경우 5V 핀을 입력으로 사용해 5V 전원 공급 장치를 연결해야 IC가 제대로 작동합니다.
이 IC는 약 2V의 전압 강하가 있습니다. 예를 들어 12V 전원 공급 장치를 사용하면 모터 단자 전압은 약 10V가 되어 12V DC 모터의 최대 속도를 낼 수 없습니다.
다음은 로직 제어 입력입니다. Enable A와 Enable B 핀은 모터 활성화와 속도 제어용입니다. 이 핀에 점퍼가 있으면 모터가 활성화되어 최대 속도로 작동하고, 점퍼를 제거하면 PWM 입력을 연결해 모터 속도를 제어할 수 있습니다. 이 핀을 그라운드에 연결하면 모터가 비활성화됩니다.
Input 1과 Input 2 핀은 모터 A의 회전 방향 제어용, Input 3과 4는 모터 B용입니다. 이 핀들로 L298N IC 내부의 H-브리지 스위치들을 제어합니다. Input 1이 LOW이고 Input 2가 HIGH면 모터가 전진, 반대의 경우 후진합니다. 두 입력이 같으면(모두 LOW 또는 HIGH) 모터가 정지합니다. Input 3, 4와 모터 B에도 동일하게 적용됩니다.
아두이노와 L298N 모터 드라이버
이제 실용적인 애플리케이션을 만들어보겠습니다. 첫 번째 예제에서는 포텐쇼미터로 모터 속도를 제어하고 푸시 버튼으로 회전 방향을 바꿉니다. 회로도는 다음과 같습니다.
/* 아두이노 DC 모터 제어 - PWM | H-브리지 | L298N - 예제 01 by Dejan Nedelkovski, www.HowToMechatronics.com */
#define enA 9
#define in1 6
#define in2 7
#define button 4
int rotDirection = 0;
int pressed = false;
void setup() {
pinMode(enA, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(button, INPUT);
// 초기 회전 방향 설정
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
}
void loop() {
int potValue = analogRead(A0); // 포텐쇼미터 값 읽기
int pwmOutput = map(potValue, 0, 1023, 0 , 255); // 0-1023을 0-255로 매핑
analogWrite(enA, pwmOutput); // L298N Enable 핀에 PWM 신호 전송
// 버튼 읽기 - 디바운싱
if (digitalRead(button) == true) {
pressed = !pressed;
}
while (digitalRead(button) == true);
delay(20);
// 버튼 눌림 - 회전 방향 변경
if (pressed == true & rotDirection == 0) {
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
rotDirection = 1;
delay(20);
}
// 버튼 눌림 - 회전 방향 변경
if (pressed == false & rotDirection == 1) {
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
rotDirection = 0;
delay(20);
}
}
설명: 먼저 핀들과 프로그램에 필요한 변수들을 정의합니다. setup 섹션에서는 핀 모드와 모터의 초기 회전 방향을 설정합니다. loop 섹션에서는 포텐쇼미터 값을 읽고 0~1023 범위의 값을 PWM 신호용 0~255(0~100% 듀티 사이클) 범위로 매핑합니다. analogWrite() 함수로 L298N 보드의 Enable 핀에 PWM 신호를 보내 모터를 구동합니다.
다음으로 버튼이 눌렸는지 확인하고, 눌렸다면 Input 1과 Input 2 상태를 반대로 설정해 모터 회전 방향을 바꿉니다. 푸시 버튼은 토글 버튼처럼 작동해 누를 때마다 모터 회전 방향이 바뀝니다.
L298N 모터 드라이버를 이용한 아두이노 로봇카 제어
이걸 배웠으니 이제 우리만의 아두이노 로봇카를 만들 수 있습니다. 회로도는 다음과 같습니다:
필요한 건 DC 모터 2개, L298N 모터 드라이버, 아두이노 보드, 제어용 조이스틱입니다. 전원 공급으로는 3.7V 리튬이온 배터리 세 개를 사용해 총 11V를 만들었습니다. 섀시는 3mm 두께 합판으로 만들고 금속 브래킷으로 모터를 고정하고 바퀴를 달았으며 앞쪽에 캐스터 휠을 부착했습니다.
이제 아두이노 코드를 보고 어떻게 작동하는지 살펴보겠습니다. (아래에 전체 코드 있음)
int xAxis = analogRead(A0); // 조이스틱 X축 읽기
int yAxis = analogRead(A1); // 조이스틱 Y축 읽기
핀 정의 후 loop 섹션에서 조이스틱 X, Y축 값을 읽습니다. 조이스틱은 두 개의 포텐쇼미터로 아두이노 아날로그 입력에 연결되어 있으며 0~1023 값 범위를 가집니다. 조이스틱이 중앙에 있을 때 두 포텐쇼미터(축) 값은 약 512입니다.
약간의 여유를 두고 470~550을 중앙으로 간주합니다. 조이스틱 Y축을 뒤로 움직여 값이 470 미만이 되면 네 개 입력 핀으로 두 모터 회전 방향을 후진으로 설정합니다. 그런 다음 470~0으로 감소하는 값을 0~255로 증가하는 PWM 값(모터 속도)으로 변환합니다.
// Y축으로 전진/후진 제어
if (yAxis < 470) {
// 모터 A 후진
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
// 모터 B 후진
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
// 후진용 Y축 감소값(470~0)을 PWM 신호용 0~255 값으로 변환
motorSpeedA = map(yAxis, 470, 0, 0, 255);
motorSpeedB = map(yAxis, 470, 0, 0, 255);
}
마찬가지로 Y축을 앞으로 움직여 값이 550을 넘으면 모터를 전진으로 설정하고 550~1023 읽기값을 0~255 PWM 값으로 변환합니다. 조이스틱이 중앙에 있으면 모터 속도는 0입니다.
이제 X축으로 좌/우 제어하는 방법을 봅시다.
// X축으로 좌/우 제어
if (xAxis < 470) {
// X축 감소값(470~0)을 증가하는 0~255 값으로 변환
int xMapped = map(xAxis, 470, 0, 0, 255);
// 좌회전 - 좌측 모터 속도 감소, 우측 모터 속도 증가
motorSpeedA = motorSpeedA - xMapped;
motorSpeedB = motorSpeedB + xMapped;
// 0~255 범위로 제한
if (motorSpeedA < 0) { motorSpeedA = 0; }
if (motorSpeedB > 255) { motorSpeedB = 255; }
}
다시 X축 읽기값을 0~255 속도 값으로 변환합니다. 좌회전 시 이 값으로 좌측 모터 속도를 줄이고 우측 모터 속도를 높입니다. 산술 연산 때문에 모터 속도 범위를 0~255로 제한하는 두 개의 추가 if 문을 사용합니다.
우회전도 같은 방식입니다.
관련: 555 타이머 IC로 PWM DC 모터 속도 컨트롤러 만들기
인가 전압과 모터 특성에 따라 저속에서 모터가 회전을 시작하지 못하고 버징 음을 낼 수 있습니다. 내 경우 PWM 신호 값이 70 미만이면 모터가 움직이지 않았습니다. 따라서 두 if 문으로 속도 범위를 70~255로 제한했습니다. 마지막에 최종 모터 속도(PWM 신호)를 L298N 드라이버의 enable 핀에 보냅니다.
// 저속에서 버징 방지 (모터에 맞게 조정. 내 모터는 PWM 값이 70 미만이면 움직이지 않음)
if (motorSpeedA < 70) { motorSpeedA = 0; }
if (motorSpeedB < 70) { motorSpeedB = 0; }
analogWrite(enA, motorSpeedA); // 모터 A에 PWM 신호 전송
analogWrite(enB, motorSpeedB); // 모터 B에 PWM 신호 전송