ESP8266 NodeMCU с датчиком температуры DS18B20 — веб-сервер с Arduino IDE
Узнайте, как использовать датчик температуры DS18B20 с ESP8266 (NodeMCU), используя Arduino IDE. Мы покажем вам, как подключить датчик к ESP8266 и построить веб-сервер для отображения показаний температуры.
Вы также можете ознакомиться с другими руководствами по DS18B20:
Знакомство с датчиком температуры DS18B20
Датчик температуры DS18B20 — это цифровой датчик температуры, работающий по протоколу one-wire. Это означает, что для связи с ESP8266 ему требуется всего одна линия данных (и GND).
Он может питаться от внешнего источника питания, или может получать питание от линии данных (так называемый «паразитный режим»), что устраняет необходимость во внешнем источнике питания.
Каждый датчик температуры DS18B20 имеет уникальный 64-битный серийный код. Это позволяет подключить несколько датчиков к одному проводу данных. Таким образом, вы можете получать температуру от нескольких датчиков, используя всего один GPIO.
Датчик температуры DS18B20 также доступен в водонепроницаемом исполнении.
Вот краткое описание наиболее важных характеристик датчика температуры DS18B20:
Связь по шине one-wire
Диапазон питания: от 3,0 В до 5,5 В
Рабочий диапазон температур: от -55 ºC до +125 ºC
Точность ±0,5 ºC (в диапазоне от -10 ºC до 85 ºC)
Для получения дополнительной информации ознакомьтесь с даташитом DS18B20.
Необходимые компоненты
Для выполнения этого руководства вам понадобятся следующие компоненты:
ESP8266 (например, NodeMCU)
Датчик температуры DS18B20 (один или несколько)
Резистор 4,7 кОм
Макетная плата
Соединительные провода
Схема подключения ESP8266 и DS18B20
Как упоминалось ранее, датчик температуры DS18B20 может питаться через вывод VDD (нормальный режим), или может получать питание от линии данных (паразитный режим). Вы можете выбрать любой из этих режимов.
Паразитный режим
Нормальный режим
Примечание
В этом руководстве мы подключаем линию данных DS18B20 к GPIO 4, но вы можете использовать любой другой подходящий GPIO.
Примечание
Если вы используете ESP-01, GPIO 2 является наиболее подходящим выводом для подключения к выводу данных DS18B20.
Подготовка Arduino IDE
Мы будем программировать ESP8266 с помощью Arduino IDE, поэтому убедитесь, что у вас установлено дополнение для ESP8266 перед продолжением.
Установка библиотек для DS18B20
Для работы с датчиком температуры DS18B20 вам необходимо установить библиотеку OneWire от Paul Stoffregen и библиотеку Dallas Temperature от Miles Burton. Выполните следующие шаги для установки этих библиотек.
Откройте Arduino IDE и перейдите в Sketch > Include Library > Manage Libraries. Должен открыться менеджер библиотек.
Введите «onewire» в поле поиска и установите библиотеку OneWire от Paul Stoffregen.
Затем введите «Dallas» и установите библиотеку Dallas Temperature от Miles Burton.
После установки библиотек перезапустите Arduino IDE.
Код (один DS18B20)
После установки необходимых библиотек вы можете загрузить следующий код в ESP8266. Код считывает температуру с датчика температуры DS18B20 и отображает показания в мониторе последовательного порта Arduino IDE.
/*********
Rui Santos
Complete project details at https://RandomNerdTutorials.com
*********/
#include <OneWire.h>
#include <DallasTemperature.h>
// GPIO, к которому подключен DS18B20
const int oneWireBus = 4;
// Создаём экземпляр oneWire для связи с любыми устройствами OneWire
OneWire oneWire(oneWireBus);
// Передаём ссылку на oneWire датчику Dallas Temperature
DallasTemperature sensors(&oneWire);
void setup() {
// Запускаем монитор последовательного порта
Serial.begin(115200);
// Запускаем датчик DS18B20
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. Однако, если вы используете только один датчик, это один из самых простых и лёгких способов.
Как работает код
Начнём с подключения библиотек OneWire и DallasTemperature.
#include <OneWire.h>
#include <DallasTemperature.h>
Создайте экземпляры, необходимые для датчика температуры. Датчик температуры подключен к GPIO 4.
// GPIO, к которому подключен DS18B20
const int oneWireBus = 4;
// Создаём экземпляр oneWire для связи с любыми устройствами OneWire
OneWire oneWire(oneWireBus);
// Передаём ссылку на oneWire датчику Dallas Temperature
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);
Демонстрация
После загрузки кода откройте монитор последовательного порта Arduino IDE на скорости 115200 бод. Вы должны увидеть температуру, отображаемую как в градусах Цельсия, так и в градусах Фаренгейта.
Получение температуры от нескольких датчиков DS18B20
Датчик температуры DS18B20 работает по протоколу one-wire, и каждый датчик имеет уникальный 64-битный серийный код, поэтому вы можете считывать температуру с нескольких датчиков, используя всего один цифровой вывод.
Схема
Для считывания температуры с нескольких датчиков нужно просто соединить все линии данных вместе, как показано на следующей схеме.
Код (несколько DS18B20)
Затем загрузите следующий код. Он сканирует все устройства на GPIO 4 и выводит температуру для каждого из них. Этот скетч основан на примере, предоставленном библиотекой DallasTemperature.
/*********
Rui Santos
Complete project details at https://RandomNerdTutorials.com
*********/
#include <OneWire.h>
#include <DallasTemperature.h>
// Провод данных подключен к GPIO 4
#define ONE_WIRE_BUS 4
// Создаём экземпляр oneWire для связи с любыми устройствами OneWire
// (не только с датчиками температуры Maxim/Dallas)
OneWire oneWire(ONE_WIRE_BUS);
// Передаём ссылку на oneWire датчику Dallas Temperature
DallasTemperature sensors(&oneWire);
// Количество найденных устройств температуры
int numberOfDevices;
// Переменная для хранения найденного адреса устройства
DeviceAddress tempDeviceAddress;
void setup(){
// Запускаем последовательный порт
Serial.begin(115200);
// Запускаем библиотеку
sensors.begin();
// Получаем количество устройств на шине
numberOfDevices = sensors.getDeviceCount();
// Ищем устройства на шине
Serial.print("Locating devices...");
Serial.print("Found ");
Serial.print(numberOfDevices, DEC);
Serial.println(" devices.");
// Проходим по каждому устройству, выводим адрес
for(int i=0;i<numberOfDevices; i++){
// Ищем адрес на шине
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(); // Отправляем команду для получения температур
// Проходим по каждому устройству, выводим данные о температуре
for(int i=0;i<numberOfDevices; i++){
// Ищем адрес на шине
if(sensors.getAddress(tempDeviceAddress, i)){
// Выводим ID устройства
Serial.print("Temperature for device: ");
Serial.println(i,DEC);
// Выводим данные
float tempC = sensors.getTempC(tempDeviceAddress);
Serial.print("Temp C: ");
Serial.print(tempC);
Serial.print(" Temp F: ");
Serial.println(DallasTemperature::toFahrenheit(tempC)); // Конвертируем в Фаренгейт
}
}
delay(5000);
}
// Функция для вывода адреса устройства
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);
Для получения температуры в градусах Фаренгейта вы можете использовать getTempF(). Альтернативно, вы можете преобразовать температуру из Цельсия в Фаренгейт следующим образом:
DallasTemperature::toFahrenheit(tempC)
Демонстрация
После загрузки кода откройте монитор последовательного порта на скорости 115200 бод. Вы должны увидеть показания всех ваших датчиков.
Отображение показаний температуры DS18B20 на веб-сервере
Для создания веб-сервера мы будем использовать библиотеку ESPAsyncWebServer, которая предоставляет простой способ создания асинхронного веб-сервера. Создание асинхронного веб-сервера имеет ряд преимуществ.
Установка библиотек веб-сервера
Мы создадим веб-сервер с использованием следующих библиотек:
Вы можете установить эти библиотеки с помощью менеджера библиотек Arduino. Перейдите в Sketch > Include Library > Manage Libraries и найдите названия библиотек.
Код (асинхронный веб-сервер DS18B20)
Откройте Arduino IDE и скопируйте следующий код.
/*********
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com
*********/
// Подключаем необходимые библиотеки
#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>
// Провод данных подключен к GPIO 4
#define ONE_WIRE_BUS 4
// Создаём экземпляр oneWire для связи с любыми устройствами OneWire
OneWire oneWire(ONE_WIRE_BUS);
// Передаём ссылку на oneWire датчику Dallas Temperature
DallasTemperature sensors(&oneWire);
// Переменные для хранения значений температуры
String temperatureF = "";
String temperatureC = "";
// Переменные таймера
unsigned long lastTime = 0;
unsigned long timerDelay = 30000;
// Замените на ваши сетевые учётные данные
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Создаём объект AsyncWebServer на порту 80
AsyncWebServer server(80);
String readDSTemperatureC() {
// Вызываем sensors.requestTemperatures() для запроса температуры
// у всех устройств на шине
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() {
// Вызываем sensors.requestTemperatures() для запроса температуры
// у всех устройств на шине
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">°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">°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";
// Заменяет плейсхолдеры значениями DS18B20
String processor(const String& var){
//Serial.println(var);
if(var == "TEMPERATUREC"){
return temperatureC;
}
else if(var == "TEMPERATUREF"){
return temperatureF;
}
return String();
}
void setup(){
// Последовательный порт для отладки
Serial.begin(115200);
Serial.println();
// Запускаем библиотеку DS18B20
sensors.begin();
temperatureC = readDSTemperatureC();
temperatureF = readDSTemperatureF();
// Подключаемся к Wi-Fi
WiFi.begin(ssid, password);
Serial.println("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
// Выводим локальный IP-адрес ESP
Serial.println(WiFi.localIP());
// Маршрут для корневой / веб-страницы
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());
});
// Запускаем сервер
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>
Инициализация датчика DS18B20
Определите GPIO, к которому подключен вывод данных DS18B20. В данном случае он подключен к GPIO 4 (D1).
#define ONE_WIRE_BUS 4
Создайте экземпляры, необходимые для инициализации датчика:
// Создаём экземпляр oneWire для связи с любыми устройствами OneWire
OneWire oneWire(ONE_WIRE_BUS);
// Передаём ссылку на oneWire датчику Dallas Temperature
DallasTemperature sensors(&oneWire);
Создайте переменные, которые будут хранить температуру в виде строковых значений:
String temperatureF = "";
String temperatureC = "";
Мы будем получать новые показания датчика каждые 30 секунд. Вы можете изменить это в переменной timerDelay.
unsigned long lastTime = 0;
unsigned long timerDelay = 30000;
Настройка сетевых учётных данных
Вставьте ваши сетевые учётные данные в следующие переменные, чтобы ESP8266 мог подключиться к вашей локальной сети.
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Создайте объект AsyncWebServer на порту 80.
AsyncWebServer server(80);
Функции чтения температуры
Затем мы создаём две функции для чтения температуры.
Функция readDSTemperatureC() возвращает показания в градусах Цельсия.
String readDSTemperatureC() {
// Вызываем sensors.requestTemperatures() для запроса температуры
// у всех устройств на шине
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 между знаками %. Это плейсхолдер для значений температуры.
Это означает, что текст %TEMPERATUREC% — это как переменная, которая будет заменена фактическим значением температуры от датчика. Плейсхолдеры в HTML-тексте должны находиться между знаками %.
Процессор
Теперь нам нужно создать функцию processor(), которая заменит плейсхолдеры в нашем HTML-тексте фактическими значениями температуры.
// Заменяет плейсхолдеры значениями DS18B20
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()
В 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();
// Выводим локальный IP-адрес ESP8266
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, мы отправляем 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", temperatureC.c_str());
});
Тот же процесс повторяется для температуры в градусах Фаренгейта.
server.on("/temperaturef", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", temperatureF.c_str());
});
Наконец, мы можем запустить сервер.
server.begin();
В loop() обновляйте значения температуры каждые 30 секунд (переменная timerDelay).
void loop(){
if ((millis() - lastTime) > timerDelay) {
temperatureC = readDSTemperatureC();
temperatureF = readDSTemperatureF();
lastTime = millis();
}
}
Вот, собственно, и всё о том, как работает код.
Демонстрация
После загрузки кода откройте монитор последовательного порта Arduino IDE на скорости 115200 бод. Через несколько секунд должен появиться ваш IP-адрес.
В вашей локальной сети откройте браузер и введите IP-адрес ESP8266.
Теперь вы можете видеть температуру в градусах Цельсия и Фаренгейта на вашем веб-сервере. Показания датчика обновляются автоматически без необходимости обновления веб-страницы.
Заключение
Это было подробное руководство по использованию датчика температуры DS18B20 с ESP8266 и отображению показаний на веб-сервере.
DS18B20 работает по протоколу one-wire, и каждый датчик имеет уникальный 64-битный серийный код, что означает, что вы можете считывать данные с множества датчиков через один вывод данных.
Мы надеемся, что это руководство было для вас полезным. У нас есть другие руководства по ESP8266, которые также могут вам понравиться:
ESP8266 с BME280 в Arduino IDE (давление, температура, влажность)
ESP8266: показания температуры и влажности DHT на OLED-дисплее
ESP8266 DHT11/DHT22 веб-сервер температуры и влажности с Arduino IDE
Узнайте больше о ESP8266 с помощью Home Automation using ESP8266 (электронная книга + видеокурс).
Также рекомендуем ознакомиться со справочным руководством по GPIO ESP8266.
Спасибо за чтение.