with-RL
로봇 / ESP322024년 1월 20일

STM32 자동차 제어하기(2) - LED / BUZZER 제어하기

이번 과정은 STM32 보드와 추가로 제작된 확장보드 및 RC카 구동체를 이용해서 자동차를 제어하기 위한 간단한 프로그램을 만드는 과정의 두 번째로 확장보드의 LED와 BUZZER를 제어하는 과정입니다.

아래 과정은 이전 과정을 완료 후 진행하시길 추천드립니다.

1. 통신규격 정의하기

/* BSP UART command */
#define CMD_LED		0x01
#define CMD_BUZZER	0x02

/* BSP UART error */
#define REQUEST		0x00
#define RES_OK		0x01
# BSP UART command
CMD_LED = 0x01
CMD_BUZZER = 0x02
CMD_MOTOR = 0x03

# BSP UART error
REQUEST = 0x00
RES_OK = 0x01

2. STM32 - 메시지 수신 및 제어 기능 구현 (LED, BUZZER)

#ifndef BSP_UART_H_
#define BSP_UART_H_

/* BSP UART command */
#define CMD_LED		0x01
#define CMD_BUZZER	0x02

/* BSP UART error */
#define REQUEST		0x00
#define RES_OK		0x01

/* BSP UART function */
void USART2_Init(void);

#endif /* BSP_UART_H_ */
#include <string.h>
#include "main.h"
#include "bsp_uart.h"


extern UART_HandleTypeDef huart2;
uint8_t rx_flag;
uint8_t rx_data[256];
uint8_t rx_csum;
uint8_t tx_data[256];
uint8_t tx_csum;


void USART2_Init(void)
{
	HAL_UART_Receive_IT(&huart2, &rx_flag, 1);
}

int Check_RxCheckSum() {
	int len = rx_data[1] + 2;
	int sum = 0;
	for(int i = 0; i < len; i++) {
		sum += rx_data[i];
	}
	sum &= 0xFF;
	return rx_csum == sum;
}

void Make_TxCheckSum() {
	int len = tx_data[1] + 2;
	int sum = 0;
	for(int i = 0; i < len; i++) {
		sum += tx_data[i];
	}
	tx_csum = sum & 0xFF;
}

void Send_Data() {
	Make_TxCheckSum();
	HAL_UART_Transmit(&huart2, tx_data, tx_data[1] + 2, 10);
	HAL_UART_Transmit(&huart2, &tx_csum, 1, 10);
}

void Set_Led() {
	if (rx_data[3] == CMD_LED) {
		HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, rx_data[5]);

		// response
		memset(tx_data, 0x00, sizeof(tx_data));
		memcpy(tx_data, rx_data, rx_data[1] + 2);
		tx_data[4] = RES_OK; // result
		Send_Data(); // send result
	}
}

void Set_Buzzer() {
	if (rx_data[3] == CMD_BUZZER) {
		HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, rx_data[5]);

		// response
		memset(tx_data, 0x00, sizeof(tx_data));
		memcpy(tx_data, rx_data, rx_data[1] + 2);
		tx_data[4] = RES_OK; // result
		Send_Data(); // send result
	}
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if (huart->Instance == USART2) {
		if (rx_flag == 0xFF) {
			memset(rx_data, 0x00, sizeof(rx_data));
			rx_data[0] = rx_flag;
			HAL_StatusTypeDef uartState = HAL_UART_Receive(&huart2, &rx_data[1], 1, 10); // recv len
			if (uartState == HAL_OK) {
				uartState = HAL_UART_Receive(&huart2, &rx_data[2], rx_data[1], 10); // recv data
			}
			if (uartState == HAL_OK) {
				uartState = HAL_UART_Receive(&huart2, &rx_csum, 1, 10); // recv crc
			}

			if (uartState == HAL_OK && Check_RxCheckSum() > 0) {
				switch (rx_data[3]) {
					case CMD_LED:
						Set_Led();
						break;
					case CMD_BUZZER:
						Set_Buzzer();
						break;
				}
			}
		}
		HAL_UART_Receive_IT(&huart2, &rx_flag, 1);
	}
}

3. Python - STM32 보드 제어기능 구현 (LED, BUZZER)

import itertools
import threading

import serial

# BSP UART command
CMD_LED = 0x01
CMD_BUZZER = 0x02

# BSP UART error
REQUEST = 0x00
RES_OK = 0x01


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())[0]
            print(data)

    def set_led(self, state):
        self.__send_data(CMD_LED, [1 if state else 0])

    def set_buzzer(self, state):
        self.__send_data(CMD_BUZZER, [1 if state else 0])

    def __send_data(self, command, data):
        seq = next(self.seq) % 0xFE + 1
        cmd = [0xFF, 0, seq, command, REQUEST]
        cmd.extend(data)
        cmd[1] = len(cmd) - 2
        checksum = sum(cmd) & 0xFF
        cmd.append(checksum)
        print(cmd)
        self.ser.write(cmd)
from Car_driver import CarDriver

driver = CarDriver(baudrate=115200, port="COM5")

driver.set_led(True)

driver.set_led(False)

driver.set_buzzer(True)

driver.set_buzzer(False)