Hướng dẫn điều khiển relay bằng điện thoại qua Bluetooth với ESP32

Hướng dẫn dùng Bluetooth Classic của ESP32 trên Arduino IDE: ghép đôi với điện thoại Android, gửi nhận chữ bằng BluetoothSerial và điều khiển module relay bằng lệnh ON, OFF.

ESP32 có sẵn Bluetooth trong chip, nên chỉ cần thêm một module relay là có thể bật tắt thiết bị bằng điện thoại ở cự ly gần mà không cần mạng Wi-Fi hay Internet. Bài viết hướng dẫn dùng Bluetooth Classic của ESP32 trên Arduino IDE: ghép đôi với điện thoại Android, gửi nhận chữ như một Serial Monitor không dây, rồi điều khiển relay bằng các lệnh ON, OFF.

1. Bluetooth trên ESP32

Chip ESP32 hỗ trợ hai kiểu Bluetooth:

  • Bluetooth Classic: kiểu kết nối quen thuộc của loa, tai nghe và các module HC-05, HC-06. Trên ESP32, thư viện BluetoothSerial dùng kiểu này để tạo một cổng nối tiếp không dây: gửi gì bên này, bên kia nhận được y như vậy.
  • Bluetooth Low Energy (BLE): tiết kiệm điện, dùng cho cảm biến và thiết bị đeo. Cách lập trình khác hẳn và không thuộc phạm vi bài này.
Sơ đồ điện thoại Android gửi lệnh ON, OFF qua Bluetooth Classic tới ESP32 để điều khiển module relay, kèm ba bước ghép đôi, kết nối, gửi lệnh
Điện thoại gửi lệnh qua Bluetooth, ESP32 điều khiển relay và trả lời (hình vẽ minh họa).

Hai điều cần biết trước khi bắt đầu:

  • Bluetooth Classic chỉ có trên dòng chip ESP32 gốc, như module ESP32-WROOM-32 trên mạch DevKit V1. Các dòng ESP32-C3, ESP32-S3 chỉ có BLE nên không chạy được chương trình trong bài.
  • Phía điều khiển nên dùng điện thoại Android hoặc máy tính Windows. iPhone không cho ứng dụng thông thường dùng kiểu kết nối nối tiếp của Bluetooth Classic.

2. Linh kiện cần chuẩn bị

3. Chương trình 1: gửi nhận chữ giữa máy tính và điện thoại

Chương trình đầu tiên chưa cần relay. ESP32 làm cầu nối: chữ gõ ở Serial Monitor hiện trên điện thoại và ngược lại.

/*
  PYWORLD.VN - ESP32 Bluetooth Classic: gửi và nhận chữ giữa Serial Monitor và điện thoại
  Chỉ cần mạch ESP32 DevKit V1 (chip ESP32 có Bluetooth Classic)
  Thư viện BluetoothSerial có sẵn trong gói esp32, không cần cài thêm
*/

#include <BluetoothSerial.h>

const char *TEN_BLUETOOTH = "ESP32-PYWORLD";   // Tên hiện ra khi điện thoại dò tìm thiết bị

BluetoothSerial SerialBT;

void setup() {
  Serial.begin(115200);
  delay(500);

  if (!SerialBT.begin(TEN_BLUETOOTH)) {
    Serial.println("Khong khoi dong duoc Bluetooth!");
    while (true) delay(1000);
  }
  Serial.printf("Bluetooth da san sang. Tim thiet bi ten %s tren dien thoai.\n", TEN_BLUETOOTH);
}

void loop() {
  // Chữ gõ ở Serial Monitor được gửi sang điện thoại
  if (Serial.available()) {
    SerialBT.write(Serial.read());
  }
  // Chữ điện thoại gửi tới được in ra Serial Monitor
  if (SerialBT.available()) {
    Serial.write(SerialBT.read());
  }
  delay(5);
}

Chọn board DOIT ESP32 DEVKIT V1, nạp chương trình rồi mở Serial Monitor ở 115200 baud. Khi thấy dòng Bluetooth da san sang, làm tiếp mục 4.

4. Ghép đôi và kết nối từ điện thoại

  1. Trên điện thoại, mở Cài đặt > Bluetooth, bật Bluetooth và dò tìm thiết bị mới.
  2. Chọn thiết bị tên ESP32-PYWORLD rồi xác nhận ghép đôi.
  3. Mở ứng dụng Bluetooth terminal, vào danh sách thiết bị, chọn ESP32-PYWORLD và bấm kết nối.
  4. Gõ vài chữ trên điện thoại rồi gửi: chữ hiện ra ở Serial Monitor. Gõ ở Serial Monitor rồi nhấn Enter: chữ hiện trên điện thoại.

