เนื้อหาในบทความ
แนะนำ
MQTT (Message Queuing Telemetry Transport) เป็นโปรโตคอลการสื่อสารแบบ Publish/Subscribe ที่เบาเพียงและเหมาะสำหรับอุปกรณ์ IoT ที่มีทรัพยากรจำกัด เมื่อรวมกับ Node-RED ซึ่งเป็นเครื่องมือสร้าง Flow แบบ Visual Programming คุณจะสามารถสร้างระบบ Smart Home ที่ยืดหยุ่นและทรงพลังได้อย่างง่ายดาย
ในบทความนี้ คุณจะได้เรียนรู้วิธีการเชื่อมต่อ ESP32 เข้ากับ MQTT Broker ส่งข้อมูลเซ็นเซอร์และควบคุม Relay ผ่าน Node-RED Dashboard พร้อมตัวอย่างโค้ดและการตั้งค่าที่สมบูรณ์
ข้อกำหนดเบื้องต้น
Hardware ที่ต้องใช้
- ESP32 Development Board (ตัวไหนก็ได้)
- Relay Module 1-4 ช่อง
- DHT22 Temperature & Humidity Sensor (หรือ DHT11)
- Jumper Wires (สายไฟเชื่อมต่อ)
- Breadboard (ไม่บังคับ)
- LED และ Resistor 330Ω (สำหรับทดสอบ)
Software ที่ต้องใช้
- Arduino IDE หรือ PlatformIO
- MQTT Broker (แนะนำ Mosquitto หรือ HiveMQ Cloud)
- Node-RED (ติดตั้งบน Raspberry Pi หรือ Docker)
- Library: PubSubClient สำหรับ Arduino
- Library: DHT สำหรับอ่านค่าเซ็นเซอร์
หมายเหตุ: หากคุณยังไม่มี MQTT Broker สามารถใช้บริการฟรีจาก HiveMQ Cloud หรือ EMQX Cloud ได้
พื้นฐาน MQTT ที่ควรรู้
MQTT ทำงานด้วยรูปแบบ Publish/Subscribe ซึ่งแตกต่างจาก HTTP Request/Response ทั่วไป:
Publisher
อุปกรณ์ที่ส่งข้อมูล (เช่น ESP32 ที่อ่านค่าเซ็นเซอร์)
Subscriber
อุปกรณ์ที่รับข้อมูล (เช่น Node-RED หรือ ESP32 อื่น)
Broker
เซิร์ฟเวอร์กลางที่คัดกรองและส่งต่อข้อความ
Topic
ชื่อหัวข้อที่ใช้จัดหมวดหมู่ข้อความ (เช่น home/livingroom/temp)
Topic Structure แนะนำ
home/livingroom/temperature
home/livingroom/humidity
home/livingroom/relay1
home/livingroom/relay2การต่อวงจร Hardware
การต่อ DHT22 Sensor
| DHT22 Pin | ESP32 Pin |
|---|---|
| VCC | 3.3V |
| Data | GPIO 4 |
| GND | GND |
การต่อ Relay Module
| Relay Pin | ESP32 Pin |
|---|---|
| VCC | 5V (หรือ VIN) |
| IN1 | GPIO 12 |
| IN2 (ถ้ามี) | GPIO 14 |
| GND | GND |
คำเตือน: Relay ใช้ไฟ 5V ในขณะที่ ESP32 ใช้ 3.3V ตรวจสอบให้แน่ใจว่า Relay Module ของคุณรองรับ 3.3V Logic หรือไม่ หรือใช้ Level Shifter
โค้ด ESP32 สำหรับ MQTT
นี่คือโค้ดสมบูรณ์สำหรับ ESP32 ที่เชื่อมต่อ MQTT อ่านค่า DHT22 และควบคุม Relay:
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
// WiFi Credentials
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
// MQTT Configuration
const char* mqtt_server = "broker.hivemq.com"; // หรือ IP ของ MQTT Broker ของคุณ
const int mqtt_port = 1883;
// Topics
const char* temp_topic = "home/livingroom/temperature";
const char* hum_topic = "home/livingroom/humidity";
const char* relay1_topic = "home/livingroom/relay1";
const char* relay2_topic = "home/livingroom/relay2";
// Pin Definitions
#define DHTPIN 4
#define DHTTYPE DHT22
#define RELAY1_PIN 12
#define RELAY2_PIN 14
DHT dht(DHTPIN, DHTTYPE);
WiFiClient espClient;
PubSubClient client(espClient);
// ตัวแปรสำหรับเก็บค่าเซ็นเซอร์
float lastTemp = 0;
float lastHum = 0;
unsigned long lastSensorTime = 0;
const long sensorInterval = 5000; // อ่านค่าทุก 5 วินาที
// เชื่อมต่อ WiFi
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
// Callback เมื่อได้รับ MQTT message
void callback(char* topic, byte* message, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("]: ");
String messageTemp;
for (int i = 0; i < length; i++) {
messageTemp += (char)message[i];
}
Serial.println(messageTemp);
// ควบคุม Relay 1
if (String(topic) == relay1_topic) {
if (messageTemp == "ON") {
digitalWrite(RELAY1_PIN, HIGH);
Serial.println("Relay 1 turned ON");
} else if (messageTemp == "OFF") {
digitalWrite(RELAY1_PIN, LOW);
Serial.println("Relay 1 turned OFF");
}
}
// ควบคุม Relay 2
if (String(topic) == relay2_topic) {
if (messageTemp == "ON") {
digitalWrite(RELAY2_PIN, HIGH);
Serial.println("Relay 2 turned ON");
} else if (messageTemp == "OFF") {
digitalWrite(RELAY2_PIN, LOW);
Serial.println("Relay 2 turned OFF");
}
}
}
// เชื่อมต่อ MQTT Broker ใหม่
void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// สร้าง Client ID แบบสุ่ม
String clientId = "ESP32Client-";
clientId += String(random(0xffff), HEX);
if (client.connect(clientId.c_str())) {
Serial.println("connected");
// Subscribe หัวข้อที่ต้องการรับ
client.subscribe(relay1_topic);
client.subscribe(relay2_topic);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
// อ่านค่าเซ็นเซอร์และส่งข้อมูล
void readAndSendSensorData() {
unsigned long currentTime = millis();
if (currentTime - lastSensorTime >= sensorInterval) {
lastSensorTime = currentTime;
// อ่านค่าอุณหภูมิและความชื้น
float h = dht.readHumidity();
float t = dht.readTemperature();
// ตรวจสอบว่าอ่านค่าได้หรือไม่
if (isnan(h) || isnan(t)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
// แปลงค่าเป็น String
char tempStr[8];
char humStr[8];
dtostrf(t, 2, 2, tempStr);
dtostrf(h, 2, 2, humStr);
// ส่งข้อมูลไปยัง MQTT
client.publish(temp_topic, tempStr);
client.publish(hum_topic, humStr);
Serial.print("Temperature: ");
Serial.print(t);
Serial.print("°C, Humidity: ");
Serial.print(h);
Serial.println("%");
}
}
void setup() {
Serial.begin(115200);
// ตั้งค่า Pin
pinMode(RELAY1_PIN, OUTPUT);
pinMode(RELAY2_PIN, OUTPUT);
// ปิด Relay เริ่มต้น
digitalWrite(RELAY1_PIN, LOW);
digitalWrite(RELAY2_PIN, LOW);
// เริ่มต้นเซ็นเซอร์
dht.begin();
// เชื่อมต่อ WiFi
setup_wifi();
// ตั้งค่า MQTT
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
}
void loop() {
// ตรวจสอบการเชื่อมต่อ MQTT
if (!client.connected()) {
reconnect();
}
client.loop();
// อ่านและส่งข้อมูลเซ็นเซอร์
readAndSendSensorData();
}เคล็ดลับ: อย่าลืมเปลี่ยน YOUR_WIFI_SSID และ YOUR_WIFI_PASSWORD เป็นค่าของคุณ และแก้ไข MQTT Broker Address หากใช้บริการอื่น
การติดตั้งและตั้งค่า Node-RED
ติดตั้ง Node-RED บน Raspberry Pi
# อัปเดตระบบ
sudo apt update && sudo apt upgrade -y
# ติดตั้ง Node.js
curl -sL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
# ติดตั้ง Node-RED
sudo npm install -g --unsafe-perm node-red
# ติดตั้ง Node-RED เพื่อเริ่มต้นอัตโนมัติ
sudo systemctl enable nodered.service
sudo systemctl start nodered.service
# ตรวจสอบสถานะ
sudo systemctl status nodered.service หลังจากติดตั้งเสร็จ เข้าถึง Node-RED ผ่าน http://<IP_ADDRESS>:1880
ติดตั้ง Node-RED Dashboard
# เข้าไปที่ directory ของ Node-RED
cd ~/.node-red
# ติดตั้ง Dashboard
npm install node-red-dashboard
# รีสตาร์ท Node-RED
sudo systemctl restart nodered.serviceสร้าง Flow ใน Node-RED
ส่วนที่ 1: รับข้อมูลจาก ESP32
- ลาก MQTT In node มาวาง
- ดับเบิลคลิกและตั้งค่า:
- Connection: เพิ่มการเชื่อมต่อ MQTT Broker ใหม่
- Topic:
home/livingroom/temperature - Output: String
- ลาก Gauge node จาก Dashboard มาวาง
- ตั้งค่า Gauge สำหรับแสดงผลอุณหภูมิ
- เชื่อมต่อ MQTT In → Gauge
ส่วนที่ 2: ควบคุม Relay
- ลาก Switch node จาก Dashboard มาวาง
- ตั้งค่า:
- Name: Relay 1
- Topic:
home/livingroom/relay1 - Output: "ON" / "OFF"
- ลาก MQTT Out node มาวาง
- ตั้งค่า Topic เป็น
home/livingroom/relay1 - เชื่อมต่อ Switch → MQTT Out
ส่วนที่ 3: แสดงผลใน Dashboard
- คลิกที่ไอคอน Dashboard ด้านขวาบน
- สร้าง Tab ใหม่ชื่อ "Living Room"
- สร้าง Group และลาก Widget ต่างๆ มาจัดวาง:
- Gauge สำหรับ Temperature
- Gauge สำหรับ Humidity
- Switch สำหรับ Relay 1
- Switch สำหรับ Relay 2
- Chart สำหรับแสดงกราฟย้อนหลัง
การทดสอบระบบ
ตรวจสอบการเชื่อมต่อ MQTT
- อัปโหลดโค้ดไปยัง ESP32
- เปิด Serial Monitor (115200 baud)
- ตรวจสอบว่า ESP32 เชื่อมต่อ WiFi และ MQTT สำเร็จหรือไม่
- ดูใน Serial Monitor ว่ามีข้อความ "Temperature: XX°C, Humidity: XX%" แสดงหรือไม่
ทดสอบใน Node-RED
- ไปที่
http://<RASPBERRY_PI_IP>:1880/ui - ดูว่ามีค่าอุณหภูมิและความชื้นแสดงผลหรือไม่
- กดปุ่ม Switch เพื่อควบคุม Relay
- ฟังเสียง "คลิก" จาก Relay และดู Serial Monitor
ยินดีด้วย! ตอนนี้คุณมีระบบ Smart Home ขั้นพื้นฐานที่ทำงานได้แล้ว
เทคนิคขั้นสูง
1. บันทึกข้อมูลลง Database
ใช้ InfluxDB หรือ SQLite เพื่อบันทึกข้อมูลเซ็นเซอร์ย้อนหลัง:
# ติดตั้ง InfluxDB
sudo apt install influxdb influxdb-client
# ติดตั้ง node-red-contrib-influxdb ใน Node-RED
cd ~/.node-red
npm install node-red-contrib-influxdb2. รับการแจ้งเตือนด้วย Telegram
ส่งการแจ้งเตือนเมื่ออุณหภูมิสูงเกินกำหนด:
- สร้าง Telegram Bot ผ่าน @BotFather
- ติดตั้ง node-red-contrib-telegrambot
- สร้าง Flow: MQTT In → Function (ตรวจสอบค่า) → Telegram Out
3. ควบคุมด้วย Voice Command
ใช้ Google Assistant หรือ Alexa ผ่าน IFTTT หรือ Home Assistant เพื่อควบคุม Relay ด้วยเสียง
การแก้ปัญหา
ปัญหา: ESP32 เชื่อมต่อ MQTT ไม่ได้
สาเหตุ: IP ผิด, Port ผิด, หรือ Firewall บล็อก
วิธีแก้: ตรวจสอบ MQTT Broker Address และ Port, ปิด Firewall ชั่วคราวเพื่อทดสอบ
ปัญหา: ค่าเซ็นเซอร์อ่านไม่ได้
สาเหตุ: DHT22 เสีย, ต่อสายผิด, หรือ Pin ผิด
วิธีแก้: ตรวจสอบการต่อสาย, เปลี่ยน DHT22, ลองเพิ่ม Resistor 10K ระหว่าง VCC และ Data
ปัญหา: Relay ไม่ทำงาน
สาเหตุ: Pin ผิด, Relay ต้องการ 5V แต่ ESP32 ให้ 3.3V
วิธีแก้: ใช้ External 5V Power Supply, ตรวจสอบ Pin IN, ลองใช้ Transistor
ปัญหา: Node-RED Dashboard ไม่แสดงผล
สาเหตุ: MQTT Subscribe ผิด, Node ไม่ได้ deploy
วิธีแก้: กด Deploy ใหม่, ตรวจสอบ Topic ให้ตรงกัน, ดู Debug messages
สรุป
ในบทความนี้ คุณได้เรียนรู้วิธีสร้างระบบ Smart Home ขั้นพื้นฐานด้วย ESP32, MQTT และ Node-RED ตั้งแต่การต่อวงจร เขียนโค้ด ติดตั้ง Node-RED ไปจนถึงการสร้าง Dashboard คุณสามารถขยายระบบนี้ได้โดยการเพิ่มเซ็นเซอร์ประเภทต่างๆ, บันทึกข้อมูลลง Database, หรือเชื่อมต่อกับระบบ Automation อื่นๆ