این یک آموزش کامل برای راه اندازی سنسور DS18B20 با ESP8266 از سری اموزش ESP8266 با استفاده از Arduino IDE است. نحوه سیم‌کشی سنسور، نصب کتابخانه‌های مورد نیاز، و نوشتن کد برای دریافت مقادیر سنسور از یک تا چند سنسور را بررسی می‌کنیم. در نهایت، ما یک وب سرور ساده برای نمایش مقادیر سنسور را راه اندازی میکنیم.

در طول این آموزش ما موضوعات زیر را بررسی خواهیم کرد:

خواندن دما از یک سنسور DS18B20 با esp8266.

خواندن دما از چندین  سنسور DS18B20 با esp8266

نمایش مقادیر سنسور DS18B20 با esp8266

معرفی سنسور دما DS18B20

سنسور دمای DS18B20 یک سنسور دمای دیجیتال با ارتباط تک سیم یا 1WIRE است. این بدان معناست که برای برقراری ارتباط با ESP8266 شما فقط به یک خط دیتا (و GND) نیاز دارد.

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

راه اندازی سنسور DS18B20 با ESP8266 در حالت تکی ، چندتایی و وب سرور (اینترنت اشیا)

هر سنسور دمای DS18B20 یک کد سریال منحصر به فرد 64 بیتی دارد. این به شما امکان می دهد چندین سنسور را به یک خط دیتا متصل کنید. بنابراین، می توانید دما را از چندین سنسور فقط با استفاده از یک GPIO دریافت کنید.

سنسور دمای DS18B20 در نسخه ضد آب نیز موجود است.

راه اندازی سنسور DS18B20 با ESP8266 در حالت تکی ، چندتایی و وب سرور (اینترنت اشیا)

در اینجا خلاصه ای از مشخصات سنسور دمای DS18B20 آمده است:

  • از طریق باس 1WIRE یا تک سیم ارتباط برقرار می کند
  • محدوده ولتاژ کاری: 3.0 ولت تا 5.5 ولت
  • محدوده دمای کارکرد: -55 درجه سانتیگراد تا +125 درجه سانتیگراد
  • دقت +/-0.5 ºC (بین محدوده -10ºC تا 85ºC)

برای اطلاعات بیشتر به دیتاشیت DS18B20 مراجعه کنید.

قطعات مورد نیاز برای راه اندازی DS18B20 با ESP8266

  • ماژول ESP8266 سنسور
  • دمای DS18B20 (یک یا چند سنسور) 
  • مقاومت 4.7 کیلو اهم
  • بردبورد
  • سیم های جامپر

شماتیک اتصال ESP8266 به DS18B20

همانطور که قبلا ذکر شد، سنسور دمای DS18B20 می تواند از طریق پین VDD (حالت عادی) تغذیه شود یا می تواند ولتاژ مورد نیاز خود را از خط داده (حالت انگل) تامین کند. شما می توانید هر دو حالت را انتخاب کنید.

حالت انگل

راه اندازی سنسور DS18B20 با ESP8266 در حالت تکی ، چندتایی و وب سرور (اینترنت اشیا)

حالت عادی

راه اندازی سنسور DS18B20 با ESP8266 در حالت تکی ، چندتایی و وب سرور (اینترنت اشیا)

توجه: در این آموزش ما خط دیتا DS18B20 را به GPIO 4 وصل می کنیم، اما می توانید از هر GPIO مناسب دیگری استفاده کنید.

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

ما ESP8266 را با استفاده از Arduino IDE برنامه ریزی می کنیم، بنابراین مطمئن شوید که قبل از ادامه، برد های ESP8266 را نصب کرده اید.

در صورتی که هنوز کتابخانه بردهای ESP8266 را نصب نکرده اید این پست را مطالعه کنید:

نصب بردهای ESP8266 در آردوینو IDE (ویندوز – مک – لینوکس)

نصب کتابخانه ها برای راه اندازی DS18B20 با ESP8266

برای ارتباط با سنسور دمای DS18B20 با ESP8266، باید کتابخانه One Wire توسط Paul Stoffregen و کتابخانه Dallas Temperature را نصب کنید. در ادامه مرحله به مرحله این قدم ها را توضیح میدهیم.

  1. آردوینو IDE خود را باز کنید و به مسیر Sketch Include Library > Manage Libraries بروید.
  2. متن “onewire” را در کادر جستجو تایپ کنید و کتابخانه OneWire توسط Paul Stoffregen را نصب کنید.
راه اندازی سنسور DS18B20 با ESP8266 در حالت تکی ، چندتایی و وب سرور (اینترنت اشیا)

3. سپس عبارت Dallas را جستجو کنید و کتابخانه Dallas Temperature توسط Miles Burton را نصب کنید.

راه اندازی سنسور DS18B20 با ESP8266 در حالت تکی ، چندتایی و وب سرور (اینترنت اشیا)

پس از نصب کتابخانه ها، آردوینو IDE خود را مجددا راه اندازی کنید.

کد (راه اندازی DS18B20 با ESP8266 به صورت تکی)

پس از نصب کتابخانه های مورد نیاز، می توانید کد زیر را در ESP8266 آپلود کنید. کد دما را از سنسور دمای DS18B20 می خواند و مقادیر را در مانیتور سریال Arduino IDE نمایش می دهد.

				
					#include <OneWire.h>
