STM32 DC Motor PWM 제어

DongHee Lim·2022년 5월 3일
0

STM32

목록 보기
11/11

서론


DC 모터를 사용한지 오래되어서 복습 겸 PWM 제어를 하기로 했다.

사용 보드 : Nucleo-F429ZI
개발 환경 : CubeIDE 1.9.0

DC Motor


DC 모터는 PWM 신호만으로 동작하기에는 힘이 약해서
DC 모터 드라이버를 함께 사용한다.

현재 가지고 있는 교육용 제품에는

AAT4685 (TDFN33-12) MOSFET
MAX14870 DC 모터 드라이버
MB3220-0637 Micro DC 모터

를 사용하고 있다.

어떤 모터를 사용하든

DC 모터는
PWM 신호와 Direction (방향) 신호만 넣어주면
조작가능하다.


Setup


교육용 제품에 DC 모터는

PA0   -> PWM
PG10 -> dir (방향)

으로 고정되어있다.

PA0의 타이머는 TIM2, TIM5 이 가능하므로
TIM5 PWM CH1을 선택하였다.


Timer 2 와 5는
F4 보드에서 32 bits 해상도를 가지고 있어
2^32 => 약 42억 을 표현할 수 있다. (0 ~ 4294967295)

그리고 Timer 2, 5는 APB1 타이머 라서

SysClk/2 = 180MHz/2 = 90MHz

주파수를 가지고 있다.


나는 DC 모터 작동에 주파수를 100Hz 로 설정하였다.

참고)
분해능을 높이기 위해서는 Prescaler 를 낮추고
Counter Period 값을 높게 설정하여도 된다.

90MHz / 90 = 1MHz

1MHz / 10000 = 1,000,000 Hz / 10,000 = 100 Hz

Prescaler = 90 - 1
Counter Period = 10000 - 1

위 첫번째 그림에서 Counter Period값 대비
Pulse 값을 조절하면 PWM 비율을 지정할 수 있다.

나는 프로그램 내부에서 조작하기 위해 0 으로 두었다.


Code


부드럽게 출발,
부드럽게 정지,
속도가 느려졌을 때
방향을 바꾸는 동작이다.

[Code 전체 Github 링크]

/* USER CODE BEGIN PV */
uint8_t dir = 0;				// 방향을 나타내는 변수
uint16_t interval = 50;			// Pulse 변화량
int16_t temp_Interval;			// 계산할 때 사용하는 Interval 변수
int32_t temp_CCR = 0;			// Pulse 값 계산 시 필요 (TIM5->CCR 연관)
uint32_t turningPoint = 2000;	// 방향 바꿀 Pulse 값	(전체(TIM5->ARR) : 10000 - 1)
/* USER CODE END PV */
  while (1)
  {

	  if(temp_CCR >= (TIM5->ARR + 1))				// 최고 회전 속도 찍었을 때
	  {
		temp_CCR = TIM5->ARR + 1;					// 10000
		temp_Interval = -interval;					// 변화량 감소
	  }
	  else if(temp_CCR <= turningPoint)				// 최저 회전 속도 찍었을 때
	  {
		temp_CCR = turningPoint;
		temp_Interval = interval;					// 변화량 증가
		dir = !dir;									// 방향 변경
		HAL_GPIO_WritePin(GPIOG, GPIO_PIN_10, dir);	// PG10 토글 동작
	  }
	  temp_CCR += temp_Interval;					// 사용할 CCR 값 계산
	  if(temp_CCR == 0)
	  {
		  TIM5->CCR1 = temp_CCR;					// Underflow 방지용 
	  }
	  else
	  {
		  TIM5->CCR1 = temp_CCR - 1;				// 기본 계산 (256은 0~255 나타내듯 -1 해야함)
	  }

	  printf("Compare : %4d | TEMP : %5d | DIR :%d\r\n", (int)TIM5->CCR1, (int)temp_CCR ,dir);	// 출력
	  HAL_Delay(10);


    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

개선할 점

1. duty ratio 로 나타낼 수 있는 함수

float dutyRatio;
TIM5->CCR1 = (uint32_t)((TIM5->ARR + 1) * 0.01 * dutyRatio) - 1;
uint32_t 는 32비트 타이머냐 16비트 타이머냐에 따라 다름

2. 방향 변환점의 가변성

turningPoint = 2000
을 while 내부로 옮기고
(uin32_t)((TIM5->ARR + 1) * 0.2) 로 계산하여 넣기


profile
하고 싶은 것, 소유하고 싶은 것, 좋아하는 것

5개의 댓글

comment-user-thumbnail
2023년 1월 31일

안녕하세요! 잘 보고 있습니다 좋은 써주셔서 감사합니다
그런데 궁금한 점이 저는 F446RE보드를 사용하고 있어서 dir이 PG10으로 되어있지 않은데 그런 경우에는 어떻게 해야 하나요? 처음만져보는 보드라 어려운 점이 많습니다 ㅠ 알려주시면 감사하겠습니다

2개의 답글