สอนใช้งาน ESP32 กับ MQTT: เชื่อมต่อ IoT แบบ Real-time

เรียนรู้วิธีเชื่อมต่อ ESP32 กับ MQTT Broker เพื่อส่งและรับข้อมูลแบบ Real-time พร้อมโค้ดตัวอย่างและการนำไปใช้กับ CynoIoT Platform

📅 6 มีนาคม 2026⏱️ 15 นาที🎯 ระดับเริ่มต้น

MQTT คืออะไร?

MQTT (Message Queuing Telemetry Transport) คือโปรโตคอลสื่อสารแบบ Lightweight ที่ออกแบบมาสำหรับ IoT devices โดยเฉพาะ ทำงานบน TCP/IP และใช้รูปแบบ Publish/Subscribe ในการส่งข้อมูล

MQTT เป็นที่นิยมเพราะ:

  • 🚀 เบาและรวดเร็ว - ใช้ bandwidth น้อยมาก
  • 📡 Real-time - ส่งข้อมูลได้ทันทีทันใด
  • 🔌 Support QoS - รับประกันการส่งข้อมูล (Quality of Service)
  • 🌐 Easy Integration - เชื่อมต่อกับ Cloud และ Local Server ได้ง่าย
  • 💡 Low Power - เหมาะกับอุปกรณ์ที่ใช้แบตเตอรี่

💡 ตัวอย่างการใช้งาน: ส่งค่าอุณหภูมิจาก ESP32 ไปยัง Server, ควบคุมหลอดไฟผ่านมือถือ, รับแจ้งเตือนจากเซ็นเซอร์, เชื่อมต่อกับ CynoIoT Platform

หลักการทำงานของ MQTT

ส่วนประกอบหลัก

📡 MQTT Broker

Server ที่ทำหน้าที่เป็นตัวกลางรับและส่งข้อมูลระหว่าง devices

📤 Publisher

Device ที่ส่งข้อมูล (เช่น ESP32 ส่งค่าอุณหภูมิ)

📥 Subscriber

Device ที่รับข้อมูล (เช่น มือถือ, Web Dashboard)

Topic และ Message

Topic คือ "ช่องทาง" ที่ใช้ส่งข้อมูล เหมือน "หมวดหมู่" ที่ devices ใช้รู้ว่าจะส่ง/รับข้อมูลเรื่องอะไร

ตัวอย่าง Topic:

  • home/livingroom/temperature - อุณหภูมิห้องนั่งเล่น
  • home/bedroom/light - ไฟห้องนอน
  • sensor/# - ทุกเซ็นเซอร์ (Wildcard)

Quality of Service (QoS)

ระดับชื่อคำอธิบาย
0At most onceส่งไปเลย ไม่รอ ACK (เร็วสุด)
1At least onceรับประกันส่งถึง (มีซ้ำได้)
2Exactly onceรับประกันส่งครั้งเดียว (ช้าสุด)

* สำหรับ IoT ส่วนใหญ่ใช้ QoS 0 หรือ 1 เพียงพอ

อุปกรณ์ที่ต้องการ

Hardware

  • ESP32 Development Board (NodeMCU, Wemos, หรือ Generic)
  • USB Cable สำหรับ programming
  • (Optional) DHT11/DHT22 Sensor สำหรับทดสอบ
  • (Optional) Relay Module สำหรับควบคุมไฟ

Software

  • Arduino IDE (version 1.8.x หรือ 2.x)
  • MQTT Broker (ใช้ฟรีจาก HiveMQ, EMQX หรือ Local Server)
  • MQTT Client สำหรับทดสอบ (MQTT Explorer, MQTT.fx)

🔧 Tip: สำหรับการทดสอบ สามารถใช้ Public MQTT Broker ฟรีได้ เช่น:

  • broker.hivemq.com (Port 1883)
  • test.mosquitto.org (Port 1883)
  • broker.emqx.io (Port 1883)

ติดตั้ง Library

