이번 과정은 STM32 보드와 추가로 제작된 확장보드 및 RC카 구동체를 이용해서 자동차를 제어하기 위한 간단한 프로그램을 만드는 과정입니다.
과정이 복잡하고 길어질 수 있어서 몇 편이 될지는 알 수 없지만 시리즈로 작성할 예정입니다.
아래 과정은 아래 환경과 보드를 이용했습니다.
- Windows 11 Home
- STM32CubeIDE-1.11.2
- STM32 NUCLEO-F103RB 보드
- 자체제작 확장보드
- 자체제작 자동체 구동체
- Anaconda
- Vscode
1. 구성품 소개
- 위 그림의 오른쪽 흰색 보드는 STM32 NECLEO-F103RB 보드입니다.
- 왼쪽의 초록색 보드는 확장보드로 IMU, 모터드라이버, 12 볼트 전원장치 등 RC카 구동을 위해 추가로 필요한 부품을 구성했습니다.
확장보드의 구성은 다음과 같습니다.
- LED
- 5 볼트
- 12 볼트
- 12 볼트에서 5 볼트 변환장치
- 부저
- IMU
- 모터 드라이버
- 모터 연결단자
- STM32 연결단자
2. STM32 프로젝트 생성
- 아래 그림과 같이 STM32CubeIDE 메뉴에서 'File >> New >> STM32 Project'를 선택합니다.
- 아래 그림과 같이 실행되는 'STM32 Project' 마법사에서 Board Selector를 선택한 후 'NUCLEO-F103RB'를 입력하고 보드를 선택한 후 'Next' 버튼을 클릭합니다.
- 아래 그림과 같이 실행되는 'STM32 Project' 마법사에서 'Project Name'을 입력한 후 'Finish' 버튼을 눌러 프로젝트를 생성합니다.
- 아래 그림과 같이 프로젝트가 생성됩니다.
3. 파이썬 프로젝트 생성
- 아나콘다 및 VSCode가 설치되어 있는 환경에서 파이썬 프로젝트를 생성하는 과정입니다. 아나콘다 또는 VSCode가 설치되어있지 않은 경우는 설치하시기 바랍니다.
- 파이썬 프로젝트를 생성하는 이유는 파이썬을 이용해 STM32 보드를 제어하기 위함입니다.
- 윈도우 실행파일에서 'Anaconda prompt (Anaconda3)'를 선택하여 실행합니다.
- 'Anaconda prompt (Anaconda3)'에서 아래와 같은 명령을 실행하여 가상환경을 생성합니다.
conda create -n ros1 python=3.7
- 'Anaconda prompt (Anaconda3)'에서 아래와 같은 명령을 실행하여 가상환경을 로딩합니다.
conda activate ros1
- 'Anaconda prompt (Anaconda3)'에서 아래와 같은 명령을 실행하여 pyserial 라이브러리를 설치합니다. pyserial 라이브러리는 STM32 보드와 serial 통신을 하기 위한 라이브러리입니다.
pip install pyserial
- 'Anaconda prompt (Anaconda3)'에서 아래와 같은 명령을 실행하여 jupyter notebook 라이브러리를 설치합니다.
pip install jupyter notebook
- 아래 그림과 같이 윈도우 탐색기를 이용해 적당한 위치에 파이썬 프로젝트 생성을 위한 폴더를 만듭니다.
- VSCode에서 방금 전에 생성한 폴더를 '폴더 열기'를 이용해 폴더를 엽니다.
- 키보드에서 'Ctrl + Shift + p' 버튼을 누르면 상단에 실행되는 창에서 'python'을 입력하고 'Python: 인터프리터 선택'을 선택합니다.
- 파이썬 인터프리터 중 'ros1'을 선택합니다.
4. STM32 - UART 통신하기
- STM32에 UART 통신을 하는 기능을 설정하는 과정입니다.
- 아래 그림과 같이 STM32CubeIDE의 'Clock Configuration' 탭을 선택한 후 'HSE'를 선택하고 '*PLLMul' 값을 'X 9'를 선택합니다.
- 'Clock Configuration'을 설정하는 이유는 STM32에서 기본적으로 설정된 Clock이 약간 불안정하여 좀 더 안정적으로 동작하는 Clock으로 변경하기 위함입니다.
- 아래 그림과 같이 'Pinout & Configuraiton' 탭에서 'Connectivity' >> 'USART2'를 선택하고 'Parameter Settings'를 아래와 같이 설정합니다.
◦ Mode: Asynchronous
◦ Baud Rate: 115200
- 아래 그림과 같이 'Pinout & Configuraiton' 탭에서 'Connectivity' >> 'USART2'를 선택하고 'NVIC Settings'를 아래와 같이 설정합니다.
◦ USART2 global interrupt: check
- 아래 그림과 같이 'Pinout & Configuraiton' 탭에서 'System' >> 'NVIC'를 선택하고 'USART global interrupt'를 check 합니다.
- 아래 그림과 같이 'Device Configuration Tool Code Generation' 버튼을 눌러서 코드를 생성합니다.
- 이후에 많은 코드를 작성해야 하므로 사용자 코드를 작성할 폴더를 만들도록 하겠습니다.
- 아래 그림과 같이 프로젝트를 선택한 후 마우스 메뉴 버튼을 누르면 뜨는 팝업메뉴에서 'New' >> 'Source Folter'를 선택합니다.
- 아래 그림과 같이 실행되는 'New Source Folder' 마법사에서 'Folder name'에 'BSP'를 입력하고 'Finish' 버튼을 눌러서 Source Folder를 생성합니다.
- BSP 폴더에 *.h 파일도 함께 만들 예정이기 때문에 Include path에도 추가해야 합니다.
- 아래 그림과 같이 프로젝트를 선택한 후 마우스 메뉴 버튼을 누르면 뜨는 팝업메뉴에서 'Properties'를 선택합니다.
- Properties 마법사에서 'C/C++ Build' >> 'Setting'를 선택하면 변경되는 창에서 'MCU GCC Compiler' >> 'Include paths'를 선택하면 변경되는 창에서 '+' 아이콘을 선택합니다.
- 'Add directory path' 마법사에서 'Directory'에 './BSP'를 입력 후 'Ok' 버튼을 누릅니다.
- 아래 그림과 같이 'BSP' 폴더가 추가된 것을 확인할 수 있습니다. 'Apply', 'Apply and Close' 버튼을 눌러서 창을 종료합니다.
- 아래 그림과 같이 'BSP' 폴더를 선택한 후 마우스 메뉴버튼을 눌러서 뜨는 팝업메뉴에서 'New' >> 'Header' 파일을 선택합니다.
- 'New Header File' 마법사에서 'Header file' 필드에 'bsp.h'를 입력한 후 'Finish' 버튼을 눌러서 파일을 생성합니다.
- 같은 방법으로 'bsp_uart.h' 파일을 생성합니다.
- 아래 그림과 같이 'BSP' 폴더를 선택한 후 마우스 메뉴버튼을 눌러서 뜨는 팝업메뉴에서 'New' >> 'Source' 파일을 선택합니다.
- 'New Source File' 마법사에서 'Source file' 필드에 'bsp.c'를 입력한 후 'Finish' 버튼을 눌러서 파일을 생성합니다.
- 같은 방법으로 'bsp_uart.c' 파일을 생성합니다.
- bsp.h 파일 중간 부분에 아래와 같은 코드를 입력합니다.
/* BSP include */
#include "bsp_uart.h"
/* BSP functions */
void Bsp_Init(void);
void Bsp_Loop(void);
- bsp_uart.h 파일 중간 부분에 아래와 같은 코드를 입력합니다.
/* BSP UART function */
void USART2_Init(void);
- bsp.c 파일아랫부분에 아래와 같은 코드를 입력합니다.
#include "bsp.h"
void Bsp_Init(void)
{
USART2_Init();
}
void Bsp_Loop(void)
{
}
- bsp_uart.c 파일 아랫부분에 아래와 같은 코드를 입력합니다.
#include <string.h>
#include "main.h"
#include "bsp_uart.h"
extern UART_HandleTypeDef huart2;
uint8_t rx_flag;
void USART2_Init(void)
{
HAL_UART_Receive_IT(&huart2, &rx_flag, 1);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART2) {
HAL_UART_Transmit(&huart2, &rx_flag, 1, 10);
HAL_UART_Receive_IT(&huart2, &rx_flag, 1);
}
}
- main.c 파일의 */ USER CODE BEGIN Includes */ 아래에 다음 코드를 입력합니다.
#include "bsp.h"
- main.c 파일의 */ USER CODE BEGIN 2 */ 아래에 다음 코드를 입력합니다.
Bsp_Init();
- main.c 파일의 */ USER CODE BEGIN 3 */ 아래에 다음 코드를 입력합니다.
Bsp_Loop();
- 툴바의 'Build Debug for project ...' 버튼을 눌러서 컴파일합니다.
- 툴바의 디버그 버튼을 누른 후 'Debug Configurations..'를 선택합니다.
- 'Debug Configurations' 마법사에서 'STM32 C/C++ Application'을 선택한 후 'New launch configuration'을 선택합니다.
- 아래와 같은 화면이 실행됩니다.
- 'Debugger' 탭을 선택한 후 'ST-LINK S/N'을 체크한 후 'Scan' 버튼을 눌러서 STM32 보드를 찾고 보드를 선택 후 'Apply' 버튼을 누른 후 'Debug' 버튼을 눌러서 프로그램을 다운로드 및 실행합니다.
- 프로그램이 실행된 후 아래 그림과 같이 'HAL_Init()' 부분에 Debug 가 멈출 때까지 기다린 후 'Resume' 버튼을 눌러 프로그램 실행을 진행합니다.
5. Python - UART 통신하기
- 이번 과정을 Python을 이용해서 STM32 보드와 통신을 하는 과정입니다.
- 아래 그림과 같이 VSCode에서 '+' 버튼을 눌러서 Python 파일을 생성합니다.
- 입력 필드에 'Car_driver.py'라고 파일 이름을 입력합니다.
- Car_driver.py 파일에 아래와 같은 코드를 입력합니다.
import itertools
import threading
import serial
class CarDriver:
def __init__(self, baudrate=115200, port="COM1"):
# unique seq counter
self.seq = itertools.count()
# serial communication driver
self.ser = serial.Serial()
self.ser.baudrate = baudrate
self.ser.port = port
self.ser.open()
# serial recive thread run
self.run_receive_thread()
def run_receive_thread(self):
task_receive = threading.Thread(target=self.__recv_data, name="serial_recv_task")
task_receive.setDaemon(True)
task_receive.start()
def __recv_data(self):
while True:
data = bytearray(self.ser.read())
print(data)
def set_led(self, state):
cmd = []
cmd.append(1 if state else 0)
self.ser.write(bytearray(cmd))
- STM32 보드와 Serial 통신을 하기 위해서 현재 연결된 포트를 알아야 합니다.
- 아래와 같이 윈도우 탐색기에서 '내 PC'를 선택하고 마우스 메뉴 버튼을 눌러서 뜨는 팝업창에서 '속성'을 선택합니다.
- 아래와 같은 '설정' 마법사에서 '시스템' 탭의 '고급 시스템 설정'을 선택합니다.
- 아래와 같은 '시스템 속성' 마법사에서 '하드웨어' 탭을 선택하고 '장치관리자' 버튼을 누릅니다.
- '장치 관리자' 마법사에서 '포트(COM & LPT)'를 선택하면 STM32가 연결된 포트를 확인할 수 있습니다. 저는 'COM5'로 연결되어 있습니다.
- 이제 Car_driver.py 파일을 테스트할 테스트 프로그램을 만들겠습니다.
- 아래 그림과 같이 VSCode에서 '+' 버튼을 눌러서 Python 파일을 생성합니다.
- 입력 필드에 'Car_driver_test.ipynb'라고 파일 이름을 입력합니다.
- Car_driver_test.ipynb 파일에 아래와 같이 코드를 입력합니다. Jupyter Notebook 파일이므로 한 줄을 한 칸에 입력 후 실행하면 아래 그림과 같이 STM32 보드와 통신 후 결과를 화면에 출력하는 것을 확인할 수 있습니다.
from Car_driver import CarDriver
driver = CarDriver(baudrate=115200, port="COM5")
driver.set_led(True)
driver.set_led(False)
- 다음에는 확장보드의 LED와 BUZZER를 제어하는 기능을 만들어 보겠습니다.
'로봇 > STM32' 카테고리의 다른 글
STM32 자동차 제어하기(3) - 모터 제어하기 (0) | 2023.03.20 |
---|---|
STM32 자동차 제어하기(2) - LED / BUZZER 제어하기 (0) | 2023.03.19 |
STM32 UART로 보드 제어하기 (1) | 2023.03.01 |
STM32 Button을 누르면 UART로 메시지 출력하기 (2) | 2023.02.28 |
STM32 Button Interrupt를 이용한 LED 제어 (0) | 2023.02.28 |