Chỉ số cảm biến hiển thị trong đồng hồ đo với Máy chủ web ESP8266

Chỉ số cảm biến hiển thị trong đồng hồ đo với Máy chủ web ESP8266

>>> 100+ Mã Sản Phẩm Dây Rút: https://mecsu.vn/san-pham/day-rut-nhua.5op

>>> 1000+ Mã Sản Phẩm Đầu Cosse: https://mecsu.vn/san-pham/dau-cosse.Q1j

Tổng quan về dự án máy chủ web ESP8266

Chúng tôi mong muốn xây dựng một trang web sẽ hiển thị số đọc cảm biến trong đồng hồ đo thu được từ BME280 được kết nối với ESP8266 NodeMCU. Chúng tôi sẽ tạo một máy chủ web dựa trên giao thức Sự kiện do máy chủ gửi (SSE) sẽ hiển thị hai loại đồng hồ đo để hiển thị số đọc của cảm biến. Nó sẽ bao gồm một tiêu đề, "Máy chủ web đồng hồ đo ESP" và hai thẻ. Thẻ đầu tiên sẽ chứa tiêu đề 'Độ ẩm' và đồng hồ đo xuyên tâm để hiển thị số đọc độ ẩm từ cảm biến BME280. Tương tự như vậy, thẻ thứ hai sẽ chứa tiêu đề 'Nhiệt độ' và đồng hồ đo tuyến tính để hiển thị số đọc nhiệt độ từ cảm biến BME280.

Việc truyền dữ liệu này từ máy chủ (ESP8266) đến máy khách (trang web) sẽ diễn ra thông qua Sự kiện do máy chủ gửi. Các bài đọc này sẽ tự động cập nhật sau mỗi 10 giây lên các giá trị mới khi trang web nhận được chúng. Thông qua giao thức SSE, sẽ rất dễ dàng cập nhật các chỉ số cảm biến trên trang web của chúng tôi mà không cần thêm bất kỳ yêu cầu bổ sung nào.

Lưu ý: Chúng tôi sẽ sử dụng thư viện JavaScript canvas-gauges để giúp chúng tôi tạo hai đồng hồ đo.

Quy trình làm việc

  1. Máy khách bắt đầu kết nối SSE. Nó gửi một yêu cầu HTTP đến mô-đun ESP8266. Điều này sẽ khiến mô-đun gửi sự kiện đến trang web.

  2. ESP8266 được kết nối với BME280 nhận được kết quả đọc cảm biến sau mỗi 10 giây.

  3. Các sự kiện 'new_readings' bao gồm chuỗi JSON bao gồm các số đọc nhiệt độ và áp suất.

  4. Các sự kiện do mô-đun gửi này có người nghe sự kiện được liên kết với chúng ở phía máy khách. Tất cả các bài đọc cập nhật đều được khách hàng nhận được về các sự kiện nói trên.

  5. Như trong trường hợp với SSE, chỉ bảng ESP8266 mới có thể gửi các sự kiện đến trang web. Trang web được cập nhật tương ứng và quá trình này vẫn tiếp tục.

Tổng quan về dự án máy chủ web ESP8266

Giới thiệu về cảm biến BME280

Các bài đọc được đề xuất:MicroPython: Máy chủ web BME280 với ESP32 / ESP8266 (Trạm thời tiết)MicroPython:
BME280 với ESP32 và ESP8266

Cảm biến BME280 được sử dụng để đo các chỉ số liên quan đến nhiệt độ môi trường, áp suất khí quyển và độ ẩm tương đối. Nó chủ yếu được sử dụng trong các ứng dụng web và di động, nơi tiêu thụ điện năng thấp là chìa khóa. Cảm biến này sử dụng+để giao tiếp dữ liệu với các bộ điều khiển vi mô. Mặc dù có một số phiên bản BME280 khác nhau có sẵn trên thị trường, nhưng phiên bản chúng tôi sẽ nghiên cứu sử dụng giao thức truyền thông I2C và SPI.

Kết nối cảm biến BME280 với bo mạch phát triển ESP8266

Việc kết nối BME280 với bo mạch NodeMCU ESP8266 rất dễ dàng. Chúng ta phải kết nối thiết bị đầu cuối VCC với 3.3V, nối đất với mặt đất (mặt bằng chung), SCL của cảm biến với chân SCL của ESP8266 và SDA của cảm biến với chân SDA của bảng ESP8266.

Chân I2C trong ESP8266 NodeMCU cho SDA là D2 (GPIO4) và cho SCL là D1 (GPIO5).

Các thành phần bắt buộc

Chúng tôi sẽ cần các thành phần sau để kết nối bảng NodeMCU ESP8266 với cảm biến BME280.

  1. Bảng mạch ESP8266 NodeMCU

  2. Cảm biến BME280

  3. Dây kết nối

  4. Breadboard

Thực hiện theo sơ đồ bên dưới cho mô-đun NodeMCU ESP8266 và kết nối chúng cho phù hợp.

BME280 giao diện với ESP8266 NodeMCU Arduino IDE

Trong một số cảm biến BME280 như được thấy trong sơ đồ kết nối ở trên, thiết bị đầu cuối SCK có nghĩa là chân SCL và được kết nối với chân GPIO tương ứng của nó trên ESP8266 NodeMCU. Tương tự như vậy, thiết bị đầu cuối SDI có nghĩa là chân SDA và được kết nối với chân GPIO tương ứng trên bo mạch. Vin được kết nối với chân 3.3V trên mô-đun và cả bo mạch ESP và cảm biến BME280 đều thường được nối đất.