วิธีที่ 1: ติดตั้งผ่าน Arduino IDE Library Manager

  1. เปิด Arduino IDE
  2. ไปที่ Sketch → Include Library → Manage Libraries
  3. ค้นหา "PubSubClient"
  4. กด Install เวอร์ชันล่าสุด

วิธีที่ 2: ติดตั้งผ่าน Terminal

# สำหรับ Arduino IDE 2.x
# จะติดตั้งอัตโนมัติเมื่อ include ในโค้ด

ตรวจสอบการติดตั้ง

สร้างไฟล์ใหม่แล้วลอง include library:

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

void setup() {
  // ถ้าไม่มี error แปลว่าติดตั้งสำเร็จ
}

void loop() {
}

Publish/Subscribe พื้นฐาน

ตัวอย่างที่ 1: Hello MQTT

โค้ดนี้เชื่อมต่อ ESP32 กับ MQTT Broker และส่งข้อความ "Hello from ESP32" ทุก 5 วินาที

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

// ===== WiFi Credentials =====
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";

// ===== MQTT Broker Settings =====
const char* mqtt_server = "broker.hivemq.com";  // หรือ IP ของ broker คุณเอง
const int mqtt_port = 1883;

// ===== Topics =====
const char* mqtt_topic = "cynoiot/esp32/test";

// ===== Objects =====
WiFiClient espClient;
PubSubClient client(espClient);

// ===== Variables =====
unsigned long lastMsg = 0;
const long interval = 5000;  // ส่งทุก 5 วินาที

// ===== WiFi Setup =====
void setup_wifi() {
  delay(10);
  Serial.println("\nเชื่อมต่อ WiFi...");
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("\nWiFi เชื่อมต่อสำเร็จ!");
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());
}

// ===== MQTT Callback =====
void callback(char* topic, byte* message, unsigned int length) {
  Serial.print("มีข้อความมาจาก topic: ");
  Serial.print(topic);
  Serial.print(". ข้อความ: ");
  
  String messageTemp;
  
  for (int i = 0; i < length; i++) {
    Serial.print((char)message[i]);
    messageTemp += (char)message[i];
  }
  Serial.println();
  
  // ประมวลผลข้อความที่ได้รับ
  if (String(topic) == mqtt_topic) {
    if (messageTemp == "on") {
      Serial.println("เปิดอุปกรณ์!");
      // digitalWrite(ledPin, HIGH);
    } else if (messageTemp == "off") {
      Serial.println("ปิดอุปกรณ์!");
      // digitalWrite(ledPin, LOW);
    }
  }
}

// ===== Reconnect to MQTT =====
void reconnect() {
  // ลองเชื่อมต่อจนกว่าจะสำเร็จ
  while (!client.connected()) {
    Serial.print("กำลังเชื่อมต่อ MQTT...");
    
    // สร้าง Client ID แบบสุ่ม
    String clientId = "ESP32Client-";
    clientId += String(random(0xffff), HEX);
    
    // พยายามเชื่อมต่อ
    if (client.connect(clientId.c_str())) {
      Serial.println("เชื่อมต่อสำเร็จ!");
      
      // Subscribe topic
      client.subscribe(mqtt_topic);
      Serial.print("Subscribe topic: ");
      Serial.println(mqtt_topic);
    } else {
      Serial.print("เชื่อมต่อไม่สำเร็จ, rc=");
      Serial.print(client.state());
      Serial.println(" ลองใหม่ใน 5 วินาที");
      
      delay(5000);
    }
  }
}

// ===== Setup =====
void setup() {
  Serial.begin(115200);
  
  // เชื่อมต่อ WiFi
  setup_wifi();
  
  // ตั้งค่า MQTT
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
}

// ===== Loop =====
void loop() {
  // ตรวจสอบการเชื่อมต่อ MQTT
  if (!client.connected()) {
    reconnect();
  }
  client.loop();  // ต้องมีเพื่อให้ callback ทำงาน
  
  // ส่งข้อความทุก 5 วินาที
  unsigned long now = millis();
  if (now - lastMsg > interval) {
    lastMsg = now;
    
    // สร้างข้อความ
    String msg = "Hello from ESP32! Uptime: " + String(millis() / 1000) + "s";
    
    // ส่งข้อความ
    Serial.println("ส่งข้อความ: " + msg);
    client.publish(mqtt_topic, msg.c_str());
  }
}

