Tải bản đầy đủ (.pdf) (20 trang)

ESP32 ESP8266 Đọc cảm biến biểu đồ trong biểu đồ thời gian thực Máy chủ web

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (639.3 KB, 20 trang )

ESP32 / ESP8266 Đọc cảm biến biểu đồ trong biểu đồ
thời gian thực - Máy chủ web
Tìm hiểu cách vẽ số đọc cảm biến (nhiệt độ, độ ẩm và áp suất) trên máy chủ web bằng
ESP32 hoặc ESP8266 với Arduino IDE. ESP sẽ lưu trữ một trang web với ba biểu đồ
thời gian thực có các bài đọc mới được thêm vào cứ sau 30 giây.

Tổng quan dự án
Trong hướng dẫn này, chúng ta sẽ xây dựng một máy chủ web không đồng bộ bằng cách
sử dụng thư viện ESPAsyncWebServer.
HTML để xây dựng trang web sẽ được lưu trữ trên Hệ thống tệp ESP32 hoặc ESP8266
(SPIFFS). Để tìm hiểu thêm về cách xây dựng máy chủ web bằng SPIFFS, bạn có thể
tham khảo các hướng dẫn tiếp theo:
Chúng tơi sẽ hiển thị các chỉ số nhiệt độ, độ ẩm và áp suất từ cảm biến BME280 trên
biểu đồ, nhưng bạn có thể sửa đổi dự án này để hiển thị số đọc cảm biến từ bất kỳ cảm
biến nào khác. Để tìm hiểu thêm về BME280, hãy đọc hướng dẫn của chúng tôi:
Để xây dựng biểu đồ, chúng ta sẽ sử dụng thư viện Highcharts. Chúng tôi sẽ tạo ba biểu
đồ: nhiệt độ, độ ẩm và áp suất theo thời gian. Biểu đồ hiển thị tối đa 40 điểm dữ liệu và
số đọc mới được thêm vào sau mỗi 30 giây, nhưng bạn thay đổi các giá trị này trong mã
của mình.

Xem video trình diễn
1/20


Để xem dự án hoạt động như thế nào, bạn có thể xem video minh họa sau:

Điều kiện tiên quyết
Hãy chắc chắn rằng bạn kiểm tra tất cả các điều kiện tiên quyết trong phần này trước khi
tiếp tục với dự án để biên dịch mã.

1. Cài đặt bảng ESP trong Arduino IDE


Chúng tơi sẽ lập trình ESP32 và ESP8266 bằng Arduino IDE. Vì vậy, bạn phải cài đặt tiện
ích bổ sung ESP32 hoặc ESP8266. Làm theo một trong các hướng dẫn tiếp theo để cài
đặt tiện ích bổ sung ESP:

2. Plugin Filesystem Uploader
Để tải tệp HTML lên bộ nhớ flash ESP32 và ESP8266, chúng tôi sẽ sử dụng plugin cho
Arduino IDE: Trình tải lên hệ thống tệp. Thực hiện theo một trong các hướng dẫn tiếp
theo để cài đặt trình tải lên hệ thống tệp tùy thuộc vào bảng bạn đang sử dụng:

3. Cài đặt thư viện
Để xây dựng máy chủ web không đồng bộ, bạn cần cài đặt các thư viện sau.
ESP32: bạn cần cài đặt ESPAsyncWebServer và các thư viện AsyncTCP.
ESP8266: bạn cần cài đặt ESPAsyncWebServer và các thư viện ESPAsyncTCP.
Các thư viện này khơng có sẵn để cài đặt thơng qua Trình quản lý thư viện Arduino, vì
vậy bạn cần sao chép các tệp thư viện vào thư mục Cài đặt Arduino.
Để đọc từ mô-đun cảm biến BME280, bạn cần cài đặt các thư viện tiếp theo:
Bạn có thể cài đặt các thư viện này thơng qua Trình quản lý thư viện Arduino.

Các bộ phận cần thiết

2/20


Để làm theo hướng dẫn này, bạn cần các phần sau:
ESP32 hoặc ESP8266 (đọc ESP32 so với ESP8266)
Cảm biến BME280
Breadboard
Dây nhảy

Sơ đồ

Mô-đun cảm biến BME280 mà chúng tôi đang sử dụng giao tiếp qua giao thức truyền
thơng I2C, vì vậy bạn cần kết nối nó với các chân ESP32 hoặc ESP8266 I2C.
Hệ thống dây điện BME280 với ESP32
BME280