Muốn thử bằng máy tính Windows thay cho điện thoại: ghép đôi với ESP32-PYWORLD trong phần cài đặt Bluetooth, Windows sẽ tạo thêm cổng COM cho kết nối Bluetooth. Mở cổng COM đó bằng một cửa sổ Serial Monitor khác là gửi nhận được.

Đổi tên thiết bị bằng cách sửa hằng TEN_BLUETOOTH. Nếu trong phòng có nhiều mạch cùng chạy, mỗi mạch nên có một tên riêng.

5. Sơ đồ nối module relay

Đấu nối module relay (bản 5 V) với ESP32 DevKit V1
Module relayESP32 DevKit V1Ghi chú
VCCVIN5 V từ cổng USB.
GNDGNDMass chung.
IN1 (hoặc IN ở module 1 kênh)D18 / GPIO18Tín hiệu điều khiển kênh 1.
Sơ đồ nối ESP32 DevKit V1 với module relay 5 V: IN1 nối D18, VCC nối VIN, GND nối GND
Sơ đồ nối ESP32 DevKit V1 với module relay (hình vẽ minh họa): IN1 – D18, VCC – VIN, GND – GND.

Chưa nối tải vào cọc vít ở bước này: tiếng tách của relay và LED của kênh đủ để kiểm tra. Cách đấu tải, ý nghĩa các cọc COM, NO, NC và lưu ý an toàn điện có trong bài ESP32 điều khiển module relay 4 kênh.

6. Chương trình 2: điều khiển relay bằng lệnh ON, OFF

ESP32 đọc từng dòng chữ điện thoại gửi tới. Gặp ON thì đóng relay, OFF thì nhả, dấu ? thì báo trạng thái hiện tại. Module relay trong bài kích ở mức thấp; nếu module của bạn kích mức cao, đổi RELAY_ACTIVE_LOW thành false.

/*
  PYWORLD.VN - ESP32 điều khiển relay bằng lệnh gửi qua Bluetooth Classic
  Module relay bản 5 V: VCC = VIN, GND = GND, IN1 = GPIO18
  Lệnh: ON, OFF hoặc ? (hỏi trạng thái), mỗi lệnh kết thúc bằng ký tự xuống dòng
  Thư viện BluetoothSerial có sẵn trong gói esp32, không cần cài thêm
*/

#include <BluetoothSerial.h>

#define RELAY_PIN 18

// true:  module kích mức thấp (IN = LOW thì relay đóng)
// false: module kích mức cao (IN = HIGH thì relay đóng)
const bool RELAY_ACTIVE_LOW = true;

const char *TEN_BLUETOOTH = "ESP32-PYWORLD";

BluetoothSerial SerialBT;
bool relayDangBat = false;
String lenh;

void datRelay(bool bat) {
  bool muc = RELAY_ACTIVE_LOW ? !bat : bat;
  digitalWrite(RELAY_PIN, muc ? HIGH : LOW);
  relayDangBat = bat;
}

void xuLyLenh(String s) {
  s.trim();
  s.toUpperCase();   // Nhận cả on, On, ON
  if (s.length() == 0) {
    return;
  }

  if (s == "ON") {
    datRelay(true);
    SerialBT.println("OK: relay BAT");
  } else if (s == "OFF") {
    datRelay(false);
    SerialBT.println("OK: relay TAT");
  } else if (s == "?") {
    SerialBT.printf("Relay dang %s\n", relayDangBat ? "BAT" : "TAT");
  } else {
    SerialBT.println("Lenh khong hop le. Dung ON, OFF hoac ?");
  }
  Serial.printf("Nhan lenh: %s -> relay dang %s\n", s.c_str(), relayDangBat ? "BAT" : "TAT");
}

void setup() {
  // Giữ relay tắt khi khởi động: ghi sẵn mức tắt rồi mới bật ngõ ra
  pinMode(RELAY_PIN, INPUT);
  datRelay(false);
  pinMode(RELAY_PIN, OUTPUT);

  Serial.begin(115200);
  delay(500);

  if (!SerialBT.begin(TEN_BLUETOOTH)) {
    Serial.println("Khong khoi dong duoc Bluetooth!");
    while (true) delay(1000);
  }
  Serial.printf("Bluetooth da san sang. Tim thiet bi ten %s tren dien thoai.\n", TEN_BLUETOOTH);
}

void loop() {
  // Gom từng ký tự nhận được thành một dòng lệnh
  while (SerialBT.available()) {
    char kyTu = SerialBT.read();
    if (kyTu == '\n') {
      xuLyLenh(lenh);
      lenh = "";
    } else if (kyTu != '\r' && lenh.length() < 32) {
      lenh += kyTu;
    }
  }
  delay(10);
}