#include <DallasTemperature.h>

// GPIO where the DS18B20 is connected to
const int oneWireBus = 4;     

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);

// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);

void setup() {
  // Start the Serial Monitor
  Serial.begin(115200);
  // Start the DS18B20 sensor
  sensors.begin();
}

void loop() {
  sensors.requestTemperatures(); 
  float temperatureC = sensors.getTempCByIndex(0);
  float temperatureF = sensors.getTempFByIndex(0);
  Serial.print(temperatureC);
  Serial.println("ºC");
  Serial.print(temperatureF);
  Serial.println("ºF");
  delay(5000);
}
				
			

راه های مختلفی برای دریافت دما از سنسورهای دما DS18B20 وجود دارد. با این حال، اگر فقط از یک سنسور استفاده می کنید، این یکی از ساده ترین و ساده ترین راه هاست.

راه اندازی سنسور DS18B20 با ESP8266 در حالت تکی ، چندتایی و وب سرور (اینترنت اشیا)

نحوه کار کد

با اضافه کردن کتابخانه های OneWire و DallasTemperature شروع میکنیم.

#include <OneWire.h> 
#include <DallasTemperature.h>

ساخت instances های مورد نیاز سنسور، سنسور به gpio 4 متصل شده است.

// GPIO where the DS18B20 is connected to 

const int oneWireBus = 4;

// Setup a oneWire instance to communicate with any OneWire devices

OneWire oneWire(oneWireBus);

// Pass our oneWire reference to Dallas Temperature sensor

DallasTemperature sensors(&oneWire);

در setup()، مانیتور سریال را با نرخ باود 115200 مقداردهی کنید.

Serial.begin(115200);

سنسور دمای DS18B20 را راه اندازی کنید:

sensors.begin();

قبل از اینکه دما را بدست آورید، باید متد requestTemperatures() را فراخوانی کنید.

sensors.requestTemperatures(); 

سپس با استفاده از متد getTempCByIndex() مانند شکل زیر، دما را بر حسب سانتیگراد بدست آورید:

float temperatureC = sensors.getTempCByIndex(0);

یا از getTempFByIndex() برای دریافت دما به فارنهایت استفاده کنید.

float temperatureF = sensors.getTempFByIndex(0);

متدهای getTempCByIndex() و getTempFByIndex() شاخص سنسور دما را به عنوان پارامتر می پذیرند. از آنجا که ما فقط از یک سنسور استفاده می کنیم، شاخص آن 0 است. اگر می خواهید بیش از یک سنسور را بخوانید، از شاخص 0 برای یک سنسور، شاخص 1 برای سنسور دیگر و غیره استفاده می کنید.

در نهایت نتایج را در Serial Monitor چاپ کنید.

Serial.print(temperatureC);
Serial.println("ºC");
Serial.print(temperatureF);
Serial.println("ºF");

درخواست مقادیر دمای جدید هر 5 ثانیه درخواست می شود.

delay(5000);

خروجی

پس از آپلود کد، مانیتور سریال Arduino IDE را با نرخ باود 115200 باز کنید. شما باید دمای نمایش داده شده در هر دو درجه سانتیگراد و فارنهایت را دریافت کنید:

راه اندازی سنسور DS18B20 با ESP8266 در حالت تکی ، چندتایی و وب سرور (اینترنت اشیا)

دریافت دما از چندین سنسور دما DS18B20

راه اندازی سنسور DS18B20 با ESP8266 در حالت تکی ، چندتایی و وب سرور (اینترنت اشیا)

سنسور دما DS18B20 با استفاده از پروتکل تک سیمه ارتباط برقرار می کند و هر سنسور دارای یک کد سریال 64 بیتی منحصر به فرد است، بنابراین شما می توانید دما را از چندین سنسور فقط با استفاده از یک پین دیجیتال دریافت کنید.

شماتیک (ds18b20 چندتایی)

برای خواندن دما از چندین سنسور، فقط باید تمام خطوط داده را همانطور که در نمودار شماتیک بعدی نشان داده شده است به هم متصل کنید:

راه اندازی DS18B20 با ESP8266

کد (DS18B20 چندتایی)

سپس کد زیر را آپلود کنید. همه دستگاه‌های موجود در GPIO 4 را اسکن می‌کند و دمای هر یک را چاپ می‌کند. این طرح بر اساس مثال ارائه شده توسط کتابخانه DallasTemperature است.

				
					#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged TO GPIO 4
#define ONE_WIRE_BUS 4

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// Number of temperature devices found
int numberOfDevices;

// We'll use this variable to store a found device address
DeviceAddress tempDeviceAddress; 

void setup(){
  // start serial port
  Serial.begin(115200);
  
  // Start up the library
  sensors.begin();
  
  // Grab a count of devices on the wire
  numberOfDevices = sensors.getDeviceCount();
  
  // locate devices on the bus
  Serial.print("Locating devices...");
  Serial.print("Found ");
  Serial.print(numberOfDevices, DEC);
  Serial.println(" devices.");

  // Loop through each device, print out address
  for(int i=0;i<numberOfDevices; i++){
    // Search the wire for address
    if(sensors.getAddress(tempDeviceAddress, i)){
      Serial.print("Found device ");
      Serial.print(i, DEC);
      Serial.print(" with address: ");
      printAddress(tempDeviceAddress);
      Serial.println();
    } else {
      Serial.print("Found ghost device at ");
      Serial.print(i, DEC);
      Serial.print(" but could not detect address. Check power and cabling");
    }
  }
}