Thiết lập Arduino IDE

Chúng tôi sẽ sử dụng Arduino IDE để lập trình bảng phát triển ESP8266 của chúng tôi. Vì vậy, bạn nên có phiên bản Arduino IDE mới nhất. Ngoài ra, bạn cũng sẽ yêu cầu tiện ích bổ sung ESP8266 NodeMCU được cài đặt trên Arduino IDE của mình. Nếu bạn chưa cài đặt nó trước khi bạn có thể làm theo hướng dẫn này:

Ngoài ra, bạn sẽ phải tải xuống và cài đặt Plugin tải lên hệ thống tệp ESP8266 NodeMCU trong Arduino IDE của mình để bạn có thể tải lên các tệp LittleFS trên bảng NodeMCU ESP8266 của mình. Nếu chưa, bạn có thể làm theo hướng dẫn sau:

Cài đặt thư viện BME280

Vì chúng tôi đang kết nối cảm biến BME280 với ESP8266, vì vậy chúng tôi sẽ phải cài đặt thư viện BME280 vào mô-đun của mình. Chúng tôi sẽ yêu cầu hai thư viện cho dự án này:

  1. Thư viện Adafruit BME280

  2. Thư viện cảm biến hợp nhất Adafruit

Chúng tôi sẽ sử dụng Trình quản lý thư viện trong Arduino IDE của chúng tôi để cài đặt các phiên bản mới nhất của thư viện. Mở Arduino IDE của bạn và đi tới Sketch > Bao gồm thư viện > Quản lý thư viện. Nhập từng tên thư viện vào thanh tìm kiếm và cài đặt cả hai.

Adafruit BME280 thư viện Arduino IDE

Cài đặt thư viện cảm biến hợp nhất Adafruit

Cài đặt ESPAsyncWebServer và ESPAsyncThư viện TCP

Thư viện ESPAsyncWebServer sẽ giúp chúng tôi tạo máy chủ web của mình một cách dễ dàng. Với thư viện này, chúng tôi sẽ thiết lập một máy chủ web không đồng bộ. Thư viện ESPAsyncTCP cũng sẽ được kết hợp vì nó là một phụ thuộc cho thư viện ESPAsyncWebServer. Hai thư viện này không có sẵn trong trình quản lý thư viện Arduino. Do đó, chúng tôi sẽ phải tự tải xuống và tải chúng trên bảng ESP8266 của mình.

  • Để cài đặt miễn phí thư viện ESPAsyncWebServer. Bạn sẽ tải xuống thư viện dưới dạng thư mục .zip mà bạn sẽ giải nén và đổi tên thành 'ESPAsyncWebServer.' Sau đó, chuyển thư mục này vào thư mục thư viện cài đặt trong Arduino IDE của bạn.

  • Để cài đặt miễn phí thư viện TCP ESPAsync. Bạn sẽ tải xuống thư viện dưới dạng thư mục .zip mà bạn sẽ giải nén và đổi tên thành 'ESPAsyncTCP.' Sau đó, chuyển thư mục này vào thư mục thư viện cài đặt trong Arduino IDE của bạn.

Tương tự như vậy, bạn cũng có thể vào Sketch > Include Library > Add .zip Library bên trong IDE để thêm các thư viện.

Cài đặt Arduino_JSON viện

Bạn cũng sẽ phải cài đặt thư viện Arduino_JSON vì chúng ta sẽ xử lý tập lệnh JSON. Mở Trình quản lý thư viện Arduino của bạn bằng cách nhấp vào Phác thảo > Bao gồm thư viện > Quản lý thư viện. Nhập 'Arduino_JSON' vào tab tìm kiếm và nhấn enter. Cài đặt thư viện được đánh dấu bên dưới.

Thư viện Arduino_Json của Arduino Install

Sau khi cài đặt các thư viện, hãy khởi động lại IDE của bạn.

Tạo tệp cho LittleFS

Trong hầu hết các dự án của chúng tôi đã bao gồm các tệp HTML và CSS bên trong bản phác thảo Arduino của mình. Chúng tôi lưu các tài liệu HTML này bên trong bản phác thảo Arduino bằng cách chuyển đổi chúng thành các chuỗi. Bất cứ khi nào một ứng dụng khách web đưa ra yêu cầu HTTTP, chúng tôi sẽ gửi chuỗi này dưới dạng phản hồi, về cơ bản là một trang web.

Ngược lại, với LittleFS, chúng ta có thể lưu các tệp HTML, CSS và Javascript trong hệ thống tệp flash NodeMCU ESP8266. Bất cứ khi nào một ứng dụng khách web đưa ra yêu cầu HTTTP, chúng tôi có thể phục vụ các tệp này trực tiếp từ LittleFS.

Để xây dựng máy chủ web ESP8266 NodeMCU bằng LittleFS, chúng tôi sẽ tạo ba tệp khác nhau: HTML, CSS và Arduino sketch và sắp xếp chúng trong một thư mục dự án như hình dưới đây:

ESP Gauges Web Server tạo tệp cho SPIFFS

Lưu ý: Bạn nên đặt các tệp HTML, CSS và JavaScript bên trong thư mục dữ liệu. Nếu không, thư viện LittleFS sẽ không thể đọc các tệp này.

Bạn có thể đọc hướng dẫn máy chủ web LittleFS trước đây của chúng tôi với ESP8266:

Tạo tệp HTML

Bên trong tệp HTML của chúng tôi, chúng tôi sẽ chỉ định tiêu đề của trang web và hai thẻ để hiển thị đồng hồ đo.