Trong ứng dụng Bluetooth terminal, bật tùy chọn gửi kèm ký tự xuống dòng ở cuối mỗi lệnh, rồi gửi lần lượt ON, ? và OFF:

Hình minh họa màn hình ứng dụng Bluetooth terminal trên điện thoại: gửi lệnh ON, dấu hỏi, OFF và nhận câu trả lời từ ESP32
Gửi lệnh và nhận trả lời trên điện thoại (hình minh họa; giao diện thật tùy ứng dụng).

Cùng lúc đó Serial Monitor trên máy tính ghi lại từng lệnh nhận được:

Hình minh họa Serial Monitor của ESP32 khi nhận các lệnh ON, dấu hỏi và OFF qua Bluetooth
Kết quả mong đợi trên Serial Monitor (hình minh họa theo định dạng in của chương trình).

Nhiều ứng dụng Bluetooth terminal cho gán sẵn lệnh vào nút bấm. Gán ON và OFF vào hai nút là có ngay một bảng điều khiển đơn giản.

7. Giải thích các lệnh chính

  • BluetoothSerial SerialBT: khai báo cổng nối tiếp Bluetooth. Các lệnh available(), read(), write(), println(), printf() dùng giống hệt Serial.
  • SerialBT.begin(TEN_BLUETOOTH): bật Bluetooth với tên thiết bị đã chọn. Hàm trả về false nếu không khởi động được.
  • Vòng while (SerialBT.available()) gom từng ký tự vào biến lenh cho đến khi gặp ký tự xuống dòng '\n', lúc đó mới xử lý cả dòng. Ký tự '\r' được bỏ qua để nhận được cả hai kiểu kết thúc dòng.
  • s.trim() và s.toUpperCase(): bỏ khoảng trắng thừa và đổi sang chữ hoa, nhờ đó on, On, ON đều được chấp nhận.
  • Ba dòng đầu của setup() ghi sẵn mức tắt rồi mới bật ngõ ra, để relay không bị đóng thoáng qua lúc ESP32 khởi động.

8. Lưu ý khi dùng thực tế

  • Tầm xa: khoảng 10 m trong nhà, giảm nhanh khi có tường hoặc vật kim loại che ăng-ten.
  • Bảo mật: ở cấu hình mặc định, ai ở gần cũng có thể ghép đôi và gửi lệnh. Không dùng nguyên chương trình này cho cửa, khóa hay thiết bị cần an toàn.
  • Mất kết nối: relay giữ nguyên trạng thái cuối cùng khi điện thoại ra khỏi tầm. Nếu cần tự tắt khi mất kết nối, kiểm tra SerialBT.hasClient() trong loop().
  • Bộ nhớ chương trình: thư viện Bluetooth chiếm khá nhiều bộ nhớ flash. Khi dùng chung Bluetooth với Wi-Fi mà Arduino IDE báo chương trình quá lớn, chọn board ESP32 Dev Module rồi đổi Tools > Partition Scheme sang Huge APP.
  • Điều khiển từ xa qua mạng: Bluetooth chỉ dùng ở cự ly gần. Muốn điều khiển qua Wi-Fi, xem bài ESP32 làm web server điều khiển relay qua Wi-Fi.

9. Xử lý lỗi thường gặp

  • Lỗi biên dịch nói chip không hỗ trợ Bluetooth Classic: đang chọn board dùng chip ESP32-C3, ESP32-S3 hoặc tương tự. Chọn lại DOIT ESP32 DEVKIT V1 và dùng mạch có module ESP32-WROOM-32.
  • Điện thoại không tìm thấy ESP32-PYWORLD: kiểm tra Serial Monitor đã hiện dòng Bluetooth da san sang chưa; đưa điện thoại lại gần; tắt rồi bật lại Bluetooth của điện thoại. Lưu ý phải dò ở mục Bluetooth của hệ thống, ứng dụng chỉ dành cho BLE sẽ không thấy thiết bị.
  • Ghép đôi được nhưng ứng dụng không kết nối được: ứng dụng chỉ hỗ trợ BLE, hoặc đang có thiết bị khác kết nối với ESP32. Mỗi lúc chỉ một thiết bị kết nối được.
  • Gửi ON mà không có phản hồi: ứng dụng chưa gửi kèm ký tự xuống dòng nên ESP32 vẫn chờ hết dòng. Bật tùy chọn kết thúc dòng LF hoặc CR+LF.
  • Gửi ON thì relay nhả, gửi OFF thì relay đóng: module kích mức cao; đổi RELAY_ACTIVE_LOW thành false.
  • ESP32 tự khởi động lại khi bật Bluetooth hoặc khi relay đóng: nguồn yếu. Dùng cáp USB tốt, cổng USB cấp đủ dòng, hoặc cấp nguồn 5 V riêng cho module relay và nối chung GND.
  • Không nạp được chương trình: dùng cáp USB có truyền dữ liệu, chọn đúng cổng COM và giữ nút BOOT khi IDE dừng ở dòng Connecting...