💡 ทดสอบด้วย MQTT Explorer:

  1. ดาวน์โหลด MQTT Explorer
  2. เชื่อมต่อไปที่ broker.hivemq.com:1883
  3. Subscribe topic: cynoiot/esp32/test
  4. ดูข้อความที่ ESP32 ส่งมา!

ตัวอย่างที่ 2: ส่งค่าเซ็นเซอร์อุณหภูมิ

ในตัวอย่างนี้ เราจะใช้ DHT11/DHT22 วัดอุณหภูมิและความชื้น แล้วส่งค่าไปยัง MQTT Broker

วิธีต่อสาย DHT11/22

  • VCC: 3.3V หรือ 5V (ตามรุ่น)
  • Data: GPIO 4 (หรือขาอื่นที่ต้องการ)
  • GND: GND

* ให้ต่อตัวต้านทาน 10kΩ ระหว่าง VCC และ Data (Pull-up)

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

// ===== WiFi & MQTT =====
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
const char* mqtt_server = "broker.hivemq.com";

// ===== DHT Sensor =====
#define DHTPIN 4        // GPIO 4
#define DHTTYPE DHT11   // DHT11 หรือ DHT22
DHT dht(DHTPIN, DHTTYPE);

// ===== Topics =====
const char* temp_topic = "cynoiot/sensor/temperature";
const char* hum_topic = "cynoiot/sensor/humidity";

// ===== Objects =====
WiFiClient espClient;
PubSubClient client(espClient);

// ===== Variables =====
unsigned long lastSensorRead = 0;
const long sensorInterval = 10000;  // อ่านทุก 10 วินาที

