ESP32 и датчик температуры DS18B20 в Arduino IDE (один датчик, несколько датчиков, веб-сервер)

Это подробное руководство по датчику температуры DS18B20 с ESP32 в Arduino IDE. Мы покажем вам, как подключить датчик, установить необходимые библиотеки и написать код для получения показаний с одного и нескольких датчиков. В конце мы создадим простой веб-сервер для отображения показаний датчика.

ESP32 с датчиком температуры DS18B20 в Arduino IDE

Вам также могут быть полезны другие руководства по DS18B20:

Знакомство с датчиком температуры DS18B20

Датчик температуры DS18B20 - это цифровой датчик температуры с однопроводным интерфейсом (one-wire). Это означает, что для связи с ESP32 ему требуется только одна линия данных (и GND).

Он может питаться от внешнего источника питания или получать питание от линии данных (так называемый «паразитный режим»), что устраняет необходимость во внешнем источнике питания.

Распиновка датчика температуры DS18B20

Каждый датчик температуры DS18B20 имеет уникальный 64-битный серийный код. Это позволяет подключить несколько датчиков к одной линии данных. Таким образом, вы можете получать температуру с нескольких датчиков, используя всего один GPIO.

Датчик температуры DS18B20 также доступен в водонепроницаемом исполнении.

Водонепроницаемый датчик температуры DS18B20

Вот краткое описание наиболее важных характеристик датчика температуры DS18B20:

  • Связь по однопроводной шине (one-wire bus)

  • Диапазон напряжения питания: от 3,0 В до 5,5 В

  • Диапазон рабочих температур: от -55°C до +125°C

  • Точность +/-0,5°C (в диапазоне от -10°C до 85°C)

Для получения дополнительной информации обратитесь к даташиту DS18B20.

Необходимые компоненты

Для выполнения этого руководства вам понадобятся следующие компоненты:

Вы можете использовать приведенные выше ссылки или перейти непосредственно на MakerAdvisor.com/tools, чтобы найти все компоненты для ваших проектов по лучшей цене!

Схема подключения – ESP32

Как упоминалось ранее, датчик температуры DS18B20 может питаться через вывод VDD (нормальный режим) или получать питание от линии данных (паразитный режим). Вы можете выбрать любой режим.

Если вы используете ESP32, следуйте одной из этих двух схем подключения.

Паразитный режим

Схема подключения датчика температуры DS18B20 к ESP32 в паразитном режиме

Нормальный режим

Схема подключения датчика температуры DS18B20 к ESP32 в нормальном режиме

Подготовка Arduino IDE

Мы будем программировать ESP32 с помощью Arduino IDE, поэтому убедитесь, что у вас установлено дополнение для ESP32, прежде чем продолжить:

Установка библиотек

Для работы с датчиком температуры DS18B20 вам необходимо установить библиотеку OneWire от Paul Stoffregen и библиотеку Dallas Temperature. Выполните следующие шаги для установки этих библиотек.

  1. Откройте Arduino IDE и перейдите в Sketch > Include Library > Manage Libraries. Должен открыться менеджер библиотек.

  2. Введите «onewire» в поле поиска и установите библиотеку OneWire от Paul Stoffregen.

Установка библиотеки OneWire от Paul Stoffregen в Arduino IDE
  1. Затем найдите «Dallas» и установите библиотеку DallasTemperature от Miles Burton.

Установка библиотеки DallasTemperature от Miles Burton в Arduino IDE

После установки библиотек перезапустите Arduino IDE.

Код (один DS18B20)

После установки необходимых библиотек вы можете загрузить код в ESP32. Следующий код считывает температуру с датчика DS18B20 и отображает показания в мониторе порта Arduino IDE.

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com
*********/

#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 OneWire с ESP32 и Arduino IDE

Как работает код

Начните с подключения библиотек OneWire и DallasTemperature.

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

Создайте экземпляры, необходимые для датчика температуры. Датчик температуры подключен к 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.print(temperatureC);
Serial.println("ºC");
Serial.print(temperatureF);
Serial.println("ºF");

Новые показания температуры запрашиваются каждые 5 секунд.

delay(5000);

Демонстрация

После загрузки кода вы должны увидеть показания датчика в мониторе порта:

Показания температуры DS18B20 в мониторе порта Arduino IDE

Получение температуры с нескольких датчиков DS18B20

Несколько датчиков температуры DS18B20 OneWire с ESP32 и Arduino IDE

Датчик температуры DS18B20 использует протокол связи one-wire, и каждый датчик имеет уникальный 64-битный серийный код, поэтому вы можете считывать температуру с нескольких датчиков, используя всего один GPIO. Вам нужно просто соединить все линии данных вместе, как показано на следующей схеме:

Схема подключения нескольких датчиков температуры DS18B20 к ESP32

Код (несколько DS18B20)

Затем загрузите следующий код. Он сканирует все устройства на GPIO 4 и выводит температуру для каждого из них. (Этот скетч основан на примере из библиотеки DallasTemperature).

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com
*********/

#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. Вот что мы получаем в мониторе порта Arduino IDE.

Показания нескольких датчиков DS18B20 ESP32 в мониторе порта

У нас есть отдельная статья о том, как подключить несколько датчиков температуры DS18B20 к ESP32. Просто перейдите к следующему руководству:

ESP32 с несколькими датчиками температуры DS18B20 в Arduino IDE

