Embedded LEe

[Embedded] STM32F103RB 보드와 초음파 센서(HC-SR04)를 이용한 거리 측정기 개발 프로젝트 (CubeMX, Keil MDK) 본문

Projects/Cortex-M3

[Embedded] STM32F103RB 보드와 초음파 센서(HC-SR04)를 이용한 거리 측정기 개발 프로젝트 (CubeMX, Keil MDK)

jh-rrr 2025. 6. 6. 22:20

서론

임베디드 프로그래밍 역량 개발을 위해 ST사의 'STM32F103RB'(Nucleo F103RB) 보드와, 초음파 센서인 'HC-SR04'를 활용하여, 초음파로 거리를 측정하는 장치를 개발해 보았습니다.

개발을 위한 IDE로는 ST사의 'CubeMX'와 ARM사의 'Keil MDK'를 사용하였고, 언어는 'C'를 사용했습니다.

 

좌: STM32F103RB 보드, 우: HC-SR04 초음파센서

 

 

본론

프로젝트 목표는 "초음파 센서를 이용해 측정한 거리를 PC로 송신하는 것" 입니다.

그림1) 전체 시스템 매커니즘

 


1. 시스템 요구사항 선정

  1. HC-SR04 센서의 측정 가능 범위인 2cm~400cm 의 측정이 가능해야한다.
  2. 측정 불가능 범위 (<2cm, >400cm)의 경우 8번 LED를 점등시켜야 한다.
  3. 통신 프로토콜을 사용하여 측정된 거리를 송신한다. ('xx cm' 형식)
  4. 외부 버튼을 통해 측정을 중단할 수 있어야 한다.
  5. 외부 버튼을 통해 일회적 측정을 수행할 수 있어야 한다.
  6. Echo 이후 다음 Trig까지 최소 10mS의 간격을 두어야 한다.
  7. 한번 신호를 보낸 이후 최소 60ms의 간격을 두어야 한다.

 

2. 하드웨어 스펙 파악

2.1. 초음파센서(HC-SR04) Spec 확인

센서 사용을 위해, 가장 먼저 HC-SR04의 User Manual로 센서 Spec을 확인했습니다.

그림2) HC-SR04 spec / 그림3) HC-SR04 Timing Diagram

1. 센서가 탐지 가능한 거리는 2cm ~ 400cm(±3mm) 이다.

2. HC-SR04의 동작 전압은 DC 3.3V ~ 5V 내외이다.

3. Trig핀에 10uS동안 3.3Vdc~5Vdc의 Pulse를 인가해 8 Cycle Sonic Burst를 만들 수 있다.

4. 물체 사이의 거리(cm)는, trigger 신호를 보낸 시점과 echo를 받은 시점의 간격(uS)을 58로 나눈 값과 같다. 

5. 물체 감지에 실패할 경우, Echo핀은 36mS의 Pulse를 발생시킨다.

6. Echo 이후 다음 Trig까지 최소 10mS의 간격을 두어야 한다.

7. 한번 신호를 보낸 이후 최소 60ms의 간격을 두어야 한다.

 

2.2. 마이크로컨트롤러(STM32F103RB) Spec 확인

이후, 프로젝트 목표인 센서를 이용해 측정된 거리 데이터를 PC로 송신하는 시스템 설계가 가능한지 파악하기 위해 보드의 Spec을 확인하였습니다.

 

1. 128KB 64bit Flash / 20KB SRAM 을 가진다.

2. VDD 동작 전압은 2~3.6V 이다.

2. STM32F103RB 보드의 HSI Clock은 최대 64MHz까지 동작 가능하다.

3. 4개의 Timer 을 가진다.

4. USART, I2C, CAN, SPI, USB 통신을 지원한다.

 

해당 조건에서 프로젝트 구현이 충분히 가능하다고 판단하여, 다음으로는 HW 개발을 진행하였습니다.

 

 

3. HW 개발

3.1 CubeMX 설정

CubeMX Pin 세팅 / Clock 세팅

CubeMX IDE를 사용해 그림4, 그림5와 같이 Pin setting과 Clock setting을 하였습니다.

1. Trig에 초음파 Pulse를 출력하기 위한 GPIO Output Pin (PA7)

2. Trig에 10uS동안 Pulse를 주기 위한 Counter TIM3

3. Echo를 통한 Input Capture용 TIM4(Input Capture Mode) (PB6)

4. 디버깅용 8개의 LED Pin (PC0~7)

5. USART (PA2, PA3)

6. Switch Pin (SW1~4, B1)

 

3.1.1 Timer 설정

(1) TIM3 : Output Compare / Counter

TIM3는 두가지 용도를 가집니다.

 

1) Trig에 10uS의 Pulse를 주기 위해 사용합니다.
TIM3는 APB1(64MHz)에 연결되어있으니, Prescaler을 64-1로, Auto Reload Register(Period)을 65536-1로 설정해 1uS 단위로 count 되도록 먼저 설정을 해 줍니다. 그리고 Output Compare모드로 CCR을 10-1로 설정해 10us 뒤 저절로 Interrupt가 걸려 Trig에 10uS길이의 Pulse를 만들 수 있도록 설정하겠습니다.

 

