1 Commits

Author SHA1 Message Date
dj99k 6ae01a0809 2026-07-22
BLE
UART1(GPIO20(TX), GPIO21(RX)) ---> CSC Check ---> SEND BLE ---> Adroid BLE 수신.
2026-07-22 23:42:16 +09:00
3 changed files with 217 additions and 310 deletions
-155
View File
@@ -1,155 +0,0 @@
#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);
}
-155
View File
@@ -1,155 +0,0 @@
#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);
}
+217
View File
@@ -0,0 +1,217 @@
/*--------------------------------------
2026-07-22 PAYLOAD
----------------------------------------*/
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#define LED_PIN1 8 // 수신 데이터에 따라 제어할 LED ESP32-C3
#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"
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
// UART1 객체 생성 (USB CDC 대신 GPIO20/21 사용)
HardwareSerial MySerial(1);
// --- CSC 계산 관련 함수 ---
char nibbleToAscii(uint8_t nibble) {
return (nibble < 10) ? ('0' + nibble) : ('A' + (nibble - 10));
}
String calcChecksum(String data) {
uint32_t sum = 0;
for (int i = 0; i < data.length(); i++) {
sum += (uint8_t)data[i];
}
uint8_t oneByte = sum & 0xFF;
char csc[3];
csc[0] = nibbleToAscii((oneByte >> 4) & 0x0F);
csc[1] = nibbleToAscii(oneByte & 0x0F);
csc[2] = '\0';
return String(csc);
}
String verifyPacket(String cmd, String len, String payload, String recvCsc) {
String body = cmd + len + payload;
String calcCsc = calcChecksum(body);
return (calcCsc == recvCsc) ? "True" : "Fault";
}
// --- BLE 서버 콜백 ---
class MyServerCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
// --- BLE RX 콜백 ---
class MyCallbacks : public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
String rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0) {
Serial.print("BLE Rx: ");
Serial.println(rxValue);
// UART1로 에코
MySerial.print("Echo to UART: ");
MySerial.println(rxValue);
digitalWrite(LED_PIN1, HIGH); // test LED
delay(500);
digitalWrite(LED_PIN1, LOW);
}
}
};
void setup() {
Serial.begin(115200); //USB to Serial Port
// while (!Serial) { ; }
// UART1 초기화 (GPIO20=RX, GPIO21=TX)
MySerial.begin(115200, SERIAL_8N1, 20, 21);
// LED 핀 설정
pinMode(LED_PIN1, OUTPUT);
pinMode(LED_PIN2, OUTPUT);
digitalWrite(LED_PIN1, HIGH);
digitalWrite(LED_PIN2, HIGH);
// BLE 초기화
BLEDevice::init("MMS UART");
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
pTxCharacteristic->addDescriptor(new BLE2902());
pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
);
pRxCharacteristic->setCallbacks(new MyCallbacks());
pService->start();
pServer->getAdvertising()->start();
Serial.println("Waiting a client connection to notify...");
}
void loop() {
if (deviceConnected) {
digitalWrite(LED_PIN2, LOW);
// UART1에서 들어온 데이터를 BLE로 전송
if (MySerial.available() > 0) {
String uartData = MySerial.readStringUntil('\n');
uartData.trim();
if (uartData.length() > 7) {
Serial.print("UART Rx(BLE SEND): ");
Serial.println(uartData);
// 파싱: CMD(1) + LEN(4) + PAYLOAD + CSC(2)
String cmd = uartData.substring(0, 1);
String len = uartData.substring(1, 5);
String payload = uartData.substring(5, uartData.length() - 2);
String recvCsc = uartData.substring(uartData.length() - 2);
Serial.print("CMD: "); Serial.println(cmd);
Serial.print("LEN: "); Serial.println(len);
Serial.print("PAYLOAD: "); Serial.println(payload);
Serial.print("Recv CSC: "); Serial.println(recvCsc);
String result = verifyPacket(cmd, len, payload, recvCsc);
Serial.print("CSC Verify Result: ");
Serial.println(result);
if (result == "True") {
// LED ON
digitalWrite(LED_PIN1, HIGH);
// BLE Notify 전송 (True일 때만)
pTxCharacteristic->setValue(uartData.c_str());
pTxCharacteristic->notify();
Serial.println("Sent to BLE (Notify).");
delay(500);
digitalWrite(LED_PIN1, LOW);
} else {
// Fault일 경우 데이터 버림, LED OFF
Serial.println("Fault detected, data discarded.");
digitalWrite(LED_PIN1, HIGH);
delay(100);
digitalWrite(LED_PIN1, LOW);
delay(100);
digitalWrite(LED_PIN1, HIGH);
delay(100);
digitalWrite(LED_PIN1, LOW);
}
}
}
} else {
digitalWrite(LED_PIN2, HIGH);
}
if (!deviceConnected && oldDeviceConnected) {
delay(500);
pServer->startAdvertising();
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
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);
}
/*
방금 올려주신 BLE/UART 브리지 코드에 UART 수신 데이터 CSC 검증을 그대로 적용한 버전을 준비했습니다.
이제 시리얼로 입력된 패킷을 <CMD><LEN><PAYLOAD><CSC> 구조로 파싱하고, CSC가 맞으면 "True", 틀리면 "Fault"를 출력하며 LED1 상태도 반영합니다.
CSC 계산 함수(calcChecksum)와 검증 함수(verifyPacket) 추가.
loop()에서 UART 수신 시 패킷을 파싱하고 CSC 검증 수행.
결과 "True"/"Fault"를 시리얼 출력.
LED1은 "True"일 때 ON, "Fault"일 때 OFF.
BLE Notify는 원본 UART 데이터를 그대로 전송.
Fault 일떄는 데이터를 버리고, 다음 데이터 수신하여 true이면 ble로 전송하도록 할 것
-> CSC 검증 후 "Fault"일 경우:
BLE 전송 하지 않음.
데이터 버림.
LED1 OFF.
"True"일 경우:
BLE Notify 전송.
LED1 ON.
*/