آموزش ساخت ایستگاه هواشناسی با ESP8266 و BME280 به زبان ساده

آموزش ساخت ایستگاه هواشناسی با ESP8266 و BME280 به زبان ساده

با ساخت ایستگاه هواشناسی با ESP8266 و BME280 دیگر به برنامه‌های آب و هوای گوشی‌های هوشمند یا ایستگاه‌های تجاری گزارش آب و هوا (که اطلاعات آن‌ها بر اساس ایستگاه‌هایی است که ممکن است کیلومترها دورتر از شما باشد) نیاز نخواهید داشت و به‌وسیله این پروژه اینترنت اشیا می‌توانید با اطمینان بیشتری برنامه‌های بیرون از خانه را تدارک ببینید.

این پروژه از ESP8266 NodeMCU به عنوان یک دستگاه کنترل کننده استفاده می‌کند که به سادگی به یکی از شبکه‌های وای‌فای موجود متصل می‌شود. این کنترل کننده وب سروری می‌سازد تا هر یک از دستگاه‌های متصل به شبکه‌ با دسترسی به این وب سرور بتوانند پارامترهای دما، رطوبت، فشار هوا و ارتفاع از سطح دریا را از سنسور BME280 خوانده و با یک رابط کاربری زیبا، به مرورگر وب ارسال می‌کند. هیجان‌انگیز است نه؟ پس بیایید شروع کنیم!

سنسور دما، رطوبت و فشار BME280

برای ساخت ایستگاه هواشناسی با ESP8266 در ابتدا نیاز است نگاهی به ماژول BME280 بیندازیم.

ماژول سنسور BME280 توسط شرکت Bosch ساخته شده و به عنوان نسل جدیدی از سنسورهای دما، رطوبت و فشار شناخته می‌شود. این سنسور جایگزین بهبودیافته سنسورهایی مانند BMP180، BMP085 و BMP183 است.

ماژول سنسور BME280 برای ساخت ایستگاه هواشناسی با ESP8266

ولتاژ کاری ماژول BME280، از 3.3 تا 5 ولت است که برای کار با میکروکنترلرهایی مانند ESP8266 ایده‌آل است.

ارتباط با این ماژول با پروتکل ساده دو سیمه I2C انجام می‌گیرد. آدرس I2C ماژول BME280 به صورت پیش‌فرض برابر 0x76 است که البته این آدرس قابل تغییر است.

نحوه اتصال سنسور BME280 به ماژول ESP8266 NodeMCU

اتصالات نسبتاً ساده هستند. ابتدا پین VIN را به خروجی 3.3 ولت برد ESP8266 NodeMCU، و GND را به زمین متصل کنید.

سپس پین SCL را به پین کلاک I2C برد ESP8266 یعنی D1 متصل کنید و در نهایت، پین SDA را به پین داده I2C یعنی D2 وصل کنید.

شکل زیر نحوه اتصالات ماژول BME280 برای ساخت ایستگاه هواشناسی با ESP8266 را نشان می‌دهد:

نحوه اتصال پایه‌های ماژول BME280 به ESP8266

آماده‌سازی IDE آردوینو

یک افزونه برای آردوینو وجود دارد که به شما اجازه می‌دهد با استفاده از IDE آردوینو، ESP8266 NodeMCU را پروگرم کنید. اگر تا به حال با ESP8266 کار نکرده‌اید، آموزش زیر را دنبال کنید:


نصب کتابخانه برای ارتباط با BME280

برقراری ارتباط با BME280 ساده نیست و نیاز به کار دارد. اما خوشبختانه با استفاده از کتابخانه Adafruit BME280، می‌توانیم بدون درگیری با پیچیدگی‌های آن و با کمک دستورات ساده‌­ای می‌توانیم دما، رطوبت و فشار بارومتریک را بخوانیم.

برای نصب کتابخانه به مسیر Arduino IDE > Sketch > Include Library > Manage Libraries بروید. صبر کنید تا Library Manager لیست کتابخانه‌ها را دانلود کرده و لیست کتابخانه‌های نصب شده را آپدیت کند.

 سپس جستجوی خود را با نوشتن عبارت ‘bme280’ فیلتر کنید. از بین چند گزینه‌ای که می‌بینید، Adafruit BME280 Library از Adafruit را پیدا کرده و آن را نصب کنید.

