본문 바로가기
임베디드 개발/아두이노

[ 아두이노 ] 초음파 거리 측정 센서 HC-SR04

by eteo 2022. 4. 25.

데이터 시트 : https://netsonic.fi/en/files/HCSR04-datasheet.pdf

 

https://netsonic.fi/en/hc-sr04-datasheet-and-pinout-ultrasonic-sensor-noncontact-range-detection/

원리

초음파는 인간의 가청 한계를 넘는 고주파음이다. Trig핀으로 최소 10μS이상의 high(5V) 펄스가 들어오면 Transmitter 에서 40KHz초음파를 8회 발사한다. echo핀은 high 상태가 되고 물체를 맞고 반사된 초음파를 reciever 가 수신하면 다시 echo핀은 low상태가 된다.(앞에 물체가 없어 발사된 후 38ms동안 수신이 없으면 echo 핀이 다시 low 상태가 됨.) 음속은 340m/s 니까 echo핀의 high pulse duration을 아두이노의 pulsein 함수로 재고 거리=속력*시간 공식으로 계산하면 물체와의 거리를 계산할 수 있다.

측정범위 : 2cm - 400cm

(안정적인 측정범위는 3cm-2m 사이라고 함)

60ms이상 사이클로 측정할 것을 권장

 

 

https://lastminuteengineers.com/arduino-sr04-ultrasonic-sensor-tutorial/
https://macduino.blogspot.com/2013/11/HC-SR04-part1.html&nbsp; 측정 유효각도 <15도

 

 

회로

빵판에 꼽아서 연결해도 되고 m/f 점퍼선이 있으면 직접 연결해줘도 된다.

VCC = 5V

GND = GND

Trig = 8번핀

Echo = 9번핀

 

 

 

코드

pulsein() 함수 : pin의 value 유지시간을 μs 단위로 반환. (ex. value가 HIGH인 경우 LOW상태에서 HIGH되는 순간부터 HIGH 유지시간)

pulseIn(pin, value)
pulseIn(pin, value, timeout) : timeout을 지정안하면 기본값은 1초. timeout(μs) 시간동안 펄스 시작을 안하면 0을 반환.

https://www.arduino.cc/reference/en/language/functions/advanced-io/pulsein/

 

#define trigPin 8
#define echoPin 9

void setup(){  
  Serial.begin(9600);       // 9600 보드레이트로 시리얼 통신 설정
  pinMode(trigPin, OUTPUT);  // 트리거 핀을 출력으로 설정
  pinMode(echoPin, INPUT);   // 에코 핀을 입력으로 설정
}

void loop(){

  float duration, distance;
  
  digitalWrite(trigPin, HIGH);  
  delay(10);  
  digitalWrite(trigPin, LOW);
  // Trig핀 10ms 동안 HIGH상태 유지

  
  // duration = echoPin 이 HIGH를 유지한 시간
  // = 초음파가 발사되었다가 반사되고 다시 돌아오기까지 걸린 시간
  duration = pulseIn(echoPin, HIGH);
  distance = ((float)(340 * duration) / 10000) / 2;  
  
  // distance = speed(음속 340m/s) * time(duration(μs))
  // m->cm *10^2, μs->s *10^-6, 단위환산을 위해 10^4을 나눠줌
  // 왕복거리이므로 다시 2로 나눔
  

  Serial.print("DIstance: ");  
  Serial.print(distance);  
  Serial.println("cm"); 

  delay(500);
}

 

 

NewPing

이 초음파센서를 사용하는데 매우 유명한 라이브러리가 있다.

https://playground.arduino.cc/Code/NewPing/

스케치->라이브러리 포함하기->라이브러리관리->NewPing 검색으로 설치 가능

위 사이트에 여러개의 초음파센서를 사용할 경우의 예제도 있는데 굉장히 유용해 보인다.

 

NewPing 헤더를 포함하고 아래와 같이 간략하게 코드를 짤 수 있다.

// include NewPing Library
#include "NewPing.h"

#define trigPin 8
#define echoPin 9

// Constructor. NewPing sonar(trigger_pin, echo_pin [, max_cm_distance]);
NewPing sonar(8, 9);

void setup(){  
  Serial.begin(9600);       // 9600 보드레이트로 시리얼 통신 설정
}

void loop(){

  Serial.print("Distance: ");  
  // Send ping, get distance in cm
  Serial.print(sonar.ping_cm());  
  Serial.println("cm"); 

  delay(500);
}

sonar.ping_cm() 함수는 distance를 cm단위로 반환하지만 소수점까지 알 수는 없어서 정확도를 높이고 싶다면 sonar.ping(); 함수로 에코펄스를 구하고 위의 거속시 공식으로 직접 변환해줘야 한다.

 

핑을 여러번 보내고 중앙값을 반환하는 함수인 sonar.ping_median()과 에코펄스 time을 distance(cm)로 변환해주는 sonar.convert_cm()함수도 있다.

void loop(){

  float duration, distance;
  // Send a ping, returns the echo time in microseconds or
  // 0 (zero) if no ping echo within set distance limit
  duration = sonar.ping_median(5);

  //Converts microseconds to distance in centimeters
  distance = sonar.convert_cm(duration);
  
  Serial.print("Distance: ");  
  Serial.print(distance);  
  Serial.println("cm"); 

  delay(500);
}

 

측정각도가 15도라서 그런가 멀어질수록 잡음이 심해지더라. 아마 실제 사용할 땐 반환값이 0일 때의 예외처리와 튀는값을 잡기위한 코드가 추가되야할 것 같다.

 

NewPing 제공함수들

  • sonar.ping(); - Send a ping, returns the echo time in microseconds or 0 (zero) if no ping echo within set distance limit
  • sonar.ping_in(); - Send a ping, returns the distance in inches or 0 (zero) if no ping echo within set distance limit
  • sonar.ping_cm(); - Send a ping, returns the distance in centimeters or 0 (zero) if no ping echo within set distance limit
  • sonar.ping_median(iterations); - Do multiple pings (default=5), discard out of range pings and return median in microseconds
  • sonar.convert_in(echoTime); - Converts microseconds to distance in inches
  • sonar.convert_cm(echoTime); - Converts microseconds to distance in centimeters
  • sonar.ping_timer(function); - Send a ping and call function to test if ping is complete.
  • sonar.check_timer(); - Check if ping has returned within the set distance limit.
  • timer_us(frequency, function); - Call function every frequency microseconds.
  • timer_ms(frequency, function); - Call function every frequency milliseconds.
  • timer_stop(); - Stop the timer.