Kết nối không dây

MQTT nhập môn - đưa robot và cảm biến ESP32 lên Internet đúng chuẩn

6 phút đọc05/07/2026HocLapTrinhRobot
MQTT nhập môn - đưa robot và cảm biến ESP32 lên Internet đúng chuẩn

MQTT là giao thức nhắn tin pub/sub chuẩn của IoT. Hiểu broker, topic, QoS qua ví dụ đời thường và code ESP32 publish cảm biến, subscribe lệnh hoàn chỉnh. Trong bài viết này, chúng ta sẽ cùng tìm hiểu chi tiết và ứng dụng thực tế trong robot.

MQTT giải bài toán gì?

Robot phát WiFi điều khiển trong phòng thì web server là đủ. Nhưng kịch bản IoT thật khác hẳn: trạm cảm biến ở nhà kính gửi số liệu về điện thoại đang ở bất kỳ đâu; một dashboard theo dõi 30 thiết bị; bật máy bơm từ xa qua 4G. Các thiết bị không nhìn thấy nhau trực tiếp, mạng chập chờn, thiết bị yếu — HTTP không sinh ra cho việc này.

MQTT (Message Queuing Telemetry Transport) là giao thức nhắn tin siêu nhẹ chuẩn công nghiệp của IoT, thiết kế từ thời đường truyền vệ tinh đắt đỏ: gói tin tối giản, chịu mạng kém, chip yếu chạy tốt. Từ cảm biến hồ cá đến xe Tesla đều có bóng dáng MQTT.

Ba khái niệm cốt lõi qua ví dụ bảng tin lớp học

Broker - bảng tin trung tâm

Mọi tin nhắn đều đi qua broker (máy chủ trung gian) — như bảng tin ở sảnh trường: người viết dán tin lên bảng, người đọc tự đến xem, hai bên không cần gặp nhau, không cần biết mặt nhau, không cần có mặt cùng lúc. Thiết bị chỉ cần biết địa chỉ broker — đây là điều kỳ diệu giải bài toán "hai thiết bị sau hai cái router khác nhau nói chuyện với nhau".

Topic - chuyên mục của bảng tin

Tin nhắn dán vào topic — chuỗi phân cấp bằng dấu gạch chéo:

text
nhakinh/khu-a/nhiet-do
nhakinh/khu-a/do-am
robot/xe01/lenh
robot/xe01/trang-thai/pin

Người đọc subscribe (đăng ký) topic quan tâm; người viết publish (đăng) lên topic. Ký tự đại diện khi subscribe: + thay một cấp (nhakinh/+/nhiet-do — nhiệt độ mọi khu), # thay mọi cấp còn lại (robot/xe01/# — tất cả về xe 01).

QoS - mức cam kết chuyển phát

  • QoS 0: gửi rồi quên — nhanh nhất, chấp nhận rơi gói (số liệu cảm biến gửi mỗi 5 giây, rơi một gói không sao)
  • QoS 1: đảm bảo đến, có thể trùng lặp (lệnh bật bơm)
  • QoS 2: đến đúng một lần — nặng nhất, hiếm khi cần ở mức học tập

Thực hành: trạm cảm biến + nhận lệnh trên ESP32

Thư viện: PubSubClient (Library Manager). Broker thử nghiệm: test.mosquitto.org hoặc broker.hivemq.com (công cộng, miễn phí, KHÔNG riêng tư — chỉ để học).

cpp
#include <WiFi.h>
#include <PubSubClient.h>

const char* WIFI_SSID = "TenWifiNha";
const char* WIFI_PASS = "matkhau";
const char* BROKER    = "test.mosquitto.org";

WiFiClient espClient;
PubSubClient mqtt(espClient);

// nhận lệnh: broker đẩy xuống qua callback
void onMessage(char* topic, byte* payload, unsigned int len) {
  String msg;
  for (unsigned int i = 0; i < len; i++) msg += (char)payload[i];
  Serial.printf("[%s] %s\n", topic, msg.c_str());

  if (String(topic) == "lop9a/robot/lenh") {
    if (msg == "den_bat") digitalWrite(2, HIGH);
    if (msg == "den_tat") digitalWrite(2, LOW);
  }
}