جستجو کردن کتابخانه Adafruit BME280 Library در library manager

کتابخانه سنسور BME280 از کتابخانه Adafruit Unified Sensor استفاده می‌کند. پس این کتابخانه را نیز جستجو و نصب کنید.

نصب کتابخانه Adafruit BME280 Library برای ساخت ایستگاه هواشناسی با esp8266

نمایش دما، رطوبت، فشار و ارتفاع از سطح دریا بر روی وب سرور ESP8266

در این مرحله می‌خواهیم ESP8266 خود را در مد ایستگاه (STA) تنظیم کنیم و یک وب سرور بسازیم. این وب سرور قرار است صفحات وب را به هر سرویس­‌گیرنده‌ای که به شبکه­‌ی موجود متصل است، تحویل دهد.

اگر می‌خواهید در مورد ساخت وب سرور با ESP8266 NodeMCU در مدهای AP و STA بیشتر بدانید، آموزش زیر را دنبال کنید:


برای کارکرد درست برنامه، قبل از اینکه برنامه را آپلود کنید ابتدا باید تغییری در آن اعمال کنید. در واقع آنچه باید انجام دهید این است که دو متغیر زیر را برحسب مشخصات شبکه خود تغییر دهید. با این کار ESP8266 می‌تواند به شبکه موجود متصل شود.

const char* ssid = "YourNetworkName";  // Enter SSID here
const char* password = "YourPassword";  //Enter Password here

پس از انجام تغییرات، برنامه زیر را امتحان کنید:

#include <ESP8266WebServer.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme;

float temperature, humidity, pressure, altitude;

/*Put your SSID & Password*/
const char* ssid = "YourNetworkName";  // Enter SSID here
const char* password = "YourPassword";  //Enter Password here

ESP8266WebServer server(80);              
 
void setup() {
  Serial.begin(115200);
  delay(100);
  
  bme.begin(0x76);   

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

  //connect to your local wi-fi network
  WiFi.begin(ssid, password);

  //check wi-fi is connected to wi-fi network
  while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected..!");
  Serial.print("Got IP: ");  Serial.println(WiFi.localIP());

  server.on("/", handle_OnConnect);
  server.onNotFound(handle_NotFound);

  server.begin();
  Serial.println("HTTP server started");

}
void loop() {
  server.handleClient();

دسترسی به وب سرور

پس از آپلود برنامه، سریال مانیتور را باز و بادریت را بر روی 115200 تنظیم کنید. سپس دکمه RST روی NodeMCU را فشار دهید. اگر همه چیز درست باشد، پیغام HTTP server started به همراه یک آدرس IP داینامیک نمایش داده می‌شود. این همان آدرسی است که از روتر شما گرفته شده­‌است.

آدرس آی‌پی داینامیک نمایش داده شده پس از تنظیم بادریت و ریست کردن esp8266

حال یک مرورگر باز کنید و آدرس آی‌پی که از سریال مانیتور دریافت کردید را در آن وارد نمایید. ESP8266 باید صفحه وبی را تحویل دهد که مقادیر دما، رطوبت، فشار و ارتفاع از سطح دریا که توسط BME280 اندازه­‌گیری شده را نشان می‌دهد.

نمایش مقادیر گرفته شده از ماژول BME280 در صفحه وب ایستگاه هواشناسی

توضیح جزئیات کد

برنامه با اضافه کردن توابع زیر شروع می‌شود:

  • ESP8266WebServer.h: این کتابخانه توابع مربوط به وای­‌فای ESP8266 را ارائه می‌کند که برای اتصال به شبکه آن‌ها را فراخوانی می‌کنیم. این کتابخانه همچنین شامل توابعی است که به ما در ساخت یک وب سرور و مدیریت درخواست‌های HTTP دریافتی، بدون نگرانی در مورد برنامه‌نویسی سطح پایین کمک می­کند.
  • Wire.h: این کتابخانه با هر دستگاهی که از پروتکل I2C پشتیبانی کند مانند BME280 ارتباط برقرار می‌کند.
  • Adafruit_BME280.h و Adafruit_Sensor.h: این کتابخانه‌های سخت‌افزاری، مدیریت توابع سطح پایین را برعهده دارند.
#include <ESP8266WebServer.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

سپس متغیرهایی برای ذخیره دما، رطوبت، فشار و ارتفاع و همچنین یک شی از سنسور ایجاد می‌کنیم.

#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme;

float temperature, humidity, pressure, altitude;

سپس متغیرهایی برای ذخیره دما، رطوبت، فشار و ارتفاع و همچنین یک شی از سنسور ایجاد می­‌کنیم.

در این پروژه ESP8266 را در مد STA تنظیم کردیم، پس این ماژول باید به شبکه وای­‌فای موجود متصل شود. در نتیجه باید پسورد و SSID شبکه خود را به آن بدهیم. سپس وب سرور را با پورت 80 راه‌­اندازی می‌کنیم

/*Put your SSID & Password*/
const char* ssid = "YourNetworkName";  // Enter SSID here
const char* password = "YourPassword";  //Enter Password here

ESP8266WebServer server(80);

تابع ()Setup

درون تابع setup، قبل از اجرای سرور HTTP ابتدا آن را کانفیگ می­‌کنیم.

ابتدا، ارتباط سریال با کامپیوتر و نیز شی BME را با استفاده از تابع ()begin راه‌اندازی می­‌کنیم. این تابع رابط I2C را با آدرس داده شده (0x76) فعال کرده و بررسی می‌کند که ID تراشه صحیح باشد. در ادامه، تراشه را به صورت نرم‌افزاری ریست می‌کند و منتظر می‌ماند تا سنسور خود را کالیبره کند.

Serial.begin(115200);
delay(100);

bme.begin(0x76);

حال باید با تابع ()WiFi.begin به شبکه وای­‌فای موجود متصل شویم. این تابع پارامترهای SSID (نام شبکه) و پسورد را به عنوان ورودی می‌گیرد.

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

//connect to your local wi-fi network
WiFi.begin(ssid, password);

زمانی‌که ESP8266 در حال تلاش برای اتصال به شبکه است، وضعیت اتصال با کمک تابع ()WiFi.status قابل بررسی است.

//check wi-fi is connected to wi-fi network
  while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.print(".");
  }

