지난 시간에 우리는 PWM이라는 것을 배웠다. 모터를 굴릴 준비는 다 되었으니 이제 굴릴 수단이 필요하다. 쉽게 말해 스위치를 껐다 켜는 것을 만들었으니 스위치가 필요한 셈이다. 모터를 제어하기 위해서는 모터 드라이버라는 스위치가 필요하다. 모터 드라이버는 모터 종류에 따라 여러 가지가 있는데 그중에 오늘 우리는 H-Bridge라는 것을 사용할 예정이다. H-Bridge는 총 4개의 스위치를 가지고 모터를 제어할 수 있도록 구성된 회로를 말한다. 아래 그림과 같이 H의 형태로 구성이 되어 있어 H-Bridge라 불리며 이 구조를 통해서 모터의 방향과 속도를 제어할 수 있다.

위 회로가 모터의 회전 방향을 바꿔줄 수 있는 이유는 바로 4개의 트랜지스터 Mosfet 덕이다. 4개의 Mosfet 들은 각각 스위치 역할을 한다. 동그란 원으로 뻗어나가는 부분이 Mosfet 기준으로 Gate라고 하는데 Gate에 전압이 인가되면 전류가 흐르게 된다. 스위치로 예를 들면 On 되는 것을 의미하는 셈이다. 반대로 전압을 인가하지 않으면 전류가 흐르는 것을 막아 Off 될 것이다. 이를 이용해서 Q1과 Q4에 전압을 인가하게 되면 모터로 흐르는 전류는 왼쪽에서 오른쪽으로 흐르게 된다. 반대로 Q2와 Q3에 전압을 인가하게 되면 모터로 흐르는 전류는 오른쪽에서 왼쪽으로 흐른다. 이것을 활용해 모터의 회전 방향을 제어하는 것이 바로 H-Bridge 회로이다. 이 간단한 회로는 모터 드라이버 형태로 판매하고 있어 쉽게 구매하여 사용할 수 있다.
나는 알리에서 구매한 MD10C R3 제품을 사용할 예정이다.

