아두이노 나노 ESP32 블루투스 채팅 예제 BLE를 통한 양방향 메시징 튜토리얼

개요

이 예제는 DIYables Bluetooth STEM 앱을 통한 BLE(블루투스 로우 에너지)를 사용하여 Arduino Nano ESP32에 양방향 텍스트 메시징 인터페이스를 구현합니다. 실시간으로 아두이노와 스마트폰 간에 텍스트 메시지를 주고받으세요. 명령줄 인터페이스, 텍스트를 통한 원격 제어, 시리얼 브리지, 대화형 디버깅에 적합합니다.

참고: Arduino Nano ESP32는 BLE만 지원하며 클래식 블루투스는 지원하지 않습니다. DIYables 블루투스 앱은 BLE를 통해 Android와 iOS 모두에서 작동합니다.

아두이노 나노 ESP32 블루투스 채팅 예제 - BLE를 통한 양방향 메시징 튜토리얼

기능

  • 양방향 메시징: 실시간으로 텍스트 메시지 송수신
  • 명령 처리: 앱에서 수신한 텍스트 명령 처리
  • 시리얼 브리지: 시리얼 모니터와 블루투스 간 메시지 전달
  • 커스텀 응답: 에코 또는 처리된 데이터로 자동 응답
  • Android 및 iOS 지원: BLE는 두 플랫폼 모두 호환
  • 페어링 불필요: BLE는 수동 페어링 없이 연결
  • 저전력: BLE는 클래식 블루투스보다 적은 전력 소비

필요한 하드웨어

1×아두이노 나노 ESP32 쿠팡 | 아마존
1×USB 케이블 타입-A to 타입-C (USB-A PC용) 쿠팡 | 아마존
1×USB 케이블 타입-C to 타입-C (USB-C PC용) 아마존
1×(추천) 아두이노 나노용 스크루 터미널 확장 보드 쿠팡 | 아마존
1×(추천) 아두이노 나노용 브레이크아웃 확장 보드 쿠팡 | 아마존
1×(추천) 아두이노 나노 ESP32용 전원 분배기 쿠팡 | 아마존
공개: 이 포스팅 에 제공된 일부 링크는 아마존 제휴 링크입니다. 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

Arduino Nano ESP32 코드

빠른 시작

  • Arduino Nano ESP32가 처음이신가요? 아두이노 나노 ESP32 - 소프트웨어 설치를 참조하세요.
  • USB로 Arduino Nano ESP32를 컴퓨터에 연결하세요.
  • Arduino IDE를 열어주세요.
  • Arduino Nano ESP32 보드와 올바른 COM 포트를 선택하세요.
  • 왼쪽 사이드바에서 라이브러리 아이콘을 클릭하세요.
  • "DIYables Bluetooth"를 검색하고 DIYables의 DIYables Bluetooth 라이브러리를 선택하세요.
  • 설치를 클릭하세요.
아두이노 나노 ESP32 diyaBLEs 블루투스 라이브러리
  • 종속성 설치 메시지가 나타나면 모두 설치를 클릭하세요.
아두이노 나노 ESP32 diyaBLEs 블루투스 dependency

BLE 코드

  • Arduino IDE에서 파일 예제 DIYables Bluetooth ArduinoBLE_Chat을 열거나, 코드를 편집기에 붙여 넣으세요.
