BLE란?
Blue tooth Low Energy의 약자로, 우리가 주로 사용하는 스마트폰, 웨어러블 기기 등과 같은 저전력의 디바이스간의 통신을 위해 디자인된 무선통신 방법이라고 할 수 있다.
블루투스와 동일한 2.4Ghz대의 주파수 대역을 사용하지만, 전력소비를 최소화해 배터리 수명을 지원한다.
핵심적인 동작원리는 Advertising과 Connection이다. Advertising 디바이스는 주변에 자신의 존재를 알리고, Connection에서는 실제 데이터 교환을 수행한다.
위와 같은 계층구조를 가지며, 위의 Stack을 거치며 Packet 전송, 분석하게 된다. 특히 GAP 프로토콜은 서로 다른 제조사가 만든 BLE끼리 호환할 수 있도록 하는 호환성을 제공하는 역할을 한다.
BLE에서도 Central 기기와 Slave기기로 분류할 수 잇는데, Central기기는 주변의 device와 Connection을 하기위해 Advertise Signal을 주기적으로 스캔하고, 연결을 요청하는 기기이다.
반대로 Slave기기는 Advertise signal을 주기적으로 보내어 Central Device가 연결 request를 보내는 것을 기다린다.
아두이노로 진행한 실습은 WiFi때 처럼 Client와 Server를 지정해 data를 송수신하여, LED를 제어하는 실습을 진행하였다.
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEServer.h>
#define bleServerName " "
static BLEUUID SERVICE_UUID ("0e2a85f7-5e02-425a-9209-c7798eedeaa6");
static BLEUUID CHARACTERISTIC_UUID ("f1141bc3-3a04-4cdf-8b92-3477677a3f10");
// BLE Server에서 설정한 bleservername
// BLE server와 동일한 BLEUUID
static BLEAddress *pServerAddress;
static BLEAdvertisedDevice* myDevice;
static boolean doConnect =false;
static boolean connected =false;
static BLERemoteCharacteristic* gRemoteCharacteristic;
void setup() {
//Start serial communication
Serial.begin(115200);
Serial.println("Starting Arduino BLE Client application...");
BLEDevice::init("");
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true);
pBLEScan->start(30);
pinMode(15, OUTPUT);
}
void loop() {
if (doConnect ==true) {
if (connectToServer(*pServerAddress)) {
Serial.println("We are now connected to the BLE Server.");
connected =true;
}
else {
Serial.println("We have failed to connect to the server; Restart your device to scan for nearby BLE server again.");
}
doConnect =false;
}
if(connected)
{
std::string value = gRemoteCharacteristic -> readValue();
Serial.print("value was:");
Serial.println(value.c_str());
if(!strcmp(value.c_str(),"ON")){
digitalWrite(15,HIGH);
Serial.println("Write value is ON");
}
else if(!strcmp(value.c_str(),"OFF"))
{
digitalWrite(15,LOW);
Serial.println("Write value is OFF");
}
}
delay(1000);
}
위는 Client 측의 코드의 일부이다.
Service UUID와 Characteristic UUID가 존재하는데, Characteristicsㄴ는 Service에 종속되는 개념으로 하나의 데이터 만들 포괄하게 된다. 하나의 service가 하나의 Characteristics를 갖는 간단한 구조를 가지게 된다.
Service UUID는 마치 IP 처럼 다른 Server와 충돌하면 정상적으로 기능하지 못하기 때문에 고유한 값을 부여할 필요가잇다.
다시말해 Service UUID는 서버 주소, Characteristic UUID는 문자열 전송을 위한 ID라고 생각하면된다.
Client가 위에서 설명한 Central Device라고 볼 수 있고, Server가 보내는 Advertising을 Advertise call back을 통해 스캔하여 접속한다.
루프에서는 접속하여 Advetsing되는 값을 받아와서 이 문자열이 "OFF" / "ON"을 확인하여 LED를 키고, 끌 수 있다.
void setup() {
Serial.begin(115200);
pinMode(2,INPUT);
BLEDevice::init("ESP_Recette");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
서버를 만들고 UUID를 지정하여 클라이언트가 접속할 수 있도록 한다.
pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE);
pCharacteristic->setCallbacks(new MyCallbacks());
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
}
void loop() {
val1 = digitalRead(2);
if(val1 == 0){
pCharacteristic->setValue("ON");
Serial.println("on sent"); // 떼면 1, 콜백할 때마다 갱신됨
}
else{
pCharacteristic->setValue("OFF"); //Serial.println("off sent");
}
pCharacteristic->notify();
delay(100);
}
Server에서는 Server를 만들고, Characteristic도 생성하여, 콜백함수를 통해 새로운 문자열이 등록되면, 그값을 notify하는 것으로 작동하도록 하였다.
'아두이노' 카테고리의 다른 글
[아두이노] WiFi 통신 (0) | 2024.08.06 |
---|---|
[아두이노]SPI 통신 (0) | 2024.08.06 |
[아두이노] I2C 통신 (0) | 2024.08.05 |
[아두이노] UART 통신 (0) | 2024.08.05 |
[아두이노] PWM으로 LED 밝기 제어 (0) | 2024.08.05 |