Bây giờ, hãy tạo một tệp chỉ mục.html và sao chép mã được cung cấp bên dưới trong tệp đó.

<!DOCTYPE html>

<html>

  <head>

    <title>ESP Gauges Web Server</title>

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

    <link rel="icon" type="image/png" href="favicon.png">

    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">

    <link rel="stylesheet" type="text/css" href="style.css">

    http://cdn.rawgit.com/Mikhus/canvas-gauges/gh-pages/download/2.1.7/all/gauge.min.js

  </head>

  <body>

    <div class="topnav">

      <h1>ESP Gauges Web Server</h1>

    </div>

    <div class="content">

      <div class="card-grid">

        <div class="card">

          <p class="card-title">Humidity</p>

          <canvas id="gauge-humidity"></canvas>

        </div>

        <div class="card">

          <p class="card-title">Temperature</p>

          <canvas id="gauge-temperature"></canvas>

        </div>

      </div>

    </div>

    http://script.js

  </body>

</html>

Xây dựng trang Web

Chúng tôi sẽ bắt đầu với tiêu đề của trang web. Thẻ sẽ cho biết phần đầu của <title> và thẻ </title> sẽ cho biết kết thúc. Ở giữa các thẻ này, chúng tôi sẽ chỉ định "Máy chủ web đồng hồ đo ESP" sẽ được hiển thị trên thanh tiêu đề của trình duyệt.

    <title>ESP Gauges Web Server</title>

Tiếp theo, chúng tôi sẽ tạo một thẻ meta để đảm bảo máy chủ web của chúng tôi có sẵn cho tất cả các trình duyệt, ví dụ: điện thoại thông minh, máy tính xách tay, máy tính, v.v.

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

Giữa các thẻ <head></head>, chúng ta sẽ tham chiếu đến tập tin CSS vì chúng ta sẽ tạo các tập tin khác nhau cho cả HTML và CSS bằng cách sử dụng thẻ <link>. Thẻ này sẽ được sử dụng để chúng ta có thể liên kết với một biểu định kiểu bên ngoài mà chúng ta sẽ chỉ định dưới dạng tệp CSS. Nó sẽ bao gồm ba thuộc tính. Cái đầu tiên là rel cho thấy mối quan hệ giữa tệp hiện tại và tệp đang được liên kết.

Chúng tôi sẽ chỉ định "biểu định kiểu" sẽ thay đổi hình ảnh của trang web. Thuộc tính thứ hai là type mà chúng ta sẽ chỉ định là "text/css" vì chúng ta sẽ sử dụng tập tin CSS cho mục đích tạo kiểu. Thuộc tính thứ ba là href và nó sẽ chỉ định vị trí của tệp được liên kết. Cả hai tệp (HTML & CSS) sẽ được lưu trong cùng một thư mục (dữ liệu) vì vậy chúng tôi sẽ chỉ định tên của tệp CSS là "style.css."

Thân thể

Bên trong nội dung trang web HTML, chúng tôi sẽ bao gồm tiêu đề và các thẻ sẽ hiển thị đồng hồ đo với số đọc cảm biến. Điều này sẽ đi vào bên trong các thẻ <body></body> sẽ đánh dấu phần đầu và phần cuối của tập lệnh.

Chúng tôi sẽ bao gồm tiêu đề của trang web của chúng tôi bên trong các thẻ <h1>< / h1> và nó sẽ là "Máy chủ web đồng hồ đo ESP".

<h1>ESP Gauges Web Server</h1>

Tiếp theo, các dòng mã sau đây sẽ được sử dụng để tạo hai đồng hồ đo. Chúng tôi đã bao gồm hai thẻ mà chúng tôi sẽ sử dụng để hiển thị đồng hồ đo. Thẻ đầu tiên có tiêu đề 'Độ ẩm' và có <canvas> id 'gauge-humidity' sẽ được sử dụng sau này để hiển thị đồng hồ đo xuyên tâm. Tương tự như vậy, thẻ thứ hai có tiêu đề 'Nhiệt độ' và có <canvas> id 'đo nhiệt độ' sẽ được sử dụng sau này để hiển thị đồng hồ đo tuyến tính.

    </div>

    <div class="content">

      <div class="card-grid">

        <div class="card">

          <p class="card-title">Humidity</p>

          <canvas id="gauge-humidity"></canvas>

        </div>

        <div class="card">

          <p class="card-title">Temperature</p>

          <canvas id="gauge-temperature"></canvas>

        </div>

      </div>

    </div>

Tạo tệp CSS

Tiếp theo, tạo một tệp "kiểu.css" khác trong thư mục dữ liệu và sao chép mã được cung cấp bên dưới trong tệp đó. CSS được sử dụng để cung cấp các kiểu cho một trang web.

html {

  font-family: New Times Roman; 

  display: inline-block; 

  text-align: center;

}

h1 {

  font-size: 2.0rem; 

  color: white;

}

p { 

  font-size: 1.6rem;

}

.topnav { 

  overflow: hidden; 

  background-color: #111d88;

}

body {  

  margin: 0;

}

.content { 

  padding: 5%;

}

.card-grid { 

  max-width: 1200px; 

  margin: 0 auto; 

  display: grid; 

  grid-gap: 2rem; 

  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));

}

.card { 

  background-color: white; 

  box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5);

}

.card-title { 

  font-size: 1.4rem;

  font-weight: bold;

  color: #034078

}

Để thêm các tệp CSS vào thẻ head, chúng ta sẽ sử dụng các thẻ <style></style> để đánh dấu phần đầu và phần cuối. Chúng tôi sẽ đặt văn bản hiển thị thành loại phông chữ Times New Roman và căn chỉnh nó ở giữa trang web. Kích thước phông chữ, màu sắc và vị trí của tiêu đề, đoạn văn và thẻ cũng sẽ được đặt.