void loop(){ 
  sensors.requestTemperatures(); // Send the command to get temperatures
  
  // Loop through each device, print out temperature data
  for(int i=0;i<numberOfDevices; i++){
    // Search the wire for address
    if(sensors.getAddress(tempDeviceAddress, i)){
      // Output the device ID
      Serial.print("Temperature for device: ");
      Serial.println(i,DEC);
      // Print the data
      float tempC = sensors.getTempC(tempDeviceAddress);
      Serial.print("Temp C: ");
      Serial.print(tempC);
      Serial.print(" Temp F: ");
      Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
    }
  }
  delay(5000);
}

// function to print a device address
void printAddress(DeviceAddress deviceAddress) {
  for (uint8_t i = 0; i < 8; i++){
    if (deviceAddress[i] < 16) Serial.print("0");
      Serial.print(deviceAddress[i], HEX);
  }
}
				
			

نحوه کار کد

این کد از چندین فانکشن مفید برای دریافت اطلاعات از چندین سنسور DS18B20 استفاده می کند.

شما از متد getDeviceCount() برای بدست آوردن تعداد سنسورهای DS18B20 در خط داده استفاده می کنید.

numberOfDevices = sensors.getDeviceCount();

متد getAddress() آدرس سنسورها را پیدا می کند:

if(sensors.getAddress(tempDeviceAddress, i)){

آدرس برای هر سنسور منحصر به فرد است. بنابراین هر سنسور را می توان با آدرس آن شناسایی کرد.

سپس از متد getTempC() استفاده می کنید که آدرس دستگاه را به عنوان آرگومان می پذیرد. با این روش می توانید دما را از یک سنسور خاص دریافت کنید:

float tempC = sensors.getTempC(tempDeviceAddress);

برای بدست آوردن دما بر حسب درجه فارنهایت، می توانید از getTemF() استفاده کنید. همچنین می‌توانید دما را بر حسب سانتیگراد به فارنهایت تبدیل کنید:

DallasTemperature::toFahrenheit(tempC)

خروجی

پس از آپلود کد، مانیتور سریال خود را با نرخ باود 115200 باز کنید. باید تمام مقادیر سنسورهای خود را مطابق شکل زیر نمایش دهید:

راه اندازی سنسور DS18B20 با ESP8266 در حالت تکی ، چندتایی و وب سرور (اینترنت اشیا)

نمایش دمای DS18B20 در یک وب سرور

برای ساخت وب سرور از کتابخانه ESPAsyncWebServer استفاده می کنیم که راه آسانی برای ساخت یک وب سرور آسنکرون ارائه می دهد. ساخت یک وب سرور آسنکرون چندین مزیت دارد. جهت اطلاعات بیشتر در رابطه با این حالت نگاهی گذرا به اسناد کتابخانه در صفحه GitHub آن داشته باشید.

نصب کتابخانه ESPAsyncWebServer

کتابخانه ESPAsyncWebServer برای نصب در Arduino IDE Library Manager در دسترس نیست. بنابراین، شما باید آن را به صورت دستی نصب کنید.

مراحل بعدی را برای نصب کتابخانه ESPAsyncWebServer دنبال کنید:

  1. برای دانلود کتابخانه ESPAsyncWebServer اینجا را کلیک کنید. شما باید یک پوشه .zip در پوشه Downloads خود داشته باشید
  2. پوشه .zip را از حالت فشرده خارج کنید و باید پوشه ESPAsyncWebServer-master را دریافت کنید.
  3. نام پوشه خود را از ESPAsyncWebServer-master به ESPAsyncWebServer تغییر دهید
  4. پوشه ESPAsyncWebServer را به پوشه کتابخانه های نصب Arduino IDE خود منتقل کنید

نصب کتابخانه TCP ESPAsync

کتابخانه ESPAsyncWebServer برای کار به کتابخانه ESPAsyncTCP نیاز دارد. برای نصب آن کتابخانه مراحل بعدی را دنبال کنید:

  1. برای دانلود کتابخانه ESPAsyncTCP اینجا را کلیک کنید. شما باید یک پوشه .zip در پوشه Downloads خود داشته باشید
  2. پوشه .zip را از حالت فشرده خارج کنید و باید پوشه ESPAsyncTCP-master را دریافت کنید
  3. نام پوشه خود را از ESPAsyncTCP-master به ESPAsyncTCP تغییر دهید
  4. پوشه ESPAsyncTCP را به پوشه کتابخانه های نصب Arduino IDE خود منتقل کنید
  5. در نهایت، Arduino IDE خود را دوباره باز کنید

کد (DS18B20 Async Web Server)

Arduino IDE خود را باز کرده و کد زیر را کپی کنید.

				
					// Import required libraries
#ifdef ESP32
  #include <WiFi.h>
  #include <ESPAsyncWebServer.h>
#else
  #include <Arduino.h>
  #include <ESP8266WiFi.h>
  #include <Hash.h>
  #include <ESPAsyncTCP.h>
  #include <ESPAsyncWebServer.h>S
#endif
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is connected to GPIO 4
#define ONE_WIRE_BUS 4

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);

