Skip to contentSkip to main navigation Skip to footer

Arduino и термометр DS18B20

Описание


DS18B20 – высокоточный цифровой датчик температуры. Основные характеристики:

  • Диапазон: -55.. 125 °C
  • Точность: 0.5 °C
  • Разрешение: 9.. 12 бит (0.48.. 0.06 °C)
  • Питание: 3-5.5V
  • Период выдачи результата:
    • 750 мс при точности 12 бит
    • 94 мс при точности 9 бит
  • Интерфейс связи: 1-Wire (OneWire)
  • Корпус: TO-92, SOIC-8 или герметичное исполнение

В наборе идёт датчик в герметичном исполнении со стандартным гнездом (шаг 2.54 мм) для подключения

Подключение


Датчик имеет следующие назначения пинов:

 

Датчик подключается к любому цифровому пину Arduino, но пин должен быть подтянут к питанию резистором 4.7 кОм. На один пин можно подключить несколько датчиков DS18B20.

В рамках набора GyverKIT резистор на 4.7 кОм можно заменить двумя резисторами на 10 кОм (есть в комплекте), подключенными параллельно:

Библиотеки


Для этого датчика есть несколько библиотек:

  • “Официальная” библиотека DallasTemperature.h, для работы которой также понадобится библиотека OneWire.h.
  • Наша библиотека microDS18B20

В примерах на этом сайте мы будем использовать microDS18B20, так как она в несколько раз легче и проще в использовании, чем официальная. Библиотека идёт в архиве к набору GyverKIT, а свежую версию всегда можно установить/обновить из встроенного менеджера библиотек Arduino по названию microDS18B20. Краткая документация находится по ссылке выше, базовые примеры есть в самой библиотеке.

Работа с microDS18B20

Без адресации


В этом режиме на один пин МК подключается один датчик, для работы с ним не требуется предварительного чтения адреса и записи его в программу. Можно подключить несколько датчиков, каждому указать свой пин, см. пример one_pin_one_sensor.

MicroDS18B20<пин1> sensor1;
MicroDS18B20<пин2> sensor2;
// ... и так далее

С адресацией


В этом режиме можно подключить сколько угодно датчиков на один пин МК, но для работы с ними понадобится занести в программу уникальные адреса датчиков. В момент чтения адреса к пину должен быть подключен только один датчик! Пример – address_read. Для дальнейшей работы адреса хранятся в массивах на стороне программы и передаются датчикам при инициализации, пин указывается один и тот же:

uint8_t addr1[] = {0x28, 0xFF, 0xCD, 0x59, 0x51, 0x17, 0x4, 0xFE};
uint8_t addr2[] = {0x28, 0xFF, 0x36, 0x94, 0x65, 0x15, 0x2, 0x80};

MicroDS18B20<пин, addr1> sensor1;
MicroDS18B20<пин, addr2> sensor2;
// ... и так далее

Также адрес можно сменить во время работы программы, см. документацию.

Чтение температуры


Чтение температуры делится на два этапа – запрос и получение данных. Запрос делается функцией requestTemp(). После получения запроса датчик начинает измерение температуры, которое длится от 90 до 750 мс в зависимости от настроенной точности (по умолчанию точность максимальная, преобразование длится 750 мс). Если прочитать температуру до окончания преобразования – датчик вернёт результат предыдущего измерения, поэтому в примерах используется задержка или опрос по таймеру на 1 секунду. Получить температуру можно при помощи getTemp() [float] или getTempInt() [int]. Если принятые данные повреждены или датчик отсутствует на линии – функция вернёт предыдущее успешно прочитанное значение температуры.

Примечание: при повторных вызовах getTemp() не запрашивает с датчика новую температуру (долгое выполнение функции), вместо этого она просто возвращает предыдущий результат до тех пор, пока не будет сделан новый запрос requestTemp().

В версии библиотеки 3.5 появилась возможность отдельно запросить температуру и определить корректность полученных данных, чтобы только после этого их прочитать и применить в программе – функция readTemp(). Также это позволяет определить состояние подключения и всё ли в порядке с датчиком. Для чтения температуры рекомендуется использовать конструкцию вида:

if (sensor.readTemp()) value = sensor.getTemp();
// else отработка ошибки

где readTemp() запрашивает данные с датчика и возвращает true, если они прочитаны корректно. После этого можно забрать текущую температуру из getTemp(), которая уже не запрашивает температуру с датчика, а отдаёт прочитанный в readTemp() результат.