ESP32

SCK (Ghim SCL)

GPIO 22 ·

SDI (chân SDA)

GPIO 21 ·

Vì vậy, hãy lắp ráp mạch của bạn như thể hiện trong sơ đồ tiếp theo.

3/20


Đề xuất đọc: Hướng dẫn tham khảo sơ đồ chân ESP32
Hệ thống dây điện BME280 với ESP8266
BME280

ESP8266

SCK (Ghim SCL)

GPIO 5 ·


SDI (chân SDA)

GPIO 4 ·

Lắp ráp mạch của bạn như trong sơ đồ tiếp theo nếu bạn đang sử dụng bảng ESP8266.

4/20


Đề xuất đọc: Hướng dẫn tham khảo sơ đồ chân ESP8266

Sắp xếp các tệp của bạn
Để xây dựng máy chủ web, bạn cần hai tệp khác nhau. Bản phác thảo Arduino và tệp
HTML. Tệp HTML nên được lưu bên trong một thư mục được gọi là dữ liệu bên trong
thư mục phác thảo Arduino, như hình dưới đây:

5/20


Tạo tệp HTML
Tạo file index.html với nội dung sau hoặc tải xuống tất cả các file project tại đây:

6/20


<!DOCTYPE HTML><html>



<head>

<meta name="viewport" content="width=device-width, initial-scale=1">

<script src=" />
<style>

body {

min-width: 310px;


max-width: 800px;


height: 400px;

margin: 0 auto;

}

h2 {


font-family: Arial;

font-size: 2.5rem;

text-align: center;

}

</style>

</head>

<body>

ESP Weather Station



<div id="chart-temperature" class="container"></div>

<div id="chart-humidity" class="container"></div>

<div id="chart-pressure" class="container"></div>

</body>

<script>

var chartT = new Highcharts.Chart({

chart:{ renderTo : 'chart-temperature' },


title: { text: 'BME280 Temperature' },

series: [{

showInLegend: false,

data: []

}],

plotOptions: {

line: { animation: false,

dataLabels: { enabled: true }

},

series: { color: '#059e8a' }

},

xAxis: { type: 'datetime',

dateTimeLabelFormats: { second: '%H:%M:%S' }

},

yAxis: {


title: { text: 'Temperature (Celsius)' }

//title: { text: 'Temperature (Fahrenheit)' }

},

credits: { enabled: false }

});

setInterval(function ( ) {

var xhttp = new XMLHttpRequest();

xhttp.onreadystatechange = function() {

7/20


if (this.readyState == 4 && this.status == 200) {

var x = (new Date()).getTime(),

y = parseFloat(this.responseText);

//console.log(this.responseText);

if(chartT.series[0].data.length > 40) {

chartT.series[0].addPoint([x, y], true, true, true);


} else {

chartT.series[0].addPoint([x, y], true, false, true);

}

}

};

xhttp.open("GET", "/temperature", true);

xhttp.send();

}, 30000 ) ;

var chartH = new Highcharts.Chart({

chart:{ renderTo:'chart-humidity' },

title: { text: 'BME280 Humidity' },

series: [{

showInLegend: false,

data: []

}],


plotOptions: {

line: { animation: false,

dataLabels: { enabled: true }

}

},

xAxis: {

type: 'datetime',

dateTimeLabelFormats: { second: '%H:%M:%S' }

},

yAxis: {

title: { text: 'Humidity (%)' }

},

credits: { enabled: false }

});

setInterval(function ( ) {


var xhttp = new XMLHttpRequest();

xhttp.onreadystatechange = function() {

if (this.readyState == 4 && this.status == 200) {

var x = (new Date()).getTime(),

y = parseFloat(this.responseText);

//console.log(this.responseText);

if(chartH.series[0].data.length > 40) {

chartH.series[0].addPoint([x, y], true, true, true);

} else {

chartH.series[0].addPoint([x, y], true, false, true);

}

}

};

xhttp.open("GET", "/humidity", true);

xhttp.send();


}, 30000 ) ;

var chartP = new Highcharts.Chart({

chart:{ renderTo:'chart-pressure' },

8/20


title: { text: 'BME280 Pressure' },

series: [{

showInLegend: false,

data: []

}],

plotOptions: {

line: { animation: false,

dataLabels: { enabled: true }

},

series: { color: '#18009c' }


},

xAxis: {

type: 'datetime',

dateTimeLabelFormats: { second: '%H:%M:%S' }

},

yAxis: {

title: { text: 'Pressure (hPa)' }

},

credits: { enabled: false }

});