/* * DIYables Bluetooth Library - ESP32 BLE Chat Example * Works with DIYables Bluetooth STEM app on Android and iOS * * This example demonstrates the Bluetooth Chat feature: * - Two-way text messaging via Bluetooth * - Receive messages from mobile app * - Send messages to mobile app * * Tutorial: https://diyables.io/bluetooth-app * Author: DIYables */ #include <DIYables_BluetoothServer.h> #include <DIYables_BluetoothChat.h> #include <platforms/DIYables_Esp32BLE.h> // BLE Configuration const char* DEVICE_NAME = "ESP32BLE_Chat"; const char* SERVICE_UUID = "19B10000-E8F2-537E-4F6C-D104768A1214"; const char* TX_UUID = "19B10001-E8F2-537E-4F6C-D104768A1214"; const char* RX_UUID = "19B10002-E8F2-537E-4F6C-D104768A1214"; // Create Bluetooth instances DIYables_Esp32BLE bluetooth(DEVICE_NAME, SERVICE_UUID, TX_UUID, RX_UUID); DIYables_BluetoothServer bluetoothServer(bluetooth); // Create Chat app instance DIYables_BluetoothChat bluetoothChat; // Variables for periodic messages unsigned long lastMessageTime = 0; const unsigned long MESSAGE_INTERVAL = 10000; // Send message every 10 seconds int messageCount = 0; void setup() { Serial.begin(115200); delay(1000); Serial.println("DIYables Bluetooth - ESP32 BLE Chat Example"); // Initialize Bluetooth server with platform-specific implementation bluetoothServer.begin(); // Add chat app to server bluetoothServer.addApp(&bluetoothChat); // Set up connection event callbacks bluetoothServer.setOnConnected([]() { Serial.println("Bluetooth connected!"); bluetoothChat.send("Hello! ESP32 BLE is ready to chat."); }); bluetoothServer.setOnDisconnected([]() { Serial.println("Bluetooth disconnected!"); messageCount = 0; }); // Set up callback for received chat messages bluetoothChat.onChatMessage([](const String& message) { Serial.print("Received: "); Serial.println(message); // Echo the message back String response = "Echo: "; response += message; bluetoothChat.send(response); // Custom command handling if (message.equalsIgnoreCase("ping")) { bluetoothChat.send("pong!"); } else if (message.equalsIgnoreCase("status")) { bluetoothChat.send("ESP32 BLE is running normally"); } else if (message.equalsIgnoreCase("time")) { String timeMsg = "Uptime: "; timeMsg += String(millis() / 1000); timeMsg += " seconds"; bluetoothChat.send(timeMsg); } else if (message.equalsIgnoreCase("heap")) { String heapMsg = "Free heap: "; heapMsg += String(ESP.getFreeHeap()); heapMsg += " bytes"; bluetoothChat.send(heapMsg); } }); Serial.println("Waiting for Bluetooth connection..."); Serial.println("Type 'ping', 'status', 'time', or 'heap' in the app to test commands"); } void loop() { bluetoothServer.loop(); if (bluetooth.isConnected() && millis() - lastMessageTime >= MESSAGE_INTERVAL) { lastMessageTime = millis(); messageCount++; String statusMsg = "Status update #"; statusMsg += String(messageCount); statusMsg += " - All systems operational"; bluetoothChat.send(statusMsg); Serial.print("Sent: "); Serial.println(statusMsg); } if (Serial.available()) { String serialMsg = Serial.readStringUntil('\n'); serialMsg.trim(); if (serialMsg.length() > 0 && bluetooth.isConnected()) { bluetoothChat.send(serialMsg); Serial.print("Sent from Serial: "); Serial.println(serialMsg); } } delay(10); }
  • 업로드를 클릭하여 스케치를 보드에 플래시하세요.
  • 시리얼 모니터를 열어주세요.
  • 시리얼 모니터 출력은 다음과 같아야 합니다:
Newbiely | Arduino IDE 2.3.8
──
File
Edit
Sketch
Tools
Help
Arduino Nano ESP32
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'Arduino Nano ESP32' on 'COM15')
New Line
9600 baud
DIYables Bluetooth - Chat Example Waiting for Bluetooth connection...
Ln 11, Col 1
Arduino Nano ESP32 on COM15
2

모바일 앱

  • 스마트폰에 DIYables 블루투스 앱을 설치하세요: Android | iOS

