[Hướng dẫn sử dụng ESP8266] Phần 10: Ứng dụng thu thập dữ liệu với ESP8266 và Webserver

0
1740

Phần 10: Ứng dụng thu thập dữ liệu với ESP8266 và Webserver

Print

Hi các bạn, đã lâu rồi mới có thời gian để viết bài chia sẻ kiến thức sử dụng ESP8266 trong các ứng dụng Internet Of Thing. Trong bài viết này, chúng ta sẽ demo ứng dụng của ESP8266 trong thu thập dữ liệu (nhiệt độ, độ ẩm hay trạng thái công tắc, etc) từ thiết bị thông qua Webserver; đồng thời demo khả năng cấu hình và điều khiển thiết bị cũng từ webserver luôn

1/ Bước chuẩn bị

  • Phần cứng
    Một điện thoại smartphone (Android hoặc iOS)
    Một NodeMCU8266 Dev Kit
    TB2YB5XoXXXXXXdXpXXXXXXXXXX_!!1796335639.jpg_600x600[1]
Thông số kỹ thuật
– IC chính: ESP8266 Wifi SoC.
– Chip nạp và giao tiếp UART: CH340G.
– Cấp nguồn: 5VDC MicroUSB hoặc V-in.
– GIPO giao tiếp mức 3.3VDC
– Tích hợp Led báo trạng thái, nút Reset, Flash.
– Tương thích hoàn toàn với trình biên dịch Arduino.
Thông tin chi tiết có thể xem tại:
http://htelectronics.vn/san-pham/nodemcu-dev-kit-v0-9-esp8266/
NodeMCU Dev kit này tích hợp nút nhấn và giao tiếp USB phục vụ cho việc nạp chương trình trên Arduino IDE một cách dễ dàng và nhanh chóng (chúng ta không cần nối dây từ mạch USB-UART và module ESP8266). Ngoài ra tất cả các chân I/O của ESP8266 đều được đưa ra jumper trên board để có thể sử dụng các Peripheral của ESP8266 như UART1, SPI, I2C, PWM, etc
NodeMCU_v0.9_Pinout[1]
  • Phần mềm
    Chúng ta sẽ sử dụng phương thức lập trình cho ESP8266 với Arduino IDE đã được giới thiệu trong Phần 7. Ưu điểm lập trình nhanh chóng và hiệu quả khi sử dụng các thư viện open-source mà vẫn sử dụng được các Peripheral phần cứng của ESP luôn
    Quá trình cài đặt thư viện cho ESP8266 trong Arduino đã được giới thiệu trong Phần 7. Các bạn có thể đọc lại nếu cần thiết nha

2/ Thiết kế webserver

Trong ứng dụng này, chúng ta sẽ lập trình ESP8266 để hiện thị 1 giao diện web để hiện thị dữ liệu và thông tin cấu hình của thiết bị; cũng như các nút điều khiển thiết bị. Do đó, việc đầu tiên là cần phải thiết kế giao diện và cấu trúc dữ liệu của Webserver. Về cơ bản thì webserver chính là các text của các lệnh HTML sẽ được gửi cho các web client (chính là smarphone, laptop) để hiện thị trên các Web Browser như Safari, Chrome, Firefox.

Để nhanh chóng thiết kế giao diện của webserver mà không cần lập trình trước cho ESP8266, chúng ta có thể sử dụng các online tool để chạy thử các lệnh HTML đến khi hoàn chỉnh. Sau đó chúng ta có thể copy các lệnh HTML đã test và paste vào chương trình của ESP8266 trên Arduino IDE. Ví dụ các bạn có thể dụng Tryit Editor