// Variables to store temperature values
String temperatureF = "";
String temperatureC = "";

// Timer variables
unsigned long lastTime = 0;  
unsigned long timerDelay = 30000;

// 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 readDSTemperatureC() {
  // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures(); 
  float tempC = sensors.getTempCByIndex(0);

  if(tempC == -127.00) {
    Serial.println("Failed to read from DS18B20 sensor");
    return "--";
  } else {
    Serial.print("Temperature Celsius: ");
    Serial.println(tempC); 
  }
  return String(tempC);
}

String readDSTemperatureF() {
  // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures(); 
  float tempF = sensors.getTempFByIndex(0);

  if(int(tempF) == -196){
    Serial.println("Failed to read from DS18B20 sensor");
    return "--";
  } else {
    Serial.print("Temperature Fahrenheit: ");
    Serial.println(tempF);
  }
  return String(tempF);
}

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link data-asynced="1" as="style" onload="this.onload=null;this.rel='stylesheet'"  rel="preload" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous"><style>html {
     font-family: Arial;
     display: inline-block;
     margin: 0px auto;
     text-align: center;
    }
    h2 { font-size: 3.0rem; }
    p { font-size: 3.0rem; }
    .units { font-size: 1.2rem; }
    .ds-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }</style></head>
<body>
  <h2>ESP DS18B20 Server</h2>
  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels">Temperature Celsius</span> 
    <span id="temperaturec">%TEMPERATUREC%</span>
    <sup class="units">&deg;C</sup>
  </p>
  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels">Temperature Fahrenheit</span>
    <span id="temperaturef">%TEMPERATUREF%</span>
    <sup class="units">&deg;F</sup>
  </p> <script data-no-optimize="1">!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).LazyLoad=e()}(this,function(){"use strict";function e(){return(e=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n,a=arguments[e];for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(t[n]=a[n])}return t}).apply(this,arguments)}function i(t){return e({},it,t)}function o(t,e){var n,a="LazyLoad::Initialized",i=new t(e);try{n=new CustomEvent(a,{detail:{instance:i}})}catch(t){(n=document.createEvent("CustomEvent")).initCustomEvent(a,!1,!1,{instance:i})}window.dispatchEvent(n)}function l(t,e){return t.getAttribute(gt+e)}function c(t){return l(t,bt)}function s(t,e){return function(t,e,n){e=gt+e;null!==n?t.setAttribute(e,n):t.removeAttribute(e)}(t,bt,e)}function r(t){return s(t,null),0}function u(t){return null===c(t)}function d(t){return c(t)===vt}function f(t,e,n,a){t&&(void 0===a?void 0===n?t(e):t(e,n):t(e,n,a))}function _(t,e){nt?t.classList.add(e):t.className+=(t.className?" ":"")+e}function v(t,e){nt?t.classList.remove(e):t.className=t.className.replace(new RegExp("(^|\\s+)"+e+"(\\s+|$)")," ").replace(/^\s+/,"").replace(/\s+$/,"")}function g(t){return t.llTempImage}function b(t,e){!e||(e=e._observer)&&e.unobserve(t)}function p(t,e){t&&(t.loadingCount+=e)}function h(t,e){t&&(t.toLoadCount=e)}function n(t){for(var e,n=[],a=0;e=t.children[a];a+=1)"SOURCE"===e.tagName&&n.push(e);return n}function m(t,e){(t=t.parentNode)&&"PICTURE"===t.tagName&&n(t).forEach(e)}function a(t,e){n(t).forEach(e)}function E(t){return!!t[st]}function I(t){return t[st]}function y(t){return delete t[st]}function A(e,t){var n;E(e)||(n={},t.forEach(function(t){n[t]=e.getAttribute(t)}),e[st]=n)}function k(a,t){var i;E(a)&&(i=I(a),t.forEach(function(t){var e,n;e=a,(t=i[n=t])?e.setAttribute(n,t):e.removeAttribute(n)}))}function L(t,e,n){_(t,e.class_loading),s(t,ut),n&&(p(n,1),f(e.callback_loading,t,n))}function w(t,e,n){n&&t.setAttribute(e,n)}function x(t,e){w(t,ct,l(t,e.data_sizes)),w(t,rt,l(t,e.data_srcset)),w(t,ot,l(t,e.data_src))}function O(t,e,n){var a=l(t,e.data_bg_multi),i=l(t,e.data_bg_multi_hidpi);(a=at&&i?i:a)&&(t.style.backgroundImage=a,n=n,_(t=t,(e=e).class_applied),s(t,ft),n&&(e.unobserve_completed&&b(t,e),f(e.callback_applied,t,n)))}function N(t,e){!e||0<e.loadingCount||0<e.toLoadCount||f(t.callback_finish,e)}function C(t,e,n){t.addEventListener(e,n),t.llEvLisnrs[e]=n}function M(t){return!!t.llEvLisnrs}function z(t){if(M(t)){var e,n,a=t.llEvLisnrs;for(e in a){var i=a[e];n=e,i=i,t.removeEventListener(n,i)}delete t.llEvLisnrs}}function R(t,e,n){var a;delete t.llTempImage,p(n,-1),(a=n)&&--a.toLoadCount,v(t,e.class_loading),e.unobserve_completed&&b(t,n)}function T(o,r,c){var l=g(o)||o;M(l)||function(t,e,n){M(t)||(t.llEvLisnrs={});var a="VIDEO"===t.tagName?"loadeddata":"load";C(t,a,e),C(t,"error",n)}(l,function(t){var e,n,a,i;n=r,a=c,i=d(e=o),R(e,n,a),_(e,n.class_loaded),s(e,dt),f(n.callback_loaded,e,a),i||N(n,a),z(l)},function(t){var e,n,a,i;n=r,a=c,i=d(e=o),R(e,n,a),_(e,n.class_error),s(e,_t),f(n.callback_error,e,a),i||N(n,a),z(l)})}function G(t,e,n){var a,i,o,r,c;t.llTempImage=document.createElement("IMG"),T(t,e,n),E(c=t)||(c[st]={backgroundImage:c.style.backgroundImage}),o=n,r=l(a=t,(i=e).data_bg),c=l(a,i.data_bg_hidpi),(r=at&&c?c:r)&&(a.style.backgroundImage='url("'.concat(r,'")'),g(a).setAttribute(ot,r),L(a,i,o)),O(t,e,n)}function D(t,e,n){var a;T(t,e,n),a=e,e=n,(t=It[(n=t).tagName])&&(t(n,a),L(n,a,e))}function V(t,e,n){var a;a=t,(-1<yt.indexOf(a.tagName)?D:G)(t,e,n)}function F(t,e,n){var a;t.setAttribute("loading","lazy"),T(t,e,n),a=e,(e=It[(n=t).tagName])&&e(n,a),s(t,vt)}function j(t){t.removeAttribute(ot),t.removeAttribute(rt),t.removeAttribute(ct)}function P(t){m(t,function(t){k(t,Et)}),k(t,Et)}function S(t){var e;(e=At[t.tagName])?e(t):E(e=t)&&(t=I(e),e.style.backgroundImage=t.backgroundImage)}function U(t,e){var n;S(t),n=e,u(e=t)||d(e)||(v(e,n.class_entered),v(e,n.class_exited),v(e,n.class_applied),v(e,n.class_loading),v(e,n.class_loaded),v(e,n.class_error)),r(t),y(t)}function $(t,e,n,a){var i;n.cancel_on_exit&&(c(t)!==ut||"IMG"===t.tagName&&(z(t),m(i=t,function(t){j(t)}),j(i),P(t),v(t,n.class_loading),p(a,-1),r(t),f(n.callback_cancel,t,e,a)))}function q(t,e,n,a){var i,o,r=(o=t,0<=pt.indexOf(c(o)));s(t,"entered"),_(t,n.class_entered),v(t,n.class_exited),i=t,o=a,n.unobserve_entered&&b(i,o),f(n.callback_enter,t,e,a),r||V(t,n,a)}function H(t){return t.use_native&&"loading"in HTMLImageElement.prototype}function B(t,i,o){t.forEach(function(t){return(a=t).isIntersecting||0<a.intersectionRatio?q(t.target,t,i,o):(e=t.target,n=t,a=i,t=o,void(u(e)||(_(e,a.class_exited),$(e,n,a,t),f(a.callback_exit,e,n,t))));var e,n,a})}function J(e,n){var t;et&&!H(e)&&(n._observer=new IntersectionObserver(function(t){B(t,e,n)},{root:(t=e).container===document?null:t.container,rootMargin:t.thresholds||t.threshold+"px"}))}function K(t){return Array.prototype.slice.call(t)}function Q(t){return t.container.querySelectorAll(t.elements_selector)}function W(t){return c(t)===_t}function X(t,e){return e=t||Q(e),K(e).filter(u)}function Y(e,t){var n;(n=Q(e),K(n).filter(W)).forEach(function(t){v(t,e.class_error),r(t)}),t.update()}function t(t,e){var n,a,t=i(t);this._settings=t,this.loadingCount=0,J(t,this),n=t,a=this,Z&&window.addEventListener("online",function(){Y(n,a)}),this.update(e)}var Z="undefined"!=typeof window,tt=Z&&!("onscroll"in window)||"undefined"!=typeof navigator&&/(gle|ing|ro)bot|crawl|spider/i.test(navigator.userAgent),et=Z&&"IntersectionObserver"in window,nt=Z&&"classList"in document.createElement("p"),at=Z&&1<window.devicePixelRatio,it={elements_selector:".lazy",container:tt||Z?document:null,threshold:300,thresholds:null,data_src:"src",data_srcset:"srcset",data_sizes:"sizes",data_bg:"bg",data_bg_hidpi:"bg-hidpi",data_bg_multi:"bg-multi",data_bg_multi_hidpi:"bg-multi-hidpi",data_poster:"poster",class_applied:"applied",class_loading:"litespeed-loading",class_loaded:"litespeed-loaded",class_error:"error",class_entered:"entered",class_exited:"exited",unobserve_completed:!0,unobserve_entered:!1,cancel_on_exit:!0,callback_enter:null,callback_exit:null,callback_applied:null,callback_loading:null,callback_loaded:null,callback_error:null,callback_finish:null,callback_cancel:null,use_native:!1},ot="src",rt="srcset",ct="sizes",lt="poster",st="llOriginalAttrs",ut="loading",dt="loaded",ft="applied",_t="error",vt="native",gt="data-",bt="ll-status",pt=[ut,dt,ft,_t],ht=[ot],mt=[ot,lt],Et=[ot,rt,ct],It={IMG:function(t,e){m(t,function(t){A(t,Et),x(t,e)}),A(t,Et),x(t,e)},IFRAME:function(t,e){A(t,ht),w(t,ot,l(t,e.data_src))},VIDEO:function(t,e){a(t,function(t){A(t,ht),w(t,ot,l(t,e.data_src))}),A(t,mt),w(t,lt,l(t,e.data_poster)),w(t,ot,l(t,e.data_src)),t.load()}},yt=["IMG","IFRAME","VIDEO"],At={IMG:P,IFRAME:function(t){k(t,ht)},VIDEO:function(t){a(t,function(t){k(t,ht)}),k(t,mt),t.load()}},kt=["IMG","IFRAME","VIDEO"];return t.prototype={update:function(t){var e,n,a,i=this._settings,o=X(t,i);{if(h(this,o.length),!tt&&et)return H(i)?(e=i,n=this,o.forEach(function(t){-1!==kt.indexOf(t.tagName)&&F(t,e,n)}),void h(n,0)):(t=this._observer,i=o,t.disconnect(),a=t,void i.forEach(function(t){a.observe(t)}));this.loadAll(o)}},destroy:function(){this._observer&&this._observer.disconnect(),Q(this._settings).forEach(function(t){y(t)}),delete this._observer,delete this._settings,delete this.loadingCount,delete this.toLoadCount},loadAll:function(t){var e=this,n=this._settings;X(t,n).forEach(function(t){b(t,e),V(t,n,e)})},restoreAll:function(){var e=this._settings;Q(e).forEach(function(t){U(t,e)})}},t.load=function(t,e){e=i(e);V(t,e)},t.resetStatus=function(t){r(t)},Z&&function(t,e){if(e)if(e.length)for(var n,a=0;n=e[a];a+=1)o(t,n);else o(t,e)}(t,window.lazyLoadOptions),t});!function(e,t){"use strict";function a(){t.body.classList.add("litespeed_lazyloaded")}function n(){console.log("[LiteSpeed] Start Lazy Load Images"),d=new LazyLoad({elements_selector:"[data-lazyloaded]",callback_finish:a}),o=function(){d.update()},e.MutationObserver&&new MutationObserver(o).observe(t.documentElement,{childList:!0,subtree:!0,attributes:!0})}var d,o;e.addEventListener?e.addEventListener("load",n,!1):e.attachEvent("onload",n)}(window,document);</script><script data-no-optimize="1">var litespeed_vary=document.cookie.replace(/(?:(?:^|.*;\s*)_lscache_vary\s*\=\s*([^;]*).*$)|^.*$/,"");litespeed_vary||fetch("/wp-content/plugins/litespeed-cache/guest.vary.php",{method:"POST",cache:"no-cache",redirect:"follow"}).then(e=>e.json()).then(e=>{console.log(e),e.hasOwnProperty("reload")&&"yes"==e.reload&&(sessionStorage.setItem("litespeed_docref",document.referrer),window.location.reload(!0))});</script><script data-optimized="1" type="litespeed/javascript" data-src="https://www.nelsco.ir/wp-content/litespeed/js/4f8678a56e1bd614deb979ab7899d250.js?ver=5bfd0"></script><script>const litespeed_ui_events=["mouseover","click","keydown","wheel","touchmove","touchstart"];var urlCreator=window.URL||window.webkitURL;function litespeed_load_delayed_js_force(){console.log("[LiteSpeed] Start Load JS Delayed"),litespeed_ui_events.forEach(e=>{window.removeEventListener(e,litespeed_load_delayed_js_force,{passive:!0})}),document.querySelectorAll("iframe[data-litespeed-src]").forEach(e=>{e.setAttribute("src",e.getAttribute("data-litespeed-src"))}),"loading"==document.readyState?window.addEventListener("DOMContentLoaded",litespeed_load_delayed_js):litespeed_load_delayed_js()}litespeed_ui_events.forEach(e=>{window.addEventListener(e,litespeed_load_delayed_js_force,{passive:!0})});async function litespeed_load_delayed_js(){let t=[];for(var d in document.querySelectorAll('script[type="litespeed/javascript"]').forEach(e=>{t.push(e)}),t)await new Promise(e=>litespeed_load_one(t[d],e));document.dispatchEvent(new Event("DOMContentLiteSpeedLoaded")),window.dispatchEvent(new Event("DOMContentLiteSpeedLoaded"))}function litespeed_load_one(t,e){console.log("[LiteSpeed] Load ",t);var d=document.createElement("script");d.addEventListener("load",e),d.addEventListener("error",e),t.getAttributeNames().forEach(e=>{"type"!=e&&d.setAttribute("data-src"==e?"src":e,t.getAttribute(e))});let a=!(d.type="text/javascript");!d.src&&t.textContent&&(d.src=litespeed_inline2src(t.textContent),a=!0),t.after(d),t.remove(),a&&e()}function litespeed_inline2src(t){try{var d=urlCreator.createObjectURL(new Blob([t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1")],{type:"text/javascript"}))}catch(e){d="data:text/javascript;base64,"+btoa(t.replace(/^(?:<!--)?(.*?)(?:-->)?$/gm,"$1"))}return d}</script></body> <script type="litespeed/javascript">setInterval(function(){var xhttp=new XMLHttpRequest();xhttp.onreadystatechange=function(){if(this.readyState==4&&this.status==200){document.getElementById("temperaturec").innerHTML=this.responseText}};xhttp.open("GET","/temperaturec",!0);xhttp.send()},10000);setInterval(function(){var xhttp=new XMLHttpRequest();xhttp.onreadystatechange=function(){if(this.readyState==4&&this.status==200){document.getElementById("temperaturef").innerHTML=this.responseText}};xhttp.open("GET","/temperaturef",!0);xhttp.send()},10000)</script> </html>)rawliteral";

// Replaces placeholder with DS18B20 values
String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMPERATUREC"){
    return temperatureC;
  }
  else if(var == "TEMPERATUREF"){
    return temperatureF;
  }
  return String();
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);
  Serial.println();
  
  // Start up the DS18B20 library
  sensors.begin();

  temperatureC = readDSTemperatureC();
  temperatureF = readDSTemperatureF();

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  Serial.println("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  
  // Print ESP Local IP Address
  Serial.println(WiFi.localIP());

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });
  server.on("/temperaturec", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", temperatureC.c_str());
  });
  server.on("/temperaturef", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", temperatureF.c_str());
  });
  // Start server
  server.begin();
}
 