پس از اینکه ESP8266 NodeMCU به شبکه متصل شد، برنامه آدرس آی‌پی اختصاص داده شده به ESP8266 را روی سریال مانیتور چاپ می‌کند. این کار با تابع ()WiFi.localIP انجام می‌شود.

Serial.println("");
  Serial.println("WiFi connected..!");
  Serial.print("Got IP: ");  Serial.println(WiFi.localIP());

برای رسیدگی به درخواست‌های HTTP دریافتی، از تابع on استفاده می‌کنیم تا مشخص کنیم هنگام رخ دادن هر URL، چه برنامه‌ای اجرا شود. این تابع دو آرگومان دریافت می‌کند. اولین آرگومان مسیر URL است و آرگومان دوم نام تابعی است که باید هنگام رخ‌دادن آن URL، اجرا شود.

برای مثال، در خط اول کد زیر وقتی سرور یک درخواست HTTP روی مسیر ریشه (/) دریافت می‌کند، تابع ()handle_OnConnect اجرا می‌شود. توجه کنید که URL مشخص شده، یک مسیر نسبی (Relative Path) است.

erver.on("/", handle_OnConnect);

در صورتی که سرویس‌گیرنده آدرسی را درخواست بدهد که با تابع ()server.on مشخص نشده، سرور باید با وضعیتHTTP 404 (Not Found) پاسخ دهد و یک پیام مناسب به کاربر نمایش دهد. این موارد را هم در یک تابع تحت عنوان server.onNotFound(handle_NotFound)، قرار می‌دهیم تا در صورت دریافت یک آدرس شناخته نشده، تابع onNotFound اجرا شود.

server.onNotFound(handle_NotFound);

اکنون برای شروع به کار سرور، تابع begin را روی شیء server فراخوانی می‌کنیم.

server.begin();
Serial.println("HTTP server started");

تابع ()Loop

برای پاسخگویی به درخواست‌های HTTP دریافتی، تابع ()handleClient را روی شیء server فراخوانی می‌کنیم.

server.handleClient();