Примеры


Без адресации

Библиотека позволяет работать по схеме “один датчик – один пин”, в которой адрес датчика получать не нужно. Достаточно подключить и использовать:

// один датчик лучше читать без адресации, это сильно экономит память
#include <microDS18B20.h>
MicroDS18B20<2> sensor;

void setup() {
  Serial.begin(9600);
}

void loop() {
  // запрос температуры  
  sensor.requestTemp();
  
  // вместо delay используй таймер на millis(), пример async_read
  delay(1000);
  
  // проверяем успешность чтения и выводим
  if (sensor.readTemp()) Serial.println(sensor.getTemp());
  else Serial.println("error");
}
Без адресации асинхронный опрос
#include <microDS18B20.h>
MicroDS18B20<2> sensor;  // датчик на D2

void setup() {
  Serial.begin(9600);
}

void loop() {
  // конструкция программного таймера на 800 мс
  static uint32_t tmr;
  if (millis() - tmr >= 800) {
    tmr = millis();

    // читаем прошлое значение
    if (sensor.readTemp()) Serial.println(sensor.getTemp());
    else Serial.println("error");

    // запрашиваем новое измерение
    sensor.requestTemp();
  }
}
Чтение адреса

Каждый датчик имеет свой уникальный адрес. Его можно прочитать следующим образом:Данный код выводит в порт адрес текущего подключенного датчика.

#include <microDS18B20.h>

MicroDS18B20 <2> sensor;  // Создаем термометр без адреса на пине D2
uint8_t address[8];       // Создаем массив для адреса

void setup() {
  Serial.begin(9600);
}

void loop() {
  // читаем адрес термометра в указанный массив
  if (sensor.readAddress(address)) {  // если успешно, выводим
    Serial.print('{');
    for (uint8_t i = 0; i < 8; i++) {
      Serial.print("0x");
      Serial.print(address[i], HEX);  // Выводим адрес
      if (i < 7) Serial.print(", ");
    }
    Serial.println('}');

  } else Serial.println("Not connected");
  delay(1000);
}
Опрос датчиков с адресацией

Зная адреса датчиков, можно подключить несколько штук на один пин и обращаться к ним в коде следующим образом:

#include <microDS18B20.h>
#define DS_PIN 2 // пин для термометров

// Уникальные адреса датчиков - считать можно в примере address_read
uint8_t s1_addr[] = {0x28, 0xFF, 0xCD, 0x59, 0x51, 0x17, 0x4, 0xFE};
uint8_t s2_addr[] = {0x28, 0xFF, 0x36, 0x94, 0x65, 0x15, 0x2, 0x80};

MicroDS18B20<DS_PIN, s1_addr> sensor1;  // Создаем термометр с адресацией
MicroDS18B20<DS_PIN, s2_addr> sensor2;  // Создаем термометр с адресацией

void setup() {
  Serial.begin(9600);
}

void loop() {
  // асинхронное чтение нескольких датчиков смотри в примере async_read_many
  sensor1.requestTemp();      // Запрашиваем преобразование температуры
  sensor2.requestTemp();

  delay(1000);           // ожидаем результат 
  
  Serial.print("t1: ");
  if (sensor1.readTemp()) Serial.println(sensor1.getTemp());
  else Serial.println("error");

  Serial.print("t2: ");
  if (sensor2.readTemp()) Serial.println(sensor2.getTemp());
  else Serial.println("error");
}
Удобный опрос массива датчиков
// количество датчиков для удобства
#define DS_SENSOR_AMOUNT 5

// создаём двухмерный массив с адресами
uint8_t addr[][8] = {
  {0x28, 0xFF, 0x78, 0x5B, 0x50, 0x17, 0x4, 0xCF},
  {0x28, 0xFF, 0x99, 0x80, 0x50, 0x17, 0x4, 0x4D},
  {0x28, 0xFF, 0x53, 0xE5, 0x50, 0x17, 0x4, 0xC3},
  {0x28, 0xFF, 0x42, 0x5A, 0x51, 0x17, 0x4, 0xD2},
  {0x28, 0xFF, 0xCD, 0x59, 0x51, 0x17, 0x4, 0xFE},
};

#include <microDS18B20.h>
// указываем DS_ADDR_MODE для подключения блока адресации
// и создаём массив датчиков на пине D2
MicroDS18B20<2, DS_ADDR_MODE> sensor[DS_SENSOR_AMOUNT];