Tạo tệp JavaScript

Bây giờ hãy tạo một tệp khác trong thư mục dữ liệu và đặt tên là 'tập lệnh.js.' Tệp JavaScript sẽ chịu trách nhiệm xử lý các sự kiện SSE và tạo đồng hồ đo bằng cách sử dụng thư viện đồng hồ đo canvas.

// Get current sensor readings when the page loads  

window.addEventListener('load', getReadings);

 

// Create Temperature Gauge

var gaugeTemperature = new LinearGauge({

  renderTo: 'gauge-temperature',

    width: 120,

    height: 400,

    units:"Degree Celsius",

    minValue: 0,

    maxValue: 50,

    majorTicks: [

        "0",

        "10",

        "20",

        "30",

        "40",

        "50",

    ],

    minorTicks: 10,

    strokeTicks: true,

    highlights: [

        {

            "from": 25,

            "to": 50,

            "color": "rgba(200, 50, 50, .75)"

        }

    ],

    colorPlate: "transparent",

    borderShadowWidth: 0,

    borders: false,

    needleType: "arrow",

    needleWidth: 2,

    animationDuration: 1500,

    animationRule: "linear",

    tickSide: "both",

    numberSide: "left",

    needleSide: "both",

    barStrokeWidth: 7,

    barBeginCircle: false,

}).draw();

  

// Create Humidity Gauge

var gaugeHumidity = new RadialGauge({

    renderTo: 'gauge-humidity',

    width: 300,

    height: 300,

    units: "%",

    title: "Humidity",

    minValue: 0,

    maxValue: 100,

    majorTicks: [

        0,

        10,

        20,

        30,

        40,

        50,

        60,

        70,

        80,

        90,

        100,

        

    ],

    minorTicks: 2,

    strokeTicks: true,

    highlights: [

        {

            "from": 0,

            "to": 50,

            "color": "rgba(0,0, 255, .3)"

        },

        {

            "from": 50,

            "to": 100,

            "color": "rgba(255, 0, 0, .3)"

        }

    ],

    ticksAngle: 225,

    startAngle: 67.5,

    colorMajorTicks: "#ddd",

    colorMinorTicks: "#ddd",

    colorTitle: "#eee",

    colorUnits: "#ccc",

    colorNumbers: "#eee",

    colorPlate: "#222",

    borderShadowWidth: 0,

    borders: true,

    needleType: "arrow",

    needleWidth: 2,

    needleCircleSize: 7,

    needleCircleOuter: true,

    needleCircleInner: false,

    animationDuration: 1500,

    animationRule: "linear",

    colorBorderOuter: "#333",

    colorBorderOuterEnd: "#111",

    colorBorderMiddle: "#222",

    colorBorderMiddleEnd: "#111",

    colorBorderInner: "#111",

    colorBorderInnerEnd: "#333",

    colorNeedleShadowDown: "#333",

    colorNeedleCircleOuter: "#333",

    colorNeedleCircleOuterEnd: "#111",

    colorNeedleCircleInner: "#111",

    colorNeedleCircleInnerEnd: "#222",

    valueBoxBorderRadius: 0,

    colorValueBoxRect: "#222",

    colorValueBoxRectEnd: "#333"

}).draw();

 

// Function to get current readings on the webpage when it loads for the first time

function getReadings(){

  var xhr = new XMLHttpRequest();

  xhr.onreadystatechange = function() {

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

      var myObj = JSON.parse(this.responseText);

      console.log(myObj);

      var temp = myObj.temperature;

      var hum = myObj.humidity;

      gaugeTemperature.value = temp;

      gaugeHumidity.value = hum;

    }

  }; 

  xhr.open("GET", "/readings", true);

  xhr.send();

}

 

if (!!window.EventSource) {

  var source = new EventSource('/events');

  

  source.addEventListener('open', function(e) {

    console.log("Events Connected");

  }, false);

 

  source.addEventListener('error', function(e) {

    if (e.target.readyState != EventSource.OPEN) {

      console.log("Events Disconnected");

    }

  }, false);

  

  source.addEventListener('message', function(e) {

    console.log("message", e.data);

  }, false);

  

  source.addEventListener('new_readings', function(e) {

    console.log("new_readings", e.data);

    var myObj = JSON.parse(e.data);

    console.log(myObj);

    gaugeTemperature.value = myObj.temperature;

    gaugeHumidity.value = myObj.humidity;

  }, false);

}

Dòng sau gọi hàm getReadings khi trang web tải.

window.addEventListener('load', getReadings);

Tạo đồng hồ đo

Để xây dựng đồng hồ đo, chúng tôi sẽ sử dụng Chúng tôi sẽ hiển thị hai loại đồng hồ đo: tuyến tính và xuyên tâm. Số đọc nhiệt độ sẽ được hiển thị trong một máy đo tuyến tính trông giống như một nhiệt kế. Tương tự, chỉ số độ ẩm sẽ được hiển thị trong một máy đo xuyên tâm.

Để tạo một máy đo tuyến tính cho nhiệt độ, chúng tôi sẽ sử dụng các dòng mã sau:

VaR 'gaugeTemperature' sẽ được sử dụng để tạo ra thước đo tuyến tính bằng phương pháp LinearGauge(). Phương pháp này lấy một số tham số liên quan đến kích thước, giá trị tối thiểu / tối đa, màu sắc và hình ảnh tổng thể của đồng hồ đo. Hơn nữa, chúng tôi chỉ định id 'đo nhiệt độ' sẽ được sử dụng để đặt đúng máy đo này trong phần tử HTML <canvas> với id thích hợp. Sử dụng phương thức draw() để hiển thị thước đo.

var gaugeTemperature = new LinearGauge({

  renderTo: 'gauge-temperature',

    width: 120,

    height: 400,

    units:"Degree Celsius",

    minValue: 0,

    maxValue: 50,

    majorTicks: [

        "0",

        "10",

        "20",

        "30",

        "40",

        "50",

    ],

    minorTicks: 10,

    strokeTicks: true,

    highlights: [

        {

            "from": 25,

            "to": 50,

            "color": "rgba(200, 50, 50, .75)"

        }

    ],

    colorPlate: "transparent",

    borderShadowWidth: 0,

    borders: false,

    needleType: "arrow",

    needleWidth: 2,

    animationDuration: 1500,

    animationRule: "linear",

    tickSide: "both",

    numberSide: "left",

    needleSide: "both",

    barStrokeWidth: 7,

    barBeginCircle: false,

}).draw();

Tương tự như vậy, để tạo một máy đo xuyên tâm để hiển thị chỉ số độ ẩm, chúng tôi sẽ sử dụng các dòng mã sau:

VaR 'gaugeHumidity' sẽ được sử dụng để tạo ra thước đo tuyến tính bằng phương pháp RadialGauge(). Phương pháp này lấy một số tham số liên quan đến kích thước, giá trị tối thiểu / tối đa, màu sắc và hình ảnh tổng thể của đồng hồ đo. Hơn nữa, chúng tôi chỉ định id 'đo độ ẩm' sẽ được sử dụng để đặt đúng máy đo này trong phần tử HTML <canvas> với id thích hợp. Sử dụng phương thức draw() để hiển thị thước đo.

// Create Humidity Gauge

var gaugeHumidity = new RadialGauge({

    renderTo: 'gauge-humidity',

    width: 300,

    height: 300,

    units: "%",

    title: "Humidity",

    minValue: 0,

    maxValue: 100,

    majorTicks: [

        0,

        10,

        20,

        30,

        40,

        50,

        60,

        70,

        80,

        90,

        100,

        

    ],

    minorTicks: 2,

    strokeTicks: true,

    highlights: [

        {

            "from": 0,

            "to": 50,

            "color": "rgba(0,0, 255, .3)"

        },

        {

            "from": 50,

            "to": 100,

            "color": "rgba(255, 0, 0, .3)"

        }

    ],

    ticksAngle: 225,

    startAngle: 67.5,

    colorMajorTicks: "#ddd",

    colorMinorTicks: "#ddd",

    colorTitle: "#eee",

    colorUnits: "#ccc",

    colorNumbers: "#eee",

    colorPlate: "#222",

    borderShadowWidth: 0,

    borders: true,

    needleType: "arrow",

    needleWidth: 2,

    needleCircleSize: 7,

    needleCircleOuter: true,

    needleCircleInner: false,

    animationDuration: 1500,

    animationRule: "linear",

    colorBorderOuter: "#333",

    colorBorderOuterEnd: "#111",

    colorBorderMiddle: "#222",

    colorBorderMiddleEnd: "#111",

    colorBorderInner: "#111",

    colorBorderInnerEnd: "#333",

    colorNeedleShadowDown: "#333",

    colorNeedleCircleOuter: "#333",

    colorNeedleCircleOuterEnd: "#111",

    colorNeedleCircleInner: "#111",

    colorNeedleCircleInnerEnd: "#222",

    valueBoxBorderRadius: 0,

    colorValueBoxRect: "#222",

    colorValueBoxRectEnd: "#333"

}).draw();

Nhận bài đọc

getReadings() sẽ chịu trách nhiệm thu được số đọc cảm biến BME280 hiện tại.

 

function getReadings(){

  var xhr = new XMLHttpRequest();

  xhr.onreadystatechange = function() {

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

      var myObj = JSON.parse(this.responseText);

      console.log(myObj);

      var temp = myObj.temperature;

      var hum = myObj.humidity;

      gaugeTemperature.value = temp;

      gaugeHumidity.value = hum;

    }

  }; 

  xhr.open("GET", "/readings", true);

  xhr.send();

}

Thông qua chức năng này, yêu cầu HTTP GET sẽ được thực hiện đến mô-đun ESP liên quan đến việc gửi số đọc cảm biến BME280.

Bên trong hàm này chúng ta sử dụng XMLHttpRequest. Điều này sẽ cho phép chúng tôi thực hiện một yêu cầu HTTP trong JavaScript. Để làm HTTP GET request chúng ta sẽ làm theo ba bước:Thứ nhất, chúng ta sẽ tạo một XMLHttpRequest như sau:

var xhr = new XMLHttpRequest();

Thứ hai, chúng ta sẽ khởi tạo request bằng cách sử dụng phương thức xhr.open(). Bên trong nó, chúng tôi sẽ truyền lại ba lập luận. Đối số đầu tiên chỉ định loại phương thức HTTP là GET trong trường hợp của chúng ta. Đối số thứ hai là URL mà ESP32 sẽ yêu cầu. Trong trường hợp của chúng tôi, nó sẽ là / bài đọc. Đối số cuối cùng là true, trong đó chỉ định rằng yêu cầu là không đồng bộ.

 xhr.open("GET", "/readings", true);