سپس، باید تابعی را که با دستور server.on به URL ریشه (/) متصل کردیم، بسازیم. اگر یادتان باشد در ابتدای این تابع مقادیر دما، رطوبت، فشار و ارتفاع از سطح دریا را از سنسور دریافت می­‌کنیم. سپس برای پاسخگویی به درخواست HTTP، از تابع send استفاده می‌کنیم. با اینکه این تابع می‌تواند با ترکیب پارامترهای دیگری هم فراخوانی شود، ساده‌ترین فرم فراخوانی آن شامل کد پاسخ به HTTP، نوع محتوا و خود محتوای صفحه است. در اینجا، ما کد 200 (یکی از کدهای وضعیت HTTP) را ارسال می‌کنیم که به معنای OK است. نوع محتوا را به‌عنوان “text/html” مشخص می‌کنیم و در نهایت تابع ()SendHTML را فراخوانی می‌کنیم. این تابع یک صفحه HTML داینامیک تولید می‌کند که شامل مقادیر خوانده شده از سنسور است.

void handle_OnConnect() {
  temperature = bme.readTemperature();
  humidity = bme.readHumidity();
  pressure = bme.readPressure() / 100.0F;
  altitude = bme.readAltitude(SEALEVELPRESSURE_HPA);
  server.send(200, "text/html", SendHTML(temperature,humidity,pressure,altitude)); 
}

به همین شکل تابعی برای مدیریت صفحه خطا 404 می‌سازیم:

void handle_NotFound(){
  server.send(404, "text/plain", "Not found");
}

نمایش صفحه وب HTML

تابع ()SendHTML برای ساخت یک صفحه وب مورد استفاده قرار می‌گیرد. بدین منظور، ابتدا باید وب سرور ESP8266  درخواست ساخت یک صفحه وب را از سرویس‌گیرنده دریافت کند. این تابع ذخیره کد HTML در یک ‌رشته (string) بزرگ و برگرداندن آن به تابع ()server.send را برعهده دارد. در مورد تابع ()server.send نیز قبلاً توضیح دادیم. این تابع پارامترهای دما، رطوبت، فشار و ارتفاع را می‌گیرد و به طور داینامیک محتوای صفحه HTML را تولید می‌کند.

اولین متنی که همیشه باید ارسال کنیم اعلان <!DOCTYPE> است. این اعلان مشخص می‌کند که در حال ارسال کد HTML هستیم.

String SendHTML(float temperature,float humidity,float pressure,float altitude){
  String ptr = "<!DOCTYPE html> <html>\n";

سپس، المان meta>viewport> قرار گرفته است که باعث واکنش‌گرایی صفحه وب روی همه مرورگرها می‌شود. تگ title هم عنوان صفحه را مشخص می‌کند.

ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
ptr +="<title>ESP8266 Weather Station</title>\n";

طراحی صفحه وب

در ادامه، با استفاده از چند خط کد CSS، ظاهر صفحه وب را طراحی می‌کنیم. ما فونت Helvetica را انتخاب کردیم، نمایش محتویات صفحه را به‌صورت inline-block تعریف و محل قرارگیری آن را در وسط صفحه قرار داده‌ایم.

ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";

کد زیر رنگ، فونت و حاشیه دور بدنه و تگ‌های H1 و p را مشخص می‌کند.

ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";
ptr +="p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n";
ptr +="</style>\n";
ptr +="</head>\n";
ptr +="<body>\n";

تغییر عنوان صفحه وب

در این بخش از کد، عنوان‌ صفحه وب مشخص شده­‌است. شما می‌توانید این متن را متناسب با کاربرد خود تغییر دهید.

ptr +="<div id=\"webpage\">\n";
ptr +="<h1>ESP8266 Weather Station</h1>\n";

نمایش مقادیر خوانده شده روی صفحه وب

برای نمایش دما، رطوبت، فشار و ارتفاع خوانده شده از سنسور، این مقادیر را در تگ پاراگراف (<p>) قرار می‌دهیم. برای نمایش نماد درجه نیز از &deg استفاده می‌کنیم.

ptr +="<p>Temperature: ";
ptr +=temperature;
ptr +="&deg;C</p>";
ptr +="<p>Humidity: ";
ptr +=humidity;
ptr +="%</p>";
ptr +="<p>Pressure: ";
ptr +=pressure;
ptr +="hPa</p>";
ptr +="<p>Altitude: ";
ptr +=altitude;
ptr +="m</p>";
ptr +="</div>\n";
ptr +="</body>\n";
ptr +="</html>\n";
return ptr;
}

طراحی حرفه‌ای‌تر صفحه وب

