이번에는 초음파 센서를 이용하여 거리를 측정하는 코드를 GPIO를 사용하여 만들어보도록 하겠습니다.
트리거 & 에코 신호
트리거 신호 (Initiate)
센서에는 일반적으로 TTL(Transistor-Transistor Logic) 신호를 사용하여 트리거 신호를 입력받습니다. 이 트리거 신호는 센서에 10마이크로초(µs) 동안 고신호를 제공하여 초음파 펄스를 발생시키라는 지시를 합니다.
초음파 펄스 발생 (Internal)
트리거 신호를 받은 센서는 40kHz의 초음파 펄스를 발생시킵니다. 이 펄스는 주변의 물체에 부딪혀 반사되어 센서로 돌아옵니다.
에코 신호 수신 (Echo back)
반사된 초음파는 센서에 도달하며, 이때의 펄스 폭(에코 신호의 길이)은 물체까지의 거리에 따라 결정됩니다. 에코 신호는 대략 150마이크로초(µs)에서 최대 25밀리초(ms)까지 지속될 수 있습니다. 만약 38밀리초 이상 신호가 없다면, 그것은 장애물이 감지되지 않았음을 의미합니다.
거리 계산
에코 신호의 길이(펄스 폭)를 측정하여 실제 거리를 계산할 수 있습니다. 계산 공식은 다음과 같습니다:
센티미터(cm) 단위: 에코 펄스 폭(마이크로초)를 58로 나눔
인치(inch) 단위: 에코 펄스 폭(마이크로초)를 148로 나눔
이 공식들은 소리의 속도(공기 중 약 343m/s)와 에코의 왕복 시간을 기반으로 계산되며, 이를 통해 정확한 거리를 산출할 수 있습니다. 이러한 원리로 작동하는 초음파 센서는 로봇의 장애물 회피, 자동차의 주차 보조 시스템 등 다양한 분야에서 활용됩니다.
트리거, 에코 모드를 GPIO로 설정해주고 트리거는 출력모드, 에코는 입력 모드로 설정해줍니다.
해당 설정을 통해서 초음파 센서의 트리거 핀으로 사용되어 센서를 활성화하기 위해 짧은 High 신호를 전송하고, 그 후 다시 Low 상태로 돌아가 센서에서 거리 측정을 시작하게 됩니다. 그리고 측정하는 시간은 타이머5를 활성화시켜 에코 신호를 통해 물체까지의 거리를 측정하게 됩니다.
트리거 & 에코 작동 원리
트리거와 에코 작동 원리:
- 트리거(Trigger)
- 초음파 센서의 작동을 시작하기 위해 사용자가 센서에 짧은 전기적 신호를 보냅니다. 보통 이 신호는 10마이크로초 길이의 TTL(TTL: Transistor-Transistor Logic, 디지털 논리 회로의 한 종류) 신호입니다.
- 이 트리거 신호는 센서에 내장된 초음파 발생기를 활성화시키며, 이는 센서에서 40kHz의 초음파 펄스를 일정 시간 동안(대개 몇 밀리초) 발생시킵니다.
- 에코(Echo)
- 발생된 초음파는 공기를 통해 전파되어 주변 물체에 부딪히고, 그 물체로부터 반사되어 다시 센서로 돌아옵니다.
- 센서는 이 반사된 초음파 신호, 즉 에코를 감지합니다. 에코 신호가 센서에 도달하는 데 걸리는 시간은 초음파가 물체에 도달하고 돌아오는 데 필요한 전체 시간입니다.
- 이 시간을 측정하여, 초음파의 속도(공기 중 약 343m/s)와 시간을 이용해 실제 거리를 계산할 수 있습니다.
거리 계산 공식:
거리는 에코 신호가 시작되고 끝나는 시간을 측정하여 계산합니다. 이를 위한 공식은 다음과 같습니다: 거리 (cm)=에코 신호의 시간(μs)58\text{거리 (cm)} = \frac{\text{에코 신호의 시간} (\mu s)}{58} 거리 (inch)=에코 신호의 시간(μs)148\text{거리 (inch)} = \frac{\text{에코 신호의 시간} (\mu s)}{148}
이 공식들은 초음파가 왕복하는 데 걸린 시간을 거리로 환산할 때 사용됩니다. 초음파 센서는 이러한 원리를 기반으로 하여 다양한 응용 분야에서 거리 측정, 물체 감지, 레벨 감지 등에 활용됩니다.
설정을 모두 완료하였으면 Generation을 해주고 생성된 코드 부분을 작성해줍니다.
먼저 트리거 및 에코신호를 처리하는 코드를 작성해주도록 하겠습니다.
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void microDelay(int us)
{
/*int t1 = htim5.Instance->CNT;
//while(1)
//{
// int tmp_us = htim5.Instance->CNT - t1; // 경과?���???????
// if(tmp_us > us) break;
//}
while((htim5.Instance->CNT - t1) < us);*/
htim5.Instance->CNT = 0;
while(htim5.Instance->CNT < us);
}
void Trigger()
{
// Trigger Signal
HAL_GPIO_WritePin(Trig_GPIO_Port, Trig_Pin, 1);
microDelay(10); // 10us delay
HAL_GPIO_WritePin(Trig_GPIO_Port, Trig_Pin, 0);
microDelay(20); // 20us delay
}
double Distance()
{
Trigger();
// Wait until Echo Rising_Edge
while(HAL_GPIO_ReadPin(Echo_GPIO_Port, Echo_Pin) != 1);
int t1 = htim5.Instance->CNT;
// Wait until Echo Falling_Edge
while(HAL_GPIO_ReadPin(Echo_GPIO_Port, Echo_Pin) != 0);
int t2 = htim5.Instance->CNT;
double dist = (t2 - t1) * (0.000170); // meter
return dist;
}
/* USER CODE END 0 */
microDelay 함수
- 이 함수는 입력된 마이크로초(us)만큼 지연을 발생시키는 역할을 합니다.
- htim5 타이머의 카운터(CNT)를 0으로 초기화하고, 지정된 마이크로초(us)만큼 카운트가 증가할 때까지 대기합니다.
- 이 지연 기능은 초음파 센서의 트리거 신호를 정확한 시간 동안 유지하기 위해 사용됩니다.
Trigger 함수
- 초음파 센서의 트리거 핀을 활성화하는 함수입니다.
- Trig_GPIO_Port의 Trig_Pin을 1로 설정하여 10마이크로초 동안 트리거 신호를 보냅니다. 이는 센서가 초음파 신호를 발생시키게 합니다.
- 이후 해당 핀을 0으로 설정하여 트리거 신호를 끝냅니다. 추가로 20마이크로초 동안 더 기다리는 이유는 센서가 다음 동작을 준비할 수 있도록 하기 위함입니다.
Distance 함수
- 거리를 측정하는 함수입니다.
- 먼저 Trigger() 함수를 호출하여 초음파 신호를 발생시킵니다.
- Echo_GPIO_Port의 Echo_Pin에서 1이 입력될 때까지 기다립니다. 이는 초음파 신호가 물체에 반사되어 돌아오기 시작한 시점입니다.
- 초음파 신호가 물체에 도달한 시점의 타이머 값을 t1에 저장합니다.
- 이후 Echo_Pin에서 0이 입력될 때까지 기다립니다. 이는 초음파 신호가 끝난 시점입니다.
- 초음파 신호가 끝난 시점의 타이머 값을 t2에 저장합니다.
- 이 두 타이머 값의 차이(t2 - t1)를 이용하여 실제 거리를 계산합니다. 거리 계산에 사용된 공식은 (t2 - t1) * 0.000170입니다. 이 공식은 초음파의 속도(공기 중 약 343m/s)를 반영하여 미터 단위로 거리를 계산합니다.
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_USART2_UART_Init();
MX_TIM5_Init();
/* USER CODE BEGIN 2 */
printf("i:%d l:%d f:%d d:%d\n",sizeof(int),sizeof(long),sizeof(float),sizeof(double));
ProgramStart("Ultra Sonic GPIO");
HAL_TIM_Base_Start(&htim5);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
double d = Distance() * 100;
printf("\033[?25l\n"); // cursor off
printf("\033[10;10f\033#3Distance : %.2f cm ", d); // upper half
printf("\033[11;10f\033#4Distance : %.2f cm \033[9;10H\n", d); // Lower
//microDelay(100000); // 10ms
HAL_Delay(100);
}
/* USER CODE END 3 */
}
여러 초기화 설정에 대한 설명은 건너 뛰고 while문 내부 초음파 부분 코드만 설명하도록 하겠습니다.
HAL_TIM_Base_Start(&htim5)
- htim5 타이머를 시작합니다. 이 타이머는 초음파 센서 데이터를 정확하게 측정하기 위해 사용될 수 있습니다.
Distance() 함수 호출
- 초음파 센서로부터 거리를 측정하는 Distance() 함수를 호출하고, 반환된 거리(미터 단위)를 센티미터로 변환합니다.
결과 출력
- ANSI 이스케이프 코드를 사용하여 터미널의 특정 위치에 거리를 출력합니다. 커서를 숨기고, 특정 포맷(\033[10;10f\033#3 및 \033[11;10f\033#4)으로 거리를 두 줄에 걸쳐 출력합니다.
- 출력은 10행 10열에서 시작하며, 거리를 두 가지 다른 스타일로 표시합니다.
초음파 센서를 사용하여 주기적으로 거리를 측정하고, 그 결과를 사용자에게 시각적으로 표시하는 코드를 작성하여 보드 연결 후 Run을 통해서 직접 결과값을 확인하도록 합니다.
'하만 세미콘 아카데미 > Embedded (STM32)' 카테고리의 다른 글
[Embedded] STM32 - US PWM (0) | 2024.05.31 |
---|---|
[Embedded] STM32 - US Interrupt (0) | 2024.05.31 |
[Embedded] STM32 - PWM (0) | 2024.05.31 |
[Embedded] STM32 - Timer (0) | 2024.05.31 |
[Embedded] STM32CubeIDE GPIO - LED 점멸 (0) | 2024.05.31 |