2) 음파가 돌아오기까지 시간을 측정합니다.
HC-SR04의 spec상, 음파의 간격을 최대 36mS까지 측정할 수 있어야 하므로, ARR을 65536-1로 설정해, 65mS까지 Count할 수 있도록 설정하여 사용하도록 하겠습니다.

TIM3

 

(2) TIM4 : Input Capture

TIM4는 Echo핀의 Rising Edge와 Falling Edge 사이의 간격을 계산하기위해 사용하겠습니다. 이 또한 최대 36mS까지 측정이 가능해야하므로, ARR은 65536-1로 설정하고, 최소 탐지 거리가 3mm(음파가 8.82uS에 이동하는 거리)이므로 prescaler은 64-1로 설정하겠습니다.

TIM4

3.2 HW 연결

그림5) Nucleo보드와 초음파센서간 연결

이후 그림5와 같이 보드와 센서를 연결해 하드웨어를 초기화했습니다.

  • 초록선 (5Vdc VDD)
  • 파랑선 (Trig, D12 == PA7)
  • 보라선 (Echo, D10 == PB6)
  • 하양선 (GND)

4. 소프트웨어 개발

 

 

 


4. 소프트웨어 개발

먼저 Pseudo Code입니다.

/* Pseudo Code */

int main():
    
    HW Initialization

    while (1):
        Default:
            Do nothing
        if Switch pressed:
            Make_Ultrawave_Pulse()
            Count untill 36mS
            duration = time between Trig & Echo
            echo_width = echo_signal_width
            
            if echo_width > 36ms:		// failed
                Send Failed Message
                Turn LED_7
            else:						// success
                distance = duration/58	// distance(cm)
                Send distance
                Turn LED_6

 

위와 같은 흐름이 '요구사항 1~7'을 모두 만족시킬 수 있다고 판단했습니다.

 

4.1. Make_Ultrawave_Pulse() 함수

Make_Ultrawave_Pulse() 는 HC-SR04 센서로 초음파를 보내도록 명령하는 함수입니다.

HC-SR04 센서로 Sonic Pulse를 만들기 위해선 Trig핀(PA7)에 10uS동안 High 신호를 인가해야 합니다.

그리고 이는 `PA7 Pin High --> 10uS delay --> PA7 Pin Low` 매커니즘을 통해 구현할 수 있다고 생각하여 다음과 같이 구현하였습니다.

void Make_Ultrawave_Pulse()
{
    /* PB6에서 Echo Signal을 받기위해 TIM4를 미리 Enable! */
    __HAL_TIM_ENABLE_IT(&htim4, TIM_IT_CC1);
    HAL_TIM_IC_Start_IT(&htim4, TIM_CHANNEL_1);

    // 10uS Pulse 생성
    HAL_TIM_Base_Start(&htim3);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);
    __HAL_TIM_SET_COUNTER(&htim3, 0);
    while (__HAL_TIM_GET_COUNTER(&htim3) < 10);		// delay 10uS
    HAL_TIM_Base_Stop(&htim3);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET);
}

 

while (__HAL_TIM_GET_COUNTER(&htim3) < 10);  의 10은 TIM3의 10ticks 를 의미합니다.

그 이유는 TIM3는 64MHz의 Clock에 연결되어있고, Prescaler는 64-1으로 설정되있기 때문에, TIM3의 1tick에 1uS가 소요되기 때문입니다.

 

4.2. Distance 계산

초음파가 물체에 반사되어 돌아오기까지 걸리는 시간(time duration)은, Make_Ultrawave_Pulse()을 실행시킨 뒤, Echo핀에 High가 들어오기까지의 시간입니다.

이 time duration을 이용해 물체까지의 거리를 구하면 다음과 같습니다.

(거리를 2로 나누어준 이유는, 초음파가 왕복했기 때문이며, 음파의 속력을 340m/sec 로 반영하였습니다.)

Distance [cm]   =   time_duration[sec] * 34,000 [cm/sec] / 2

 

4.3. 통신 프로토콜 선정 / 반영

다음으로 사용자 요구사항 3번(통신 프로토콜을 사용해 측정된 거리를 송신한다)을 만족시키기 위해, 계산된 Distance를 PC로 송신하는 코드를 구성해보았습니다.

사용중인 Nucleo-F103RB 보드는 UART, I2C, USB, SPI 통신을 지원하며, 현 프로젝트는 최소 60ms 간격으로 데이터를 송신할 수 있어야 합니다(Simplex). 따라서 네가지 통신 모두 사용이 가능하지만, 저는 가장 용이한 통신방식인 UART 통신을 사용하였습니다.

4.4 전체 Code

 

 

 

 

 

이미지 출처

https://www.st.com/en/microcontrollers-microprocessors/stm32f103rb.html

https://kr.rs-online.com/web/p/bbc-micro-bit-add-ons/2153181

 

참고 사이트

https://controllerstech.com/hcsr04-ultrasonic-sensor-and-stm32/

https://www.youtube.com/watch?v=ti_1ZwRolU4

https://eteo.tistory.com/155