در ادامه‌ی ساخت ایستگاه هواشناسی با ESP8266 قصد داریم صفحه وب هواشناسی خود را زیباتر کنیم.

در صورتی که فکر می‌کنید طراحی صفحه وب کار دشواری است، با ما همراه باشید تا به روشی ساده این کار را انجام دهیم! عکس زیر ایده کلی کاری که می‌خواهیم انجام دهیم را به شما نشان می‌دهد:

طراحی زیباتر و حرفه‌ای‌تر صفحه وب ایستگاه هواشناسی

پس بدون اتلاف وقت، کد زیر را کپی کرده و در برنامه بالا جایگزین تابع ()SendHTML کنید. با این کار صفحه وب جذاب‌تر و حرفه‌ای‌تری خواهید داشت.

String SendHTML(float temperature,float humidity,float pressure,float altitude){
  String ptr = "<!DOCTYPE html>";
  ptr +="<html>";
  ptr +="<head>";
  ptr +="<title>ESP8266 Weather Station</title>";
  ptr +="<meta name='viewport' content='width=device-width, initial-scale=1.0'>";
  ptr +="<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,600' rel='stylesheet'>";
  ptr +="<style>";
  ptr +="html { font-family: 'Open Sans', sans-serif; display: block; margin: 0px auto; text-align: center;color: #444444;}";
  ptr +="body{margin: 0px;} ";
  ptr +="h1 {margin: 50px auto 30px;} ";
  ptr +=".side-by-side{display: table-cell;vertical-align: middle;position: relative;}";
  ptr +=".text{font-weight: 600;font-size: 19px;width: 200px;}";
  ptr +=".reading{font-weight: 300;font-size: 50px;padding-right: 25px;}";
  ptr +=".temperature .reading{color: #F29C1F;}";
  ptr +=".humidity .reading{color: #3B97D3;}";
  ptr +=".pressure .reading{color: #26B99A;}";
  ptr +=".altitude .reading{color: #955BA5;}";
  ptr +=".superscript{font-size: 17px;font-weight: 600;position: absolute;top: 10px;}";
  ptr +=".data{padding: 10px;}";
  ptr +=".container{display: table;margin: 0 auto;}";
  ptr +=".icon{width:65px}";
  ptr +="</style>";
  ptr +="</head>";
  ptr +="<body>";
  ptr +="<h1>ESP8266 Weather Station</h1>";
  ptr +="<div class='container'>";
  ptr +="<div class='data temperature'>";
  ptr +="<div class='side-by-side icon'>";
  ptr +="<svg enable-background='new 0 0 19.438 54.003'height=54.003px id=Layer_1 version=1.1 viewBox='0 0 19.438 54.003'width=19.438px x=0px xml:space=preserve xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink y=0px><g><path d='M11.976,8.82v-2h4.084V6.063C16.06,2.715,13.345,0,9.996,0H9.313C5.965,0,3.252,2.715,3.252,6.063v30.982";
  ptr +="C1.261,38.825,0,41.403,0,44.286c0,5.367,4.351,9.718,9.719,9.718c5.368,0,9.719-4.351,9.719-9.718";
  ptr +="c0-2.943-1.312-5.574-3.378-7.355V18.436h-3.914v-2h3.914v-2.808h-4.084v-2h4.084V8.82H11.976z M15.302,44.833";
  ptr +="c0,3.083-2.5,5.583-5.583,5.583s-5.583-2.5-5.583-5.583c0-2.279,1.368-4.236,3.326-5.104V24.257C7.462,23.01,8.472,22,9.719,22";
  ptr +="s2.257,1.01,2.257,2.257V39.73C13.934,40.597,15.302,42.554,15.302,44.833z'fill=#F29C21 /></g></svg>";
  ptr +="</div>";
  ptr +="<div class='side-by-side text'>Temperature</div>";
  ptr +="<div class='side-by-side reading'>";
  ptr +=(int)temperature;
  ptr +="<span class='superscript'>&deg;C</span></div>";
  ptr +="</div>";
  ptr +="<div class='data humidity'>";
  ptr +="<div class='side-by-side icon'>";
  ptr +="<svg enable-background='new 0 0 29.235 40.64'height=40.64px id=Layer_1 version=1.1 viewBox='0 0 29.235 40.64'width=29.235px x=0px xml:space=preserve xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink y=0px><path d='M14.618,0C14.618,0,0,17.95,0,26.022C0,34.096,6.544,40.64,14.618,40.64s14.617-6.544,14.617-14.617";
  ptr +="C29.235,17.95,14.618,0,14.618,0z M13.667,37.135c-5.604,0-10.162-4.56-10.162-10.162c0-0.787,0.638-1.426,1.426-1.426";
  ptr +="c0.787,0,1.425,0.639,1.425,1.426c0,4.031,3.28,7.312,7.311,7.312c0.787,0,1.425,0.638,1.425,1.425";
  ptr +="C15.093,36.497,14.455,37.135,13.667,37.135z'fill=#3C97D3 /></svg>";
  ptr +="</div>";
  ptr +="<div class='side-by-side text'>Humidity</div>";
  ptr +="<div class='side-by-side reading'>";
  ptr +=(int)humidity;
  ptr +="<span class='superscript'>%</span></div>";
  ptr +="</div>";
  ptr +="<div class='data pressure'>";
  ptr +="<div class='side-by-side icon'>";
  ptr +="<svg enable-background='new 0 0 40.542 40.541'height=40.541px id=Layer_1 version=1.1 viewBox='0 0 40.542 40.541'width=40.542px x=0px xml:space=preserve xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink y=0px><g><path d='M34.313,20.271c0-0.552,0.447-1,1-1h5.178c-0.236-4.841-2.163-9.228-5.214-12.593l-3.425,3.424";
  ptr +="c-0.195,0.195-0.451,0.293-0.707,0.293s-0.512-0.098-0.707-0.293c-0.391-0.391-0.391-1.023,0-1.414l3.425-3.424";
  ptr +="c-3.375-3.059-7.776-4.987-12.634-5.215c0.015,0.067,0.041,0.13,0.041,0.202v4.687c0,0.552-0.447,1-1,1s-1-0.448-1-1V0.25";
  ptr +="c0-0.071,0.026-0.134,0.041-0.202C14.39,0.279,9.936,2.256,6.544,5.385l3.576,3.577c0.391,0.391,0.391,1.024,0,1.414";
  ptr +="c-0.195,0.195-0.451,0.293-0.707,0.293s-0.512-0.098-0.707-0.293L5.142,6.812c-2.98,3.348-4.858,7.682-5.092,12.459h4.804";
  ptr +="c0.552,0,1,0.448,1,1s-0.448,1-1,1H0.05c0.525,10.728,9.362,19.271,20.22,19.271c10.857,0,19.696-8.543,20.22-19.271h-5.178";
  ptr +="C34.76,21.271,34.313,20.823,34.313,20.271z M23.084,22.037c-0.559,1.561-2.274,2.372-3.833,1.814";
  ptr +="c-1.561-0.557-2.373-2.272-1.815-3.833c0.372-1.041,1.263-1.737,2.277-1.928L25.2,7.202L22.497,19.05";
  ptr +="C23.196,19.843,23.464,20.973,23.084,22.037z'fill=#26B999 /></g></svg>";
  ptr +="</div>";
  ptr +="<div class='side-by-side text'>Pressure</div>";
  ptr +="<div class='side-by-side reading'>";
  ptr +=(int)pressure;
  ptr +="<span class='superscript'>hPa</span></div>";
  ptr +="</div>";
  ptr +="<div class='data altitude'>";
  ptr +="<div class='side-by-side icon'>";
  ptr +="<svg enable-background='new 0 0 58.422 40.639'height=40.639px id=Layer_1 version=1.1 viewBox='0 0 58.422 40.639'width=58.422px x=0px xml:space=preserve xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink y=0px><g><path d='M58.203,37.754l0.007-0.004L42.09,9.935l-0.001,0.001c-0.356-0.543-0.969-0.902-1.667-0.902";
  ptr +="c-0.655,0-1.231,0.32-1.595,0.808l-0.011-0.007l-0.039,0.067c-0.021,0.03-0.035,0.063-0.054,0.094L22.78,37.692l0.008,0.004";
  ptr +="c-0.149,0.28-0.242,0.594-0.242,0.934c0,1.102,0.894,1.995,1.994,1.995v0.015h31.888c1.101,0,1.994-0.893,1.994-1.994";
  ptr +="C58.422,38.323,58.339,38.024,58.203,37.754z'fill=#955BA5 /><path d='M19.704,38.674l-0.013-0.004l13.544-23.522L25.13,1.156l-0.002,0.001C24.671,0.459,23.885,0,22.985,0";
  ptr +="c-0.84,0-1.582,0.41-2.051,1.038l-0.016-0.01L20.87,1.114c-0.025,0.039-0.046,0.082-0.068,0.124L0.299,36.851l0.013,0.004";
  ptr +="C0.117,37.215,0,37.62,0,38.059c0,1.412,1.147,2.565,2.565,2.565v0.015h16.989c-0.091-0.256-0.149-0.526-0.149-0.813";
  ptr +="C19.405,39.407,19.518,39.019,19.704,38.674z'fill=#955BA5 /></g></svg>";
  ptr +="</div>";
  ptr +="<div class='side-by-side text'>Altitude</div>";
  ptr +="<div class='side-by-side reading'>";
  ptr +=(int)altitude;
  ptr +="<span class='superscript'>m</span></div>";
  ptr +="</div>";
  ptr +="</div>";
  ptr +="</body>";
  ptr +="</html>";
  return ptr;
}