Отображение показаний температуры DS18B20 на веб-сервере

Отображение показаний температуры DS18B20 на веб-сервере ESP32 в Arduino IDE

Для создания веб-сервера мы используем библиотеку ESPAsyncWebServer, которая предоставляет удобный способ создания асинхронного веб-сервера. Создание асинхронного веб-сервера имеет ряд преимуществ. Мы рекомендуем кратко ознакомиться с документацией библиотеки на её странице GitHub.

Установка библиотек ESPAsyncWebServer и AsyncTCP

Для создания веб-сервера в рамках данного проекта вам необходимо установить следующие библиотеки в Arduino IDE.

Вы можете установить эти библиотеки через менеджер библиотек Arduino IDE. Перейдите в Sketch > Include Library > Manage Libraries и найдите названия библиотек.

Код (асинхронный веб-сервер DS18B20)

Откройте Arduino IDE и скопируйте следующий код.

/*********
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com
*********/

// 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>
#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 rel="stylesheet" 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>
</body>
<script>
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", true);
  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", true);
  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(200, "text/html", index_html, processor);
  });
  server.on("/temperaturec", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", temperatureC.c_str());
  });
  server.on("/temperaturef", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(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";

Как работает код

В следующих абзацах мы объясним, как работает код. Продолжайте чтение, если хотите узнать больше, или перейдите к разделу «Демонстрация», чтобы увидеть конечный результат.

Импорт библиотек

Сначала импортируйте необходимые библиотеки для платы ESP32:

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

Создание экземпляра датчика DS18B20

Определите GPIO, к которому подключен вывод данных DS18B20. В данном случае он подключен к 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);

Настройка сетевых учетных данных

Вставьте свои сетевые учетные данные в следующие переменные, чтобы ESP32 мог подключиться к вашей локальной сети.

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 "--";

Функция readDSTemperatureF() работает аналогичным образом, но возвращает показания в градусах Фаренгейта.

Показания возвращаются в виде строкового типа. Для преобразования float в строку используется функция String().

return String(tempC);

Создание веб-страницы

Следующий шаг – создание веб-страницы. HTML и CSS, необходимые для создания веб-страницы, сохраняются в переменной index_html.

В HTML-тексте мы имеем TEMPERATUREC и TEMPERATUREF между знаками %. Это заполнитель (placeholder) для значений температуры.

Это означает, что текст %TEMPERATUREC% является чем-то вроде переменной, которая будет заменена фактическим значением температуры от датчика. Заполнители в HTML-тексте должны быть помещены между знаками %.

Мы подробно объяснили, как работают HTML и CSS, используемые в этом веб-сервере, в предыдущем руководстве. Если вы хотите узнать больше, обратитесь к следующему проекту:

Процессор

Теперь нам нужно создать функцию processor(), которая заменит заполнители в нашем HTML-тексте фактическими значениями температуры.

String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMPERATUREC"){
    return readDSTemperatureC();
  }
  else if(var == "TEMPERATUREF"){
    return readDSTemperatureF();
  }
  return String();
}

Когда запрашивается веб-страница, мы проверяем, есть ли в HTML какие-либо заполнители. Если находится заполнитель %TEMPERATUREC%, мы возвращаем температуру в градусах Цельсия, вызывая созданную ранее функцию readDSTemperatureC().

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

Если заполнитель – %TEMPERATUREF%, мы возвращаем температуру в градусах Фаренгейта.

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

Функция setup()

В функции setup() инициализируйте монитор порта для целей отладки.

Serial.begin(115200);

Инициализируйте датчик температуры DS18B20.

sensors.begin();

Подключитесь к локальной сети и выведите IP-адрес ESP32.

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", readDSTemperatureC().c_str());
});
server.on("/temperaturef", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", readDSTemperatureF().c_str());
});

Когда мы делаем запрос к корневому URL, мы отправляем HTML-текст, хранящийся в переменной index_html. Нам также нужно передать функцию processor, которая заменит все заполнители правильными значениями.

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", readDSTemperatureC().c_str());
});

Тот же процесс повторяется для температуры в градусах Фаренгейта.

server.on("/temperaturef", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", readDSTemperatureF().c_str());
});

Наконец, мы можем запустить сервер.

server.begin();

Поскольку это асинхронный веб-сервер, нам не нужно писать ничего в функции loop().

void loop(){

}

Вот примерно так и работает этот код.

Демонстрация

После загрузки кода откройте монитор порта Arduino IDE на скорости 115200 бод. Нажмите кнопку RST на плате ESP32, и через несколько секунд должен отобразиться ваш IP-адрес.

В вашей локальной сети откройте браузер и введите IP-адрес ESP32.

Теперь вы можете видеть температуру в градусах Цельсия и Фаренгейта на вашем веб-сервере. Показания датчика обновляются автоматически без необходимости обновления веб-страницы.

Веб-сервер ESP32 с датчиком температуры DS18B20 OneWire в Arduino IDE

Заключение

Мы надеемся, что это руководство было для вас полезным. У нас есть руководства для других датчиков и модулей с ESP32, которые могут вам понравиться:

Если вы хотите узнать больше о ESP32, ознакомьтесь с нашим курсом или бесплатными ресурсами по ESP32:

Спасибо за чтение.


Источник: ESP32 DS18B20 Temperature Sensor with Arduino IDE (Single, Multiple, Web Server)