void loop(){
  if ((millis() - lastTime) > timerDelay) {
    temperatureC = readDSTemperatureC();
    temperatureF = readDSTemperatureF();
    lastTime = millis();
  }  
}
				
			

نام و پسورد شبکه وایفای خود را در متغیرهای زیر وارد کنید و کد بلافاصله کار خواهد کرد.

const char* ssid = "REPLACE_WITH_YOUR_SSID"; 
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

نحوه کار کد

در پاراگراف های بعدی نحوه عملکرد کد را توضیح خواهیم داد. اگر می‌خواهید بیشتر بدانید به خواندن ادامه دهید یا برای دیدن نتیجه نهایی به بخش «خروجی» بروید.

اضافه کردن کتابخانه ها

#include <Arduino.h> 
#include <ESP8266WiFi.h>
#include <Hash.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <OneWire.h>
#include <DallasTemperature.h>

GPIO را که پین داده DS18B20 به آن متصل است، تعریف کنید. در این مورد، به GPIO 4 (D1) متصل است.

#define ONE_WIRE_BUS 4

ساخت instances های مورد نیاز سنسور، سنسور به gpio 4 متصل شده است.

// Setup a oneWire instance to communicate with any OneWire devices 
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Da
DallasTemperature sensors(&oneWire);

 

