Giới Thiệu
Trong phần trước mình đã hướng dẫn các bạn cách cài đặt và gửi dữ liệu từ NodeMCU lên Server MQTT Mosquitto trên Raspberry Pi (RasPi). Trong bài viết này chúng ta sẽ điều khiển đèn led onBoard trên NodeMCU thông qua Terminal từ Server!
Để thực hiện được bài này các bạn cần tham khảo bài hướng dẫn trước: Raspberry Pi giao tiếp với NodeMCU ESP8266 qua giao thức MQTT – Phần 1
Trong dự án này mình sẽ chia làm 3 phần
- Tạo một Topic subscribe tên là “Makerlab” trên RasPi
- Theo dõi Topic đó trên NodeMCU
- Nhận dữ liệu trả về từ Topic và xử lí data thông qua việc bật tắt đèn led , sau đó gửi dữ liệu lên lại Topic
Chuẩn bị
1. Phần cứng
- Kit RF Thu Phát Wifi ESP8266 NodeMCU Lua CP2102
- Một board Raspberry Pi ( ở đây mình sử dụng Raspberry Pi 3 Model B) bạn có thể tham khảo mua tại đây . Bạn nên mua đủ nguồn , thẻ nhớ – ít nhất 16GB và vỏ case để bảo vệ tốt cho board RasPi của bạn!
2. Phần mềm
-
Raspberry Pi
Các bạn cần cài đặt hệ điều hành cho Raspberry Pi , ở đây mình sử dụng Raspbian.
-
Arduino IDE
Các bạn cần cài đặt sẵn Arduino IDE có tương thích với ESP8266. Nếu bạn chưa biết cách cài đặt có thể tham khảo bài viết sau: Hướng dẫn lập trình ESP8266 với Arduino IDE.
Hướng dẫn
1. Mosquitto MQTT RasPi
Các bạn khởi động Raspian lên và mở Terminal và tạo một sub với topic là “Makerlab”.

Sau đó chúng ta thử publish dữ liệu lên topic mới tạo.

Vậy là đã xong phần RasPi , bây giờ chuyển sang NodeMCU code nào !!
2. NodeMCU ESP8266
Lưu ý: Bạn phải chắc chắn mình đã cài đặt được tool board NodeMCU cho Arduino IDE trước. Và đã được cài đặt thư viện PubSubClient. Nếu chưa bạn hãy xem lại cách cài đặt bài viết trước
Ở bài trước mình đã hướng dẫn sơ lược về phần sourcode , vì thế trong phần này mình chỉ giải thích thêm về phần xử lí dữ liệu
Các bạn lưu ý hàm Call Back sẽ nhận dữ liệu trả về mỗi khi topic subcribe thay đổi dữ liệu
Serial.print(“Message read [“);
Serial.print(topic);
Serial.print(“] “);
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
xulidulieu(payload);
}
Ở dưới cùng hàm Callback có một hàm xulidulieu(payload) các bạn sẽ xử lí dữ liệu tại đây
if ((char)data[0] == ‘1’) {
digitalWrite(D0, LOW);
client.publish(m_topic, “LED ON”);
} else if ((char)data[0] == ‘0’) {
digitalWrite(D0, HIGH);
client.publish(m_topic, “LED OFF”);
}
}
Hàm này sẽ kiểm tra dữ liệu đọc được có = 1 không ?
+ Nếu có thì sẽ xuất chân D0 ra mức thấp -> Đèn ON -> Gửi dữ liệu lên topic
+ Nếu không thì sẽ xuất chân D0 ra mức cao -> Đèn OFF -> Gửi dữ liệu lên topic
Full source code
#include <ESP8266WiFi.h> #include <PubSubClient.h> const char* ssid = "NhaptenWiFi"; // Nhập tên WiFi const char* password = "Nhapmatkhau"; // Nhập Mật khẩu WiFi const char* mqttServer = "IPADDRESS"; // Nhập địa chỉ của server MQTT String clientId = "ClientESP8266"; // Client ID của mạch const char* m_topic = "Makerlab"; // Topic mình đã tạo ở trên WiFiClient espClient; PubSubClient client(espClient); long lastMsg = 0; char msg[50]; int value = 0; void setup() { pinMode(D0, OUTPUT); Serial.begin(115200); setup_wifi(); /* Hàm start - read Callback client */ client.setServer(mqttServer, 1883); client.setCallback(callback); } 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()); } /* Ham call back nhan lai du lieu */ void callback(char* topic, byte* payload, unsigned int length) { Serial.print("Message read ["); Serial.print(topic); Serial.print("] "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(); xulidulieu(payload); } void xulidulieu(byte* data) { if ((char)data[0] == '1') { digitalWrite(D0, LOW); client.publish(m_topic, "LED ON"); } else if ((char)data[0] == '0') { digitalWrite(D0, HIGH); client.publish(m_topic, "LED OFF"); } } void reconnect() { while (!client.connected()) { Serial.print("Attempting MQTT connection..."); if (client.connect(clientId.c_str())) { Serial.println("connected"); client.publish(m_topic, "Reconnect"); // Gửi dữ liệu client.subscribe(m_topic); // Theo dõi dữ liệu } else { Serial.print("failed, rc="); Serial.print(client.state()); // Doi 1s delay(1000); } } } void loop() { if (!client.connected()) { reconnect(); } client.loop(); }
Nếu NodeMCU kết nối thành công với Server bạn sẽ thấy chữ Reconnect trong sub topic Terminal (RasPi)
Bây giờ chúng ta sẽ dùng một Terminal publish dữ liệu lên topic để điều khiển đèn LED trên NodeMCU CP2102
Tắt đèn onBoard trên NodeMCU CP2102 bằng message “0”

Bật đèn onBoard trên NodeMCU CP2102 bằng message “1”

Sau khi tắt/bật đèn thì NodeMCU sẽ gửi dữ liệu “LED OFF”/”LED ON” về topic server , bạn sẽ thấy ở bên Terminal sub topic hiển thị dữ liệu gửi từ NodeMCU
Tổng Kết
Vậy trong bài này chúng ta đã:
+ Điều khiển đèn LED trên NodeMCU
+ Gửi và đọc dữ liệu lên topic thông qua NodeMCU CP2102
Bài này chỉ dừng ở mức giúp các bạn hiểu cách đọc và gủi dữ liệu lên topic của Client -> Topic -> Client . Nếu mỗi lần bạn muốn điều khiển cái gì thì chúng ta lại phải mở Pi lên và gõ lệnh … thì rất là củ chuối :)). Ở bài viết tới mình sẽ hướng dẫn về Node-Red và cách xây dựng giao diện Node-Red để điều khiển đèn led onBoard trên NodeMCU. Và RasPi của chúng ta vẫn đóng vai trò là Server
Chúc các bạn thành công với dự án của mình !