1. 초음파센서란?

 

초음파란 사람의 귀에 들리지 않을 정도로 높은 주파수 (20 kHz 이상)의 소리를 말한다. 이와 같은 특성을 이용한 것이 초음파센서로 음파를 쏘아올리고 반사되어 오는 음파까지의 시간차를 거리로 계산하여 측정하는 방식으로 동작된다. 이번에 실습해볼 예제는 HC-SR04라는 초음파센서를 활용하여 거리를 측정하는 것이며 이를 통해 초음파센서의 기초 원리를 이해하고 갈릴레오보드의 활용법을 숙달한다.


동작 전압

5V

동작 전류

15mA

동작 주파수

40Hz

발생 주파수

40kHz

측정 거리

최대 4m

측정 각도

15

 

 

2. 동작 원리

 

초음파센서는 두 개의 눈으로 구성되어 있으며, 하나는 초음파를 발생시켜 송신(Trig)하는 기능을 수행하고, 나머지 하나는 송신된 초음파의 신호를 수신(Echo)하는 기능을 수행하게 된다. 따라서 두 개의 눈이 서로 송신하고 수신되는 시간의 차이에 따라 물체와의 거리를 계산하는 방식으로 동작하며 주파수가 높은 만큼 파장이 매우 짧기 때문에 거리 방향의 분해력이 우수하고 정밀도가 높은 계측을 할 수 있다. 이러한 센서의 원리 때문에 거리감지센서나 레인지센서라고도 불린다HC-SR04 초음파센서의 경우에는 4개의 핀으로 구성되어 있으며 각각 순서대로 Vcc, Trig, Echo, Gnd 이다.

 


 

3. 준비물

 

갈릴레오보드, HC-SR04, 브레드보드, 점퍼선



4. 회로도


Vcc부분에 5V의 전원을 인가하고 Gnd끼리 연결해준다. 그리고 D2D3를 각각 echotrig순으로 연결하면 기본적인 회로 구성이 완료된다.

 

 

5. 동작 방법

 

동작 설명에 앞서 어떤 보드를 사용하여 회로를 구성할 것인가가 중요하다. 필자는 초기의 갈릴레오보드1을 사용하였는데 처음에 초음파센서를 활용한 결과값이 제대로 나오지 않아 많은 시간을 허비했다. 분명 센서는 문제가 없었으며 코드 부분도 이상이 없음에도 불구하고 결과가 0m를 보여주는 현상이 일어났다. 때문에 보드에 무엇인가 문제가 있다고 판단하여 갈릴레오보드의 데이터시트를 확인해 보았는데 여기서 문제를 발견할 수 있었다. 바로 갈릴레오보드의 초기 모델은 GPIO핀의 동작주파수 범위가 매우 낮기 때문에 초음파센서에 나오는 출력 주파수 40kHz를 보드 자체에서 읽지 못하여 0m가 계속해서 나타나는 것이었다.

이러한 문제는 의외로 단순하게 해결할 수 있는데 갈릴레오보드에서는 동작주파수 범위가 큰 Fast I/O 핀이 따로 설정할 수 있다. 여기서는 D2D3핀이 해당되며 해당 핀을 사용하고 pinMode()함수를 사용하여 기존의 입력이나 출력을 INPUT_FASTOUTPUT_FAST로 설정하면 큰 주파수 범위의 출력에서도 무리없이 사용할 수 있다. 위 문제는 갈릴레오보드 초기모델에서만 나타나며 갈릴레오보드2나 아두이노보드에서는 동작주파수 범위가 넓기 때문에 문제없이 동작하여 굳이 Fast I/O를 사용할 필요가 없다.



동작 방법은 앞에서 설명했던 초음파의 원리를 응용한 것으로 센서에서 음파를 발생시키고 물체에 반사되어 되돌아오기까지의 시간을 측정하여 거리로 표시해주는 방식이다. 여기에서 중요한 역할을 하는 것이 바로 pulseIn() 함수이다. 이 함수는 해당 출력이 HIGHLOW가 되는 순간까지의 시간을 계산해주는 함수로서 초음파센서의 음파가 되돌아오는 시간을 계산해주는 역할을 한다. 또한 밑의 소스코드에서 pulseIn()함수로 측정된 값을 58로 나누어주고 있음을 알 수 있는데 그 이유는 소리의 속도가 대략 340m/s 이기 때문에 1cm를 이동하는데 걸리는 시간이 29.155 마이크로초가 된다. 따라서 측정된 시간 값은 음파가 갔다가 되돌아오는 시간이기 때문에 2로 나누어주고 여기에 방금 계산한 29.155를 다시 나눠주게 되면 우리가 원하는 거리의 값을 나타낼 수 있다.