متغیرهایی ایجاد کنید که دما را به عنوان مقادیر رشته نگه می دارند:

String temperatureF = "";

String temperatureC = "";

هر 30 ثانیه یک بار مقادیر سنسورها را دریافت خواهیم کرد. می توانید آن را در متغیر timerDelay تغییر دهید.

unsigned long lastTime = 0; 

unsigned long timerDelay = 30000;

تنظیم اعتبار شبکه شما
مقادیر ssid و password شبکه خود را در متغیرهای زیر وارد کنید تا ESP8266 بتواند به شبکه محلی شما متصل شود.

const char* ssid = "REPLACE_WITH_YOUR_SSID";

const char* password = "REPLACE_WITH_YOUR_PASSWORD";

یک شی AsyncWebServer در پورت 80 ایجاد کنید.

AsyncWebServer server(80);

توابع دما را فراخوانی کنید.

دو تابع برای خواندن دما ایجاد می کنیم. تابع readDSTemperatureC() قرائت ها را بر حسب درجه سانتیگراد برمی گرداند.

String readDSTemperatureC() { // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus

sensors.requestTemperatures();

float tempC = sensors.getTempCByIndex(0);

if(tempC == -127.00){

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

return "--";

}

else {

Serial.print("Temperature Celsius: ");

Serial.println(tempC);

}

return String(tempC);

}

