

이렇게 생긴게 DCMotor
PWM이라는 제어 방법을 통해 모터를 구동해볼것이다
PWM (Pulse Width Modulation)은 펄스 폭 변조라고해서 0과 1을 반복하는 디지털 신호에서 한번 0에서 1로 갈때 그 0과 1의 비율을 조절하는 것이다

이렇게 펄스를 조절해서 모터에 힘들 다르게 준다
모터의 회전 속도나 LED의 밝기 조절 등에서 사용된다
PWM 제어를 사용하기 위해 ioc에서 TIM4의 Channel1 PWM Generation CH1로 활성화하자

그러면 자동으로 PD12번 핀이 TIM4_CH1으로 자동 활성화된다
이제 타이머 생성때와 마찬가지로 TIM4의 주파수를 조절해야한다
데이터시트에서 TIM4가 어느 버스에 연결되어 있는지 확인하자

TIM4는 APB1 버스에 연결되어 있고

Clock Configuration을 확인하면 APB1은 84MHz의 주파수를 가진 것을 확인할 수 있다
이제 분주기를 840으로 설정하여 분주해주면 84000000 / 840 = 100000 = 100KHz가 되고 1주기는 1 / 100000 = 0.00001 = 10us가 된다
이어서 Counter Period를 100으로 설정해주면 0.00001 * 100 = 0.001 = 1ms, 1ms의 타이머가 생성된다


기본 Pulse (Duty Cycle)를 70, Fast Mode를 Enable로 설정해주면 설정이 마무리된다
저장후 코드를 생성하자
// dcmotor.h
#include "main.h"
#include "button.h"
dcmotor.h 파일을 생성하고
// dcmotor.c
#include "dcmotor.h"
extern TIM_HandleTypeDef htim4;
volatile uint8_t pwm_start_flag = 0; // dcmotor start & stop indicator flag
volatile uint16_t CCR_Value = 0; // Duty Cycle
// BUTTON0 : start/stop : LED1 (toggle)
// BUTTON1 : SPEED-UP : LED2 (toggle)
// BUTTON2 : SPEED-DOWN : LED3 (toggle)
void dcmotor_pwm_control(void)
{
// BUTTON0 : START / STOP
if (get_button(BUTTON0_GPIO_Port, BUTTON0_Pin, 0) == BUTTON_PRESS)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0); // LED1
if (!pwm_start_flag)
{
pwm_start_flag = 1;
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1); // fan run
}
else
{
pwm_start_flag = 0;
HAL_TIM_PWM_Stop(&htim4, TIM_CHANNEL_1); // fan stop
}
}
// BUTTON1 : SPEED UP
if (get_button(BUTTON1_GPIO_Port, BUTTON1_Pin, 1) == BUTTON_PRESS)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7); // LED2
CCR_Value = __HAL_TIM_GET_COMPARE(&htim4, TIM_CHANNEL_1);
CCR_Value += 10;
if (CCR_Value > 100) CCR_Value = 100;
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, CCR_Value);
}
// BUTTON2 : SPEED DOWN
if (get_button(BUTTON2_GPIO_Port, BUTTON2_Pin, 2) == BUTTON_PRESS)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_14); // LED3
CCR_Value = __HAL_TIM_GET_COMPARE(&htim4, TIM_CHANNEL_1);
CCR_Value -= 10;
if (CCR_Value < 40) CCR_Value = 40;
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, CCR_Value);
}
}
dcmotor.c를 위와같이 생성한다

dcmotor_pwm_control() 함수를 extern 해주고

main()의 while문 안에서 함수를 호출해준다

연결은 위와 같이 IN-를 -전하에 IN+를 아까 활성화된 PD12번 핀과 연결해준다
BUTTON0을 누르면 팬이 시작하거나 멈추고 BUTTON1와 BUTTON2로 Duty Cycle을 설정해 팬의 속도를 조절할 수 있다
추가적으로 모터 드라이버 모듈을 사용해서 팬의 회전 방향을 제어해보자