اگر این تابع را با تابع قبلی مقایسه کنید متوجه می‌­شوید که به جز تغییرات زیر، در سایر موارد مشابه هم هستند:

  • ما برای صفحه وب خود از فونت سفارشی گوگل به نام Open Sans استفاده کرده‌­ایم. توجه کنید فونت­‌های گوگل به صورت آنلاین بارگذاری می­‌شوند؛ پس بدون دسترسی به اینترنت با دستگاه خود، نمی‌توانید فونت­‌های گوگل را ببینید.
ptr +="<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,600' rel='stylesheet'>";

  • آیکن­‌هایی که برای نمایش مقادیر دما، رطوبت، فشار و ارتفاع استفاده شده‌­اند، در حقیقت بردارهای گرافیکی با قابلیت تغییر اندازه (Scalable Vector Graphics یا SVG) هستند که با تگ <svg> تعریف شده­‌اند. ساخت SVGها به مهارت برنامه‌نویسی خاصی نیاز ندارد. شما می‌توانید با استفاده از ابزار Google SVG Editor برای صفحه وب خود اشکال گرافیکی بسازید. ما برای ساخت ایستگاه هواشناسی با ESP8266 از آیکن­‌های SVG زیر استفاده کردیم:
آیکن‌های SVG استفاده شده در صفحه وب و ساخته شده توسط ابزار Google SVG Editor

