반응형



HC-05를 연결한 Arduino UNO와 Raspberry PI 3간 통신 테스트를 진행했습니다.




1. bluetoothctl 명령을 사용하여 페어링하는 방법


2. LED 제어 테스트




1. bluetoothctl 명령을 사용하여 페어링하는 방법

라즈베리파이와 Arduino UNO간 페어링하는 방법을 설명합니다.



1. Arduino UNO와 HC-05 Bluetooth 모듈을 다음처럼 연결하고 Arduino UNO에 전원을 연결합니다.

 


Arduino UNO D3  → HC-05 Bluetooth 모듈 RXD

Arduino UNO D2  → HC-05 Bluetooth 모듈 TXD

Arduino UNO GND  → HC-05 Bluetooth 모듈 GND

Arduino UNO 5V  → HC-05 Bluetooth 모듈 VCC





2.  필요한 패키지를 설치합니다.


pi@raspberrypi:~ $ sudo apt-get install bluetooth bluez bluez-tools



Raspberry Pi 3의 터미널에서  bluetoothctl  명령을 실행합니다.

현재 디폴트로 설정되어 있는 Raspberry Pi 3에 내장된 Bluetooth 모듈의 맥어드레스를 출력해줍니다.

[bluetooth] # 옆에 커서가 깜박이면서  명령 입력 대기모드가 됩니다.


pi@raspberrypi:~ $ bluetoothctl
[NEW] Controller B8:27:EB:DA:FA:66 raspberrypi [default]
[bluetooth]#


bluetoothctl는 블루투스 디바이스를 검색하고 페어링 및 연결 등의 목적으로 사용할 수 있는 유틸리티입니다.

대화형 명령 방식이라서  명령을 입력하면 바로 결과를 보여줍니다.




3. show를 입력하면 Raspberry Pi 3에서 사용중인 모듈의 정보를 보여줍니다.


블루투스 모듈의 맥어드레스는 B8:27:E8:DA:FA:66입니다.

Powered: yes 현재 모듈의 전원이 켜져 있습니다.

Discoverable: no 다른 블루투스 장치에서 검색할 수 없도록 설정되어 있습니다.

Pairable: yes 페어링이 가능하도록 설정되어 있습니다.

Discovering: no 현재 다른 블루투스 장치를 검색하고 있지 않습니다.

UUID 목록은 라즈베리파이에서 제공하는 블루투스 서비스입니다.


[bluetooth]# show
Controller B8:27:EB:DA:FA:66
       Name: raspberrypi
       Alias: raspberrypi
       Class: 0x480000
       Powered: yes
       Discoverable: no
       Pairable: yes
       UUID: Headset AG                (00001112-0000-1000-8000-00805f9b34fb)

       UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)

       UUID: A/V Remote Control        (0000110e-0000-1000-8000-00805f9b34fb)

       UUID: Generic Access Profile    (00001800-0000-1000-8000-00805f9b34fb)

       UUID: PnP Information           (00001200-0000-1000-8000-00805f9b34fb)

       UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb)

       UUID: Audio Source              (0000110a-0000-1000-8000-00805f9b34fb)

       UUID: Handsfree Audio Gateway   (0000111f-0000-1000-8000-00805f9b34fb)

       Modalias: usb:v1D6Bp0246d052B
       Discovering: no




4. 모듈의 전원이 꺼져있다면(Powered: no) 다음 명령으로 모듈의 전원을 켜줍니다.


[bluetooth]# power on
[CHG] Controller B8:27:EB:DA:FA:66 Class: 0x6c0000
Changing power on succeeded
[CHG] Controller B8:27:EB:DA:FA:66 Powered: yes




5. 에이전트를 활성화하고 기본값으로 설정합니다. 페어링 핀 코드를 요청 및 확인을 하기 위해 필요합니다.


[bluetooth]# agent on
Agent registered
[bluetooth]# default-agent
Default agent request successful




6. 주변에 있는 블루투스 디바이스를 검색합니다.  HC-05가 검색될 때까지 대기합니다.


