#include #include #include #include #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); }