بهبود کد با اضافه کردن به‌روزرسانی خودکار صفحه

یکی از بهبودهایی که می‌توانیم در برنامه خود اعمال کنیم، به‌روزرسانی خودکار صفحه به‌منظور به‌روزرسانی مقادیر خوانده شده از سنسورها است.

تنها با اضافه‌کردن یک تگ meta به فایل HTML، می‌توانیم به مرورگر نشان دهیم صفحه را پس از مدت‌زمان معینی به­‌روزرسانی کند.

<meta http-equiv="refresh" content="2" >

این کد را در تگ <head> برنامه خود قرار دهید، این متا تگ باعث می‌شود مرورگر هر دو ثانیه یک‌بار صفحه را به‌­روزرسانی کند.

بارگذاری داینامیک اطلاعات سنسور با استفاده از AJAX

چنانچه یک صفحه وب سنگین و حجیمی داشته باشید، به‌روزرسانی کامل آن امری کاربردی نیست. یک روش بهتر برای این کار استفاده از “جاوا اسکریپت و Xml آسنکرون” (Asynchronous Javascript And Xml یا AJAX) است. در این روش می‌توانیم به صورت آسنکرون (در پس زمینه) و بدون نیاز به به‌­روزرسانی، اطلاعات را از سرور درخواست کنیم.

معمولا برای اجرای AJAX روی صفحات وب در جاوا اسکریپت، از شیء XMLHttpRequest استفاده می‌شود. این شئ یک درخواست GET به سرور می‌دهد و بخشی از صفحه وب را به روز می‌کند. AJAX یک فناوری جدید یا یک زبان متفاوت نیست؛ بلکه فقط استفاده‌ای جدید از فناوری‌های موجود است. جدا از این، AJAX قابلیت‌های زیر را به ما می­دهد:

  • درخواست اطلاعات از سرور پس از بارگذاری صفحه وب
  • دریافت اطلاعات از سرور پس از بارگذاری صفحه وب
  • ارسال اطلاعات به سرور در پس‌زمینه