setInterval(function ( ) {

var xhttp = new XMLHttpRequest();

xhttp.onreadystatechange = function() {

if (this.readyState == 4 && this.status == 200) {

var x = (new Date()).getTime(),


y = parseFloat(this.responseText);

//console.log(this.responseText);

if(chartP.series[0].data.length > 40) {

chartP.series[0].addPoint([x, y], true, true, true);

} else {

chartP.series[0].addPoint([x, y], true, false, true);

}

}

};

xhttp.open("GET", "/pressure", true);

xhttp.send();

}, 30000 ) ;

</script>

</html>


Xem mã thơ

Chúng ta hãy xem nhanh các phần có liên quan để xây dựng biểu đồ.
Trước tiên, bạn cần bao gồm thư viện highcharts:
<script src=" />
Bạn cần tạo phần <div> cho mỗi đồ họa có id duy nhất. Trong trường hợp này: nhiệt độ
biểu đồ, độ ẩm biểu đồ và áp suất biểu đồ.
<div id="chart-temperature" class="container"></div>

<div id="chart-humidity" class="container"></div>

<div id="chart-pressure" class="container"></div>

9/20


Để tạo biểu đồ và thêm dữ liệu vào biểu đồ, chúng tơi sử dụng mã javascript. Nó sẽ đi
vào bên trong thẻ <script> và </script>.
Các spinet sau đây tạo ra biểu đồ nhiệt độ. Bạn xác định id biểu đồ, bạn có thể đặt tiêu
đề, nhãn trục, v.v.
var chartT = new Highcharts.Chart({

chart:{ renderTo : 'chart-temperature' },

title: { text: 'BME280 Temperature' },

series: [{

showInLegend: false,

data: []


}],

plotOptions: {

line: { animation: false,

dataLabels: { enabled: true }

},

series: { color: '#059e8a' }

},

xAxis: { type: 'datetime',

dateTimeLabelFormats: { second: '%H:%M:%S' }

},

yAxis: {

title: { text: 'Temperature (Celsius)' }

//title: { text: 'Temperature (Fahrenheit)' }

},

credits: { enabled: false }


});

Sau đó, hàm setInvertal() thêm điểm vào biểu đồ. Cứ sau 30 giây, nó sẽ đưa ra yêu cầu
đến URL / temperature để nhận chỉ số nhiệt độ từ ESP32 hoặc ESP8266 của bạn.
setInterval(function ( ) {

var xhttp = new XMLHttpRequest();

xhttp.onreadystatechange = function() {

if (this.readyState == 4 && this.status == 200) {

var x = (new Date()).getTime(),

y = parseFloat(this.responseText);

//console.log(this.responseText);

if(chartT.series[0].data.length > 40) {

chartT.series[0].addPoint([x, y], true, true, true);

} else {

chartT.series[0].addPoint([x, y], true, false, true);

}

}


};

xhttp.open("GET", "/temperature", true);

xhttp.send();

}, 30000 ) ;

Các đồ họa khác được tạo ra theo cách tương tự. Chúng tôi đưa ra yêu cầu trên URL
/moisture và /pressure để có được chỉ số độ ẩm và áp suất tương ứng.

10/20


Trong bản phác thảo Arduino, chúng ta nên xử lý những gì xảy ra khi chúng ta nhận
được những yêu cầu đó: chúng ta nên gửi các bài đọc cảm biến tương ứng.

Bản phác thảo Arduino
Sao chép đoạn mã sau vào Arduino IDE hoặc tải xuống tất cả các tệp dự án tại đây.
Sau đó, bạn cần nhập thơng tin đăng nhập mạng của mình (SSID và mật khẩu) để làm
cho nó hoạt động.

11/20


/*********

Rui Santos

Complete project details at


Permission is hereby granted, free of charge, to any person obtaining a copy

of this software and associated documentation files.

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

*********/

// Import required libraries

#ifdef ESP32

#include <WiFi.h>

#include <ESPAsyncWebServer.h>

#include <SPIFFS.h>

#else

#include <Arduino.h>

#include <ESP8266WiFi.h>

#include <Hash.h>

#include <ESPAsyncTCP.h>


#include <ESPAsyncWebServer.h>

#include <FS.h>

#endif

#include <Wire.h>

#include <Adafruit_Sensor.h>

#include <Adafruit_BME280.h>