[bluetooth]# scan on
Discovery started
[CHG] Controller B8:27:EB:DA:FA:66 Discovering: yes
[NEW] Device 00:09:A7:24:A7:CF Beoplay E8
[NEW] Device 57:F3:99:2E:15:7B 57-F3-99-2E-15-7B
[NEW] Device 54:BD:5A:3F:4E:62 54-BD-5A-3F-4E-62
[NEW] Device 44:CD:06:A2:89:EC 44-CD-06-A2-89-EC
[NEW] Device 9C:8C:6E:E1:7E:23 9C-8C-6E-E1-7E-23
[NEW] Device 5E:5A:12:DB:1E:AC 5E-5A-12-DB-1E-AC
[NEW] Device 64:1C:B0:14:A8:44 64-1C-B0-14-A8-44
[NEW] Device 4D:A4:8C:6C:A6:00 4D-A4-8C-6C-A6-00
[NEW] Device 5A:F6:24:E8:93:7C 5A-F6-24-E8-93-7C
[NEW] Device 20:15:08:13:18:58 20-15-08-13-18-58
[CHG] Device 20:15:08:13:18:58 LegacyPairing: no
[CHG] Device 20:15:08:13:18:58 Name: HC-05
[CHG] Device 20:15:08:13:18:58 Alias: HC-05




7. 주변 블루투스 디바이스 검색을 중지합니다.


[bluetooth]# scan off
Discovery stopped
[CHG] Controller B8:27:EB:DA:FA:66 Discovering: no




8. pair 명령과 앞에서 확인한 HC-05의 블루투스 모듈 맥어드레스를 같이 적어주면 페어링이 진행됩니다.

핀번호로 1234를 입력하고 엔터키를 누릅니다.


[bluetooth]# pair 20:15:08:13:18:58
Attempting to pair with 20:15:08:13:18:58
[CHG] Device 20:15:08:13:18:58 Connected: yes
Request PIN code
[agent] Enter PIN code: 1234




9. 잠시 후 페어링이 완료됩니다.


[CHG] Device 20:15:08:13:18:58 UUIDs: 00001101-0000-1000-8000-00805f9b34fb
[CHG] Device 20:15:08:13:18:58 ServicesResolved: yes
[CHG] Device 20:15:08:13:18:58 Paired: yes
Pairing successful
[CHG] Device 20:15:08:13:18:58 ServicesResolved: no
[CHG] Device 20:15:08:13:18:58 Connected: no

[bluetooth]#




10. 페어링 완료후, trust 명령을 해줘야 합니다.


[bluetooth]# trust 20:15:08:13:18:58
[CHG] Device 20:15:08:13:18:58 Trusted: yes

Changing 20:15:08:13:18:58 trust succeeded




11.  info 명령과 블루투스 모듈 맥어드레스를 같이 적어주면 모듈 상태를 보여줍니다. PairedTrusted 항목이 yes입니다.


[bluetooth]# info 20:15:08:13:18:58

Device 20:15:08:13:18:58

       Name: HC-05

       Alias: HC-05

       Class: 0x001f00

       Paired: yes

       Trusted: yes

       Blocked: no

       Connected: no

       LegacyPairing: yes

       UUID: Serial Port               (00001101-0000-1000-8000-00805f9b34fb)




12.  페어링을 취소하는 방법을 잠시 설명하겠습니다.  지금 진행하지는 마세요.

paired-devices 명령으로 현재 페어링된 디바이스 확인을 할 수 있습니다.


[bluetooth]# paired-devices
Device 20:15:08:13:18:58 HC-05



remove 명령과 HC-05 블루투스 모듈 맥어드레스를 같이 적어주면 페어링 설정이 Raspberry Pi 에서 삭제됩니다.


[bluetooth]# remove 20:15:08:13:18:58
[DEL] Device 20:15:08:13:18:58 HC-05

Device has been removed




13.  quit 명령으로  bluetoothctl를 종료합니다.


[bluetooth]# quit
Agent unregistered
[DEL] Controller B8:27:EB:DA:FA:66 raspberrypi [default]



2. LED 제어 테스트

1. 아두이노 우노에 다음 코드를 업로드합니다.

 

#include <SoftwareSerial.h>


SoftwareSerial softwareSerial(2, 3); // RX, TX



void setup() {


softwareSerial.begin(9600);

pinMode(LED_BUILTIN, OUTPUT);

}