در صورتی که سنسور نتواند یک مقدار معتبر دریافت کند، -127 را برمی گرداند. بنابراین، یک دستور if داریم که در صورتی که سنسور نتواند مقادیر را دریافت کند، دو خط تیره (–-) برمی گرداند.

if(tempC == -127.00){

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

return "--";

تابعreaDSTemperatureF() به روشی مشابه کار می کند اما مقادیر را در درجه فارنهایت برمی گرداند.

مقادیر به صورت رشته ای برگردانده می شوند. برای تبدیل یک float به رشته، از تابع String() استفاده کنید.

return String(tempC);

ساخت صفحه وب

مرحله بعدی ساخت صفحه وب است. HTML و CSS مورد نیاز برای ساخت صفحه وب در متغیر index_html ذخیره می شوند.

در متن HTML ما بین علامت % TEMPERATUREC و TEMPERATUREF داریم. این قسمت برای متغیر های دما میباشد.

این بدان معنی است که این متن %TEMPERATUREC% مانند متغیری است که با مقدار دمای واقعی سنسور جایگزین می شود. مکان‌ها در متن HTML باید بین علامت % قرار گیرند.

پردازش

اکنون، باید تابع ()processor را ایجاد کنیم، که جای جای‌گیرها را در متن HTML ما با مقادیر دمای واقعی جایگزین می‌کند.

// Replaces placeholder with DS18B20 values 

String processor(const String& var){

//Serial.println(var);

if(var == "TEMPERATUREC"){

return temperatureC;

}

else if(var == "TEMPERATUREF"){

return temperatureF;

}

return String();

}

هنگامی که صفحه وب درخواست می‌شود، بررسی می‌کنیم که آیا HTML دارای مقادیر متغیر است یا خیر. اگر مکان‌نمای %TEMPERATUREC% را پیدا کند، با فراخوانی تابع readDSTemperatureC() که قبلا ایجاد شده بود، دما را بر حسب سانتی‌گراد برمی‌گردانیم.

if(var == "TEMPERATUREC"){ return temperatureC; }

اگر مکان نگهدار %TEMPERATUREF باشد، دما را به فارنهایت برمی‌گردانیم.

else if(var == "TEMPERATUREF"){ return temperatureF; }

در setup()، مانیتور سریال را برای اهداف اشکال زدایی مقداردهی اولیه کنید.

Serial.begin(115200);

سنسور دمای DS18B20 را راه اندازی کنید.

sensors.begin();

مقادیر دمای فعلی را بدست آورید:

temperatureC = readDSTemperatureC();

temperatureF = readDSTemperatureF();

به شبکه محلی خود متصل شوید و آدرس IP ESP8266 را چاپ کنید.

WiFi.begin(ssid, password);

Serial.println("Connecting to WiFi");

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

delay(500);

Serial.print(".");

}

