아두이노프로세싱 프로그래밍

경기 꿈의 대학 일곱째주 “ 블루투스 HC-06 스마트폰 조종 초음파 센서 충돌 방지 RC카 ”

coding art 2019. 6. 6. 11:06
728x90

 

거리 측정을 위한 초음파 센서 SR-04는 아두이노 센서 중에서 가장 중요한 센서 중의 하나이다. 초음파 센서의 구조는 크리스탈 발진회로에 의해서 40kHz 주파수를 만들어 Triggering 하여 쏜 다음 벽면으로부터의 반사파 즉 echo를 수신하는데 그 사이 경과 시간을 정밀하게 측정하여 공기 중의 초음파 속도와 곱하여 거리를 환산한다.

 

공기 중의 초음파 전달 속도는 340m/sec

 

초음파 센서는 주둥이형 센서의 높이가 1cm 정도이므로 50cm 거리 측정 실험에서 이 정도의 오차 범위 내에 있어야 한다.

물론 제품에 따라서 최대 500cm 까지의 거리 측정이 가능하기도 하다.

 

 

최대 측정 거리는 수직으로 마주한 벽면을 대상으로 500 cm 이며 그 이상의 거리에서는 0 cm 라는 결과를 보여 준다. 한편 반사파가 돌아오지 못할 정도로 벽면에 기울여 초음파를 발사하는 경우에도 0 cm 라는 결과를 줄 수밖에 없다. 주변 환경 에서 보면 울퉁불퉁 튀어 나온 부분이 많기 때문에 갑자기 이상한 숫자를 보여 줄 수도 있음에 유의하자.

 

 초음파 센서의 배선은 Vcc 는 반드시 5V 에 배선한다. 3.3V에서도 동작할 수 있다고는 하나 측정 거리가 짧아질 수 도 있음에 유의하자. Trig Echo는 아래 그림에서 2번과 3번에 배선되어 있지만 RC카에서는 모터쉴드가 3번 핀에서 부터 12번 핀까지 모조리 사용하기 때문에 유일하게 남은 핀은 2번과 13번 핀이다. ECHO2번 핀 TRIG13핀에 배선하자.

 

 

 

초음파 센서를 사용하기 위한 특별한 라이브러리 지원은 별도로 없다.

마이크로 세컨드 단위로 경과 시간 정수형 변수 us를 설정한다.

cm 단위로 하는 대상물과의 거리를 정수형 변수 cm 으로 설정한다.

setup()에서 통신 속도와 ECHO TRIG 핀의 모드를 설정한다. TRIG는 초음파를 발사하라는 듀티 신호를 SR-04 보드에 보내야 하므로 출력 즉 OUTPUT 이다. 반면에 ECHO 핀은 SR-04 보드로부터 듀티 신호를 받는 핀이므로 INPUT 으로 설정해야 한다.

 

 

TRIG 듀티의 시간 폭은 10 마이크로 세컨드로서 delayMicroseconds()를 사용한다. 경과 시간은 pulseln(ECHO,HIGH) 명령에서 ECHO 핀이 LOW에서 HIGH로 변화 시작하는 시점을 체크하여 지속된 시간이 끝나고 LOW로 바뀌는 시점까지 경과 시간을 측정한다.

 

이 초음파 거리 측정 코드를 그대로 블루투스 RC카 코드에 옮기자.

주의할 점은 초음파 센서에 의해 30cm 이내에 장애물이 발견되었을 때 멈추도록 한다.

특히 리튬배터리와 같이 파워가 큰 배터리 사용시에 mpsd = 120 의 작은 값을 설정한다.

아울러 delay 를 50 msec 로 짧게 주도록 한다.

 

 

지난 주의 HC-06 블루투스 조종 RC카 코드는 그대로 살아 있으며 스마트폰 앱도 그대로 사용이 가능하다.

단지 loop() 시작 부분에 초음파에 의한 장애물과의 거리를 측정하는 루틴이 부가되었을 따름이다.

이 코드를 업로딩하여 실행 시켰을 때에 RC 카가 30cm 전방의 장애물 발견 시 멈추게 된다.

이 범위 안에서도 주행이 가능하지만 loop() 문 실행 속도가 제법 빠르므로 찔끔 찔끔씩 움직임이 가능하다. 따라서 후진하여 30cm를 벗어나면 자유롭게 주행이 가능하다.

 

트랙에 장애물이 있는 RC 카 경주를 위해서는 loop() 문 내의 모든 delay 를 50 msec  로 맞춰 스마트폰 조작 시 잦은 터치가 일어나도 랙 발생이 없도록 하자.

maspd 값은 드론용 리튬배터리 사용 시 상당히 작은 값인 120 을 추천한다.

 

 

#RCCAR_BT_ULTRASONIC_01

#define ECHO 2
#define TRIG 13

#include <AFMotor.h>
AF_DCMotor motor1(3);
AF_DCMotor motor2(4);
int mspd = 180;
char command;

void setup() {      
  Serial.begin(9600);
  pinMode(TRIG,OUTPUT);
  pinMode(ECHO,INPUT);
  Stop();
  delay(1000);
}

void loop()  {
        digitalWrite(TRIG,HIGH);   //send Pulse
        delayMicroseconds(10);
        digitalWrite(TRIG,LOW); 
        int us = pulseIn(ECHO,HIGH);    //get return time
        int cm = us/58;
        Serial.print("cm : ");
        Serial.println(cm);

        if( cm < 30 ) {
          Stop();
          delay(50);
        }
              
 if(Serial.available() > 0){
    command = Serial.read();
//     if( command == 'F') {
     if( command == 'G' || command == 'g' || command == 'F') {
      forward();
      delay(50);
     }

//     if( command == 'B') {
     if( command == 'B' || command == 'b' || command == 'BK') {
      back();
      delay(50);
     }

//     if( command == 'L') {
     if( command == 'L' || command == 'l' || command == 'LA') {
      left();
      delay(50);
     }

//     if( command == 'R') {
     if( command == 'R' || command == 'r' || command == 'h') {
      right();
      delay(50);
     }

//     if( command == 'S') {
     if( command == 'S' || command == 's' || command == 'st') {
      Stop();
      delay(50);
     }
 }
}

void forward()  {
  motor1.setSpeed(mspd); //Define maximum velocity
  motor1.run(FORWARD); //rotate the motor clockwise
  motor2.setSpeed(mspd); //Define maximum velocity
  motor2.run(FORWARD); //rotate the motor clockwise
}

void back()  {
  motor1.setSpeed(mspd);
  motor1.run(BACKWARD); //rotate the motor counterclockwise
  motor2.setSpeed(mspd);
  motor2.run(BACKWARD); //rotate the motor counterclockwise
}

void left()  {
  motor1.setSpeed(mspd); //Define maximum velocity
  motor1.run(FORWARD); //rotate the motor clockwise
  motor2.setSpeed(0);
  motor2.run(RELEASE); //turn motor2 off
}

void right()  {
  motor1.setSpeed(0);
  motor1.run(RELEASE); //turn motor1 off
  motor2.setSpeed(mspd); //Define maximum velocity
  motor2.run(FORWARD); //rotate the motor clockwise
}

void Stop()  {
  motor1.setSpeed(0);
  motor1.run(RELEASE); //turn motor1 off
  motor2.setSpeed(0);
  motor2.run(RELEASE); //turn motor2 off
}

//끝