void setup() {
  Serial.begin(9600);
  // устанавливаем адреса
  for (int i = 0; i < DS_SENSOR_AMOUNT; i++) {
    sensor[i].setAddress(addr[i]);
  }
}

void loop() {
  // конструкция программного таймера на 1c
  static uint32_t tmr;
  if (millis() - tmr >= 1000) {
    tmr = millis();

    // выводим показания в порт
    for (int i = 0; i < DS_SENSOR_AMOUNT; i++) {
      Serial.print(sensor[i].getTemp());
      Serial.print(',');
    }
    Serial.println();

    // запрашиваем новые
    for (int i = 0; i < DS_SENSOR_AMOUNT; i++) {
      sensor[i].requestTemp();
    }
  }
}

Видео


Домашнее задание


  • Изучить остальные возможности библиотеки
  • Измерить температуру тела, сравнить со ртутным термометром

 

Связанные уроки

Полезный пример?

Похожие примеры
29 Комментариев
  • Приветствую!
    В код по получению адреса датчика вкралась опечатка.
    В Serial.print(addressBuf, HEX); не хватает [i]. Без неё выдает ошибку.

    // выводим в порт
    Serial.print(“Address: {“);
    for (uint8_t i = 0; i < 8; i++) {
    Serial.print("0x");
    Serial.print(addressBuf [i], HEX);
    if (i < 7) Serial.print(", ");
    }
    Serial.println("};");
    delay(1000);
    }

  • Доброго времени суток)
    Есть такой затык, библиотека microDS18B20 не хочет работать с GyverCore, выдаёт 0.0 градусов. Со стандартным ядром всё ок, плата Uno, Китай, само собой. Обвязка датчика в порядке. Со старой библиотекой и GyverCore почти всё норм, но иногда датчик выдаёт больше 80 градусов при комнатной температуре. Где копать? Библа 3.3, новая.

  • И вот ещё, забыл. Есть ли способ достать из DS3231 время и параметры будильника с библиотекой RTClib? Нигде не нашёл, может, вы знаете. Или нужно использовать другую либу? Или пользоваться стандартным протоколом? Заранее спасибо)

  • Здравствуйте!
    А как можно вывести значение температуры,чтобы после 30 градусов
    текст под значением температуры менялся

  • Как то возможно сделать калибровку датчиков три рядом лежат разные показания №1. 25.25;
    №2 25.37; №3 25.0.

  • А можно отправлять запрос на вычисление температуры одной командой сразу всем датчикам на одном пине? Потом читать каждый по отдельности. В стандартной библиотеке это возможно.

    • стандартная библиотека не просто так весит как УАЗ буханка =) В микродс18б20 отправлять обзий запрос нужно вручную в цикле, как в примере async_read_many

  • в общем , у меня на OLED выводится показания с 2х датчиков без видимых задержек, но ниже я вывожу меню (двойной массив, где во втором столбце значения на шим ( спасибо за гайды по ускорению) которые я задаю кнопками , как в принципе и управляю всем меню , а вот , собсна , и проблема , в меню появилась задержка , думаю это связано с порядком вызова функций в лупе ( сначала делаю запрос показаний , после бегаю по циклам в меню, все в лупе) или правилом обращения с библиотекой далласа, надеюсь норм обьяснил , подскажите плиз

  • Здравствуйте! У меня в монитор порта выводится значение температуры 3.06. При этом, если воспользоваться примером из библиотеки “OneWire.h” я вижу нормальное значение в 24.19 градусов, что явно соответствует действительности. Подскажите пж, если это не трудно, что это?

  • Удобный опрос массива датчиков – не работает –
    D:\MY_doc\Arduino\libraries\microDS18B20\src/microDS18B20.h:89:16: note: ‘_empDsAddr’ was not declared ‘constexpr’
    static uint8_t _empDsAddr[1] = {1};
    ^
    exit status 1
    Ошибка компиляции для платы NodeMCU 1.0 (ESP-12E Module).

    • Обновил библиотеку – все ок. Но как сделать, что бы при отключении датчика – показания с него обнулялись? (сейчас продолжает показывать последнюю

  • У мене датчик на 4 піна, можете підказати як його підключити і запрограмувати????

Оставить комментарий

Ваш адрес email не будет опубликован.