/*#include <SPI.h>

#define BME_SCK 18

#define BME_MISO 19

#define BME_MOSI 23

#define BME_CS 5*/

Adafruit_BME280 bme; // I2C

//Adafruit_BME280 bme(BME_CS); // hardware SPI

//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI

// Replace with your network credentials


const char* ssid = "REPLACE_WITH_YOUR_SSID";

const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Create AsyncWebServer object on port 80

AsyncWebServer server(80);

String readBME280Temperature() {

// Read temperature as Celsius (the default)

float t = bme.readTemperature();

// Convert temperature to Fahrenheit

//t = 1.8 * t + 32;

if (isnan(t)) {


Serial.println("Failed to read from BME280 sensor!");

return "";

}

else {

Serial.println(t);


12/20


return String(t);

}

}

String readBME280Humidity() {

float h = bme.readHumidity();

if (isnan(h)) {

Serial.println("Failed to read from BME280 sensor!");

return "";

}

else {

Serial.println(h);

return String(h);

}


}

String readBME280Pressure() {

float p = bme.readPressure() / 100.0F;

if (isnan(p)) {

Serial.println("Failed to read from BME280 sensor!");

return "";

}

else {

Serial.println(p);

return String(p);

}

}

void setup(){

// Serial port for debugging purposes

Serial.begin(115200);


bool status;

// default settings

// (you can also pass in a Wire library object like &Wire2)

status = bme.begin(0x76);

if (!status) {

Serial.println("Could not find a valid BME280 sensor, check wiring!");

while (1);

}

// Initialize SPIFFS

if(!SPIFFS.begin()){

Serial.println("An Error has occurred while mounting SPIFFS");

return;

}

// Connect to Wi-Fi

WiFi.begin(ssid, password);


while (WiFi.status() != WL_CONNECTED) {

delay(1000);

Serial.println("Connecting to WiFi..");

}

// Print ESP32 Local IP Address

Serial.println(WiFi.localIP());

13/20


// Route for root / web page

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){

request->send(SPIFFS, "/index.html");

});

server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){

request->send_P(200, "text/plain", readBME280Temperature().c_str());

});

server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){


request->send_P(200, "text/plain", readBME280Humidity().c_str());

});

server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest *request){

request->send_P(200, "text/plain", readBME280Pressure().c_str());

});

// Start server

server.begin();

}



void loop(){

}


Xem mã thô

Cách mã hoạt động
Chúng ta hãy xem nhanh mã và xem nó hoạt động như thế nào.
Bao gồm các thư viện
Đầu tiên, bao gồm các thư viện cần thiết. Bạn bao gồm các thư viện khác nhau tùy thuộc

vào bảng bạn đang sử dụng. Nếu bạn đang sử dụng ESP32, mã sẽ tải các thư viện sau:
#include
#include
#include
#include
#include
#include

<WiFi.h>

<ESPAsyncWebServer.h>

<SPIFFS.h>

<WiFi.h>

<ESPAsyncWebServer.h>

<SPIFFS.h>

Nếu bạn đang sử dụng ESP8266, mã sẽ tải các thư viện sau:
#include
#include
#include
#include
#include
#include
#include
#include
#include


<Arduino.h>

<ESP8266WiFi.h>

<Hash.h>

<ESPAsyncTCP.h>

<ESPAsyncWebServer.h>

<FS.h>

<Wire.h>

<Adafruit_Sensor.h>

<Adafruit_BME280.h>

Tạo một phiên bản để giao tiếp với cảm biến BME280 bằng I2C:

14/20


Adafruit_BME280 bme; // I2C

Chèn thông tin đăng nhập mạng của bạn vào các biến sau:
// Replace with your network credentials

const char* ssid = "REPLACE_WITH_YOUR_SSID";


const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Tạo đối tượng AsyncWebServer trên cổng 80:
AsyncWebServer server(80);

Đọc nhiệt độ, độ ẩm và áp suất
Sau đó, chúng ta tạo ba hàm readBME280Temperature(), readBME280Humidity() và
readBME280Pressure(). Các chức năng này yêu cầu nhiệt độ, độ ẩm và áp suất từ cảm
biến BME280 và trả về số đọc dưới dạng loại Chuỗi.
String readBME280Temperature() {

// Read temperature as Celsius (the default)

float t = bme.readTemperature();

// Convert temperature to Fahrenheit

//t = 1.8 * t + 32;

if (isnan(t)) {

Serial.println("Failed to read from BME280 sensor!");

return "";

}

else {


Serial.println(t);

return String(t);

}

}