void connectMqtt() {
  while (!mqtt.connected()) {
    // clientId phải KHÁC NHAU giữa các thiết bị
    if (mqtt.connect("esp32-xe01-ngau-nhien-4721")) {
      mqtt.subscribe("lop9a/robot/lenh");
      Serial.println("MQTT da ket noi");
    } else {
      delay(2000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(2, OUTPUT);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) delay(300);
  mqtt.setServer(BROKER, 1883);
  mqtt.setCallback(onMessage);
}

unsigned long lastPublish = 0;

void loop() {
  if (!mqtt.connected()) connectMqtt();   // tự nối lại khi rớt
  mqtt.loop();                            // BẮT BUỘC gọi dày - tim của MQTT

  if (millis() - lastPublish > 5000) {
    float tempC = readTemperature();      // DHT22 như bài cảm biến
    char buf[16];
    dtostrf(tempC, 4, 1, buf);
    mqtt.publish("lop9a/nhakinh/nhiet-do", buf);
    lastPublish = millis();
  }
}

Kiểm chứng không cần viết thêm gì: điện thoại cài app MQTT Dashboard / IoT MQTT Panel, trỏ cùng broker, subscribe lop9a/# — số nhiệt độ hiện lên mỗi 5 giây; tạo nút publish "den_bat" lên lop9a/robot/lenh — LED trên bo sáng. Hai thiết bị cách nhau nghìn km vẫn vậy.

Thiết kế topic tử tế ngay từ đầu

Thói quen đặt topic phân biệt dự án nghiêm túc với demo:

  • Cấu trúc khu-vực/thiết-bị/loại-dữ-liệu: nha/phong-khach/nhiet-do — dashboard tự gom nhóm được
  • Tách kênh lệnh và kênh trạng thái: robot/xe01/lenh (app ghi) với robot/xe01/trang-thai (robot ghi) — không bao giờ chung một topic hai chiều
  • Tiền tố riêng độc nhất khi dùng broker công cộng (lop9a-thcs-xyz/...) — tránh đụng topic người lạ
  • Payload có cấu trúc khi dữ liệu nhiều trường: JSON {"t":28.5,"h":72} với thư viện ArduinoJson

Broker nào cho dự án của bạn?

Lựa chọnChi phíHợp với
test.mosquitto.org / broker.hivemq.comMiễn phí, công cộngBuổi học, thử nghiệm — dữ liệu ai cũng đọc được
HiveMQ Cloud / EMQX Cloud free tierMiễn phí có tài khoản + mật khẩu + TLSDự án cá nhân, KHKT — khuyến nghị chính
Mosquitto tự cài (Raspberry Pi/laptop)Miễn phí, tự quảnPhòng lab trường — chạy LAN không cần Internet
Home Assistant tích hợpMiễn phíHệ nhà thông minh hoàn chỉnh

Lớp học lý tưởng: Mosquitto trên một Raspberry Pi của phòng lab — cả lớp chung broker LAN, không phụ thuộc Internet trường, giáo viên thấy mọi luồng tin bằng lệnh mosquitto_sub -t '#' -v.

Câu hỏi thường gặp

MQTT có điều khiển robot thời gian thực được không?

Lái xe kiểu tay cầm — không nên: đường đi qua broker (thường trên Internet) trễ 100-500 ms và thất thường. MQTT hợp lệnh rời rạc ("tuần tra đi", "về trạm sạc") và telemetry. Lái thời gian thực dùng ESP-NOW hoặc WebSocket cục bộ — xem bài Điều khiển robot từ xa ở mục Kiến thức.

Vì sao thiết bị của tôi cứ tự rớt kết nối MQTT liên tục?

Nghi phạm số một: hai thiết bị trùng clientId — broker đá con này để nhận con kia, hai bên đá nhau vòng lặp. Mỗi thiết bị một clientId duy nhất (thêm số ngẫu nhiên/MAC vào tên). Nghi phạm hai: quên gọi mqtt.loop() thường xuyên khiến broker coi là chết (quá keepalive).

Dữ liệu MQTT có riêng tư không?

Trên broker công cộng: hoàn toàn không — ai subscribe # đọc được tất cả. Mức tối thiểu cho dữ liệu thật: broker có tài khoản/mật khẩu + TLS (cổng 8883, WiFiClientSecure). Không bao giờ đẩy vị trí nhà, mật khẩu, ảnh lên broker công cộng.

Retained message và Last Will là gì, có cần không?

Hai tính năng nhỏ mà chuyên nghiệp: retained — broker giữ tin cuối của topic, dashboard mở sau vẫn thấy trạng thái hiện tại thay vì màn hình trống; Last Will — broker tự đăng "thiết bị offline" khi thiết bị rớt đột ngột. Dùng cả hai cho topic trạng thái là dấu hiệu của người thiết kế IoT có nghề.

Tài nguyên tải về

Tải bản PDF của bài viết để in giáo án hoặc gửi trước cho học viên.

Tải PDF
Chia sẻ bài viết