Cuối cùng, chúng ta sẽ sử dụng xhr.send() để mở kết nối. Máy chủ của chúng tôi (ESP32) bây giờ sẽ có thể nhận được yêu cầu HTTP GET bất cứ khi nào trang tải lần đầu tiên.

xhr.send();

Ngoài ra, chúng ta sẽ định nghĩa một hàm sẽ được thực thi khi thuộc tính readyState thay đổi. Trong trường hợp của chúng tôi, chúng tôi đã đặt phản hồi sẽ được gửi khi trạng thái là OK (200) và readyState thành '4' có nghĩa là phản hồi đã sẵn sàng.

Bây giờ, như phản hồi, bảng ESP32 gửi các số đọc cảm biến trong một chuỗi JSON. Chuỗi này trước tiên sẽ được chuyển đổi thành một đối tượng JSON và được ghi lại trên bảng điều khiển. Hơn nữa, để đặt số đọc của đồng hồ đo, chúng tôi sẽ đặt giá trị của đồng hồ đo với số đọc cảm biến hiện tại. Trong trường hợp của chúng tôi, đồng hồ đo nhiệt độ được gọi là 'gaugeTemperature' do đó chúng tôi sẽ đặt giá trị của nó bằng cách sử dụng gaugeTemperature.value thành temp (đọc nhiệt độ hiện tại). Tương tự, đối với máy đo độ ẩm, chúng tôi sẽ sử dụng gaugeHumidity.value để hum (đọc độ ẩm hiện tại).

  xhr.onreadystatechange = function() {

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

      var myObj = JSON.parse(this.responseText);

      console.log(myObj);

      var temp = myObj.temperature;

      var hum = myObj.humidity;

      gaugeTemperature.value = temp;

      gaugeHumidity.value = hum;

    }

  }; 

Tiếp nhận và xử lý các sự kiện SSE

Chúng tôi chủ yếu sẽ xử lý bốn loại sự cố:

  1. Kết nối

  2. Ngắt kết nối

  3. Tin nhắn được gửi bởi máy chủ

  4. Sự kiện

Đầu tiên, chúng ta sẽ định nghĩa một nguồn sự kiện và truyền URL /events bên trong nó. URL này sẽ gửi các bản cập nhật đến trang web của chúng tôi.

if (!!window.EventSource) {

  var source = new EventSource('/events');

Sau đó, chúng ta sẽ sử dụng hàm addEventListener() để lắng nghe các sự kiện đến. Nó sẽ có hai lập luận. Đầu tiên sẽ là tên sự kiện và thứ hai sẽ là hàm (e).

Sau đây là những người nghe để kết nối, ngắt kết nối và tin nhắn đến từ máy chủ. Chúng tôi đã sử dụng trình nghe sự kiện mặc định trong trường hợp này được liệt kê trong Tài liệu.

  source.addEventListener('open', function(e) {

    console.log("Events Connected");

  }, false);

 

  source.addEventListener('error', function(e) {

    if (e.target.readyState != EventSource.OPEN) {

      console.log("Events Disconnected");

    }

  }, false);

  

  source.addEventListener('message', function(e) {

    console.log("message", e.data);

  }, false);

Tiếp theo, chúng tôi sẽ bao gồm listener cho 'new_readings'. Sự kiện này sẽ được gửi đến máy chủ web. Khi khách hàng sẽ nhận được sự kiện cụ thể, nó sẽ in số đọc cảm biến BME280 trên bảng điều khiển trình duyệt. Ngoài ra, các số đọc sẽ được thay đổi thành một đối tượng JSON, sau đó sẽ được hiển thị trên các đồng hồ đo tương ứng của chúng.

 

  source.addEventListener('new_readings', function(e) {

    console.log("new_readings", e.data);

    var myObj = JSON.parse(e.data);

    console.log(myObj);

    gaugeTemperature.value = myObj.temperature;

    gaugeHumidity.value = myObj.humidity;

  }, false);

Arduino Sketch ESP8266 Đồng hồ đo Máy chủ Web

Bây giờ, hãy mở Arduino IDE của bạn và đi tới Tệp > Mới để mở một tệp mới. Sao chép mã được cung cấp bên dưới trong tệp đó và lưu nó dưới dạng 'ESP_Web_Server'.

Hãy nhớ thay thế thông tin đăng nhập mạng của bạn.

#include <Arduino.h>

#include <ESP8266WiFi.h>

#include <ESPAsyncTCP.h>

#include <ESPAsyncWebServer.h>

#include <LittleFS.h>

#include <Arduino_JSON.h>

#include <Adafruit_BME280.h>

#include <Adafruit_Sensor.h>

 

// Replace with your network credentials

const char* ssid = "YOUR_SSID";

const char* password = "YOUR_PASSWORD";

 

AsyncWebServer server(80);

AsyncEventSource events("/events");

 

JSONVar readings;

 

unsigned long previous_time = 0;

unsigned long Delay = 10000;

 

Adafruit_BME280 bme; 

 

// Get Sensor Readings and return JSON object

String getReadings(){

  readings["temperature"] = String(bme.readTemperature());

  readings["humidity"] =  String(bme.readHumidity());

  String jsonString = JSON.stringify(readings);

  return jsonString;

}

 

void setup() {

  Serial.begin(115200);

  if (!bme.begin(0x76)) {

    Serial.println("Could not find BME280 sensor, check circuit!");

    while (1);

  }

 

  WiFi.mode(WIFI_STA);

  WiFi.begin(ssid, password);

  Serial.println(" ");

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

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

    Serial.print('.');

    delay(1000);

  }

  Serial.println(WiFi.localIP());

 

   // Initialize LittleFS

  if(!LittleFS.begin()){

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

    return;

  }

 

  // Web Server Root URL

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

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

  });

 

  server.serveStatic("/", LittleFS, "/");

 

  // Request for the latest sensor readings

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

    String json = getReadings();

    request->send(200, "application/json", json);

    json = String();

  });

 

  events.onConnect([](AsyncEventSourceClient *client){

    if(client->lastId()){

      Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId());

    }

    client->send("hello!", NULL, millis(), 10000);

  });

  server.addHandler(&events);

  server.begin();

}

 