6. 소스 코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#define trig 3 // trig 단자를 Digital 3번 단자에 연결
#define echo 2 // echo 단자를 Digital 2번 단자에 연결
long duration, distance;
 
void setup() {
  Serial.begin (9600); // Serial 통신
  pinMode(trig, OUTPUT_FAST); // trig 단자를 빠른 출력모드로 설정
  pinMode(echo, INPUT_FAST); // echo 단자를 빠른 출력모드로 설정
}
 
void loop() {
  digitalWrite(trig, LOW); // Trig 단자 LOW로 설정
  delayMicroseconds(2);
  digitalWrite(trig, HIGH); // Trig 단자 HIGH로 설정
  delayMicroseconds(10);
  digitalWrite(trig, LOW); // Trig 단자 LOW로 설정
 
  duration = pulseIn(echo, HIGH); // pulseIn 함수 호출
  distance = duration / 58// 반환값을 cm로 단위 변환
  Serial.print(distance); // 거리 표시
  Serial.println(" cm");
  delay(1000);
}
 
cs



6. 결과 화면


  


 

 

'Electronic > Arduino' 카테고리의 다른 글

지그비 무선 통신하기  (13) 2016.01.26
XBee 모듈 정보 및 종류  (0) 2016.01.17
지그비 통신의 개념 (네트워크의 이해)  (8) 2016.01.16

라즈베리파이와 아두이노 사이에는 SPI, I2C, UART 등 다양한 통신 방법들을 적용할 수 있다. 하지만 아두이노의 입출력 핀 전압이 5V인 반면에 라즈베리파이의 GPIO 입출력 핀 전압은 3.3V이기 때문에 직접적으로 결선할 경우 문제가 발생하게 된다. 따라서 여기서는 가장 간편하게 사용할 수 있는 Serial(UART) 통신을 활용해보자. 


시리얼통신은 라즈베리파이와 아두이노를 USB케이블로 연결하는 것으로 간단하게 구현할 수 있으며 전압에 따른 문제 또한 발생하지 않는다.



1. 아두이노 Idle 설치하기


  $ sudo apt-get install arduino


패키지 설치를 위해 라즈베리파이에 update 명령어를 통해 업데이트 시켜주고 위 명령어를 입력하여 아두이노 패키지를 설치한다. 이때 설치된 패키지는 권한을 아직 가지고 있지 않은 상태이므로 바로 실행시키지 말고 아래 명령어를 입력하여 아두이노 패키지가 시리얼 포트에 엑세스 할 수 있는 권한을 얻도록 한다.


  $ sudo usermod -a -G tty pi

  $ sudo usermod -a -G dialout pi


위 과정을 완료하였다면 아두이노 패키지가 성공적으로 라즈베리파이에 설치되었다. 이제 아두이노를 실행시키고 라즈베리파이에 아두이노를 연결한 후에 포트를 설정하고 ("/dev/ttyACM0" 일 것이다.) blink 예제를 업로드하여 제대로 동작하는지 확인해본다.




2. 시리얼 통신하기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/*
 Pi_Serial_test.cpp - SerialProtocol library - demo
 Copyright (c) 2014 NicoHood.  All right reserved.
 Program to test serial communication
 
 Compile with:
 sudo gcc -o Pi_Serial_Test.o Pi_Serial_Test.cpp -lwiringPi -DRaspberryPi -pedantic -Wall
 sudo ./Pi_Serial_Test.o
 */
 
// just that the Arduino IDE doesnt compile these files.
#ifdef RaspberryPi 
 
//include system librarys
#include <stdio.h> //for printf
#include <stdint.h> //uint8_t definitions
#include <stdlib.h> //for exit(int);
#include <string.h> //for errno
#include <errno.h> //error output
 
//wiring Pi
#include <wiringPi.h>
#include <wiringSerial.h>
 
// Find Serial device on Raspberry with ~ls /dev/tty*
// ARDUINO_UNO "/dev/ttyACM0"
// FTDI_PROGRAMMER "/dev/ttyUSB0"
// HARDWARE_UART "/dev/ttyAMA0"
char device[]= "/dev/ttyACM0";
// filedescriptor
int fd;
unsigned long baud = 9600;
unsigned long time=0;
 
//prototypes
int main(void);
void loop(void);
void setup(void);
 
