Взаимодействие нескольких DS18B20, цифровых датчиков температуры, с Arduino

Добавлено 23 декабря 2019 в 23:30

Одним из самых больших преимуществ датчиков температуры DS18B20 является то, что на одной шине 1-Wire могут сосуществовать несколько таких датчиков. Поскольку каждый DS18B20 имеет уникальный 64-битный последовательный код, зашитый на заводе, их легко отличать друг от друга.

Взаимодействие с несколькими DS18B20, цифровыми датчиками температуры, с Arduino
Взаимодействие с несколькими DS18B20, цифровыми датчиками температуры, с Arduino

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

Это может показаться пугающим, но, прежде чем углубляться в это руководство, вы должны быть знакомы с основами работы с однопроводными датчиками температуры DS18B20. Если вы не знакомы с ними, посмотрите следующую статью:

А теперь, без дальнейших задержек, давайте подключим датчики DS18B20 к нашей плате Arduino.

Подключение нескольких датчиков DS18B20 к Arduino

Подключение довольно простое.

Начните с подключения всех датчиков DS18B20 параллельно, то есть объединения всех выводов VDD, выводов GND и сигнальных выводов. Затем подключите шину VDD к выходу 5V на Arduino, GND к выводу земли Arduino, и подключите сигнальные выводы к цифровому выводу 2 на Arduino.

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

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

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

Протокол Dallas 1-Wire несколько сложен и требует много кода для парсинга связи. Чтобы скрыть эту ненужную сложность, мы установим библиотеку DallasTemperature.h, чтобы мы могли выполнять простые команды для получения показаний температуры от датчика.

Чтобы установить библиотеку, перейдите в раздел «Скетч»→ «Подключить библиотеку» → «Управление библиотеками…». Подождите, пока менеджер библиотеки загрузит индекс библиотек и обновит список установленных библиотек.

Рисунок 2 Установка библиотеки Arduino – выбор управления библиотеками в Arduino IDE
Рисунок 2 – Установка библиотеки Arduino – выбор управления библиотеками в Arduino IDE

Чтобы отфильтровать результаты поиска, введите «ds18b20». Там должна быть пара записей. Ищите DallasTemperature от Miles Burton. Нажмите на эту запись, а затем выберите Установка.

Рисунок 3 Установка библиотеки DallasTemperature в Arduino IDE
Рисунок 3 – Установка библиотеки DallasTemperature в Arduino IDE

Эта библиотека DallasTemperature является аппаратно-зависимой библиотекой, которая обрабатывает функции более низкого уровня. Она должна быть связана с библиотекой OneWire для связи с любым устройством 1-Wire, а не только с DS18B20. Установите и эту библиотеку.

Рисунок 4 Установка библиотеки OneWire в Arduino IDE
Рисунок 4 – Установка библиотеки OneWire в Arduino IDE

Способ 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);
}

Вывод вышеприведенного скетча выглядит так:

Рисунок 5 Вывод показаний нескольких датчиков DS18B20 индексным методом
Рисунок 5 – Вывод показаний нескольких датчиков DS18B20 индексным методом

Объяснение кода

Скетч начинается с включения библиотек, объявления вывода, к которому подключена шина датчиков, и создания объекта библиотеки 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("");
}

Теперь откройте монитор последовательного порта. Вы должны получить что-то подобное:

Рисунок 6 Нахождение адресов 1-Wire всех датчиков DS18B20 на шине
Рисунок 6 – Нахождение адресов 1-Wire всех датчиков DS18B20 на шине

Скопируйте все адреса, так как они нам понадобятся в следующем скетче.

Чтение показаний датчиков 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");
}

Вывод вышеприведенного эскиза выглядит так

Рисунок 7 Вывод показаний нескольких датчиков DS18B20 методом адреса
Рисунок 7 – Вывод показаний нескольких датчиков DS18B20 методом адреса

Объяснение кода

Как обычно, скетч начинается с включения библиотек, объявления вывода, к которому подключена шина датчиков, и создания объекта библиотеки 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() для отображения температуры в градусах Фаренгейта.

Теги

ArduinoDallasTemperature.hDS18B20ДатчикДатчик температурыИзмерениеИзмерение температурыИнтерфейс 1-Wire (OneWire)Температура

На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.

В случае комментирования в качестве гостя (без регистрации на disqus.com) для публикации комментария требуется время на премодерацию.


  • 2021-10-10baksser

    Ясен пень тоже самое, но без функций и лишних печатей. Вы этим уроком что хотели преподнести? Как функции работают или как датчики подключать. Уроки для начинающих? Надо думать как начинающий. Нахрена туда пихать лишнее. Кое как разобрался в вашей писанине. Проще надо быть и люди потянутся.

  • 2021-10-09radioprog

    Что именно усложнено? Какие циклы?
    Вы переписали всё то же самое, но без отдельной функции печати температуры в градусах Цельсия и Фаренгейта с символами градусов '°'.

  • 2021-10-05baksser

    Трындец всё как сложно запутываете нет чтобы тремя простыми словами нет надо циклы мутить запутанные.

    #include <onewire.h>
    #include <dallastemperature.h>
    #define ONE_WIRE_BUS 2

    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);

    uint8_t sensor1[8] = { 0x28, 0xFF, ... };
    uint8_t sensor2[8] = { 0x28, 0xFF, ... };
    uint8_t sensor3[8] = { 0x28, 0xFF, ... };

    void setup(void)
    {
    Serial.begin(115200);
    sensors.begin();
    }

    void loop(void)
    {
    sensors.requestTemperatures();
    Serial.print("температура");
    Serial.print(sensors.getTempC(sensor1));
    Serial.print("температура");
    Serial.print(sensors.getTempC(sensor2));
    Serial.print("температура");
    Serial.print(sensors.getTempC(sensor3));
    delay(1000);
    }

    И всё. Чё усложнять?

  • 2020-12-14Dmitry Bezborodov

    Здравствуйте. Подскажите, пожалуйста, в каком порядке датчикам присваиваются индексы? Могут ли одни и те же датчики получать разные индексы? Спасибо.