void loop() {

  if ((millis() - previous_time) > Delay) {

    Serial.println(getReadings());

    events.send("ping",NULL,millis());

    events.send(getReadings().c_str(),"new_readings" ,millis());

    previous_time = millis();

  }

}

Mã hoạt động như thế nào?

Đầu tiên, chúng tôi sẽ bao gồm các thư viện cần thiết. Vì chúng tôi phải kết nối ESP8266 của mình với mạng không dây, do đó chúng tôi cần thư viện ESP8266WiFi.h cho mục đích đó. Các thư viện ESPAsyncWebServer.h và ESPAsyncTCP.h là những thư viện mà chúng tôi đã tải xuống gần đây và sẽ được yêu cầu để xây dựng máy chủ web không đồng bộ. Thư viện Adafruit_BME280 được sử dụng để triển khai các chức năng phần cứng của cảm biến trong khi Adafruit_Sensor là một thư viện cảm biến thống nhất. Ngoài ra, thư viện Arduino_JSON sẽ được sử dụng vì chúng ta sẽ sử dụng chuỗi JSON để lưu trữ số đọc cảm biến. Ngoài ra, thư viện LittleFS sẽ cho phép chúng tôi truy cập hệ thống tệp bộ nhớ flash của lõi ESP8266 của chúng tôi.

#include <Arduino.h>

#include <ESP8266WiFi.h>

#include <ESPAsyncTCP.h>

#include <ESPAsyncWebServer.h>

#include <LittleFS.h>

#include <Arduino_JSON.h>

#include <Adafruit_BME280.h>

#include <Adafruit_Sensor.h>

Tiếp theo, chúng ta sẽ tạo hai biến toàn cục, một biến cho SSID và một biến khác cho mật khẩu. Chúng sẽ giữ thông tin đăng nhập mạng của chúng tôi sẽ được sử dụng để kết nối với bộ định tuyến không dây của chúng tôi. Thay thế cả hai bằng thông tin đăng nhập của bạn để đảm bảo kết nối thành công.

const char* ssid = "YOUR_SSID";

const char* password = "YOUR_PASSWORD";

Tạo một đối tượng AsyncWebServer

Đối tượng AsyncWebServer sẽ được sử dụng để thiết lập máy chủ web ESP8266. Chúng ta sẽ truyền cổng HTTP mặc định là 80, làm đầu vào cho hàm xây dựng. Đây sẽ là cổng nơi máy chủ sẽ lắng nghe các yêu cầu.

AsyncWebServer server(80);

Xác định một EventSource

Tiếp theo, chúng ta sẽ định nghĩa một nguồn sự kiện có tên là '/events.' Bạn có thể sử dụng bất kỳ tên thích hợp nào.

AsyncEventSource events("/events");

Xác định biến

Chúng ta sẽ tạo một biến JSON được gọi là 'số đọc' để lưu trữ số đọc của cảm biến.

JSONVar readings;

Thêm độ trễ

Máy chủ web sẽ cập nhật số đọc của cảm biến sau mỗi 10 giây. Chúng tôi sẽ kết hợp giá trị này trong biến 'Độ trễ' tính bằng mili giây.

unsigned long previous_time = 0;

unsigned long Delay = 10000;

Tạo đối tượng BME280

Ngoài ra, chúng tôi cũng sẽ tạo một đối tượng của Adafruit_BME280 gọi là 'bme' mà chúng tôi sẽ sử dụng sau này để khởi tạo cảm biến và truy cập các bài đọc.

Adafruit_BME280 bme;

Nhận kết quả đọc cảm biến

Hàm getReadings() sau đây sẽ trả về một chuỗi JSON bao gồm các số đọc nhiệt độ và độ ẩm. Chúng ta sẽ sử dụng đối tượng bme trên các phương thức sau: readTemperature() và readHumidity() riêng lẻ để truy cập vào mỗi lần đọc.

String getReadings(){

  readings["temperature"] = String(bme.readTemperature());

  readings["humidity"] =  String(bme.readHumidity());

  String jsonString = JSON.stringify(readings);

  return jsonString;

}

thiết lập()

Bên trong hàm setup(), chúng ta sẽ mở một kết nối nối tiếp với tốc độ truyền là 115200.

  Serial.begin(115200);

Tiếp theo chúng ta sẽ khởi tạo cảm biến BME280. Nếu kết nối giữa mô-đun và cảm biến không chính xác, nó sẽ in thông báo đó trên màn hình nối tiếp.

  if (!bme.begin(0x76)) {

    Serial.println("Could not find BME280 sensor, check circuit!");

    while (1);

  }

Phần mã sau đây sẽ kết nối bo mạch ESP8266 của chúng tôi với mạng cục bộ có thông tin đăng nhập mạng mà chúng tôi đã chỉ định ở trên. Sau khi kết nối được thiết lập, địa chỉ IP của bo mạch ESP8266 sẽ được in trên màn hình nối tiếp. Điều này sẽ giúp chúng tôi thực hiện một yêu cầu đến máy chủ.

  WiFi.mode(WIFI_STA);

  WiFi.begin(ssid, password);

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

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

    Serial.print('.');

    delay(1000);

  }

  Serial.println(WiFi.localIP());