void setup_wifi() {
  delay(10);
  Serial.println("\nเชื่อมต่อ WiFi...");
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("\nWiFi เชื่อมต่อสำเร็จ!");
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("เชื่อมต่อ MQTT...");
    String clientId = "ESP32-";
    clientId += String(random(0xffff), HEX);
    
    if (client.connect(clientId.c_str())) {
      Serial.println("สำเร็จ!");
    } else {
      Serial.print("ล้มเหลว, rc=");
      Serial.println(client.state());
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  
  // เริ่มใช้งาน DHT
  dht.begin();
  
  // เชื่อมต่อ WiFi
  setup_wifi();
  
  // ตั้งค่า MQTT
  client.setServer(mqtt_server, 1883);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  
  // อ่านเซ็นเซอร์ทุก 10 วินาที
  unsigned long now = millis();
  if (now - lastSensorRead > sensorInterval) {
    lastSensorRead = now;
    
    // อ่านค่าอุณหภูมิ (เซลเซียส)
    float temperature = dht.readTemperature();
    
    // อ่านค่าความชื้น (%)
    float humidity = dht.readHumidity();
    
    // ตรวจสอบว่าอ่านได้หรือไม่
    if (isnan(temperature) || isnan(humidity)) {
      Serial.println("อ่านค่าจาก DHT ไม่สำเร็จ!");
      return;
    }
    
    // แปลงค่าเป็น String
    char tempStr[8];
    char humStr[8];
    dtostrf(temperature, 1, 2, tempStr);  // ทศนิยม 2 ตำแหน่ง
    dtostrf(humidity, 1, 2, humStr);
    
    // ส่งค่าไปยัง MQTT
    client.publish(temp_topic, tempStr);
    client.publish(hum_topic, humStr);
    
    // แสดงผลใน Serial Monitor
    Serial.print("อุณหภูมิ: ");
    Serial.print(temperature);
    Serial.print("°C | ความชื้น: ");
    Serial.print(humidity);
    Serial.println("%");
  }
}

🎯 ข้อดีของการใช้ JSON:

แทนที่จะส่งค่าแยกกัน 2 topics สามารถส่งเป็น JSON ใน topic เดียวได้:

{"temp": 28.5, "hum": 65.2}

ตัวอย่างที่ 3: ควบคุม Relay ผ่าน MQTT

ตัวอย่างนี้รับคำสั่งจาก MQTT เพื่อเปิด/ปิด Relay (เช่น ไฟ, ปั๊มน้ำ)

วิธีต่อสาย Relay Module

  • VCC: 5V (หรือ 3.3V ตามรุ่น)
  • IN: GPIO 2 (หรือขาอื่น)
  • GND: GND
#include <WiFi.h>
#include <PubSubClient.h>

// ===== WiFi & MQTT =====
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
const char* mqtt_server = "broker.hivemq.com";

// ===== Relay =====
#define RELAY_PIN 2  // GPIO 2
const char* relay_topic = "cynoiot/relay/1";

// ===== State =====
bool relayState = false;

WiFiClient espClient;
PubSubClient client(espClient);

void setup_wifi() {
  // ... เหมือนตัวอย่างที่แล้ว ...
}

// ===== MQTT Callback - รับคำสั่ง =====
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("มีข้อความจาก ");
  Serial.println(topic);
  
  // แปลง payload เป็น string
  String message = "";
  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  
  Serial.print("คำสั่ง: ");
  Serial.println(message);
  
  // ตรวจสอบคำสั่ง
  if (message == "ON" || message == "on" || message == "1") {
    digitalWrite(RELAY_PIN, HIGH);  // เปิด Relay
    relayState = true;
    Serial.println("เปิด Relay!");
    
    // ส่งสถานะกลับ
    client.publish(relay_topic, "ON");
  } 
  else if (message == "OFF" || message == "off" || message == "0") {
    digitalWrite(RELAY_PIN, LOW);   // ปิด Relay
    relayState = false;
    Serial.println("ปิด Relay!");
    
    // ส่งสถานะกลับ
    client.publish(relay_topic, "OFF");
  }
}

void reconnect() {
  // ... เหมือนตัวอย่างที่แล้ว ...
}

void setup() {
  Serial.begin(115200);
  
  // ตั้งค่า Relay pin
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);  // เริ่มต้นปิด
  
  setup_wifi();
  
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);  // ตั้งค่า callback
}

void loop() {
  if (!client.connected()) {
    reconnect();
    
    // Subscribe topic หลังเชื่อมต่อสำเร็จ
    client.subscribe(relay_topic);
    Serial.println("Subscribe: " + String(relay_topic));
  }
  client.loop();
}

🎮 ทดสอบควบคุม:

เปิด MQTT Explorer → ไปที่ topic cynoiot/relay/1 → พิมพ์ ON หรือ OFF → Relay จะทำงาน!

เชื่อมต่อกับ CynoIoT Platform

CynoIoT รองรับ MQTT protocol สำหรับเชื่อมต่ออุปกรณ์ IoT เข้าสู่แพลตฟอร์ม

ขั้นตอนการเชื่อมต่อ

1. สร้าง Device บน CynoIoT

  • Login ที่ cynoiot.com
  • ไปที่ Device Management → Add Device
  • เลือก Protocol: MQTT
  • คัดลอก MQTT Credentials (Host, Port, Username, Password)

2. อัปเดตโค้ด ESP32

// แทนที่ค่าเหล่านี้ด้วยค่าจาก CynoIoT
const char* mqtt_server = "mqtt.cynoiot.com";  // จาก CynoIoT
const int mqtt_port = 1883;                      // จาก CynoIoT
const char* mqtt_user = "YOUR_DEVICE_USERNAME";  // จาก CynoIoT
const char* mqtt_pass = "YOUR_DEVICE_PASSWORD";  // จาก CynoIoT

// ใน reconnect():
if (client.connect(clientId.c_str(), mqtt_user, mqtt_pass)) {
  // ...
}

3. ใช้ Topic ตามที่ CynoIoT กำหนด

