Files
esp32/BLE_Serial_rx_tx.ino
T
2026-07-18 01:02:30 +09:00

156 lines
5.0 KiB
Arduino

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#define LED_PIN1 8 // 수신 데이터에 따라 제어할 LED
#define LED_PIN2 7 // BLE 연결 상태 표시 LED
BLEServer *pServer = NULL;
BLECharacteristic *pTxCharacteristic; // ESP32 -> Central (Notify)
BLECharacteristic *pRxCharacteristic; // Central -> ESP32 (Write)
bool deviceConnected = false;
bool oldDeviceConnected = false;
// Nordic UART UUID 세트 (원본 블로그와 동일)
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" // Central -> ESP32
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" // ESP32 -> Central
// 서버 콜백: 연결 / 해제 상태 갱신
class MyServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
// Rx 콜백: Central에서 보낸 데이터를 수신해서 UART와 LED에 반영
class MyCallbacks : public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
// Arduino String 타입으로 받기 (ESP32 BLE 예제와 동일)
String rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0) {
Serial.print("BLE Rx: ");
Serial.println(rxValue);
digitalWrite(LED_PIN1, LOW);
/*
// 첫 글자로 LED 제어 (원본 예제와 같은 방식)
char cmd = rxValue[0]; // char cmd = rxValue; -> rwValue[0];
if (cmd == 'a') {
digitalWrite(LED_PIN1, LOW); // 예: LED ON
} else if (cmd == 'b') {
digitalWrite(LED_PIN1, HIGH); // 예: LED OFF
}
*/
// 받은 데이터를 그대로 UART로 에코 (양방향 브리지)
Serial.print("Echo to UART: ");
Serial.println(rxValue);
digitalWrite(LED_PIN1, HIGH);
}
}
};
void setup() {
// UART 초기화
Serial.begin(115200);
while (!Serial) {
; // USB 시리얼 준비 대기 (PC 연결 환경에 따라 생략 가능)
}
// LED 핀 설정 (원본 글과 동일 핀)
pinMode(LED_PIN1, OUTPUT);
pinMode(LED_PIN2, OUTPUT);
digitalWrite(LED_PIN1, HIGH); // 초기 OFF
digitalWrite(LED_PIN2, HIGH); // 초기 OFF (연결 안 된 상태 표시)
// 1) BLE Device 생성 (장치 이름 설정)
BLEDevice::init("ECPC3 UART");
// 2) BLE Server 생성 및 콜백 등록
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// 3) BLE Service 생성
BLEService *pService = pServer->createService(SERVICE_UUID);
// 4) TX Characteristic 생성 (Notify)
pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
pTxCharacteristic->addDescriptor(new BLE2902()); // Client에서 Notify 활성화용
// 5) RX Characteristic 생성 (Write)
pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
);
pRxCharacteristic->setCallbacks(new MyCallbacks()); // 수신 처리 콜백 연결
// 6) Service 시작
pService->start();
// 7) Advertising 시작 (스캔 가능하게)
pServer->getAdvertising()->start();
Serial.println("Waiting a client connection to notify...");
}
void loop() {
// BLE 연결 상태에 따라 LED2 제어 및 통신 처리
if (deviceConnected) {
digitalWrite(LED_PIN2, LOW); // 연결됨 표시
// UART에서 들어온 데이터를 읽어서 BLE로 전송 (양방향: UART -> BLE)
if (Serial.available() > 0) {
String uartData = Serial.readStringUntil('\n'); // 한 줄 단위로 읽기
uartData.trim(); // 앞뒤 공백 제거
if (uartData.length() > 0) {
Serial.print("UART Rx: ");
Serial.println(uartData);
// BLE TX characteristic에 값 설정 후 Notify
pTxCharacteristic->setValue(uartData.c_str());
pTxCharacteristic->notify();
Serial.println("Sent to BLE (Notify).");
}
}
} else {
digitalWrite(LED_PIN2, HIGH); // 연결 안 됨 표시
}
// disconnect 처리: 끊어진 후 다시 광고 시작 (원본 예제 패턴)
if (!deviceConnected && oldDeviceConnected) {
delay(500); // BLE 스택 정리 시간
pServer->startAdvertising(); // 광고 재시작
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// connect 처리: 최초 연결 시 한 번만 처리할 내용이 있다면 여기에
if (deviceConnected && !oldDeviceConnected) {
// 연결 직후에만 실행할 코드가 있으면 여기에 추가
digitalWrite(LED_PIN1, HIGH);
delay(500);
digitalWrite(LED_PIN1, LOW);
delay(500);
digitalWrite(LED_PIN1, HIGH);
delay(500);
digitalWrite(LED_PIN1, LOW);
oldDeviceConnected = deviceConnected;
}
// 너무 자주 패킷을 보내면 스택이 혼잡해질 수 있으므로, 짧게 딜레이
delay(10);
}