요게 모터 드라이버 모듈이다
빨간선 연결된 곳에 +5V, 검정선 연결된 곳에 GND를 연결해주면 되고, PD12번 핀을 ENA 핀에 꽂아주면 연결된다
이게 없어도 DCMotor는 잘 돌아가는데 왜 굳이 이걸 쓰느냐?
모터 드라이버 모듈을 사용하면 토크 제어, 속도 제어, 전압 제어, 전류 제어, 위치 제어, 모터 보호 등이 가능하기 때문에 모터를 다양하게 사용할 수 있게된다
여기서는 팬의 회전 방향을 제어하려고 사용할건데, 모터의 IN1, 2에 연결된 핀의 값을 다르게 주면 원하는데로 모터를 작동시킬 수 있다

PE8번, 9번 핀을 GPIO_Output으로 활성화하고
#include "dcmotor.h"
extern TIM_HandleTypeDef htim4;
volatile uint8_t pwm_start_flag = 0; // dcmotor start & stop indicator flag
uint8_t way_flag = 1; // 0 : reverse | 1 : normal
volatile uint16_t CCR_Value = 0; // Duty Cycle
// BUTTON0 : start/stop : LED1 (toggle)
// BUTTON1 : SPEED-UP : LED2 (toggle)
// BUTTON2 : SPEED-DOWN : LED3 (toggle)
// BUTTON3 : change way
void dcmotor_pwm_control(void)
{
// BUTTON0 : START / STOP
if (get_button(BUTTON0_GPIO_Port, BUTTON0_Pin, 0) == BUTTON_PRESS)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0); // LED1
if (pwm_start_flag == 0)
{
pwm_start_flag = 1;
}
else
{
pwm_start_flag = 0;
}
}
// BUTTON1 : SPEED UP
if (get_button(BUTTON1_GPIO_Port, BUTTON1_Pin, 1) == BUTTON_PRESS)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7); // LED2
CCR_Value = __HAL_TIM_GET_COMPARE(&htim4, TIM_CHANNEL_1);
CCR_Value += 10;
if (CCR_Value > 100) CCR_Value = 100;
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, CCR_Value);
}
// BUTTON2 : SPEED DOWN
if (get_button(BUTTON2_GPIO_Port, BUTTON2_Pin, 2) == BUTTON_PRESS)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_14); // LED3
CCR_Value = __HAL_TIM_GET_COMPARE(&htim4, TIM_CHANNEL_1);
CCR_Value -= 10;
if (CCR_Value < 40) CCR_Value = 40;
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, CCR_Value);
}
// BUTTON3 : right_way / asdf
if (get_button(BUTTON3_GPIO_Port, BUTTON3_Pin, 3) == BUTTON_PRESS)
{
if (way_flag == 0) // right_way
{
way_flag = 1;
}
else // right_way
{
way_flag = 0;
}
}
if (pwm_start_flag == 1)
{
if (way_flag == 1)
{
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_8, 1); // normal way
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_9, 0);
}
else
{
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_8, 0); // reverse way
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_9, 1);
}
}
else
{
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_8, 1); // break
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_9, 1);
}
}
dcmotor.c를 위와같이 수정해준다
그러면 버튼0, 1, 2, 3을 통해 각각 start flag, duty cycle, way flag의 값을 변경하며 맨 아래 if 문에서 변경된 플래그와 듀티 사이클에 따라 DCMotor를 작동시킨다

main.c에 해당 코드도 추가해주자

연결은 위와같이 해주었다
PE8번 9번 핀을 각각 IN1, IN2에 연결해주고 PD12번 핀을 ENA에 연결
BUTTON3을 눌러 회전 방향을 바꿀 수 있다
혹시나 자신이 원한 방향과 반대로 돌아가는 경우에는
IN1과 IN2에 꽂은 핀을 서로 바꾸면 된다
'임베디드 > STM32 (ARM Cortex - M4)' 카테고리의 다른 글
| [STM32] FREERTOS를 사용한 쓰레드와 뮤텍스 (1) | 2024.01.26 |
|---|---|
| [STM32] RTC (1) | 2023.10.22 |
| [STM32] I2C LCD 출력 (1) | 2023.10.22 |
| [STM32] 초음파 측정기 (1) | 2023.10.21 |
| [STM32] DHT11 온 습도 측정기 (0) | 2023.10.21 |