void loop() {


if (softwareSerial.available() > 0 ) {



  char command = softwareSerial.read();

  int ledStatus = digitalRead(LED_BUILTIN);


  switch (command){


    case '1':

    

      if (ledStatus == LOW){

        digitalWrite(LED_BUILTIN, HIGH);

        softwareSerial.println("LED가 켜졌습니다.\n");

      }

      else{

        softwareSerial.println("이미 LED가 켜져있습니다.\n");

      }

      break;


    case '2':

    

      if (ledStatus == HIGH){

        digitalWrite(LED_BUILTIN, LOW);

        softwareSerial.println("LED가 꺼졌습니다.\n");

      }

      else{

        softwareSerial.println("이미 LED가 꺼져있습니다.\n");

      }

      break;


    case 'S':

    case 's':

        

      if (ledStatus == LOW){

        softwareSerial.println("LED 상태: 꺼짐\n");

      }

      else {

        softwareSerial.println("LED 상태: 켜짐\n");

      }

      break;

    

  }    

}

}

 

 

 

2. HC-05의 맥어드레스를 확인합니다.

 

pi@raspberrypi:~ $ hcitool scan
Scanning ...
       20:15:08:13:18:58       HC-05

 

보이지 않는 경우 앞에서 확인한 맥어드레스를 사용하세요.

 

 

3. HC-05와 시리얼 통신을 하기 위해  /dev/rfcomm0 디바이스를 생성합니다.

 

pi@raspberrypi:~ $ sudo rfcomm bind rfcomm0 20:15:08:13:18:58

 

 

 

4. 아래 첨부한 miniterm 소스  코드를 miniterm.c로 저장하여 컴파일합니다.

http://www.openfoundry.org/svn/xenids/xen-4.0.0/tools/misc/miniterm/miniterm.c

 

pi@raspberrypi:~ $ gcc -o miniterm miniterm.c

 

 

/******************************************************************************
* miniterm.c
*
* Adapted from the example program distributed with the Linux Programmer's
* Guide (LPG). This has been robustified and tweaked to work as a debugging
* terminal for Xen-based machines.
*
* Modifications are released under GPL and copyright (c) 2003, K A Fraser
* The original copyright message and license is fully intact below.
*/

/*
*  AUTHOR: Sven Goldt (goldt@math.tu-berlin.de)
*
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU General Public License
*  as published by the Free Software Foundation; either version 2
*  of the License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*/

#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>

#define DEFAULT_BAUDRATE   115200
#define DEFAULT_SERDEVICE  "/dev/ttyS0"
#define ENDMINITERM        0x1d

volatile int stop = 0;

void child_handler(int s)
{
   stop = 1;
}

int cook_baud(int baud)
{
   int cooked_baud = 0;
   switch ( baud )
   {
   case     50: cooked_baud =     B50; break;
   case     75: cooked_baud =     B75; break;
   case    110: cooked_baud =    B110; break;
   case    134: cooked_baud =    B134; break;
   case    150: cooked_baud =    B150; break;
   case    200: cooked_baud =    B200; break;
   case    300: cooked_baud =    B300; break;
   case    600: cooked_baud =    B600; break;
   case   1200: cooked_baud =   B1200; break;
   case   1800: cooked_baud =   B1800; break;
   case   2400: cooked_baud =   B2400; break;
   case   4800: cooked_baud =   B4800; break;
   case   9600: cooked_baud =   B9600; break;
   case  19200: cooked_baud =  B19200; break;
   case  38400: cooked_baud =  B38400; break;
   case  57600: cooked_baud =  B57600; break;
   case 115200: cooked_baud = B115200; break;
   }
   return cooked_baud;
}

