본문 바로가기
나의 전자 공부방/STM32

2. STM32를 사용하여 도어락만들기(LCD, RFID, 서보모터)

by 나만의생각 2023. 4. 12.

STM32를 이용해서 도어락을 만들어보았습니다. 작동방법은 RFID에 저장되어진 카드의 설정에 대해서 내가 지정한 카드의 데이터만을 받았을때 servomotor가 90도가 움직이고 lcd에 표시가됩니다. 카드를 떼었을때 servomotor가 90도로 다시 돌아오고 lcd에 표시가됩니다.

 

TIM11설정

이와같은 페이지에서 TIM11설정을 해줍니다. prescaler는 84-1을 설정해 주고,  counter period는 1000-1을 설정해줍니다.

 

Prescaler 값은 내부 클럭 주파수를 분주하여 타이머 모듈의 클럭 주파수를 설정하는 값입니다. 이 예제에서는 84-1 값을 사용하여 내부 클럭 주파수(기준 주파수)를 84로 나누어 타이머 모듈의 클럭 주파수를 1 MHz로 설정합니다.

Counter period 값은 타이머 카운터가 0에서 시작하여 일정 주기마다 overflow를 발생시키고, 다시 0부터 시작하여 반복되는 주기를 설정하는 값입니다. 이 예제에서는 1000-1 값을 사용하여, 1초(1 MHz / 1000)마다 overflow가 발생하도록 설정합니다.

 

 

TIM2 설정


PWM 주파수 = Timer clock source / (Prescaler x Counter Period + 1)

여기서 Prescaler 값을 1680-1로 설정하고, Counter Period 값을 1000-1로 설정하면 PWM 주파수는 다음과 같이 계산됩니다.

PWM 주파수 = 84MHz / ((1680-1) x (1000-1) + 1) ≈ 1kHz

따라서, PWM 주파수를 1kHz로 설정하기 위해 Prescaler를 1680-1, Counter Period를 1000-1로 설정한 것입니다.

 

uint8_t rx_rfid_data[16];
uint8_t matched_flag = 0;
int temp_data[5];

uint8_t rfid_key_table[2][5] = {
    {0x13, 0xe2, 0x80, 0x02, 0x73},
    {0xbc, 0x5a, 0xc5, 0x22, 0x01}
};

void rfid_tagging_test()
{
	matched_flag = 0;
	rfid_reader_init();
	//0. 초기화


	// 1. 카드를 리더기에 갖다 대었는지 확인
	rfid_rx = mfrc522_request(PICC_REQALL, rx_rfid_data);
	if (rfid_rx == CARD_FOUND)
	{
		// 2. 카드를 읽는다.
		rfid_rx = mfrc522_get_card_serial(rx_rfid_data);
		while(!matched_flag)
		{
			if ( (*rx_rfid_data == *rfid_key_table[0]) || (*rx_rfid_data == *rfid_key_table[1]) ) //내 카드키네?
			{
				matched_flag = 1;
				temp_data[0] = rx_rfid_data[0];
				temp_data[1] = rx_rfid_data[1];
				temp_data[2] = rx_rfid_data[2];
				temp_data[3] = rx_rfid_data[3];
				temp_data[4] = rx_rfid_data[4];
				printf("\n My Card!\n\n");
			}
			else
			{
				matched_flag = 0;
				printf("\nNot! My Card!\n\n");
			}
		}

	}
	HAL_Delay(1000);
}

만약 카드가 감지되면 mfrc522_get_card_serial() 함수를 사용하여 카드 UID를 읽습니다. 이 함수는 카드 UID를 리더기에서 읽고, rx_rfid_data 배열에 저장합니다.

그 다음, while 루프를 사용하여 matched_flag가 true인 동안 계속해서 카드를 검사합니다. 카드의 UID와 rfid_key_table 배열에 저장된 내 카드의 UID를 비교하여 일치하는지 확인합니다. 만약 일치한다면 matched_flag를 1로 설정하고, 카드의 UID를 temp_data 배열에 저장합니다. 그리고 My Card! 라는 문자열을 출력합니다.

만약 카드의 UID가 내 카드의 UID와 일치하지 않는다면 matched_flag를 0으로 설정하고, "Not! My Card!" 라는 문자열을 출력합니다.

 

lcd_i2c.c

 

void disp_timer()
{
	char lcd_buff[20];

	if(!matched_flag)
	{
		lcd_command(CLEAR_DISPLAY);
		move_cursor(0,0);
		lcd_string("  DOOR CLOSE");
	}
	else
	{
		move_cursor(0,0);
		lcd_string("DOOR OPEN ");
		sprintf(lcd_buff, "%02x %02x %02x %02x %02x", temp_data[0], temp_data[1], temp_data[2], temp_data[3], temp_data[4]);
		move_cursor(1,0);
		lcd_string(lcd_buff);


	}
	HAL_Delay(50);
}

 

함수 내부에서는 matched_flag라는 변수를 검사하여 문이 열려있는지 닫혀있는지를 판단합니다. matched_flag가 false인 경우, 즉 문이 닫혀있는 경우에는 LCD 화면을 지우고 "DOOR CLOSE"라는 문자열을 첫 번째 라인에 출력합니다.

matched_flag가 true인 경우, 즉 문이 열려있는 경우에는 "DOOR OPEN"이라는 문자열을 첫 번째 라인에 출력하고, 온도 센서에서 읽은 데이터를 temp_data 배열에 저장한 후 sprintf() 함수를 사용하여 이 데이터를 16진수 문자열로 변환하여 lcd_buff 배열에 저장합니다. 그리고 두 번째 라인에 lcd_buff 배열을 출력합니다.

 

 

servo_motor.c

 

void rfid_card_key_motor_control(void)
{
	int pwm_data;
	if(matched_flag)
	{
		t11ms_counter = 0;
		pwm_data = 10;
	}
	if(t11ms_counter >= 3000)
	{
		t11ms_counter = 0;
		pwm_data = 65;
	}
	__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pwm_data);
}

servo_motor 로 문을 닫고 여는 것을 확인합니다.

 

 

void ap_run()

{

rfid_tagging_test();

disp_timer();

rfid_card_key_motor_control();


}

 

 

main.c

 

int main()
{
	while(1){
    	ap_run();
        }
}

 

 

이렇게 함으로서 도어락이 완성되었습니다.

 

https://youtu.be/0ihgQ-poPmI