일반 DC 모터는 단순히 전압을 인가하면 돌아간다.
모터에 인가되는 전압을 높이면 빨라지고, 줄이면 느려진다.
하지만 하지만 정확히 몇 바퀴를 돌았는지, 어떤 속도로 도는지는 알 수 없다. 즉, 정밀한 모터 제어가 어려운 것이다.
모터 축의 회전량을 전기적 펄스 신호로 변환해주는 Encoder를 장착한 Encdoer Motor는 몇 회전 했는지(위치), 얼마나 빨리 도는지(속도), 어느 방향으로 도는지까지 알 수 있다.

위 모터의 배선을 보면 일반 DC 모터와 다르게 6개의 선이 있다.
좌측 검은색과 빨간색은 DC모터 제어 배선이다.
모터의 축에 연결된 자석의 회전을 두개의 센서가 측정하는 방식으로 모터의 회전을 확인한다.
다음은 나머지 선에 대한 정보이다.
Brown : Sensor VCC
Green : Sensor GND
Blue : Sensor B
Purple : Sensor A
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
volatile long encoderCount = 0;
// ===== UART 초기화 =====
void uart_init(unsigned int ubrr) {
UBRR0H = (unsigned char)(ubrr >> 8);
UBRR0L = (unsigned char)ubrr;
// 송신/수신 enable
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
// 프레임: 8N1
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
}
void uart_transmit(unsigned char data) {
while (!(UCSR0A & (1 << UDRE0))); // 송신버퍼 준비 대기
UDR0 = data;
}
void uart_print(const char* str) {
while (*str) uart_transmit(*str++);
}
// 숫자를 문자열로 변환해서 출력
void uart_print_num(long num) {
char buf[16];
itoa(num, buf, 10);
uart_print(buf);
}
// ===== 인코더 초기화 =====
void encoder_init(void) {
// D2(PD2), D3(PD3) 입력 + 풀업
DDRD &= ~((1 << PD2) | (1 << PD3));
PORTD |= (1 << PD2) | (1 << PD3);
// INT0 (D2) Rising Edge 인터럽트
EICRA |= (1 << ISC01) | (1 << ISC00);
EIMSK |= (1 << INT0);
sei(); // 전역 인터럽트 허용
}
// ===== 인터럽트 서비스 루틴 =====
ISR(INT0_vect) {
if (PIND & (1 << PD3)) {
encoderCount++;
} else {
encoderCount--;
}
}
// ===== 메인 루프 =====
int main(void) {
// 보레이트 계산: 9600bps
unsigned int ubrr = F_CPU / 16 / 9600 - 1;
uart_init(ubrr);
encoder_init();
while (1) {
uart_print("Encoder Count: ");
uart_print_num(encoderCount);
uart_print("\r\n");
_delay_ms(500);
}
}
위 코드를 실행하고 모터를 돌려보면 다음과 같은 결과가 시리얼 모니터에 나온다

코드가 실행되는 시점의 모터의 상태를 0으로 인식하고 시계방향으로 돌리면 숫자가 커지고 반시계방향으로 돌리면 작아진다.
자율주행 차량에서는 이러한 인코더 모터가 필수적이다.
인코더 없이 단순히 PWM으로만 모터를 제어한다면, 배터리 잔량, 바닥 마찰, 경사 등에 따라 속도가 달라져서 동일한 제어 신호를 주더라도 차량의 실제 움직임은 매번 달라진다.
이 경우 직진이 잘 안 되고, 원하는 거리만큼 이동하거나 정확히 회전하는 동작을 보장하기 어렵다.
반면 인코더를 사용하면 목표 속도와 실제 속도의 차이를 보정할 수 있어 정확한 직진, 일정한 회전, 원하는 거리 주행이 가능해지고, 이는 자율주행의 기본이 되는 주행 안정성을 보장해준다.
'임베디드' 카테고리의 다른 글
| STM32 개발 환경 세팅 — CubeMX + CubeIDE (Nucleo-F401RE) (0) | 2026.05.06 |
|---|---|
| RTOS (0) | 2026.04.30 |
| Arduino UNO 와 Raspberry Pi 통신 (1) | 2025.08.27 |
| [AVR Programming] 아두이노 서보모터 제어 (1) | 2025.08.18 |
| I2C 통신 / 센서 주소 찾기 (3) | 2025.08.16 |