Init BME280
Trong setup(), khởi tạo cảm biến:
status = bme.begin(0x76);

if (!status) {

Serial.println("Could not find a valid BME280 sensor, check wiring!");

while (1);

}

Init SPIFFS
Khởi tạo hệ thống tệp (SPIFFS):
if(!SPIFFS.begin()){

Serial.println("An Error has occurred while mounting SPIFFS");

return;

}


Kết nối với Wi-Fi
Kết nối với Wi-Fi và in địa chỉ IP trong Màn hình nối tiếp:
15/20


WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {

delay(1000);

Serial.println("Connecting to WiFi..");

}

// Print ESP32 Local IP Address

Serial.println(WiFi.localIP());

Xử lý yêu cầu
Sau đó, chúng ta cần xử lý những gì xảy ra khi ESP nhận được yêu cầu.
Khi nó nhận được yêu cầu trên URL gốc, chúng tôi sẽ gửi văn bản HTML được lưu trong
SPIFFS dưới tên chỉ mục.html:
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){

request->send(SPIFFS, "/index.html");

});

Khi chúng tôi nhận được yêu cầu trên các URL /temperature, /moisture hoặc /pressure,

hãy gọi các hàm trả về số đọc cảm biến.
Ví dụ: nếu chúng ta nhận được một yêu cầu trên URL /temperature, chúng ta gọi hàm
readBME280Temperature() trả về nhiệt độ.
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){

request->send_P(200, "text/plain", readBME280Temperature().c_str());

});

Điều tương tự cũng xảy ra đối với các bài đọc khác.
Cuối cùng, khởi động máy chủ:
server.begin();

Bởi vì đây là một máy chủ web khơng đồng bộ, chúng tơi khơng cần phải viết bất cứ điều
gì trong vòng lặp ().
void loop(){

}

Tải lên mã và tệp
Lưu mã dưới dạng ESP_Chart_Web_Server hoặc tải xuống tất cả các tệp dự án tại đây.
Đi tới Sketch > Show Sketch Folder và tạo một thư mục có tên data. Bên trong thư mục
đó, bạn nên lưu tệp HTML đã tạo trước đó.
Bây giờ bạn cần tải tệp HTML lên hệ thống tệp ESP32 hoặc ESP8266. Đi tới Công cụ >
Tải lên bản phác thảo dữ liệu ESP32 / ESP8266 và đợi các tệp được tải lên.

16/20


Sau đó, tải mã lên bảng của bạn. Đảm bảo rằng bạn đã chọn đúng bo mạch và cổng

COM. Ngoài ra, hãy đảm bảo bạn đã chèn thông tin đăng nhập mạng của mình vào mã.

Khi mọi thứ được tải lên thành cơng, hãy mở Màn hình nối tiếp với tốc độ truyền là
115200. Nhấn nút "EN / RST" trên bảng và nó sẽ in địa chỉ IP của nó.

17/20


Cuộc biểu tình
Mở trình duyệt trên mạng cục bộ của bạn và nhập địa chỉ IP ESP32 hoặc ESP8266. Bạn
sẽ thấy ba biểu đồ. Một điểm dữ liệu mới được thêm vào cứ sau 30 giây với tổng số 40
điểm. Dữ liệu mới tiếp tục được hiển thị trên biểu đồ miễn là bạn mở tab trình duyệt web
của mình.
Dưới đây là một ví dụ về biểu đồ độ ẩm:

Bạn có thể chọn từng điểm để xem dấu thời gian chính xác.

18/20


Tổng kết
Trong hướng dẫn này, bạn đã học cách tạo biểu đồ để hiển thị dữ liệu trong máy chủ web
của mình. Bạn có thể sửa đổi dự án này để tạo bao nhiêu biểu đồ tùy thích và sử dụng
bất kỳ cảm biến nào khác.
Tiếp theo, chúng tôi khuyên bạn nên xây dựng một dự án hiển thị biểu đồ từ dữ liệu được
lưu trữ trên cơ sở dữ liệu của bạn. Dưới đây là các hướng dẫn khác mà bạn có thể thích:

19/20



Hình dung các bài đọc cảm biến ESP32 / ESP8266 của bạn từ mọi nơi trên thế giới
ESP32 / ESP8266 Chèn dữ liệu vào Cơ sở dữ liệu MySQL bằng PHP và Arduino
IDE
Cảm ơn bạn đã đọc.

20/20



×