Подключение нескольких цифровых датчиков температуры DS18B20 к Arduino
Одна из самых замечательных особенностей датчика температуры DS18B20 — возможность подключить множество таких датчиков, используя всего один провод данных. Это возможно благодаря тому, что каждый датчик DS18B20 имеет свой собственный уникальный 64-битный адрес. Этот специальный адрес позволяет вашему микроконтроллеру идентифицировать каждый датчик индивидуально, даже когда все они подключены к одному проводу данных.
Эта функция очень полезна, когда вы хотите контролировать температуру в разных местах — например, в разных комнатах дома, секциях теплицы или на любой большой территории. И самое лучшее — всё это можно сделать с помощью одного провода данных!
В этом руководстве вы узнаете, как настроить и считывать температуру с нескольких датчиков DS18B20, подключённых к одному проводу.
Прежде чем начать, вам следует разобраться в основах работы однопроводного датчика температуры DS18B20. Если вы новичок в работе с этим датчиком или вам нужно освежить знания, ознакомьтесь с руководством ниже:
Теперь, когда вы готовы, давайте начнём подключение датчиков DS18B20 к нашему Arduino!
Схема подключения нескольких датчиков DS18B20 к Arduino
Подключение нескольких датчиков DS18B20 к вашему Arduino довольно простое.
Начните с параллельного подключения всех датчиков — это означает, что все выводы VDD, GND и сигнальные выводы каждого датчика соединяются вместе.
Затем подключите провод VDD к выходу 5 В на Arduino, провод GND — к выводу заземления Arduino, а сигнальный провод — к цифровому выводу 2 на Arduino.
Для стабильной передачи данных вам нужно добавить подтягивающий резистор 4,7 кОм между сигнальной линией и линией питания. Обратите внимание — использование внутренних подтягивающих резисторов Arduino в данном случае не подойдёт, поэтому вам необходимо использовать настоящий физический резистор.
Вот краткая справочная таблица подключения выводов:
| DS18B20 | Arduino | Notes | |
| VDD | 5V | – | |
| GND | GND | – | |
| DQ | 2 | pulled up by 4.7kΩ |
Установка библиотеки
Протокол связи 1-Wire®, используемый датчиком DS18B20, довольно сложен, и написание всего кода для него с нуля заняло бы много времени. К счастью, существует специальная библиотека DallasTemperature, которая значительно упрощает задачу.
Для установки библиотеки:
Сначала откройте вашу программу Arduino IDE. Затем нажмите на иконку Менеджер библиотек на левой боковой панели.
Введите «ds18b20» в поле поиска для фильтрации результатов.
Найдите библиотеку DallasTemperature от Miles Burton.
Нажмите кнопку Install, чтобы добавить её в вашу Arduino IDE.
Для правильной работы библиотеке DallasTemperature необходима другая библиотека — OneWire.
Для установки библиотеки OneWire:
Снова откройте Менеджер библиотек.
В поле поиска введите «onewire».
Найдите библиотеку OneWire и нажмите Install.
После установки обеих библиотек вы будете готовы начать работу с датчиками DS18B20!
Методы считывания нескольких датчиков DS18B20
Когда у вас подключено более одного датчика DS18B20 к одному проводу данных, существует два основных метода считывания температуры с каждого из них.
Считывание по индексу — в этом методе библиотека автоматически присваивает каждому датчику номер индекса в порядке их обнаружения. Вы можете использовать эти номера индексов, чтобы запросить у Arduino считывание температуры с конкретного датчика. Этот метод полезен, когда вам не нужно точно знать, какой датчик является каким физически, а просто хотите прочитать все в порядке их обнаружения.
Считывание по адресу — каждый датчик DS18B20 имеет свой уникальный 64-битный адрес. В этом методе вы используете эти специальные адреса для прямой связи с каждым датчиком, поэтому вы всегда знаете, с какого именно датчика получаете температуру — независимо от его расположения на шине.
Давайте подробнее рассмотрим, как работает каждый метод.
Метод 1: Считывание датчиков DS18B20 по индексу
Когда мы используем библиотеку DallasTemperature с датчиками DS18B20, первое, что она делает — сканирует шину 1-Wire для поиска всех подключённых датчиков. Библиотека присваивает каждому датчику индекс, начиная с нуля. После присвоения индекса мы можем легко считать температуру с любого датчика, просто обратившись к его номеру индекса.
Пример скетча ниже показывает, как настроить Arduino для поиска всех подключённых датчиков DS18B20 и отображения их показаний температуры.
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into digital pin 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire device
OneWire oneWire(ONE_WIRE_BUS);
// Pass oneWire reference to DallasTemperature library
DallasTemperature sensors(&oneWire);
int deviceCount = 0;
float tempC;
void setup(void) {
sensors.begin(); // Start up the library
Serial.begin(9600);
// locate devices on the bus
Serial.print("Locating devices...");
Serial.print("Found ");
deviceCount = sensors.getDeviceCount();
Serial.print(deviceCount, DEC);
Serial.println(" devices.");
Serial.println("");
}
void loop(void) {
// Send command to all the sensors for temperature conversion
sensors.requestTemperatures();
// Display temperature from each sensor
for (int i = 0; i < deviceCount; i++) {
Serial.print("Sensor ");
Serial.print(i + 1);
Serial.print(" : ");
tempC = sensors.getTempCByIndex(i);
Serial.print(tempC);
Serial.print("°C | ");
Serial.print(DallasTemperature::toFahrenheit(tempC));
Serial.println("°F");
}
Serial.println("");
delay(1000);
}
После загрузки скетча на ваш Arduino откройте монитор последовательного порта и установите скорость 9600 бод. Вы увидите текущую температуру от каждого датчика в градусах Цельсия (°C) и Фаренгейта (°F).
Объяснение кода:
Скетч начинается с подключения двух важных библиотек: OneWire.h, которая обеспечивает связь с устройствами, использующими протокол 1-Wire, и DallasTemperature.h, которая упрощает работу с датчиками DS18B20 для получения показаний температуры.
#include <OneWire.h>
#include <DallasTemperature.h>
Далее мы указываем Arduino, к какому выводу подключены датчики — в данном случае это цифровой вывод 2.
#define ONE_WIRE_BUS 2
Для связи с датчиками нужно сделать две вещи. Сначала мы создаём объект OneWire и указываем, к какому выводу подключён датчик. Затем создаём объект DallasTemperature и передаём ему ссылку на только что созданный объект OneWire.
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
Мы также создаём две переменные: deviceCount хранит количество найденных на шине датчиков, а tempC хранит показания температуры от каждого датчика.
int deviceCount = 0;
float tempC;
В секции setup мы сначала вызываем функцию begin(), которая сканирует шину для поиска всех подключённых датчиков DS18B20. По мере обнаружения каждого датчика библиотека присваивает ему номер индекса.
sensors.begin();
Затем мы используем getDeviceCount(), чтобы узнать, сколько датчиков было обнаружено, и выводим это число в монитор последовательного порта.
Serial.print("Locating devices...");
Serial.print("Found ");
deviceCount = sensors.getDeviceCount();
Serial.print(deviceCount, DEC);
Serial.println(" devices.");
В секции loop() мы вызываем функцию sensors.requestTemperatures(). Эта команда сообщает всем датчикам на шине о необходимости выполнить преобразование температуры.
sensors.requestTemperatures();
Наконец, мы используем простой цикл for для последовательного перебора каждого датчика. Для каждого датчика мы получаем его температуру с помощью getTempCByIndex(index) и выводим температуру в градусах Цельсия и Фаренгейта.
for (int i = 0; i < deviceCount; i++) {
Serial.print("Sensor ");
Serial.print(i + 1);
Serial.print(" : ");
tempC = sensors.getTempCByIndex(i);
Serial.print(tempC);
Serial.print("°C | ");
Serial.print(DallasTemperature::toFahrenheit(tempC));
Serial.println("°F");
}
После вывода всех температур делается пауза в одну секунду перед повторением.
Метод 2: Считывание датчиков DS18B20 по адресу
Каждый датчик температуры DS18B20 имеет свой уникальный 64-битный адрес. Этот специальный адрес позволяет идентифицировать каждый датчик индивидуально, даже если несколько датчиков подключены к одному проводу данных.
В этом примере мы используем два скетча. Сначала мы используем один скетч для поиска и записи адреса каждого датчика. Затем, во втором скетче, мы используем эти адреса для индивидуального считывания температуры с каждого датчика.
Поиск адресов DS18B20 на шине
Первое, что нам нужно сделать — узнать адрес каждого датчика. Наш скетч будет искать все датчики DS18B20, подключённые к проводу данных, и выводить адрес каждого из них в монитор последовательного порта.
Рекомендуется подключать по одному датчику за раз при выполнении этого шага. Так вы сможете легко отслеживать, какой датчик имеет какой адрес, и даже присвоить каждому метку или имя.
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// variable to hold device addresses
DeviceAddress Thermometer;
int deviceCount = 0;
void setup(void) {
// start serial port
Serial.begin(9600);
// Start up the library
sensors.begin();
// locate devices on the bus
Serial.println("Locating devices...");
Serial.print("Found ");
deviceCount = sensors.getDeviceCount();
Serial.print(deviceCount, DEC);
Serial.println(" devices.");
Serial.println("");
Serial.println("Printing addresses...");
for (int i = 0; i < deviceCount; i++) {
Serial.print("Sensor ");
Serial.print(i + 1);
Serial.print(" : ");
sensors.getAddress(Thermometer, i);
printAddress(Thermometer);
}
}
void loop(void) {
}
void printAddress(DeviceAddress deviceAddress) {
for (uint8_t i = 0; i < 8; i++) {
Serial.print("0x");
if (deviceAddress[i] < 0x10) Serial.print("0");
Serial.print(deviceAddress[i], HEX);
if (i < 7) Serial.print(", ");
}
Serial.println("");
}
После загрузки скетча на ваш Arduino откройте монитор последовательного порта. Вы увидите адрес каждого подключённого датчика.
Примечание: Обязательно скопируйте эти адреса и сохраните их, так как они понадобятся для следующего скетча.
Объяснение кода:
Мы начинаем с подключения двух важных библиотек, необходимых для связи с датчиками DS18B20. Затем указываем, какой цифровой вывод Arduino подключён к проводу данных — в данном случае вывод 2. Мы также создаём специальную переменную для хранения адреса каждого найденного датчика.
В секции setup() кода мы запускаем последовательную связь, инициализируем библиотеку датчиков и просим её выполнить поиск подключённых датчиков. После их обнаружения библиотека подсчитывает их количество и выводит это число. Затем программа последовательно перебирает каждый датчик и отображает его уникальный адрес.
Функция printAddress() используется для форматирования адреса, чтобы он отображался в удобном виде в мониторе последовательного порта.
Считывание DS18B20 по адресу
Теперь, когда мы обнаружили и сохранили адреса каждого датчика, мы можем использовать их для индивидуального считывания температуры с каждого из них. Перед запуском этого второго скетча убедитесь, что вы заменили примеры адресов в коде на те, которые нашли у ваших собственных датчиков на предыдущем шаге.
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// Addresses of 3 DS18B20s
uint8_t sensor1[8] = { 0x28, 0xEE, 0xD5, 0x64, 0x1A, 0x16, 0x02, 0xEC };
uint8_t sensor2[8] = { 0x28, 0x61, 0x64, 0x12, 0x3C, 0x7C, 0x2F, 0x27 };
uint8_t sensor3[8] = { 0x28, 0x61, 0x64, 0x12, 0x3F, 0xFD, 0x80, 0xC6 };
void setup(void) {
Serial.begin(9600);
sensors.begin();
}
void loop(void) {
sensors.requestTemperatures();
Serial.print("Sensor 1: ");
printTemperature(sensor1);
Serial.print("Sensor 2: ");
printTemperature(sensor2);
Serial.print("Sensor 3: ");
printTemperature(sensor3);
Serial.println();
delay(1000);
}
void printTemperature(DeviceAddress deviceAddress) {
float tempC = sensors.getTempC(deviceAddress);
Serial.print(tempC);
Serial.print("°C | ");
Serial.print(DallasTemperature::toFahrenheit(tempC));
Serial.println("°F");
}
После загрузки этого скетча на ваш Arduino вы увидите температуру от всех датчиков, чётко отображённую в мониторе последовательного порта. Поскольку вы используете их уникальные адреса, вы всегда будете точно знать, какой датчик сообщает какую температуру.
Объяснение кода:
Как и прежде, мы подключаем необходимые библиотеки, указываем, к какому выводу подключён провод данных, и создаём объект из библиотеки DallasTemperature.
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
Далее мы вводим адреса датчиков в том же формате, который был отображён ранее. Эти адреса хранятся в специальных массивах — по одному на каждый датчик.
uint8_t sensor1[8] = { 0x28, 0xEE, 0xD5, 0x64, 0x1A, 0x16, 0x02, 0xEC };
uint8_t sensor2[8] = { 0x28, 0x61, 0x64, 0x12, 0x3C, 0x7C, 0x2F, 0x27 };
uint8_t sensor3[8] = { 0x28, 0x61, 0x64, 0x12, 0x3F, 0xFD, 0x80, 0xC6 };
В секции setup() мы вызываем функцию begin(), которая сканирует шину для поиска всех подключённых датчиков DS18B20.
void setup(void) {
Serial.begin(9600);
sensors.begin();
}
В секции loop() мы даём всем датчикам команду выполнить преобразование температуры с помощью функции requestTemperatures(). Затем мы последовательно перебираем каждый датчик и используем пользовательскую функцию printTemperature(deviceAddress) для отображения температуры датчика, чей deviceAddress передаётся в качестве параметра.
void loop(void) {
sensors.requestTemperatures();
Serial.print("Sensor 1: ");
printTemperature(sensor1);
Serial.print("Sensor 2: ");
printTemperature(sensor2);
Serial.print("Sensor 3: ");
printTemperature(sensor3);
Serial.println();
delay(1000);
}
Функция printTemperature() просто вызывает функцию getTempC(deviceAddress) для получения температуры от конкретного датчика по его адресу, а затем выводит температуру в градусах Цельсия и Фаренгейта.
void printTemperature(DeviceAddress deviceAddress) {
float tempC = sensors.getTempC(deviceAddress);
Serial.print(tempC);
Serial.print("°C | ");
Serial.print(DallasTemperature::toFahrenheit(tempC));
Serial.println("°F");
}