Giao diện webserver của demo này bao gồm 3 phần

  • Phần cài đặt cấu hình cho cảm biến nhiệt độ
  • Phần cài đặt cấu hình cho cảm biến độ ẩm
  • Phần hiện thị giá trị cảm biến hiện tại và các giá trị cảm biến trước đó theo format .csv (các giá trị cách nhau bằng dấu ‘,’

Code HTML và kết quả test trên Tryit Editor như sau:

webserve_correct

Như các bạn có thể thấy, chúng ta có thể test trực tiếp code HTML mà chưa cần lập trình ESP8266.  Đến khi có code HTML hoàn chỉnh, chúng ta có thể sử dụng code HTML này trong chương trình ESP8266.

Sau đây chúng ta sẽ giải thích sơ qua về cấu trúc của code HTML cho demo này:

  • Tất cả nội dung của trang HTML sẽ nằm trong 2 tag là <html> và </html>
  • Chúng ta sử dụng tag <h1> </h1> để hiện thị các dòng tiêu đề. Ngoài <h1> còn có <h2>, <h3>, etc với font chữ nhỏ hơn
  • Để hiện thị giá trị, chúng ta sẽ sử dụng <input name='<name>’  value='<value>’ >
    <value> = giá trị hiện thị trong textbox
    <name> = tên textbox để reference trong code
  • Để hiện thị nút nhấn, chúng ta sẽ sử dụng <input type=’submit’ value='<label>’ >
    <label> = tên của nút nhấn
    Chú ý, ứng với mỗi nút nhấn chúng ta phải kèm theo 1 tag <form> </form> để định nghĩa 1 URI đặc trưng cho nút nhấn đó. Sau này trong code chúng ta sẽ sử dụng URI này để liên kết với 1 callback tương ứng.
    Ví dụ: Với nút nhấn “Ghi Cấu hình” cho cảm biến độ ẩm, URI sẽ là “/setHumidSensor”
    <form action=’/setHumidSensor’ method=’POST’> <input type=’submit’ name=’action’   value=’Ghi Cấu hình’><br><br></form>
    Với trường hợp cần submit các thông tin trong text box, tag <form> </form> cần phải bao các textbox muốn submit khi ấn nút tương ứng.
    Ví dụ: Khi ấn nút “Ghi cấu hình” của cảm biến độ ẩm, chúng ta muốn gửi các giá trị cấu hình của các textbox như “Số bit dữ liệu”, “Tần số lấy mẫu”, “Chu kỳ lấy mẫu”, nên tag <form> </form> sẽ bao luôn các dòng code HTML của các textbox này
  • Để hiện thị xuống hàng, chúng ta sử dụng tag <br>. Nếu cần xuống nhiều hàng thì cứ thêm <br> liên tiếp nhau. Nếu không sử dụng <br> thì các phần tử sẽ được layout trên cùng 1 hàng trên giao diện web
  • Để hiện thị 1 danh sách các giá trị, chúng ta có thể dùng tag <textarea> </textarea>. Chúng ta không dùng textbox trong trường hợp này vì cần hiện thị nhiều dòng của danh sách và có thể scroll up/down để xem toàn bộ danh sách

Code HTML hoàn chỉnh của webserver như sau:

<html> <h1>Cấu hình cảm biến độ ẩm</h1> <form action=’/setTempSensor’ method=’POST’> Số bit dữ liệu:<input name=’temp_resolution’ value=’10’> Tần số lấy mẫu:<input name=’temp_frequency’ value=’500′>(Hz)<br><br> Chu kỳ lấy mẫu:<input name=’temp_period’ value=’20’>(s)<br><br> <input type=’submit’ name=’action’ value=’Ghi Cấu hình’></form> <form action=’/getTempSensor’ method=’POST’> <input type=’submit’ name=’action’ value=’Đọc cấu hình’></form><br> <h1>Cấu hình cảm biến nhiệt độ</h1> <form action=’/setHumidSensor’ method=’POST’> Số bit dữ liệu:<input name=’humid_resolution’ value=’24’><br><br> Chu kỳ lấy mẫu:<input name=’humid_period’ value=’60’>(s)<br><br> <input type=’submit’ name=’action’ value=’Ghi Cấu hình’><br><br></form> <h1>Dữ liệu cảm biến</h1> Giá trị nhiệt độ hiện tại:<input name=’temp’ value=’28’>(độ C)<br> Log giá trị nhiệt độ(độ C):<br><textarea row=’30’ cols=’60’>26,26,28 </textarea><br><br> Giá trị độ ẩm hiện tại:<input name=’humid’ value=’90’>(%)<br> Log giá trị độ ẩm(%):<br><textarea row=’30’ cols=’60’> 89,100,95,95,96</textarea><br><br> <form action=’/startTesting’ method=’POST’><input type=’submit’ name=’action’ value=’Bắt đầu’></form> <form action=’/stopTesting’ method=’POST’><input type=’submit’ name=’action’ value=’Dừng lại’></form> </html>

Các bạn có thể thấy toàn bộ code là 1 dòng text rất dài như trên. Chúng ta sẽ tạo 1 biến kiểu String trong Arduino để chứa dòng text này và input vào API của thư viện Webserver để gửi đến web client

3/ Lập trình ESP8266 trong Arduino

Đến đây, chúng ta đã có mã code HTML hoàn chỉnh cho giao diện và cấu trúc dữ liệu của web server. Công việc tiếp theo là lập trình cho ESP8266 trong Arduino IDE.

Thư viện sử dụng

Với ứng dụng này, chúng ta sẽ sử dụng các thư viện open-source ESP8266Wifi và ESP8266WebServer. Các thư viện này đã được cài đặt khi chúng ta cài đặt thư viện cho board ESP8266.

Liên kết giá trị biến trong chương trình với code HTML của webserver

Câu hỏi đầu tiên là làm sao hiện thị giá trị biến trong chương trình trên webserver và làm sao lấy được giá trị input trên webserver để điều khiển trong code?

  • Để in giá trị của 1 biến trong code lên webserver, chúng ta chỉ đơn giản chuyển biến đó thành kiểu String và gắn vào vị trí của thuộc tính “value=” của textbox tương ứng.

Ví dụ, giả sử ta có biến “temperature_val”  chứa giá trị cảm biến nhiệt độ, để hiện thị giá trị của biến này trên webserver, chúng ta có thể làm như sau:

“….Giá trị nhiệt độ hiện tại:<input name=’temp’ value=” + String(temperature_val) + “>(độ C)…”

Ở đây chúng ta gắng text của giá trị cảm biến nhiệt độ vào thuộc tính “value” của textbox tương ứng

  • Để đọc giá trị người dùng điền trên giao diện của webserver, chúng ta có thể sử dụng API hasArg(“<name>”) trong hàm callback của 1 URI tương ứng. Ví dụ:

void handleSetTempSensor()
{
  if(server.hasArg(“temp_resolution”)) {
     temp_resolution = server.arg(“temp_resolution”).toInt();
  }
……….
}

Hàm handleSetTempSensor() là hàm callback khi user ấn nút “Ghi cấu hình” của phần cảm biến nhiệt độ trên webserver, biến “server” là 1 biến đối tượng Webserver trong code. Ở đây chúng ta sẽ kiểm tra kết quả submit có chứa textbox có trường “name” là “temp_resolution” không, nếu có thì chúng ta sẽ lấy giá trị của textbox đó dùng API arg() rồi chuyển thành kiểu integer với API toInt(), cuối cùng ghi vào biến tương ứng là “temp_resolution” sẽ được sử dụng trong code.

Flow chương trình hoàn chỉnh

  • Các khai báo global

#include <ESP8266Wifi.h>
#include <ESP8266WebServer.h>
ESP8266WebServer  server(80);
uint8_t TempSensor_Resolution, TempSensor_Frequency, TempSensor_Period;
uint32_t TempSensor_Value;
String TempSensor_Log;
uint8_t HumidSensor_Resolution, HumidSensor_Period;
uint32_t HumidSensor_Value;
String HumidSensor_Log;

  • Hàm setup()

Khởi động ESP8266 trong chế độ SoftAP với thông tin SSID và password. Lưu ý là password phải lớn hơn 11 ký tự.
WiFi.softAP(“<ssid>”, “<password>”);

Đăng ký các hàm callback cho các nút nhấn trên webserver:
server.on(“/”, handleRoot);
server.on(“/setTempSensor”,handleSetTempSensor);
server.on(“/getTempSensor”,handleGetTempSensor);
server.on(“/setHumidSensor”, handleSetHumidSensor);
server.on(“/startTesting”, handleStartTesting);
server.on(“/stopTesting”, handleStopTesting);

Bắt đầu chạy webserver
server.begin()

  • Hàm loop()
    Chỉ gọi API handleClient() để xử lý các event của Webserver
    server.handleClient()
  • Hàm buildWebserver()
    Tạo chuỗi text cho code HTML của webserver và hiện thị giá trị biến lên web page và gửi lên web client
String s = “<html>”;
s += “<h1>Cấu hình cảm biến độ ẩm</h1>”;
s += “<form action=’/setTempSensor’ method=’POST’>”;
s += “Số bit dữ liệu:<input name=’temp_resolution’ value=” + String(TempSensor_Resolution) + “>”;
s += “Tần số lấy mẫu:<input name=’temp_frequency’ value=” + String(TempSensor_Frequency) + “>(Hz)<br><br>”;
s += “Chu kỳ lấy mẫu:<input name=’temp_period’ value=” + String(TempSensor_Period) + “>(s)<br><br>”;
s += “<input type=’submit’ name=’action’ value=’Ghi Cấu hình’></form>”;
s += “<form action=’/getTempSensor’ method=’POST’>”;
s += “<input type=’submit’ name=’action’ value=’Đọc cấu hình’></form><br>”;
s += “<h1>Cấu hình cảm biến nhiệt độ</h1>”; s += “<form action=’/setHumidSensor’ method=’POST’>”;
s += “Số bit dữ liệu:<input name=’humid_resolution’ value=” + String(HumidSensor_Resolution) + “><br><br>”;
s += “Chu kỳ lấy mẫu:<input name=’humid_period’ value=” + String(HumidSensor_Period) + “>(s)<br><br>”;
s += “<input type=’submit’ name=’action’ value=’Ghi Cấu hình’><br><br></form>”; s += “<h1>Dữ liệu cảm biến</h1>”;
s += “Giá trị nhiệt độ hiện tại:<input name=’temp’ value=” + String(TempSensor_Value) + “>(độ C)<br>”;
s += “Log giá trị nhiệt độ(độ C):<br><textarea row=’30’ cols=’60’>” + TempSensor_Value + “</textarea><br><br>”;
s += “Giá trị độ ẩm hiện tại:<input name=’humid’ value=” + String(HumidSensor_Value) + “>(%)<br>”;
s += “Log giá trị độ ẩm(%):<br><textarea row=’30’ cols=’60’>” + HumidSensor_Log + “</textarea><br><br>”;
s += “<form action=’/startTesting’ method=’POST’><input type=’submit’ name=’action’ value=’Bắt đầu’></form>”;
s += “<form action=’/stopTesting’ method=’POST’><input type=’submit’ name=’action’ value=’Dừng lại’></form>”;
s += “</html>”;

Gửi nội dung lên web client
server.send(200, “text/html”, s);

Các bạn có thể chú ý cách hiện thị giá trị biến trong code chương trình lên giao diện webserver như đã giới thiệu ở trên. Sau này, sau khi thực hiện logic chương trình, cập nhật giá trị biến, chúng ta có thể gọi hàm buildWebserver() này để gửi giao diện webserver có cập nhật lên smarphone, máy tính.

  • Các hàm callback để đọc giá trị cấu hình từ người dùng thông qua Webserver
    void handleSetTempSensor() {
    if(server.hasArg(“temp_resolution”)) {
    TempSensor_Resolution = server.arg(“temp_resolution”).toInt();
    }
    if(server.hasArg(“temp_frequency”)) {
    TempSensor_Frequency = server.arg(“temp_frequency”).toInt();
    }
    if(server.hasArg(“temp_period”)) {
    TempSensor_Period = server.arg(“temp_period”).toInt();
    }
    //call functions to write sensor setting
    buidWebSever();
    }
void handleSetHumidSensor() {
if(server.hasArg(“humid_resolution”)) {
HumidSensor_Resolution = server.arg(“humid_resolution”).toInt();
}
if(server.hasArg(“humid_period”)) {
TempSensor_Period = server.arg(“temp_period”).toInt();
}
//call functions to write sensor setting
buidWebSever();
}
void handleGetTempSensor() {
//call functions to read sensor setting and store to TempSensor_*** variables
buidWebSever();
}
void handleGetHumidSensor() {
//call functions to read sensor setting and store to HumidSensor_*** variables
buidWebSever();
}
void handleStartTesting() {
//call functions to start humid and temperature sensors
buidWebSever();
}
void handleStopTesting() {
//call functions to stop humid and temperature sensors
buidWebSever();
}

Các bạn có thể thấy ở cuối các hàm callback, chúng ta đều gọi hàm buildWebserver() để gửi code HTML của webserver cho smartphone, máy tính. Nếu không gửi lại nội dung của website, trên smartphone và máy tính sẽ hiện thị trang web trống, không có nội dung

  • Hàm đọc giá trị cảm biến
    Giả sử chúng ta có 1 hàm readTempSensor() sẽ được gọi khi có dữ liệu cảm biến (thông qua timer hoặc thông qua interrupt). Trong hàm này chúng ta sẽ lưu giá trị cảm biến hiện tại vào TempSensor_Value và cập nhật danh sách các giá trị cảm biến nhiệt độ theo thời gian

    void readTempSensor() {
    TempSensor_Log += “,” + String(TempSensor_Value);
    // TempSensor_Value = function to read temp sensor
    }

Tương tự chúng ta có thể viết cho hàm readHumidSensor()

Nạp code vào NodeMCU 8266 Dev kit trong Arduino

Chúng ta sẽ thiết lập cấu hình nạp trong Arduino như hình sau:

arduion_settings

Kết nối USB cable từ dev kit đến máy tính, ấn nút FLASH trên board và ấn nút Download trên Arduino để tiến hành build code và nạp vào NodeMCU Dev Kit

Kết nối smartphone với ESP8266 webserver

Chúng ta có thể bật Wifi setting trên smartphone và kết nối vào mạng Wifi tạo bởi ESP8266. Sau khi kết nối thành công, mở trình duyệt web bất kỳ và truy cập vào địa chỉ IP 192.168.4.1 chính là địa chỉ IP mặc định của ESP8266 Webserver. Chúng ta sẽ thấy được giao diện web đã thiết kế và có thể tương tác với ESP8266 như cài đặt cấu hình, đọc giá trị hiện tại của cảm biến cũng như danh sách các giá trị trước đó.

Chúng ta có thể copy nội dung của log giá trị cảm biến và lưu thành file text có đuôi là .csv. Sau đó mở trong Excel để có thể vẽ graph, phân tích dữ liệu, v.v…

Bài viết đến đây là hết rồi. Cảm ơn các bạn đã theo dõi