스마트 디바이스 5주차 블루투스 - yubiine/25-1_smartdevice GitHub Wiki
- 블루투스 통신의 기본 개념을 이해한다.
- ESP32의 클래식 블루투스 및 BLE 방식을 활용하여 데이터를 송수신한다.
- BLE를 이용하여 RGB LED를 제어하는 실습을 진행한다.
전선(케이블) 없이 전파(RF), 적외선(IR), 빛 등을 이용해 정보(데이터)를 주고받는 통신 방식 (전자기파 사용)
- 무선통신은 **전파(전자기파)**를 사용
- 전파는 공기 중을 통해 에너지와 신호를 전달
- 전파는 파형으로 전달되고, **1초당 진동 수(Hz)**로 표현
- 주파수 대역에 따라 용도가 나뉨
주파수 대역 | 예시 | 특징 |
---|---|---|
13.56 MHz | NFC | 매우 근거리, 낮은 속도, 높은 보안성 |
2.4 GHz | Bluetooth, Zigbee, Wi-Fi | 비교적 넓은 커버리지, 간섭 가능성 ↑ |
5 GHz | Wi-Fi | 높은 속도, 짧은 거리 |
3~10 GHz | UWB | 초정밀 위치인식 가능 |
주파수가 높을수록 데이터 전송 속도 ↑, 거리 ↓
주파수가 낮을수록 통신거리 ↑, 데이터 속도 ↓
- 송신기: 데이터를 무선 신호로 변환해 보냄
- 수신기: 신호를 받아서 원래의 데이터로 변환함
의미: 주파수 대역 내에서 데이터 전송을 위해 사용되는 세부 주파수 영역
예시:
- Bluetooth: 2.4 GHz 대역에서 1 MHz 폭의 79개 채널 사용 (Classic)
- Wi-Fi: 2.4 GHz 대역에서 20 MHz 폭의 13~14개 채널
- NFC: 채널 구분 없음, 단일 주파수 사용
✅ 채널 분할 이유: 여러 사용자가 같은 주파수 대역을 동시에 사용할 수 있도록 하기 위해
✅ 간섭:
여러 기기가 같은 주파수 대역에서 통신할 때 신호 충돌이 발생하는 현상
→ 데이터 손실, 연결 불안정 발생
주파수 호핑 (Frequency Hopping Spread Spectrum, FHSS)기술 사용
원리: 짧은 시간 간격으로 통신 주파수를 랜덤하게 변경하며 데이터 송수신
특징 | 내용 |
---|---|
장점 | 간섭에 강함, 도청·해킹 방지 |
방식 | Bluetooth Classic: 1600회/초 주파수 변경 |
BLE | Low Energy에서는 Adaptive Frequency Hopping (AFH) 사용 → 혼잡 채널 회피 |
근거리 무선 통신 기술로, 2.4GHz 주파수를 사용해 여러 기기를 무선으로 연결하는 기술
항목 | 블루투스 클래식 | BLE (Bluetooth Low Energy) |
---|---|---|
주 용도 | 음악, 통화, 파일 전송 등 대용량, 지속적 데이터 통신 | 센서, IoT, 스마트워치 등 저전력 통신 |
속도 | 최대 3 Mbps | 약 1 Mbps |
전력 소모 | 높음 (지속 연결 필요) | 매우 낮음 (필요할 때만 통신) |
연결 방식 | 지속적 연결 (스트리밍 중심) | 광고(advertising) & 필요 시 연결 |
멀티 디바이스 | 연결 수 적음 | 다수 연결 가능 (센서 네트워크 적합) |
대표 예시 | 무선 이어폰, 블루투스 스피커, 차량 핸즈프리 | 스마트워치, 심박 센서, 스마트 전구, 온도 센서. |
✅ Bluetooth Classic
- 주파수 대역: 2.402 GHz ~ 2.480 GHz
- 채널: 1 MHz 폭, 79개 채널
- 호핑 속도: 초당 1600회
✅ Bluetooth Low Energy (BLE)
- 주파수 대역: 2.402 GHz ~ 2.480 GHz
- 채널: 2 MHz 폭, 40개 채널
- 37개 데이터 채널 + 3개 광고 채널
- Adaptive Frequency Hopping 사용:
- 사용 중인 환경에서 혼잡한 채널을 피하고, 안정적인 채널만 사용
무선통신 품질 = 주파수 대역 + 채널 활용 + 간섭 방지 기술 조합
요소 | 역할 |
---|---|
주파수 | 속도와 커버리지 결정 |
채널 | 여러 사용자 간의 구분 |
주파수 호핑 | 간섭 회피, 보안성 향상 |
채널 선택 | 혼잡 회피, 데이터 효율 ↑ |
- 처음에 위와 같이 글자가 깨지는 오류 발생
- Baud rate 설정 (9600)
#include "BluetoothSerial.h"
String device_name = "ESP32_DEVICE";
// Check if Bluetooth is available
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
// Check Serial Port Profile
#if !defined(CONFIG_BT_SPP_ENABLED)
#error Serial Port Profile for Bluetooth is not available or not enabled. It is only available for the ESP32 chip.
#endif
BluetoothSerial SerialBT;
void setup() {
Serial.begin(9600);
SerialBT.begin(device_name);
SerialBT.deleteAllBondedDevices();
Serial.printf("The device with name \"%s\" is started.\nNow you can pair it with Bluetooth!\n", device_name.c_str());
}
void loop() {
if (Serial.available()) {
SerialBT.write(Serial.read());
}
if (SerialBT.available()) {
Serial.write(SerialBT.read());
}
delay(20);
}
IMG_6231.2.MOV
#include "BluetoothSerial.h"
String device_name = "ESP32_DEVICE";
const int ledPin = 2; // LED가 연결된 핀 번호
BluetoothSerial SerialBT;
void setup() {
Serial.begin(9600);
SerialBT.begin(device_name); //Bluetooth device name
Serial.printf("The device with name \"%s\" is started.\nNow you can pair it with Bluetooth!\n", device_name.c_str());
pinMode(ledPin, OUTPUT); // LED 핀을 출력으로 설정
digitalWrite(ledPin, LOW); // 초기 상태를 OFF로 설정
}
void loop()
{
if (SerialBT.available())
{
char incoming = SerialBT.read();
Serial.write(incoming); // 수신된 데이터를 시리얼 모니터에 출력
if (incoming == '1')
{
digitalWrite(ledPin, HIGH); // '1'을 수신하면 LED ON
Serial.println("LED ON");
}
else if (incoming == '0')
{
digitalWrite(ledPin, LOW); // '0'을 수신하면 LED OFF
Serial.println("LED OFF");
}
}
}
IMG_6232.2.MOV
#include "BluetoothSerial.h"
String device_name = "ESP32_DEVICE";
const int RED_PIN = 4;
const int GREEN_PIN = 15;
const int BLUE_PIN = 2;
BluetoothSerial SerialBT;
void setup() {
Serial.begin(9600);
SerialBT.begin(device_name); //Bluetooth device name
Serial.printf("The device with name \"%s\" is started.\nNow you can pair it with Bluetooth!\n", device_name.c_str());
pinMode(RED_PIN, OUTPUT); // LED 핀을 출력으로 설정
pinMode(GREEN_PIN, OUTPUT);
pinMode(BLUE_PIN, OUTPUT);
digitalWrite(RED_PIN, HIGH); // 초기 상태를 OFF로 설정
digitalWrite(GREEN_PIN, HIGH);
digitalWrite(BLUE_PIN, HIGH);
}
void loop() {
// 빨강
analogWrite(RED_PIN, 0);
analogWrite(GREEN_PIN, 255);
analogWrite(BLUE_PIN, 255);
delay(1000);
// 초록
analogWrite(RED_PIN, 255);
analogWrite(GREEN_PIN, 0);
analogWrite(BLUE_PIN, 255);
delay(1000);
// 파랑
analogWrite(RED_PIN, 255);
analogWrite(GREEN_PIN, 255);
analogWrite(BLUE_PIN, 0);
delay(1000);
// 백색
analogWrite(RED_PIN, 0);
analogWrite(GREEN_PIN, 0);
analogWrite(BLUE_PIN, 0);
delay(1000);
// 끄기
analogWrite(RED_PIN, 255);
analogWrite(GREEN_PIN, 255);
analogWrite(BLUE_PIN, 255);
delay(1000);
}
IMG_6234.2.MOV
//라이브러리를 가져옵니다.
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
//서비스와 특성에 대한 UUID를 정의합니다.
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define RGB_CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
#define NOTYFY_CHARACTERISTIC_UUID "d501d731-f0f9-4121-a7f6-2c0f959f1583"
//RGB LED에 사용될 핀 번호를 정의합니다
#define RED_PIN 4
#define GREEN_PIN 15
#define BLUE_PIN 2
//BLE 관련 객체를 선언합니다.
BLEServer *pServer; //BLE 서버 객체
BLEService *pService; // BLE 서비스 객체
BLECharacteristic *pRGBCharacteristic = NULL; //BLE 특성 객체
BLECharacteristic* pCharacteristic = NULL; //BLE 특성 객체
//RGB 값을 저장할 변수들을 초기화합니
int redValue = 0;
int greenValue = 0;
int blueValue = 0;
//BLE 특성에 대한 콜백 클래스를 정의합니다.
class MyCallbacks : public BLECharacteristicCallbacks {
//특성의 값을 읽어와 RGB 값을 파싱하고 LED를 제어합니다.
void onWrite(BLECharacteristic *pCharacteristic) {
String value = pCharacteristic->getValue().c_str(); //특성의 값을 문자열로 읽어옵니다.
// 값이 유효한 경우에만 처리
if (value.length() > 0) {
// RGB 값을 파싱하여 각각의 변수에 저장
int delimiterPos1 = value.indexOf(',');
int delimiterPos2 = value.lastIndexOf(',');
if (delimiterPos1 != -1 && delimiterPos2 != -1 \
&& delimiterPos2 < value.length() - 1) {
redValue = value.substring(0, delimiterPos1).toInt();
greenValue = value.substring(delimiterPos1 + 1, delimiterPos2).toInt();
blueValue = value.substring(delimiterPos2 + 1).toInt();
// RGB 값을 LED의 밝기로 변환하여 제어합니다.
analogWrite(RED_PIN, 255 - redValue);
analogWrite(GREEN_PIN, 255 - greenValue);
analogWrite(BLUE_PIN, 255 - blueValue);
}
}
}
};
void setup() {
// BLE 초기화하고 이름을 "RGB LED Control"로 설정합니다
BLEDevice::init("LDevRGB");
pServer = BLEDevice::createServer();
pService = pServer->createService(SERVICE_UUID);
// RGB 특성 생성 및 설정
pRGBCharacteristic = pService->createCharacteristic(
RGB_CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_WRITE
);
pRGBCharacteristic->setCallbacks(new MyCallbacks());
// Notify/Indicate 특성 생성 및 설정
pCharacteristic = pService->createCharacteristic(
NOTYFY_CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
// Create a BLE Descriptor
pCharacteristic->addDescriptor(new BLE2902());
// 서비스를 서버에 추가
pService->start();
// BLE 광고 시작
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
// 모든 핀을 HIGH로 설정하여 LED를 꺼진 상태로 초기화합니다.
digitalWrite(RED_PIN, HIGH);
digitalWrite(GREEN_PIN, HIGH);
digitalWrite(BLUE_PIN, HIGH);
}
void loop() {
// RGB 값을 16진수 형태로 변환하여 Notify
char hexValue[8];
sprintf(hexValue, "#%02X%02X%02X", redValue, greenValue, blueValue);
//Notify 특성의 값을 hexValue로 설정합니다.
pCharacteristic->setValue(hexValue);
pCharacteristic->notify(); //Notify를 통해 값을 전달합니다.
delay(100); // 알림 간격을 조절할 수 있습니다.
}