Взаимодействие нескольких DS18B20, цифровых датчиков температуры, с Arduino
Одним из самых больших преимуществ датчиков температуры DS18B20 является то, что на одной шине 1-Wire могут сосуществовать несколько таких датчиков. Поскольку каждый DS18B20 имеет уникальный 64-битный последовательный код, зашитый на заводе, их легко отличать друг от друга.
В следующем руководстве показано, как подключить несколько датчиков DS18B20 к одной шине и получать показания температуры от каждого из них. Эта функция может быть огромным преимуществом, если вы хотите управлять несколькими датчиками DS18B20, распределенными по большой площади.
Это может показаться пугающим, но, прежде чем углубляться в это руководство, вы должны быть знакомы с основами работы с однопроводными датчиками температуры DS18B20. Если вы не знакомы с ними, посмотрите следующую статью:
А теперь, без дальнейших задержек, давайте подключим датчики DS18B20 к нашей плате Arduino.
Подключение нескольких датчиков DS18B20 к Arduino
Подключение довольно простое.
Начните с подключения всех датчиков DS18B20 параллельно, то есть объединения всех выводов VDD, выводов GND и сигнальных выводов. Затем подключите шину VDD к выходу 5V на Arduino, GND к выводу земли Arduino, и подключите сигнальные выводы к цифровому выводу 2 на Arduino.
Затем, чтобы обеспечить стабильную передачу данных, вам нужно добавить один подтягивающий резистор 4,7 кОм для всей шины между сигнальными выводами и выводами питания (внутренние подтягивающие резисторы на ардуино не работают).
Установка библиотеки для DS18B20
Протокол Dallas 1-Wire несколько сложен и требует много кода для парсинга связи. Чтобы скрыть эту ненужную сложность, мы установим библиотеку DallasTemperature.h, чтобы мы могли выполнять простые команды для получения показаний температуры от датчика.
Чтобы установить библиотеку, перейдите в раздел «Скетч»→ «Подключить библиотеку» → «Управление библиотеками…». Подождите, пока менеджер библиотеки загрузит индекс библиотек и обновит список установленных библиотек.
Чтобы отфильтровать результаты поиска, введите «ds18b20». Там должна быть пара записей. Ищите DallasTemperature от Miles Burton. Нажмите на эту запись, а затем выберите Установка.
Эта библиотека DallasTemperature является аппаратно-зависимой библиотекой, которая обрабатывает функции более низкого уровня. Она должна быть связана с библиотекой OneWire для связи с любым устройством 1-Wire, а не только с DS18B20. Установите и эту библиотеку.
Способ 1: чтение показаний DS18B20 по индексу
В этом методе библиотека Dallas Temperature при инициализации обнаруживает все датчики, использующие одну шину. Она рассматривает всю шину как массив датчиков и присваивает им индексы. Поэтому мы можем точно выбрать каждый датчик по его индексу и прочитать показания температуры.
#include <OneWire.h>
#include <DallasTemperature.h>
// линия данных подключена к цифровому выводу 2 Arduino
#define ONE_WIRE_BUS 2
// настройка объекта oneWire для связи с любым устройством OneWire
OneWire oneWire(ONE_WIRE_BUS);
// передать ссылку на oneWire библиотеке DallasTemperature
DallasTemperature sensors(&oneWire);
int deviceCount = 0;
float tempC;
void setup(void)
{
sensors.begin(); // запустить библиотеку
Serial.begin(9600);
// найти устройства на шине
Serial.print("Locating devices...");
Serial.print("Found ");
deviceCount = sensors.getDeviceCount();
Serial.print(deviceCount, DEC);
Serial.println(" devices.");
Serial.println("");
}
void loop(void)
{
// послать команду всем датчикам для преобразования температуры
sensors.requestTemperatures();
// отобразить температуру с каждого датчика
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((char)176);// напечатать символ градусов
Serial.print("C | ");
Serial.print(DallasTemperature::toFahrenheit(tempC));
Serial.print((char)176);// напечатать символ градусов
Serial.println("F");
}
Serial.println("");
delay(1000);
}
Вывод вышеприведенного скетча выглядит так:
Объяснение кода
Скетч начинается с включения библиотек, объявления вывода, к которому подключена шина датчиков, и создания объекта библиотеки DallasTemperature
.
В настроечной части кода мы сначала вызываем функцию begin()
. Она инициализирует шину и обнаруживает все DS18B20, присутствующие на ней. Затем каждому датчику присваивается индекс и устанавливается разрешение в 12 бит.
Затем мы вызываем функцию getDeviceCount()
, чтобы получить количество устройств, найденных на шине.
В циклической части кода мы используем функцию requestTemperatures()
, чтобы отправить команду всем датчикам для преобразования температуры.
Теперь, используя простой цикл for(int i = 0; i < deviceCount; i++)
, мы можем перебирать массив датчиков и считывать температуру DS18B20 по индексу i
, просто вызывая getTempCByIndex(i)
.
Способ 2: чтение датчика DS18B20 по адресу
Мы знаем, что каждому DS18B20 назначен уникальный 64-битный адрес, чтобы отличать их друг от друга. В этом методе мы найдем этот адрес для соответствующей маркировки каждого датчика. Затем этот адрес можно использовать для считывания каждого датчика в отдельности.
Поиск адресов датчиков DS18B20s на шине
Следующий скетч обнаруживает все DS18B20, присутствующие на шине, и печатает их адреса на 1-Wire в монитор последовательного порта.
Вы можете подключать только один датчик за раз, чтобы определить его адрес (или последовательно добавлять по одному новому датчику, чтобы вы могли идентифицировать каждый из них по его адресу). Затем вы можете пометить каждый датчик.
#include <OneWire.h>
#include <DallasTemperature.h>
// линия данных подключена к цифровому выводу 2 Arduino
#define ONE_WIRE_BUS 2
// настройка объекта oneWire для связи с любым устройством OneWire
OneWire oneWire(ONE_WIRE_BUS);
// передать ссылку на oneWire библиотеке DallasTemperature
DallasTemperature sensors(&oneWire);
// переменная для хранения адресов устройств
DeviceAddress Thermometer;
int deviceCount = 0;
void setup(void)
{
// запустить последовательный порт
Serial.begin(9600);
// запустить библиотеку
sensors.begin();
// найти устройства на шине
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("");
}
Теперь откройте монитор последовательного порта. Вы должны получить что-то подобное:
Скопируйте все адреса, так как они нам понадобятся в следующем скетче.
Чтение показаний датчиков DS18B20 по адресу
Следующий скетч считывает температуру датчиков DS18B20 по их адресам. Прежде чем приступить к загрузке скетча, вам нужно изменить адреса датчиков DS18B20 на те, которые вы определили в предыдущем скетче.
#include <OneWire.h>
#include <DallasTemperature.h>
// линия данных подключена к цифровому выводу 2 Arduino
#define ONE_WIRE_BUS 2
// настройка объекта oneWire для связи с любым устройством OneWire
OneWire oneWire(ONE_WIRE_BUS);
// передать ссылку на oneWire библиотеке DallasTemperature
DallasTemperature sensors(&oneWire);
// адреса трех датчиков DS18B20
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((char)176);
Serial.print("C | ");
Serial.print(DallasTemperature::toFahrenheit(tempC));
Serial.print((char)176);
Serial.println("F");
}
Вывод вышеприведенного эскиза выглядит так
Объяснение кода
Как обычно, скетч начинается с включения библиотек, объявления вывода, к которому подключена шина датчиков, и создания объекта библиотеки DallasTemperature
.
Далее мы вводим адреса, которые были найдены ранее для каждого датчика температуры. В нашем случае имеем следующее.
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 };
Во фрагменте настройки мы инициализируем библиотеку путем вызова функции begin()
и инициализируем последовательную связь с ПК.
В цикле мы просто посылаем команду всем датчикам для преобразования температуры, используя функцию requestTemperatures()
.
Затем, чтобы напечатать температуру датчика, мы вызываем пользовательскую функцию printTemperature(DeviceAddress deviceAddress)
, для которой deviceAddress
передается в качестве параметра.
void printTemperature(DeviceAddress deviceAddress)
{
float tempC = sensors.getTempC(deviceAddress);
Serial.print(tempC);
Serial.print((char)176);
Serial.print("C | ");
Serial.print(DallasTemperature::toFahrenheit(tempC));
Serial.print((char)176);
Serial.println("F");
}
Вышеприведенная функция просто вызывает библиотечные функции getTempC(deviceAddress)
для отображения температуры в градусах Цельсия и DallasTemperature::toFahrenheit()
для отображения температуры в градусах Фаренгейта.