728x90
이번에는 블루투스를 이용한 RC Car를 만들어 봤습니다.
RC Car
Pinout & Configuration
RC Car 구현을 위해 STM32에서 사용된 핀은 아래와 같습니다.
Timer 3을 사용하였고, Channel은 두 개의 채널을 사용하였습니다.
또한, 블루투스 모듈을 사용하기위해 USART1을 사용하였고, USART2는 PC에서 RC Car를 테스트하기 위해 사용되었습니다.
블루투스 사용을 위해 USART1은 Rate를 9600으로 설정한 것을 확인할 수 있습니다.
타이머 설정은 위의 내용과 같이 Clock 및 PWM Channel을 선언하였습니다.
RCC와 SYS는 위와 같이 설정하였습니다.
Clock Configuration은 위와 같이 설정하였습니다.
Detail Code
위의 코드는 RC Car의 모터(바퀴 부분)을 제어하는 코드를 나타냅니다.
각각의 GPIO Pin에 HIGH, LOW를 선언하여 전진 및 후진을 설정하였습니다.
위의 코드는 전진, 좌회전, 우회전, 후진의 속도를 제어하는 코드를 나타냅니다.
CCR1, 2 의 값을 적절히 조절하여 설정하였습니다.
전체적인 main의 코드 부분은 아래의 내용과 같습니다.
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
uint8_t rxData[8];
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1)
{
HAL_UART_Transmit_IT(&huart1, rxData, sizeof(rxData));
HAL_UART_Receive_IT(&huart1, rxData, sizeof(rxData));
}
}
void setMotorDirection(uint8_t direction) {
if (direction == 1) { // Go
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET); // IN10 HIGH
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET); // IN4 LOW
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET); // IN5 HIGH
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); // IN3 LOW
} else { // Back
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET); // IN10 LOW
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET); // IN4 HIGH
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET); // IN5 LOW
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET); // IN3 HIGH
}
}
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_TIM3_Init();
MX_USART2_UART_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
HAL_UART_Receive_IT(&huart1, rxData, sizeof(rxData));
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
uint8_t dutyValue = 0; // local valiable
while (1)
{
if(rxData[6] == 0 || rxData[6] == 1 || rxData[6] == 4 || rxData[6] == 8 || rxData[6] == 2)
{
dutyValue = rxData[6];
switch(dutyValue)
{
case 0:
setMotorDirection(0); // STOP
TIM3->CCR1 = 0;
TIM3->CCR2 = 0;
break;
case 1:
setMotorDirection(1); // GO
TIM3->CCR1 = 600;
TIM3->CCR2 = 600;
break;
case 4:
setMotorDirection(1); // LEFT
TIM3->CCR1 = 700;
TIM3->CCR2 = 0;
break;
case 8:
setMotorDirection(1); // RIGHT
TIM3->CCR1 = 0;
TIM3->CCR2 = 700;
break;
case 2:
setMotorDirection(0); // REVERSE
TIM3->CCR1 = 600;
TIM3->CCR2 = 600;
break;
default:
break;
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 100;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
HW
전반적인 RC Car의 HW는 아래와 같습니다.
블루투스
블루투스 제어 어플은 "Dabble"을 사용하였고, 제어 화면은 아래와 같습니다.
좌측의 4개의 버튼으로 RC Car를 제어할 수 있습니다.
시연 연상
728x90
'Language > AVR' 카테고리의 다른 글
STM32 : Button, Timer (1) | 2024.09.13 |
---|---|
STM32 : UART (2) | 2024.09.12 |
STM32 : LED (0) | 2024.09.12 |
ATmega 128 : CLCD, I2C (0) | 2024.09.10 |
ATmega 128 : 4-Digit FND 동작 구현 (0) | 2024.05.30 |