참고: DIYables 블루투스 앱은 BLE를 통해 Android와 iOS 모두에서 작동합니다. 수동 페어링이 필요 없습니다.

  • DIYables 블루투스 앱을 실행하세요.
  • 처음 실행 시 다음 권한을 허용하세요:
    • 근처 기기 (Android 12+) / 블루투스 (iOS) — 블루투스 기기 스캔 및 연결에 필요
    • 위치 (Android 11 이하에만 해당) — 구형 Android 버전에서 BLE 스캔에 필요
  • 기기에서 블루투스가 활성화되어 있는지 확인하세요.
  • 홈 화면에서 연결을 탭하세요. 앱이 BLE 기기를 스캔합니다.
diyaBLEs 블루투스 앱 - 스캔 버튼이 있는 홈 화면
  • 스캔 결과에서 "Arduino_Chat"을 탭하세요.
  • 연결 후 홈 화면으로 돌아가 채팅 앱을 여세요.
diyaBLEs 블루투스 앱 - 채팅 앱이 있는 홈 화면

홈 화면의 설정 아이콘을 탭하여 앱을 표시하거나 숨길 수 있습니다. 자세한 내용은 DIYables 블루투스 앱 사용 설명서를 참조하세요.

  • 채팅 입력 필드에 메시지를 입력하고 전송 버튼을 탭하세요.
diyaBLEs 블루투스 앱 - 채팅 화면

Arduino IDE의 시리얼 모니터를 다시 확인하면 다음과 같이 표시됩니다:

Newbiely | Arduino IDE 2.3.8
──
File
Edit
Sketch
Tools
Help
Arduino Nano ESP32
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'Arduino Nano ESP32' on 'COM15')
New Line
9600 baud
Bluetooth connected! Received: Hello
Ln 11, Col 1
Arduino Nano ESP32 on COM15
2
  • 아두이노가 메시지를 에코하고, 응답이 앱 채팅에 표시됩니다.

창의적인 커스터마이징 - 프로젝트에 코드 적용하기

채팅 메시지 처리

onChatMessage() 콜백을 사용하여 앱에서 수신한 메시지를 처리하세요. 필요에 따라 커스텀 명령어를 정의하면 아두이노가 그에 맞게 응답합니다:

bluetoothChat.onChatMessage([](const String& message) { Serial.print("Received: "); Serial.println(message); // Echo the message back String response = "Echo: "; response += message; bluetoothChat.send(response); // Handle custom commands if (message.equalsIgnoreCase("ping")) { bluetoothChat.send("pong!"); } else if (message.equalsIgnoreCase("status")) { bluetoothChat.send("Arduino is running normally"); } else if (message.equalsIgnoreCase("time")) { String timeMsg = "Uptime: " + String(millis() / 1000) + " seconds"; bluetoothChat.send(timeMsg); } else { bluetoothChat.send("Unknown command: " + message); } });

각 명령에 대해 추가 else if 블록을 작성하세요. 예를 들어, 핀 제어에 LED_ON / LED_OFF를 사용하거나 센서 읽기를 트리거하려면 READ를 사용하세요.

아두이노에서 메시지 전송

// Send a text message to the app bluetoothChat.send("Hello from Arduino!"); // Send sensor reading float temp = readTemperature(); bluetoothChat.send("Temperature: " + String(temp, 1) + " °C");

시리얼-블루투스 브리지

시리얼 모니터와 블루투스 간에 메시지를 전달합니다:

// In loop(): if (Serial.available()) { String serialMsg = Serial.readStringUntil('\n'); serialMsg.trim(); if (serialMsg.length() > 0 && bluetooth.isConnected()) { bluetoothChat.send(serialMsg); Serial.print("Sent from Serial: "); Serial.println(serialMsg); } }

연결 이벤트 처리

bluetoothServer.setOnConnected([]() { Serial.println("Bluetooth connected!"); bluetoothChat.send("Hello! Arduino is ready to chat."); }); bluetoothServer.setOnDisconnected([]() { Serial.println("Bluetooth disconnected!"); });

채팅 사용 방법

앱 인터페이스

DIYables 블루투스 앱의 채팅 앱은 다음을 제공합니다:

  • 메시지 목록: 타임스탬프와 함께 전송 및 수신 메시지 표시
  • 텍스트 입력: 아두이노에 전송할 메시지 입력
  • 전송 버튼: 탭하여 메시지 전송

통신 흐름

  1. 앱에서 메시지 입력 → 아두이노가 onChatMessage() 콜백을 통해 수신
  2. 아두이노가 메시지를 처리하고 필요 시 bluetoothChat.send()로 응답
  3. 응답이 앱 채팅 창에 표시됨

프로그래밍 예제

릴레이 제어 명령 핸들러

const int RELAY_PIN = 7; bluetoothChat.onChatMessage([](const String& message) { String cmd = message; cmd.toUpperCase(); if (cmd == "ON") { digitalWrite(RELAY_PIN, HIGH); bluetoothChat.send("Relay turned ON"); } else if (cmd == "OFF") { digitalWrite(RELAY_PIN, LOW); bluetoothChat.send("Relay turned OFF"); } else if (cmd == "STATUS") { int state = digitalRead(RELAY_PIN); bluetoothChat.send("Relay is " + String(state ? "ON" : "OFF")); } else { bluetoothChat.send("Commands: ON, OFF, STATUS"); } });

센서 쿼리 시스템

bluetoothChat.onChatMessage([](const String& message) { String cmd = message; cmd.toUpperCase(); if (cmd == "TEMP") { float temp = readTemperature(); bluetoothChat.send("Temperature: " + String(temp, 1) + " °C"); } else if (cmd == "LIGHT") { int light = analogRead(A0); int percent = map(light, 0, 1023, 0, 100); bluetoothChat.send("Light level: " + String(percent) + "%"); } else if (cmd == "ALL") { bluetoothChat.send("=== Sensor Report ==="); bluetoothChat.send("Temp: " + String(readTemperature(), 1) + " °C"); bluetoothChat.send("Light: " + String(map(analogRead(A0), 0, 1023, 0, 100)) + "%"); bluetoothChat.send("Uptime: " + String(millis() / 1000) + "s"); } else { bluetoothChat.send("Commands: TEMP, LIGHT, ALL"); } });

주기적 상태 업데이트

unsigned long lastMessageTime = 0; const unsigned long MESSAGE_INTERVAL = 10000; // Every 10 seconds int messageCount = 0; void loop() { bluetoothServer.loop(); if (bluetooth.isConnected() && millis() - lastMessageTime >= MESSAGE_INTERVAL) { lastMessageTime = millis(); messageCount++; String statusMsg = "Status #" + String(messageCount) + " - All systems OK"; bluetoothChat.send(statusMsg); } delay(10); }

고급 프로그래밍 기법

다중 단어 명령 파싱

bluetoothChat.onChatMessage([](const String& message) { // Parse "SET PIN 13 HIGH" style commands if (message.startsWith("SET PIN ")) { String rest = message.substring(8); int spaceIdx = rest.indexOf(' '); if (spaceIdx > 0) { int pin = rest.substring(0, spaceIdx).toInt(); String state = rest.substring(spaceIdx + 1); state.toUpperCase(); pinMode(pin, OUTPUT); if (state == "HIGH") { digitalWrite(pin, HIGH); bluetoothChat.send("Pin " + String(pin) + " set HIGH"); } else if (state == "LOW") { digitalWrite(pin, LOW); bluetoothChat.send("Pin " + String(pin) + " set LOW"); } } } });

타임스탬프가 있는 채팅 로거

bluetoothChat.onChatMessage([](const String& message) { unsigned long seconds = millis() / 1000; String timestamp = "[" + String(seconds / 3600) + ":" + String((seconds % 3600) / 60) + ":" + String(seconds % 60) + "] "; Serial.println(timestamp + "RX: " + message); // Log and acknowledge bluetoothChat.send(timestamp + "Received: " + message); });

문제 해결

일반적인 문제

1. 앱에서 기기가 보이지 않음

  • 보드에 전원이 공급되고 스케치가 업로드되었는지 확인하세요
  • 스마트폰에서 블루투스가 활성화되어 있는지 확인하세요
  • Android 11 이하에서는 위치 서비스도 활성화하세요
  • 스마트폰의 블루투스를 재시작해 보세요

2. 아두이노가 메시지를 수신하지 못함

  • 앱의 블루투스 연결 상태를 확인하세요
  • onChatMessage 콜백이 올바르게 등록되었는지 확인하세요
  • 오류 메시지를 시리얼 모니터에서 확인하세요

3. 앱에 아두이노 응답이 표시되지 않음

  • bluetoothChat.send()가 호출되고 있는지 확인하세요
  • 메인 루프에 bluetoothServer.loop()가 있는지 확인하세요
  • bluetooth.isConnected()로 연결 상태를 확인하세요

4. 시리얼 모니터에 깨진 텍스트가 표시됨

  • 시리얼 모니터의 보드율이 Serial.begin(9600)과 일치하는지 확인하세요
  • Arduino IDE에서 올바른 보드가 선택되어 있는지 확인하세요

5. 연결이 자주 끊김

  • 아두이노와의 거리를 줄이세요
  • 다른 BLE 기기의 간섭을 확인하세요
  • 안정적인 USB 전원 공급을 확보하세요

6. 업로드 실패 또는 보드 인식 불가

  • 보드 매니저를 통해 최신 Arduino Nano ESP32 보드 패키지를 설치하세요
  • 다른 USB 케이블이나 포트를 시도해 보세요
  • 업로드 전에 리셋 버튼을 눌러보세요

프로젝트 아이디어

통신

  • 홈 자동화를 위한 텍스트 명령 인터페이스
  • 무선 디버깅을 위한 시리얼-블루투스 브리지
  • 원격 센서 쿼리 시스템
  • 대화형 퀴즈 또는 게임

제어 시스템

  • 음성-텍스트 릴레이 제어
  • 다중 기기 명령 라우터
  • 채팅 명령을 통한 설정 관리자
  • 펌웨어 버전 보고기

로깅 및 모니터링

  • 타임스탬프가 있는 이벤트 로거
  • 알람 알림 시스템
  • 상태 보고서 생성기
  • 진단 챗봇

다른 블루투스 앱과의 통합

블루투스 모니터와 결합

채팅으로 명령을, 모니터로 연속 출력을 처리:

bluetoothChat.onChatMessage([](const String& message) { if (message == "START") { monitoring = true; bluetoothChat.send("Monitoring started"); } else if (message == "STOP") { monitoring = false; bluetoothChat.send("Monitoring stopped"); } }); // In loop: if (monitoring) { bluetoothMonitor.send("Sensor: " + String(analogRead(A0))); }

블루투스 테이블과 결합

채팅 명령으로 테이블에 표시할 데이터를 제어:

bluetoothChat.onChatMessage([](const String& message) { if (message == "REFRESH") { updateTableValues(); bluetoothChat.send("Table refreshed"); } });

다음 단계

블루투스 채팅 예제를 완료한 후 다음을 살펴보세요:

  1. 블루투스 모니터 — 단방향 상태 메시지 스트리밍
  2. 블루투스 슬라이더 — 아날로그 값 제어
  3. 블루투스 테이블 — 구조화된 데이터 표시
  4. 블루투스 다중 앱 — 채팅과 다른 앱 위젯 결합

지원

추가 도움이 필요하시면:

  • API 레퍼런스 문서를 확인하세요
  • DIYables 튜토리얼을 방문하세요
  • 아두이노 커뮤니티 포럼