CynoIoT ใช้รูปแบบ topic เฉพาะ:

  • ขึ้นข้อมูล: device/{device_id}/telemetry
  • รับคำสั่ง: device/{device_id}/command

แก้ปัญหาที่พบบ่อย

❓ ปัญหา: เชื่อมต่อ MQTT ไม่ได้ (Connection Failed)

สาเหตุที่เป็นไปได้:

  • WiFi ยังไม่เชื่อมต่อ
  • MQTT Broker address ผิด
  • Port ผิด (ควรใช้ 1883 สำหรับ non-TLS, 8883 สำหรับ TLS)
  • Firewall บน router บล็อก port

วิธีแก้: ตรวจสอบ WiFi status, ลอง ping broker, ใช้ MQTT Explorer ทดสอบ

❓ ปัญหา: ส่งข้อมูลแล้วไม่ปรากฏบน MQTT Explorer

สาเหตุ:

  • Subscribe topic ผิด (case-sensitive)
  • ต้อง Subscribe ก่อน Publish ครั้งแรก
  • Client ID ซ้ำกับ device อื่น (Broker จะ kick ตัวเก่า)

วิธีแก้: ตรวจสอบตัวสะกด topic, ใช้ Client ID แบบสุ่ม, Subscribe topic ให้ตรง

❓ ปัญหา: Callback ไม่ทำงาน

สาเหตุ:

  • ลืมเรียก client.setCallback()
  • ลืมเรียก client.loop() ใน loop()
  • ยังไม่ได้ Subscribe topic

วิธีแก้: เพิ่ม client.setCallback(callback) ใน setup(), ต้องมี client.loop() ทุกรอบ

❓ ปัญหา: ESP32 รีสตาร์ทบ่อย (Watchdog Reset)

สาเหตุ:

  • โค้ดใน loop() ใช้เวลานานเกินไป (block)
  • MQTT connection หลุดแล้ว reconnect ไม่หยุด

วิธีแก้: ใช้ millis() แทน delay(), ใส่ timeout ใน reconnect

สรุป

MQTT คือโปรโตคอลที่เหมาะกับ IoT projects มากๆ เพราะเบา รวดเร็ว และง่ายต่อการใช้งาน ด้วย ESP32 และ Library PubSubClient คุณสามารถสร้างระบบ IoT ที่ส่งและรับข้อมูลแบบ Real-time ได้ในไม่กี่นาที

สิ่งที่ได้เรียนรู้:

  • ✅ หลักการทำงานของ MQTT (Publisher, Subscriber, Broker)
  • ✅ การติดตั้งและใช้งาน PubSubClient Library
  • ✅ การส่งค่าเซ็นเซอร์ไปยัง MQTT Broker
  • ✅ การรับคำสั่งจาก MQTT เพื่อควบคุม Relay
  • ✅ การเชื่อมต่อ ESP32 เข้ากับ CynoIoT Platform

ถัดไป

  • ลองใช้ MQTT over TLS สำหรับความปลอดภัยยิ่งขึ้น
  • สร้าง Dashboard ดูข้อมูลจาก ESP32 แบบ Real-time
  • เรียนรู้เกี่ยวกับ JSON Payload สำหรับส่งข้อมูลหลายค่าพร้อมกัน
  • ดู Deep Sleep Guide สำหรับประหยัดพลังงาน

🚀 เริ่มต้นใช้งาน CynoIoT

พร้อมจะเชื่อมต่อ ESP32 ของคุณเข้าสู่ Cloud Platform แล้วหรือยัง? CynoIoT ช่วยให้คุณจัดการอุปกรณ์ IoT ได้ง่ายๆ

CynoIoT LogoCynoIoT

แพลตฟอร์ม IoT ที่ช่วยให้คุณเชื่อมต่อและจัดการอุปกรณ์ IoT ได้ง่ายๆ
พัฒนาโปรเจกต์ IoT ของคุณกับเราวันนี้

© 2026 CynoIoT. All rights reserved.