Serial.println(); // Print ESP8266 Local IP Address Serial.println(WiFi.localIP());

در نهایت، خطوط بعدی کد را برای مدیریت وب سرور اضافه کنید.

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
server.on("/temperaturec", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", temperatureC.c_str());
});
server.on("/temperaturef", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", temperatureF.c_str()
});

وقتی درخواستی را روی URL بخش root ارسال میکنیم، متن HTML را که در متغیر index_html ذخیره می‌شود، ارسال می‌کنیم. ما همچنین باید تابع پردازنده را اجرا کنیم، که همه جای‌بان‌ها متغیر ها را با مقادیر مناسب جایگزین می‌کند.

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

request->send_P(200, "text/html", index_html, processor);

});

برای به‌روزرسانی مقادیر دما، باید دو کنترل‌کننده اضافی اضافه کنیم. هنگامی که درخواستی را در URL /temperaturec دریافت می کنیم، فقط باید مقدار دمای به روز شده را ارسال کنیم. این متن ساده است و باید به صورت char ارسال شود، بنابراین از متد ()c_str استفاده می کنیم.

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

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

});

همین روند برای درجه حرارت فارنهایت تکرار می شود.

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

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

});

در نهایت، ما می توانیم سرور را راه اندازی کنیم.

server.begin();

در حلقه اصلی، مقادیر دما را هر 30 ثانیه به روز کنید (متغیر timerDelay).

void loop(){ 

if ((millis() - lastTime) > timerDelay) {

temperatureC = readDSTemperatureC();

temperatureF = readDSTemperatureF(); lastTime = millis();

}

}

این تقریباً نحوه عملکرد کد است.

خروجی

پس از آپلود کد، مانیتور سریال Arduino IDE را با نرخ باود 115200 باز کنید. پس از چند ثانیه آدرس IP شما نمایش داده می شود.

در شبکه محلی خود، یک مرورگر باز کنید و آدرس IP ESP8266 را تایپ کنید.

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

راه اندازی سنسور DS18B20 با ESP8266 در حالت تکی ، چندتایی و وب سرور (اینترنت اشیا)

در نهایت

این یک راهنمای عمیق و کامل در مورد نحوه استفاده از سنسور دمای DS18B20 با ESP8266 و نمایش مقادیر ها در یک وب سرور بود.

DS18B20 از طریق پروتکل یک سیم ارتباط برقرار می کند و هر سنسور دارای یک کد سریال 64 بیتی منحصر به فرد است، به این معنی که می توانید بسیاری از سنسورها را روی یک پین داده یکسان بخوانید.
این آموزش از سری اموزش ESP8266 با پایان رسید امیدواریم این آموزش برای شما مفید بوده باشد.

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

شروع کار با ماژول ESP8266 (معرفی)

نصب بردهای ESP8266 در آردوینو IDE (ویندوز – مک – لینوکس)

راهنمای جامع پین های ESP8266 (کدام پین ها را میتوانیم استفاده کنیم؟)

راه اندازی سنسور BME680 با استفاده از ESP8266 اندازه گیری گاز، فشار، رطوبت و دما به صورت ساده و وب سرور

برای امتیاز به این نوشته کلیک کنید!
[کل: 0 میانگین: 0]

نوشته های مشابه

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

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