본문 바로가기
IoT 디바이스 활용/Arduino

Arduino - 초음파 센서 (Ultra.h, Pulse.h)

by cooluk 2020. 10. 15.

초음파 센서


초음파 센서

초음파 센서

  • 초음파를 이용하여 벽이나 사물의 거리를 측정하는 센서

  • HC-SR04 모듈

    • Vcc: 전원
    • Trig : 트리거 (초음파 송출 제어)
    • Echo : 에코(초음파 수신)
    • GND: 접지
    image-20200916163426888

초음파센서 사용하기

초음파 센서 동작 원리

  • Trig에 HIGH 전압 인가시 초음파 발사
  • Echo에서 초음파 수신(처음에는 LOW)
  • 시간차이를 측정하여 거리 계산
image-20200916163516773 image-20200916163546633

거리 계산

  • 음속 : 340 m/s

  • 비례식

    • 1,000,000 us : 34,000 cm = x us : y cm
    • y = 34,000*x/1,000,000 = 0.034*x cm
  • 왕복 반영

    • y = 0.034*x/2 = 0.017 *x cm = x/58 cm

delayMicroseconds()

  • 아두이노 보드를 일정 시간 멈추는 함수입니다.

  • delayMicroseoonds(멈출 시간)

  • 매개변수

    • 멈출 시간: 단위는 마이크로초로 (0.000001초)
  • 반환 값

    • 없음
  • 사용 예

    • delayMicroseconds(2);
      // 아두이노 보드를 0.002 밀리초(0.000002초) 멈춥니다.

pulseln()

  • 디지털 입력 핀의 전압이 LOW 또는 HIGH가 될 때까지 걸린 시간 측정

  • 핀은 꼭 pinMode 함수를 이용해 입력 모드로 설정

  • pulseln(핀 번호,전압)

    • 매개변수
      • 핀 번호: 전압이 바뀌는 시간을 재고자 하는 핀 번호
      • 전압: 바뀌는 전압. HIGH - LOW에서 HIGH가 될 때
  • 반환값

    • 전압이 바뀌는 데 걸린 시간을 마이크로초 기준으로 반환
    • 만약 1초 동안 기다렸는데도 전압이 바뀌지 않으면 0을 반환
  • 사용 예

    • long duration = pulseln(3, HIGH);

      //3번 핀의 전압이 HIGH가 될 때까지 걸린 시간


image-20200916164204079

초음파 센서 거리 측정

int echoPin = 2;
int triggerPin = 3;
void setup() {
Serial.begin(9600);
pinMode(echoPin, INPUT); // 수신
pinMode(triggerPin, OUTPUT); // 출력
}
void loop() {
// trigger 핀으로 10us의 펄스를 발생
digitalWrite(triggerPin, HIGH);
delayMicroseconds(10); // HIGH의 폭이 10㎲
digitalWrite(triggerPin, LOW);
// echo 핀 입력으로부터 거리를 cm 단위로 계산
int distance = pulseIn(echoPin, HIGH) / 58; // 시간 측정 후 /58해서 거리를 알 수 있다.
Serial.println("Distance(cm) = " + String(distance));
delay(1000);
}

초음파 센서 거리 측정 LCD (MiniCom.h)

#include <MiniCom.h>
MiniCom com;
int echoPin = 2;
int triggerPin = 3;
void checkDistance() {
// trigger 핀으로 10us의 펄스를 발생
digitalWrite(triggerPin, HIGH);
delayMicroseconds(10); // HIGH의 폭이 10㎲
digitalWrite(triggerPin, LOW);
// echo 핀 입력으로부터 거리를 cm 단위로 계산
int distance = pulseIn(echoPin, HIGH) / 58;
com.print(0, "distance", distance);
}
void setup() {
com.init();
pinMode(echoPin, INPUT); // 수신
pinMode(triggerPin, OUTPUT); // 출력
com.setInterval(1000, checkDistance);
}
void loop() {
com.run();
}

초음파 센서 객체

Ultra.h

#pragma once
#include <Arduino.h>
class Ultra {
protected:
int echo;
int trig;
public:
Ultra(int echo, int trig);
int read();
};

Ultra.cpp

#include "Ultra.h"
Ultra::Ultra(int echo, int trig) : echo(echo), trig(trig) {
pinMode(trig, OUTPUT);
pinMode(echo, INPUT);
}
int Ultra::read() {
// trigger 핀으로 10us의 펄스를 발생
digitalWrite(trig, HIGH);
delayMicroseconds(10); // HIGH의 폭이 10㎲
digitalWrite(trig, LOW);
// echo 핀 입력으로부터 거리를 cm 단위로 계산
int distance = pulseIn(echo, HIGH) / 58;
return distance;
}