در زیر اسکریپت AJAX مورد استفاده را می‌بینید. کافیست این اسکریپت را قبل از بستن تگ </head> قرار دهید.

ptr +="<script>\n";
ptr +="setInterval(loadDoc,1000);\n";
ptr +="function loadDoc() {\n";
ptr +="var xhttp = new XMLHttpRequest();\n";
ptr +="xhttp.onreadystatechange = function() {\n";
ptr +="if (this.readyState == 4 && this.status == 200) {\n";
ptr +="document.body.innerHTML =this.responseText}\n";
ptr +="};\n";
ptr +="xhttp.open(\"GET\", \"/\", true);\n";
ptr +="xhttp.send();\n";
ptr +="}\n";
ptr +="</script>\n";

اسکریپت با تگ <script> آغاز می­شود. با توجه به اینکه اسکریپت AJAX از جنس جاوا اسکریپت است، باید در تگ <script> قرار گیرد و برای اینکه این تابع مرتب فراخوانی شود از تابع جاوا اسکریپت ()setInterval استفاده می‌کنیم. این تابع دو پارامتر به عنوان ورودی می‌گیرد. اولین پارامتر تابعی برای اجرا است و دومین پارامتر فاصله زمانی بین اجرای دوباره تابع (برحسب میلی ثانیه) می­باشد.

ptr +="<script>\n";
ptr +="setInterval(loadDoc,1000);\n";

در قلب این اسکریپت، تابع ()loadDoc قرار دارد. به طوری که درون این تابع یک شیء ()XMLHttpRequest ساخته شده که اطلاعات را از وب سرور درخواست می‌کند.

ptr +="function loadDoc() {\n";
ptr +="var xhttp = new XMLHttpRequest();\n";

به محض تغییر readyState، تابع ()xhttp.onreadystatechange فراخوانی می‌شود. مشخصه readyState وضعیت XMLHttpRequest را ذخیره می­کند که می­تواند یکی از مقادیر زیر باشد:

  • 0 : درخواست شروع نشده است.
  • ·        1 : ارتباط با سرور برقرار شده­است.
  • ·        2 : درخواست دریافت شد.
  • ·        3 : درخواست در حال پردازش است.
  • ·        4 : درخواست انجام شده و پاسخ آماده است.

مشخصه status نیز وضعیت شیء XMLHttpRequest را ذخیره می‌کند که می‌­تواند یکی از مقادیر زیر باشد:

  • 200 : OK
  • ·        403 : ممنوع
  • ·        404 : صفحه پیدا نشد.

وقتی مقادیر readyState و status به ترتیب برابر 4 و 200 باشد، یعنی پاسخ آماده است. اکنون محتوای بدنه‌­ی صفحه که مقادیر دمای خوانده شده را دربردارد به­‌روز می‌شود.

ptr +="xhttp.onreadystatechange = function() {\n";
ptr +="if (this.readyState == 4 && this.status == 200) {\n";
ptr +="document.body.innerHTML =this.responseText}\n";
ptr +="};\n";

سپس درخواست HTTP با توابع ()open و ()send آماده و ارسال می‌گردد.

ptr +="xhttp.open(\"GET\", \"/\", true);\n";
ptr +="xhttp.send();\n";
ptr +="}\n";

با ساخت ایستگاه هواشناسی با ESP8266 و ماژول BME280 به راحتی می‌توانید تمام پارامترهای مورد نیاز در هواشناسی را کنترل کنید، و با این پروژه به دنیای بزرگ اینترنت اشیا پا بگذارید. پس اگر شماهم به اینترنت اشیا علاقه دارید ازاین پروژه کاربردی در خانه، باغچه یا گلخانه خودتان استفاده کنید.
برای آموزش ساخت پروژه‌های متنوع اینترنت اشیا، می‌توانید مقالات آکادمی روبوایکیو را مطالعه کنید.
ما مشتاقانه پذیرای هرگونه سوال و نظرات شما هستیم، پس آن‌هارا در بخش دیدگاه با ما درمیان بگذارید.

مقالات مشابه

۶ دیدگاه. Leave new

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

Fill out this field
Fill out this field
لطفاً یک نشانی ایمیل معتبر بنویسید.
You need to agree with the terms to proceed

پر بازدید ترین مقالات