Những dòng mã này sẽ khởi tạo LittleFS.

   // Initialize LittleFS

  if(!LittleFS.begin()){

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

    return;

  }

Xử lý yêu cầu

Chúng ta sẽ sử dụng phương thức on() trên đối tượng server để lắng nghe các HTTP request đến và thực thi các hàm cho phù hợp. Phương thức send() sử dụng để trả về phản hồi HTTP.

File index.html sẽ gửi đến client, bất cứ khi nào server sẽ nhận được request trên URL "/".

  // Web Server Root URL

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

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

  });

 

  server.serveStatic("/", LittleFS, "/");

Khi máy chủ sẽ nhận được yêu cầu trên URL /readings, chuỗi JSON với số đọc cảm biến BME280 hiện tại sẽ được gửi.

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

    String json = getReadings();

    request->send(200, "application/json", json);

    json = String();

  });

Nguồn sự kiện sẽ được thiết lập trên bảng ESP8266 của chúng tôi kỹ lưỡng các dòng mã sau:

 

  events.onConnect([](AsyncEventSourceClient *client){

    if(client->lastId()){

      Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId());

    }

    client->send("hello!", NULL, millis(), 10000);

  });

  server.addHandler(&events);

Để start server, chúng ta sẽ gọi begin() trên đối tượng server của chúng ta.

  server.begin();

vòng lặp()

Trong hàm loop(), chúng tôi sẽ kiểm tra xem 10 giây đã trôi qua chưa kể từ khi số đọc cảm biến được cập nhật. Sau đó, chúng ta sẽ gọi hàm getReadings(). Trên màn hình nối tiếp, các số đọc cảm biến hiện tại này sẽ được hiển thị dưới dạng chuỗi JSON. Cuối cùng, chúng tôi sẽ gửi tất cả các bài đọc cảm biến cập nhật này đến trình duyệt web. Máy chủ web bây giờ sẽ được cập nhật lên các bài đọc cảm biến mới.

void loop() {

  if ((millis() - previous_time) > Delay) {

    Serial.println(getReadings());

    events.send("ping",NULL,millis());

    events.send(getReadings().c_str(),"new_readings" ,millis());

    previous_time = millis();

  }

}

Demonstration

Thực hiện theo các bước chặt chẽ để đảm bảo tất cả các tệp HTML, CSS và JavaScript được tải lên bộ nhớ flash của bảng phát triển của bạn.

  • Lưu bản phác thảo Arduino được đưa ra ở trên.

  • Chọn đúng bảng và cổng COM. Đi tới Bảng > Công cụ và chọn NodeMCU 1.0. Tiếp theo, đi tới Công cụ > Cổng và chọn cổng thích hợp mà qua đó bảng của bạn được kết nối.

chọn bảng ESP8266 NodeMCU

 

  • Trước khi tải bản phác thảo lên bảng ESP8266 của bạn, trước tiên hãy chuyển đến Phác thảo > Hiển thị Thư mục Phác thảo. Thao tác này sẽ mở ra thư mục lưu bản phác thảo Arduino của bạn. Bây giờ hãy tạo một thư mục mới bên trong thư mục đó và lưu nó dưới dạng 'dữ liệu'. Đặt tất cả các tệp bên trong thư mục dữ liệu. Nếu không, thư viện LittleFS sẽ không thể đọc chúng.

  • Bây giờ, chúng tôi sẽ tải các tệp lên bảng ESP8266 của chúng tôi. Đi tới Công cụ > Tải lên dữ liệu ESP8266 LittleFS.

Tải dữ liệu phác thảo LittleFS lên hệ thống tệp esp8266

Sau một lúc, các tệp sẽ được tải lên. Bạn sẽ nhận được thông báo 'LittleFS Image Uploaded' trên cửa sổ gỡ lỗi.

Lưu ý: Đảm bảo rằng tổng kích thước của tệp dữ liệu nằm trong kích thước bộ nhớ flash. Nếu không, bạn sẽ gặp lỗi khi tải tệp lên LittleFS.

  • Nhấp vào nút tải lên để tải mã lên bảng phát triển ESP8266.

  • Sau khi bạn đã tải mã của mình lên bảng phát triển, hãy nhấn nút RST của nó.

Nút đặt lại ESP8266 NodeMCU

Trong Arduino IDE của bạn, hãy mở màn hình nối tiếp và bạn sẽ có thể thấy địa chỉ IP của mô-đun ESP8266 của mình.

ESP8266 Đồng hồ đo Web Server Project nối tiếp màn hình demo

Sao chép địa chỉ đó vào trình duyệt web và nhấn enter. Máy chủ web sẽ trông giống như thế này:

ESP8266 Đồng hồ đo dự án máy chủ web Chế độ xem máy tính xách tay

Bạn có thể xem cả ba lần đọc cảm biến Sau mỗi 10 giây, số đọc của cảm biến sẽ được cập nhật trên cả màn hình nối tiếp và trang web.

ESP8266 Đồng hồ đo Dự án Máy chủ Web Dạng xem Di động

 

Bài viết cùng chuyên mục

NHANH

NHANH

Vì Đổi mới liên tục nên Nhanh hơn

ĐÚNG

ĐÚNG

Coi trọng và ưu tiên việc làm Đúng

ĐỦ

ĐỦ

Tìm và mua Đủ Đơn hàng hơn

KỊP THỜI

KỊP THỜI

Hiệu suất tối ưu bởi Kịp Thời hơn