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 명령과 블루투스 모듈 맥어드레스를 같이 적어주면 모듈 상태를 보여줍니다. Paired와 Trusted 항목이 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