int main(int argc, char **argv)
{
   int              fd, c, cooked_baud = cook_baud(DEFAULT_BAUDRATE);
   char            *sername = DEFAULT_SERDEVICE;
   struct termios   oldsertio, newsertio, oldstdtio, newstdtio;
   struct sigaction sa;
   static char start_str[] =
       "************ REMOTE CONSOLE: CTRL-] TO QUIT ********\r\n";
   static char end_str[] =
       "\n************ REMOTE CONSOLE EXITED *****************\n";

   while ( --argc != 0 )
   {
       char *p = argv[argc];
       if ( *p++ != '-' )
           goto usage;
       if ( *p == 'b' )
       {
           p++;
           if ( (cooked_baud = cook_baud(atoi(p))) == 0 )
           {
               fprintf(stderr, "Bad baud rate '%d'\n", atoi(p));
               goto usage;
           }
       }
       else if ( *p == 'd' )
       {
           sername = ++p;
           if ( *sername == '\0' )
               goto usage;
       }
       else
           goto usage;
   }

   /* Not a controlling tty: CTRL-C shouldn't kill us. */
   fd = open(sername, O_RDWR | O_NOCTTY);
   if ( fd < 0 )
   {
       perror(sername);
       exit(-1);
   }

   tcgetattr(fd, &oldsertio); /* save current modem settings */

   /*
    * 8 data, no parity, 1 stop bit. Ignore modem control lines. Enable
    * receive. Set appropriate baud rate. NO HARDWARE FLOW CONTROL!
    */
   newsertio.c_cflag = cooked_baud | CS8 | CLOCAL | CREAD;

   /* Raw input. Ignore errors and breaks. */
   newsertio.c_iflag = IGNBRK | IGNPAR;

   /* Raw output. */
   newsertio.c_oflag = OPOST;

   /* No echo and no signals. */
   newsertio.c_lflag = 0;

   /* blocking read until 1 char arrives */
   newsertio.c_cc[VMIN]=1;
   newsertio.c_cc[VTIME]=0;

   /* now clean the modem line and activate the settings for modem */
   tcflush(fd, TCIFLUSH);
   tcsetattr(fd,TCSANOW,&newsertio);

   /* next stop echo and buffering for stdin */
   tcgetattr(0,&oldstdtio);
   tcgetattr(0,&newstdtio); /* get working stdtio */
   newstdtio.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
   newstdtio.c_oflag &= ~OPOST;
   newstdtio.c_cflag &= ~(CSIZE | PARENB);
   newstdtio.c_cflag |= CS8;
   newstdtio.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
   newstdtio.c_cc[VMIN]=1;
   newstdtio.c_cc[VTIME]=0;
   tcsetattr(0,TCSANOW,&newstdtio);

   /* Terminal settings done: now enter the main I/O loops. */
   switch ( fork() )
   {
   case 0:
       close(1); /* stdout not needed */
       for ( c = (char)getchar(); c != ENDMINITERM; c = (char)getchar() )
           write(fd,&c,1);
       tcsetattr(fd,TCSANOW,&oldsertio);
       tcsetattr(0,TCSANOW,&oldstdtio);
       close(fd);
       exit(0); /* will send a SIGCHLD to the parent */
       break;
   case -1:
       perror("fork");
       tcsetattr(fd,TCSANOW,&oldsertio);
       close(fd);
       exit(-1);
   default:
       write(1, start_str, strlen(start_str));
       close(0); /* stdin not needed */
       sa.sa_handler = child_handler;
       sa.sa_flags = 0;
       sigaction(SIGCHLD,&sa,NULL); /* handle dying child */
       while ( !stop )
       {
           read(fd,&c,1); /* modem */
           c = (char)c;
           write(1,&c,1); /* stdout */
       }
       wait(NULL); /* wait for child to die or it will become a zombie */
       write(1, end_str, strlen(end_str));
       break;
   }

   return 0;

usage:
   printf("miniterm [-b<baudrate>] [-d<devicename>]\n");
   printf("Default baud rate: %d\n", DEFAULT_BAUDRATE);
   printf("Default device: %s\n", DEFAULT_SERDEVICE);
   return 1;
}

 

 

 

5. 다음처럼 실행 후, 테스트를 해봅니다.

1을 누르면 아두이노에 연결된 LED가 켜지고 2를 누르면 LED가 꺼집니다.

s를 입력하면 현재 LED 상태를 출력합니다. 종료시에는 Ctrl + ] 를 입력하세요.

 

pi@raspberrypi:~ $ ./miniterm -b9600 -d/dev/rfcomm0
************ REMOTE CONSOLE: CTRL-] TO QUIT ********
LED가 켜졌습니다.

이미 LED가 켜져있습니다.

LED가 꺼졌습니다.

LED 상태: 꺼짐

LED 상태: 꺼짐

LED가 켜졌습니다.

LED가 꺼졌습니다.

LED가 켜졌습니다.

LED가 꺼졌습니다.

LED 상태: 꺼짐

LED가 켜졌습니다.

LED가 꺼졌습니다.



************ REMOTE CONSOLE EXITED *****************

 

 

마지막 업데이트 2019. 8. 8

 

 

 

 


문제 발생시 지나치지 마시고 댓글 남겨주시면 가능한 빨리 답장드립니다.


제가 쓴 책도 한번 검토해보세요 ^^

+ Recent posts