app.ino

#include <MiniCom.h>
#include "Ultra.h"
MiniCom com;
Ultra ultra(2, 3);
void checkDistance() {
int distance = ultra.read();
com.print(0, "distance", distance);
}
void setup() {
com.init();
com.setInterval(1000, checkDistance);
}
void loop() {
com.run();
}

초음파 센서 - 거리 측정 후 LED, 부저 켜기

LED, 부저 병렬로 한 라인에 연결

#include <MiniCom.h>
#include <Ultra.h>
#include <Led.h>
MiniCom com;
Ultra ultra(2, 3);
Led led(5);
void checkDistance() {
int distance = ultra.read();
com.print(0, "distance", distance);
if(distance < 10) {
led.on();
} else {
led.off();
}
}
void setup() {
com.init();
com.setInterval(1000, checkDistance);
}
void loop() {
com.run();
}

초음파 센서 - 거리 측정 후 LED, 부저, 서보모토 켜기

#include <MiniCom.h>
#include <Servo.h>
#include <Ultra.h>
#include <Led.h>
MiniCom com;
Ultra ultra(2, 3);
Led led(5);
Servo servo;
void checkDistance() {
int distance = ultra.read();
com.print(0, "distance", distance);
if(distance < 10) {
led.on();
servo.write(90);
} else {
led.off();
servo.write(0);
}
}
void setup() {
com.init();
servo.attach(9);
servo.write(0);
com.setInterval(1000, checkDistance);
}
void loop() {
com.run();
}

Pulse 클래스 만들기

Pulse.h

#pragma once
#include <Arduino.h>
typedef void (*pulse_callback_t)(int);
class Pulse {
protected:
int onDelay; // HIGH 시간
int offDelay; // LOW 시간
int value; // 현재 상태값 (H/L)
unsigned long oldTime; // 최근 상태 변경 시점 기록
bool state; // 펄스의 운영 여부
pulse_callback_t callback;
public:
Pulse(int onDelay, int offDelay);
void setDelay(int onDelay, int offDelay);
void run();
int read() { return value; }
bool getState() { return state; }
void play();
void stop();
void setCallback(pulse_callback_t callback)
{this->callback = callback;}
};

Pulse.cpp

#include "Pulse.h"
Pulse::Pulse(int onDelay, int offDelay)
: onDelay(onDelay), offDelay(offDelay) {
value = HIGH;
state = false; // 시작은 운영 안함
callback = NULL;
oldTime = millis();
}
void Pulse::setDelay(int onDelay, int offDelay) {
this->onDelay = onDelay;
this->offDelay = offDelay;
}
void Pulse::play() {
state = true;
value = HIGH;
oldTime = millis();
}
void Pulse::stop() {
state = false;
value = LOW;
}
void Pulse::run() {
if(!state) return;
unsigned long currentTime = millis();
unsigned long diff = currentTime - oldTime;
long interval = value ? onDelay : offDelay;
if(diff >= interval) {
oldTime = currentTime;
value = !value;
if(callback!=NULL) {
callback(value);
}
}
}

자동차 후방 감지기 만들기

LED 신호 Low의 길이를 distance와 비례하게 한다.

app.ino

#include <MiniCom.h>
#include <Servo.h>
#include <Ultra.h>
#include "Pulse.h"
#include <Led.h>
MiniCom com;
Ultra ultra(2, 3);
Led led(5);
Servo servo;
Pulse pulse(100, 500);
// 5단계로 운용
int delaytimes[] = {
50, 100, 200, 500, 1000
};
void pulseCallback(int value) {
// LED 제어
led.set(value);
}
void checkDistance() {
int distance = ultra.read();
com.print(0, "distance", distance);
if(distance < 10) {
// led.on();
// Pulse의 offDelay를 distance를 고려하여 조정
int offDelay = map(distance, 0, 9, 0, 4);
pulse.setDelay(10, delaytimes[offDelay]);
servo.write(90);
if(!pulse.getState()) { // 처음 10cm 이하로 됐을 때
pulse.play();
}
} else {
if(pulse.getState()) {
pulse.stop();
}
// led.off();
servo.write(0);
}
}
void setup() {
com.init();
servo.attach(9);
servo.write(0);
pulse.setCallback(pulseCallback);
com.setInterval(1000, checkDistance);
}
void loop() {
com.run();
pulse.run();
}

댓글