Xem thêm: ESP32 điều khiển module relay 4 kênh, ESP32 làm web server điều khiển relay qua Wi-Fi và mạch hạ áp LM2596 và MP1584 để cấp nguồn cho ESP32.


Tin tức liên quan

Hướng dẫn làm cân điện tử với ESP32, HX711 và load cell trên Arduino IDE
Hướng dẫn làm cân điện tử với ESP32, HX711 và load cell trên Arduino IDE

7 Lượt xem

Hướng dẫn nối load cell với module HX711 và ESP32 DevKit V1, gá load cell đúng cách, hiệu chuẩn bằng vật đã biết khối lượng và viết chương trình cân trên Arduino IDE.

Hướng dẫn làm đồng hồ Internet với ESP32, NTP và màn hình OLED 0.96 inch
Hướng dẫn làm đồng hồ Internet với ESP32, NTP và màn hình OLED 0.96 inch

5 Lượt xem

Hướng dẫn ESP32 lấy giờ Việt Nam từ Internet bằng NTP trên Arduino IDE, in ra Serial Monitor và làm đồng hồ hiển thị thứ, ngày, giờ trên màn hình OLED 0.96 inch SSD1306.

Hướng dẫn dùng MQTT với ESP32: gửi dữ liệu và điều khiển relay bằng PubSubClient
Hướng dẫn dùng MQTT với ESP32: gửi dữ liệu và điều khiển relay bằng PubSubClient

5 Lượt xem

Hướng dẫn dùng MQTT với ESP32 trên Arduino IDE: broker, topic, publish, subscribe, cài Mosquitto và PubSubClient, gửi dữ liệu và điều khiển module relay qua mạng nội bộ.

Hướng dẫn nạp chương trình cho ESP32 qua Wi-Fi (OTA) bằng Arduino IDE
Hướng dẫn nạp chương trình cho ESP32 qua Wi-Fi (OTA) bằng Arduino IDE

4 Lượt xem

Hướng dẫn bật OTA trên ESP32 bằng thư viện ArduinoOTA có sẵn, nạp chương trình qua Wi-Fi từ Arduino IDE 2.x, đặt mật khẩu và các quy tắc để không mất khả năng cập nhật từ xa.

Hướng dẫn dùng màn hình OLED 0.96 inch SSD1306 với Arduino Nano
Hướng dẫn dùng màn hình OLED 0.96 inch SSD1306 với Arduino Nano

5 Lượt xem

Hướng dẫn nối màn hình OLED 0.96 inch SSD1306 (I2C) với Arduino Nano, cài thư viện Adafruit, hiện chữ nhiều cỡ, vẽ thanh mức theo điện áp và lưu ý về bộ nhớ RAM.

Hướng dẫn đọc ADC trên ESP32 và đo điện áp pin 18650 bằng cầu phân áp
Hướng dẫn đọc ADC trên ESP32 và đo điện áp pin 18650 bằng cầu phân áp

5 Lượt xem

Hướng dẫn đọc điện áp analog bằng ADC của ESP32 trên Arduino IDE, dùng analogReadMilliVolts, làm cầu phân áp đo pin Li-ion 18650 và ước lượng phần trăm pin còn lại.

Hướng dẫn dùng Deep Sleep trên ESP32: tiết kiệm pin, đánh thức bằng timer và nút nhấn
Hướng dẫn dùng Deep Sleep trên ESP32: tiết kiệm pin, đánh thức bằng timer và nút nhấn

5 Lượt xem

Hướng dẫn đưa ESP32 vào Deep Sleep trên Arduino IDE để tiết kiệm pin: các chế độ nguồn, đánh thức bằng timer và nút nhấn, giữ biến trong bộ nhớ RTC và ước tính thời lượng pin.

Hướng dẫn kết nối Wi-Fi trên ESP32: quét mạng, tự kết nối lại, IP tĩnh và phát Wi-Fi riêng
Hướng dẫn kết nối Wi-Fi trên ESP32: quét mạng, tự kết nối lại, IP tĩnh và phát Wi-Fi riêng

4 Lượt xem

Hướng dẫn các thao tác Wi-Fi cần dùng nhất trên ESP32 với Arduino IDE: quét mạng, kết nối có thời gian chờ, xem IP và cường độ sóng, tự kết nối lại, đặt IP tĩnh, phát Wi-Fi riêng.


Bình luận
Đã thêm vào giỏ hàng