เนื้อหาในบทความ
MQTT คืออะไร?
MQTT (Message Queuing Telemetry Transport) เป็นโพรโทคอลการสื่อสารแบบ lightweight ที่ออกแบบมาสำหรับ IoT devices โดยเฉพาะ มีข้อดีคือ:
- ขนาดเล็กและรวดเร็ว - ใช้ bandwidth น้อยมาก เหมาะกับ devices ที่มีทรัพยากรจำกัด
- ประหยัดพลังงาน - ช่วยให้แบตเตอรี่อยู่ได้นานขึ้น
- ส่งข้อความแบบ Real-time - รับส่งข้อมูลได้ทันทีทันใด
- ง่ายต่อการใช้งาน - มี library สำเร็จรูปมากมาย
การทำงานของ MQTT ใช้รูปแบบ Publish/Subscribe ซึ่งประกอบด้วย:
- MQTT Broker - เซิร์ฟเวอร์กลางที่รับส่งข้อความ (เช่น HiveMQ, EMQX, Mosquitto)
- Publisher - อุปกรณ์ที่ส่งข้อมูล (เช่น ESP32 ที่มีเซ็นเซอร์)
- Subscriber - อุปกรณ์ที่รับข้อมูล (เช่น ESP32 ที่ควบคุมรีเลย์)
- Topic - ชื่อช่องทางสำหรับจัดหมวดหมู่ข้อความ (เช่น
home/livingroom/temperature)
ข้อกำหนดเบื้องต้น
Hardware ที่ต้องใช้:
- ESP32 Board (ESP32-DevKitC, NodeMCU-ESP32, หรือบอร์ดอื่นๆ)
- เซ็นเซอร์อุณหภูมิและความชื้น DHT11/DHT22
- Relay Module 5V (สำหรับควบคุมไฟ/อุปกรณ์ไฟฟ้า)
- Jumper wires และ Breadboard
- USB Cable สำหรับอัปโหลดโปรแกรม
Software ที่ต้องใช้:
- Arduino IDE - สำหรับเขียนและอัปโหลดโค้ด
- Library:
PubSubClient- MQTT client library - Library:
DHT- สำหรับอ่านค่าเซ็นเซอร์ DHT - MQTT Broker - ใช้บริการฟรีจาก HiveMQ Cloud หรือติดตั้ง Mosquitto ในเครื่อง
ระดับความยาก:
เริ่มต้น - กลาง (ควรมีพื้นฐาน ESP32 และ Arduino เบื้องต้น)
การติดตั้งและตั้งค่า
1. ติดตั้ง Library ใน Arduino IDE
เปิด Arduino IDE → ไปที่ Sketch → Include Library → Manage Libraries
- ค้นหา "PubSubClient" แล้วกดติดตั้งเวอร์ชันล่าสุด
- ค้นหา "DHT sensor library" แล้วกดติดตั้ง
2. สมัครใช้ MQTT Broker ฟรี
ในบทความนี้จะใช้ HiveMQ Cloud เพราะฟรีและง่าย:
- ไปที่ https://www.hivemq.com/
- สมัครบัญชีฟรี
- สร้าง Cluster ใหม่
- จด URL และ Port ไว้ (เช่น
xxxxxxxxxx.s1.eu.hivemq.cloud:8883) - สร้าง Username และ Password สำหรับ authentication
3. ต่อวงจร Hardware
การต่อ DHT22:
- VCC → 3.3V
- GND → GND
- DATA → GPIO 4
การต่อ Relay:
- VCC → 5V
- GND → GND
- IN1 → GPIO 2
MQTT พื้นฐาน: การเชื่อมต่อครั้งแรก
มาเริ่มต้นด้วยโค้ดพื้นฐานที่เชื่อมต่อ ESP32 เข้ากับ MQTT Broker:
#include <WiFi.h>
#include <PubSubClient.h>
// ========== ตั้งค่า WiFi ==========
const char* ssid = "YOUR_WIFI_SSID";
const char* wifi_password = "YOUR_WIFI_PASSWORD";
// ========== ตั้งค่า MQTT ==========
const char* mqtt_server = "xxxxxxxxxx.s1.eu.hivemq.cloud"; // HiveMQ Cloud URL
const int mqtt_port = 8883; // HiveMQ Cloud TLS port
const char* mqtt_user = "YOUR_MQTT_USERNAME";
const char* mqtt_password = "YOUR_MQTT_PASSWORD";
// ========== อุปกรณ์ ==========
WiFiClient espClient;
PubSubClient client(espClient);
// ตั้งเวลา reconnect (5 วินาที)
unsigned long lastReconnectAttempt = 0;
// ========== ฟังก์ชันเชื่อมต่อ WiFi ==========
void setup_wifi() {
delay(10);
Serial.println("\\nเชื่อมต่อ WiFi...");
WiFi.begin(ssid, wifi_password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\\nWiFi เชื่อมต่อสำเร็จ!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
}
// ========== ฟังก์ชันรับข้อความจาก MQTT ==========
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("มีข้อความใหม่จาก Topic: ");
Serial.print(topic);
Serial.print(" | ข้อความ: ");
String message;
for (int i = 0; i < length; i++) {
message += (char)payload[i];
Serial.print((char)payload[i]);
}
Serial.println();
// ตัวอย่าง: ควบคุม LED ถ้าได้รับข้อความ "ON" หรือ "OFF"
if (message == "ON") {
digitalWrite(2, HIGH); // เปิด LED
Serial.println("→ เปิด LED");
} else if (message == "OFF") {
digitalWrite(2, LOW); // ปิด LED
Serial.println("→ ปิด LED");
}
}
// ========== ฟังก์ชันเชื่อมต่อ MQTT ใหม่ ==========
boolean reconnect() {
if (client.connect("ESP32Client", mqtt_user, mqtt_password)) {
Serial.println("เชื่อมต่อ MQTT สำเร็จ!");
// Subscribe topic ที่ต้องการรับข้อความ
client.subscribe("home/led/control");
} else {
Serial.print("เชื่อมต่อ MQTT ล้มเหลว, rc=");
Serial.print(client.state());
Serial.println(" ลองใหม่ใน 5 วินาที");
}
return client.connected();
}
// ========== การตั้งค่าเริ่มต้น ==========
void setup() {
Serial.begin(115200);
pinMode(2, OUTPUT); // ตั้งค่า LED pin เป็น output
setup_wifi(); // เชื่อมต่อ WiFi
// ตั้งค่า MQTT
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
}
// ========== ลูปหลัก ==========
void loop() {
// ลองเชื่อมต่อ MQTT ใหม่ถ้าหลุด
if (!client.connected()) {
unsigned long now = millis();
if (now - lastReconnectAttempt > 5000) {
lastReconnectAttempt = now;
if (reconnect()) {
lastReconnectAttempt = 0;
}
}
} else {
client.loop(); // รักษาการเชื่อมต่อ MQTT
}
}คำอธิบาย:
- setup_wifi() - เชื่อมต่อ ESP32 เข้ากับ WiFi
- callback() - ฟังก์ชันที่ถูกเรียกเมื่อมีข้อความใหม่มาถึง
- reconnect() - พยายามเชื่อมต่อ MQTT ใหม่ถ้าหลุด
- client.loop() - รักษาการเชื่อมต่อและรับข้อความตลอดเวลา
ส่งค่าเซ็นเซอร์ผ่าน MQTT
ตอนนี้มาเพิ่มฟังก์ชันอ่านค่า DHT22 และส่งค่าไปยัง MQTT Broker:
#include <DHT.h>
// กำหนดขา DHT
#define DHTPIN 4
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
unsigned long lastSensorRead = 0;
const long sensorInterval = 5000; // อ่านทุก 5 วินาที
void setup() {
// ... (โค้ดเดิมจากขั้นตอนที่แล้ว)
dht.begin(); // เริ่มต้นเซ็นเซอร์ DHT
}
void loop() {
if (!client.connected()) {
// ... (โค้ด reconnect เดิม)
} else {
client.loop();
// อ่านเซ็นเซอร์ทุก 5 วินาที
unsigned long now = millis();
if (now - lastSensorRead >= sensorInterval) {
lastSensorRead = now;
readAndSendSensor();
}
}
}
// ฟังก์ชันอ่านและส่งค่าเซ็นเซอร์
void readAndSendSensor() {
// อ่านอุณหภูมิ (เซลเซียส)
float temperature = dht.readTemperature();
// อ่านความชื้น (%)
float humidity = dht.readHumidity();
// ตรวจสอบว่าอ่านสำเร็จหรือไม่
if (isnan(temperature) || isnan(humidity)) {
Serial.println("❌ อ่านเซ็นเซอร์ DHT ล้มเหลว!");
return;
}
// แสดงค่าใน Serial Monitor
Serial.print("อุณหภูมิ: ");
Serial.print(temperature);
Serial.print("°C | ความชื้น: ");
Serial.print(humidity);
Serial.println("%");
// แปลงค่าเป็น String เพื่อส่งผ่าน MQTT
String tempString = String(temperature);
String humString = String(humidity);
// ส่งค่าไปยัง MQTT Topics
client.publish("home/livingroom/temperature", tempString.c_str());
client.publish("home/livingroom/humidity", humString.c_str());
Serial.println("✅ ส่งค่าเซ็นเซอร์ไปยัง MQTT แล้ว!");
}Topics ที่ใช้:
home/livingroom/temperature- ส่งค่าอุณหภูมิhome/livingroom/humidity- ส่งค่าความชื้น
💡 เคล็ดลับ: คุณสามารถทดสอบดูข้อความได้โดยใช้ MQTT Explorer หรือ HiveMQ Websocket Client
ควบคุม Relay ผ่าน MQTT
มาเพิ่มฟังก์ชันควบคุม Relay ผ่าน MQTT กัน:
#define RELAY_PIN 2 // ขาที่ต่อ Relay
void setup() {
// ... (โค้ดเดิม)
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW); // เริ่มต้นให้ Relay ปิด
// Subscribe topic สำหรับควบคุม Relay
client.subscribe("home/livingroom/relay");
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("มีข้อความใหม่: ");
Serial.println(topic);
String message;
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.print("คำสั่ง: ");
Serial.println(message);
// ตรวจสอบ Topic
if (String(topic) == "home/livingroom/relay") {
if (message == "ON") {
digitalWrite(RELAY_PIN, HIGH); // เปิด Relay
Serial.println("✅ เปิด Relay");
// ส่งสถานะกลับไปยัง MQTT
client.publish("home/livingroom/relay/status", "ON");
}
else if (message == "OFF") {
digitalWrite(RELAY_PIN, LOW); // ปิด Relay
Serial.println("✅ ปิด Relay");
// ส่งสถานะกลับไปยัง MQTT
client.publish("home/livingroom/relay/status", "OFF");
}
else if (message == "TOGGLE") {
// สลับสถานะ
int currentState = digitalRead(RELAY_PIN);
digitalWrite(RELAY_PIN, !currentState);
String newState = !currentState ? "ON" : "OFF";
Serial.print("✅ สลับสถานะ Relay: ");
Serial.println(newState);
// ส่งสถานะกลับไปยัง MQTT
client.publish("home/livingroom/relay/status", newState.c_str());
}
}
}คำสั่งที่รองรับ:
"ON"- เปิด Relay"OFF"- ปิด Relay"TOGGLE"- สลับสถานะ
เชื่อมต่อกับ CynoIoT Platform
CynoIoT Platform รองรับ MQTT โดยตรง ทำให้สามารถส่งข้อมูลจาก ESP32 ได้ทันที:
ขั้นตอนการเชื่อมต่อ:
- เข้าสู่ระบบ CynoIoT Platform
- สร้าง Device ใหม่ และจด MQTT credentials ไว้
- อัปเดตโค้ด ESP32 ให้ใช้ MQTT settings จาก CynoIoT
- ส่งข้อมูลไปยัง Topics ที่ CynoIoT กำหนด
// ========== ตั้งค่า CynoIoT MQTT ==========
const char* cynoiot_mqtt_server = "mqtt.cynoiot.com";
const int cynoiot_mqtt_port = 1883;
const char* cynoiot_device_id = "YOUR_DEVICE_ID";
const char* cynoiot_device_key = "YOUR_DEVICE_KEY";
// Topic สำหรับ CynoIoT
String cynoiot_topic = "cynoiot/" + String(cynoiot_device_id) + "/data";
void readAndSendSensor() {
// ... (โค้ดอ่านเซ็นเซอร์เดิม)
// สร้าง JSON payload สำหรับ CynoIoT
String payload = "{";
payload += "\\"temperature\\":" + String(temperature) + ",";
payload += "\\"humidity\\":" + String(humidity);
payload += "}";
// ส่งไปยัง CynoIoT Platform
client.publish(cynoiot_topic.c_str(), payload.c_str());
Serial.println("✅ ส่งข้อมูลไปยัง CynoIoT แล้ว!");
}🎉 ข้อดีของ CynoIoT: ข้อมูลจะถูกแสดงใน Dashboard พร้อมกราฟและการแจ้งเตือนอัตโนมัติ!
การแก้ปัญหาที่พบบ่อย
❌ ปัญหา: ESP32 เชื่อมต่อ WiFi ไม่ได้
สาเหตุ: รหัสผ่านผิด, อยู่ไกลเกินไป, หรือ router ไม่รองรับ
วิธีแก้: ตรวจสอบ SSID/password, ลองย้ายใกล้ router, หรือใช้ WiFi 2.4GHz
❌ ปัญหา: เชื่อมต่อ MQTT ไม่ได้
สาเหตุ: Server URL ผิด, port ไม่ถูกต้อง, หรือ auth ล้มเหลว
วิธีแก้: ตรวจสอบ URL, port, username, password ให้ถูกต้อง
❌ ปัญหา: อ่านค่า DHT ไม่ได้
สาเหตุ: ต่อสายผิด, เซ็นเซอร์เสีย, หรือใช้เวลาอ่านน้อยเกินไป
วิธีแก้: ตรวจสอบการต่อสาย, เพิ่ม delay 2-3 วินาทีระหว่างการอ่าน
❌ ปัญหา: ข้อความ MQTT ไม่ถึงปลายทาง
สาเหตุ: Subscribe topic ผิด, broker ไม่อนุญาต
วิธีแก้: ตรวจสอบ topic ให้ตรงกัน, ตรวจสอบ permissions
สรุป
ในบทความนี้คุณได้เรียนรู้:
- ✅ หลักการทำงานของ MQTT (Publish/Subscribe)
- ✅ การเชื่อมต่อ ESP32 กับ MQTT Broker
- ✅ การส่งค่าเซ็นเซอร์ผ่าน MQTT
- ✅ การควบคุม Relay ผ่าน MQTT
- ✅ การเชื่อมต่อกับ CynoIoT Platform
ถัดไป:
- สร้าง Dashboard แสดงผลข้อมูลแบบ Real-time
- เพิ่มฟีเจอร์แจ้งเตือน (Notifications)
- ใช้งาน QoS levels สำหรับการส่งข้อมูลที่เชื่อถือได้
- สร้างระบบ Automation ซับซ้อนขึ้น