원래는 모터 드라이버를 선정할 때는 가장 먼저 Mosfet이 버틸 수 있는 전류 한계 등을 복합적으로 고려하여 선정 해야 한다. 하지만 나는 RC카를 굴리는 것으로 전류만 다소 낭랑한 것으로 골랐다. 그리고 무엇보다 해당 보드는 PWM 신호 없이 버튼으로 모터 테스트를 해볼 수 있어 좋다. 드라이버에 대한 설명은 충분한 것 같으니 전원, 모터, 신호를 연결하여 우리 의도 대로 모터가 빙글빙글 굴러가는지 확인해 보면 된다. 추가로 해당 드라이버는 DIR Pin으로 방향을 바꿀 수 있는데, 데이터 시트를 참고하자
(너무 낮은 Duty를 주면 모터를 돌릴만큼의 충분한 힘이 만들어지지 않아 돌지 않습니다)
모터를 돌리는 것 만큼이나 중요한 게 하나 더 있다. 그것은 바로 모터가 어떠한 속도로 어느 방향으로 돌아가고 있는지 아는 것이 중요하다. 모든 제어에서는 현재 상태를 알아야 그에 대한 피드백을 통해 제어를 하게 된다. 그렇기에 우리는 모터가 구동되는 과정에서 필요한 정보들이 몇 가지 있다.
그 중 하나가 회전 방향, 회전 속도이다. 그럼 우린 모터 회전 수를 어떻게 알 수 있을까? 가장 기본적인 방법으로 엔코더를 사용하는 것이다. 엔코더란 로터가 회전하게 되면 특정 각도마다 Pulse를 생성하게 된다. 오실로 스코프로 측정하게 되면, 마치 PWM 신호가 나오는 것처럼 보인다. 여기서 말한 특정 각도는 엔코더 스펙마다 다르며, Resolution이 좋을수록 더 작은 각도마다 파형이 생성된다.
우리는 모터에 내장된 엔코더를 사용할 예정이다. 모터에 내장된 엔코더는 1바퀴에 11 Pulse를 낸다. 반대로 이야기해서 1 Pulse당 32.72 degree정도라고 볼 수 있는 것이다. 엔코더에서 나오는 신호를 가지고 Pulse 값을 Count 하면 몇 도로 돌고 있는지 알 수 있다는 이야기 이다.
그럼 방향은 어떻게 알 수 있을까? 그것은 Phase Shift된 엔코더를 추가하면 된다. Phase Shift란 쉽게 말해 Pulse가 반정도 밀린 것을 의미한다. 이를 통해 어떻게 회전 방향을 알 수 있다는 것일까? 그것은 바로 반정도가 밀려있기 때문에 첫 번째 엔코더의 Pulse가 시작된 지점에서 두 번째 엔코더의 값을 보면 된다. 특정 방향으로 회전하고 있을 때, 두 엔코더의 센싱 값은 아래와 같다고 해보자. 두 번째 엔코더가 먼저 Pulse가 발생하기 시작하고 첫 번째 엔코더는 아직 Pulse가 발생하지 않았다. (두 번째 엔코더는 첫 번째 엔코더보다 반주기 빠르다) 여기서 첫 번째 엔코더가 Pulse가 시작되는 시점에서 두 번째 엔코더의 신호 값은 High의 중간을 지나가고 있다. 그럼 첫 번째 엔코더 기준으로 Pulse가 시작하는 타이밍에 두 번째 엔코더의 Logic Level이 High이면 정방향으로 돌고 있다고 보면 되는 것이다. (역방향으로 정의해도 된다. 그것은 바라보는 방향 관점에서 정방향인지 역방향인지 정하면 되는 것이기 때문에)
그럼 반대로 모터를 역방향으로 돌리게 되면, 첫번째 엔코더의 Pulse가 먼저 시작될 것이고 첫 번째 엔코더의 신호가 반쯤 지나갈 때 두 번째 엔코더의 Pulse가 시작될 것이다. 그럼 아까 기준을 그대로 가지고 오면, 첫 번째 엔코더의 Pulse가 시작되는 타이밍엔 두 번째 엔코더의 Logic Level은 Low일 것이다. 그렇다면 이것은 우린 역방향으로 정의하면 된다. 이 두 개의 개념을 합쳐 우리는 모터의 방향과 속도를 알 수 있는 것이다. 과거 ATMEL사의 마이컴을 가지고 구현한다고 했을 때, External Interrupt를 띄워서 확인을 했어야 했다. 엔코더의 신호를 Edge Detect 하여 Code 내에서 Interrupt를 띄우고 두 번째 엔코더의 Logic Level을 확인 후 회전 방향을 파악하여 Count를 Up 할 것인지 Down 할 것인지 구현해 주었어야 했다. 하지만 STM32의 경우 엔코더 모드를 지원하는 타이머를 가지고 있다. 타이머에 엔코더 두 신호를 연결하면, 타이머가 위 두 가지 논리를 가지고 Count를 세어준다. 이 Count를 주기적으로 체크하여 우리는 현재 모터가 정방향/역방향으로 어떠한 회전 속도를 가지고 돌고 있는지 계산할 수 있다. 서론이 길었는데 코드로 봐보자.
TIM_HandleTypeDef *vBswPwm_DriveTimer;
LPTIM_HandleTypeDef *vBswPwm_EncoderTimer;
void BswPwm_Init(TIM_HandleTypeDef *htim, LPTIM_HandleTypeDef *hlptim){
vBswPwm_DriveTimer = htim;
vBswPwm_EncoderTimer = hlptim;
}
HAL_StatusTypeDef BswPwm_Start(void){
HAL_StatusTypeDef err = HAL_ERROR;
HAL_TIM_PWM_Start(vBswPwm_DriveTimer, TIM_CHANNEL_1);
HAL_LPTIM_Encoder_Start(vBswPwm_EncoderTimer, 0xFFFFU);
return err;
}
Encoder를 위한 Timer가 추가되어야 한다. Encoder Mode를 찾아 이런저런 Timer를 찾아보았는데, LPTIM이 Encoder Mode를 지원했다.
앞에서 말했던 Encoder 2개를 활용한 로직은 신경 안쓰고 Pin만 꽂아 준다면 Timer가 알아서 방향성을 고려하여 Count값을 늘렸다 줄였다 해준다. Pin은 각각 PD11과 PB10에 연결해 주면 된다. 방향성을 고려하여 두 Pin을 교차해서 설계해도 된다.
이제 초기화 단계에서 Timer Start를 외쳐주면 'HAL_LPTIM_Encoder_Start(vBswPwm_EncoderTimer, 0xFFFFU)' 그때부터 Timer는 엔코더의 값을 확인하여 Count값을 더해주거나 빼주게 된다. Encoder Count 값은 아래와 같이 Timer Instance에서 CNT 값을 확인하면 된다.
uint16_t BswPwm_Get_EncoderCnt(void){
uint16_t EncoderValue;
EncoderValue = vBswPwm_EncoderTimer->Instance->CNT;
return EncoderValue;
}
위 API를 통하여 값을 받아보면 방향에 따라서 값이 계속 증가햇다 감소했다를 반복하는 것을 볼 수 있다.
이제 모터 제어에 대한 준비는 모두 끝났다. 지금까지 준비해온 API들을 활용하면 PID 제어 등을 마친 셈이니 다음 개발로 넘어가 보자.
'프로젝트 일지 > Whale Car' 카테고리의 다른 글
[Whale Car] Motor 제어 - PWM (0) | 2025.03.05 |
---|---|
[Whale Car] Core간 Communication (0) | 2024.11.27 |
[Whale Car] Schedule 이식 그리고 CPU Load (0) | 2024.10.21 |
[Whale Car] 1ms Timer의 늪 (5) | 2024.10.15 |
[Whale Car] STM32H745ZIQ 보드 연결 (0) | 2024.10.03 |