void setup(){
 
  printf("%s \n""Raspberry Startup!");
  fflush(stdout);
 
  //get filedescriptor
  if ((fd = serialOpen (device, baud)) < 0){
    fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
    exit(1); //error
  }
 
  //setup GPIO in wiringPi mode
  if (wiringPiSetup () == -1){
    fprintf (stdout, "Unable to start wiringPi: %s\n", strerror (errno)) ;
    exit(1); //error
  }
 
}
 
void loop(){
  // Pong every 3 seconds
  if(millis()-time>=3000){
    serialPuts (fd, "Pong!\n");
    // you can also write data from 0-255
    // 65 is in ASCII 'A'
    serialPutchar (fd, 65);
    time=millis();
  }
 
  // read signal
  if(serialDataAvail (fd)){
    char newChar = serialGetchar (fd);
    printf("%c", newChar);
    fflush(stdout);
  }
 
}
 
// main function for normal c++ programs on Raspberry
int main(){
  setup();
  while(1) loop();
  return 0;
}
 
#endif //#ifdef RaspberryPi
cs

위 코드는 wiringPi 라이브러리를 활용하여 아두이노와 통신할 수 있는 예제 코드이다. 여기서 "/dev/ttyACM0" 부분은 아두이노가 연결된 장치의 포트명을 말하는 것으로 가끔씩 에러가 발생할 경우 ACM1, ACM2 이렇게 순차적으로 증가할 수 있으니 유의하도록 한다. 라즈베리파이의 USB포트 구성 목록을 확인하려면 다음 과 같은 명령어를 입력하면 된다.

  $ dmesg|tail



그럼 이제 위 소스코드를 컴파일한다. 필자는 소스코드의 파일명을 test.c로 하였으며 hello라는 이름으로 컴파일했다. 컴파일할 때는 파일이 저장된 디렉토리로 들어간 후에 하도록 한다.


  $ sudo gcc test.c -o hello -l wiringPi -DRaspberryPi

  $ sudo ./hello


아래는 간단하게 구현한 아두이노 소스코드이며 1초마다 라즈베리파이로 Hello World 문자를 송신할 것이다.


1
2
3
4
5
6
7
8
void setup(){  
  Serial.begin(9600);
 
void loop(){
  Serial.println("Hello World");
  delay(1000);
}
cs


3. 결과 확인


위와 같은 결과가 나오면 성공이다. 여기서 실행된 프로그램을 종료하려면 Ctrl + C를 눌러주면 된다. 만약 종료를 하지 않을경우 터미널을 종료해도 계속해서 프로그램이 동작하며 아두이노를 다시 연결시 ttyACM0 포트는 사용하지 못하기 때문에 테스트 종료시에 유의하도록 한다.


라즈베리파이의 대표적인 운영체제인 라즈비안은 리눅스를 기반으로 하며 사용자가 손쉽게 프로그래밍 할 수 있도록 파이썬 언어를 지원한다. 하지만 여기에서는 기존 임베디드 환경에서 익숙한 언어인 C를 통해 개발할 수 있도록 wiringPi라는 라이브러리를 활용하여 라즈베리파이를 제어해보도록 하자. wiringPi 라이브러리는 I2C, SPI, UART 등의 통신을 제어할 수 있는 함수를 제공하며 GPIO포트에 대한 설정이나 프로그래밍을 가능하게 해준다.



1. 패키지 설치 준비


  $ sudo apt-get update

  $ sudo apt-get upgrade


새로운 패키지를 설치하기 전에 꼭 해야하는 부분이 바로 업데이트이다. 위 명령은 패키지 관리 서버로부터 이용 가능한 프로그램 패키지의 목록을 최신버전으로 업데이트 해주며 갱신된 패키지 목록을 통해 새로운 버전으로 설치해준다.



2. wiringPi 설치하기


  $ sudo apt-get install git-core

  $ git clone git://git.drogon.net/wiringPi


wiringPi 설치를 위해 소스 관리 툴인 git을 다운로드하고 git을 이용하여 wiringPi 라이브러리를 다운로드 한다. 위 주소는 실제 git주소를 통해 다운로드하기 때문에 대소문자에 주의해서 입력하도록 한다.

또한 위 명령어는 해당 폴터를 통째로 복사해오기 때문에 홈디렉토리에 wiringPi 폴터가 생성된다. 따라서 해당 디렉토리 이동 후에 사용자가 직접 설치하도록 하자.


  $ cd wiringPi

  $ ./build



3. wiringPi 설치 확인


  $ gpio -v

  $ gpio readall


제대로 설치가 되었는지 확인하기 위해 위 명령어를 입력하여 확인해본다.