[Embedded] Motor
모터는 PWM으로 속도를 조절하고 인코더로 회전 결과를 측정한다.
PWM은 출력이고 인코더는 입력으로, 두 가지가 한 쌍을 이뤄야 정확한 제어가 가능함.
PWM, Timer 등 지난번에 센서를 공부할 때 다뤘던 내용들이 모터에 그대로 등장한다.
다만 모터의 회전을 측정하는 인코더와 보정 파라미터를 찾는 Calibration이 새로 도입됨.

DC 모터는 자석에 흐르는 전류의 방향과 세기를 조절해 모터에 회전력을 발생시킨다.
전류의 방향이 회전 방향을 결정하고, 전류의 세기가 회전 속도를 결정한다.
일단 전류를 어떻게 조절하는지가 핵심.
인코더는 모터의 회전 방향과 이동거리 계산을 위해 사용된다.
모터에 전류를 줘서 돌리더라도, 얼마나 돌았는지 계산해야 한다. 그러니 이 측정을 인코더가 담당함.
가변 저항으로 전압 자체를 줄이거나 PWM으로 ON/OFF 를 빠르게 반복하면 모터의 전압을 조절할 수 있다.
두 방법 중 PWM을 사용하면 전력 손실도 없고 효율도 좋음.
이미지에서 Duty Cycle이 곧 속도가 됨. 그러니 저걸 조절하면 모터 속도가 조절된다.
이전에 초음파센서를 다룰 때 Trigger 신호 길이를 조절할 때와 같은 방식으로 PWM 기능을 사용함.

인코더 때문에 선이 6개 나온다.
모터 전원 관련 2개 / 인코더 전원 관련 2개 / 인코더 출력 관련 2개로 구성됨.
정방향으로 돌리려면 +쪽에 전압을 주고 역방향으로 돌리려면 -쪽에 전압을 줘야 한다. 그러니 두 선 모두 제어할 수 있어야 함.
신호 하나로는 회전 방향을 알 수 없으니 A와 B 두 신호의 위상 차이로 방향을 알아냄.
MC_EN은 PB2에 연결하는데, 모터에 전원을 공급할지 말지를 결정하는 마스터 스위치 역할을 수행한다.
하드웨어를 직접 다루는거니 안전에 주의해야 함. 전원을 켜자마자 모터가 돌면 위험하니 PB2를 low로 두면 안전하다.
센서를 다룰 때는 echo 측정 시 Timer Input Capture를 사용했다.
인코더 측정에서는 EXTI 외부 인터럽트를 사용함.
두 방법 모두 가능함. Timer의 Encoder Mode라는 전용 기능을 사용해도 된다.
다만 uBrain 코드에서는 이해하기 쉽고 직관적인 방식인 EXTI 외부 인터럽트를 사용한다.

역시 하드웨어의 스펙 표가 중요하다.
모터 한개에 채널 두개가 연결됨. + / - 모터 두 선 모두 제어해야 하니까..
STM32 핀에서 나오는 전기로는 모터를 돌릴 수 없으니 CMOS 전압과 전류를 모터 구동을 위한 전류로 변환해야 한다.
그러니 모터 드라이버 칩인 L6227Q를 사용함.

GPIO 포트의 각 핀은 그룹으로 묶이고 EXTI0 ~ EXTI15 까지 16개의 외부인터럽트를 발생시킬 수 있음.
GPIO 핀이 변하면 EXTI 회로가 감지한다.
센서의 Input Capture는 언제 변했는지 정확한 시간도 기록하지만, EXTI는 변했다는 사실만 알려준다.
회로에서의 규칙은 EXTI 번호는 핀 번호의 끝자리와 같다는 것.
같은 번호의 EXTI는 한 번에 하나의 포트만 쓸 수 있음.
여기서 핸들러 이름은 좀 다른데, 인터럽트 벡터 슬롯을 절약하기 위해서이다.
EXTI0 ~ EXTI4 까지는 각각 다른 핸들러를 사용하고,
EXTI5 ~ EXTI9 는 묶어서 하나의 핸들러로 사용한다.
EXTI10 ~ EXTI15 까지도 묶어서 하나의 핸들러로 사용함.
Hall 효과는 자기장 속에 전류가 흐르는 도체를 두면 전류와 자기장 양쪽에 수직 방향으로 전압이 발생하는 현상이다.
Hall 센서를 사용해 자기장 변화를 감지하고 출력으로 펄스를 발생시킨다.

두 센서를 90도로 위상차로 배치한다. 이러면 어느 신호가 먼저 변하는지 파악할 수 있고, 이를 통해 방향을 결정할 수 있음.
uBrain의 모터는 1회전에 26개의 펄스가 생성되니 A입력의 펄스를 카운트하고 회전당 펄스 수를 나누면 전체 회전수를 구할 수 있다.
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
switch(GPIO_Pin)
{
case GPIO_PIN_15: // PA15, 오른쪽 인코더 A
encoder_right = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3); // B 읽기
if(encoder_right == 0) // B=0 → Forward
{
motorInterrupt1++;
encoder_right = READY;
}
else if(encoder_right == 1) // B=1 → Backward
{
motorInterrupt1--;
encoder_right = READY;
}
break;
// (case GPIO_PIN_4 는 다음 슬라이드에서)
}
}
A가 변한 순간 B를 읽고, 상태 변수를 READY로 표시해 다음 인터럽트를 받을 준비를 마친다.
모터가 한 바퀴 회전했을 때, 인코더 신호로부터 계산된 카운터의 변화량에 따른 이동거리는 모터의 상태에 따라 다르니 인코더 값을 측정한 후 모터의 상태에 따라 코드를 조절해야 함.
이런 차이는 소프트웨어로 측정할 수 없으니 Calibration이 필요하다.
어제 잘 됐다고 오늘 잘 될거라는 보장이 없으니.. 매번 Calibration을 해 줘야 함.
IR 센서를 사용할 때 Lookup 테이블이 필요했는데, 저것도 일종의 Calibration이다. 센서와 액추에이터는 실제로 돌려보면 이론이랑 다르니 꼭 필요함.
'Computer Science > Embedded Software' 카테고리의 다른 글
| [Embedded] Device Driver (0) | 2026.05.14 |
|---|---|
| [Embedded] Embedded Operating System (0) | 2026.05.13 |
| [Embedded] Sensor (0) | 2026.05.13 |
| [Embedded] Communication Programming (0) | 2026.05.12 |
| [Embedded] Communication Protocol (1) (0) | 2026.05.12 |
댓글
이 글 공유하기
다른 글
-
[Embedded] Device Driver
[Embedded] Device Driver
2026.05.14 -
[Embedded] Embedded Operating System
[Embedded] Embedded Operating System
2026.05.13 -
[Embedded] Sensor
[Embedded] Sensor
2026.05.13 -
[Embedded] Communication Programming
[Embedded] Communication Programming
2026.05.12