Подключение ds18b20 к arduino. Вот так выглядит эта «супер-сложная» схема DS18B20 подключение к Arduino

Рассмотрим как при помощи Arduino считывать показания с цифрового датчика температуры DS18B20 или DS18S20. В настоящий момент м/с DS18B20 фирмы Dallas является наиболее распространенным и доступным цифровым датчиком температуры. Работает по протоколу . Даташит датчика:

Схема подключения датчика DS18B20 к Arduino приведена ниже. Подтягивающий Pull-Up резистор номиналом 4.7 кОм (5 кОм) включается между выводом DQ (Data) и питанием датчика Vdd.

Рабочий скетч представлен ниже. Необходима библиотека OneWire, последнюю версию которой можно скачать .

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

#include "OneWire.h" // OneWire DS18S20, DS18B20, DS1822 Temperature Example // // http://www.pjrc.com/teensy/td_libs_OneWire.html // // The DallasTemperature library can do all this work for you! // http://milesburton.com/Dallas_Temperature_Control_Library OneWire ds(10); // on pin 10 (a 4.7K resistor is necessary) void setup(void) { Serial.begin(9600); } void loop(void) { byte i; byte present = 0; byte type_s; byte data; byte addr; float celsius, fahrenheit; if (!ds.search(addr)) { Serial.println("No more addresses."); Serial.println(); ds.reset_search(); delay(250); return; } Serial.print("ROM ="); for(i = 0; i < 8; i++) { Serial.write(" "); Serial.print(addr[i], HEX); } if (OneWire::crc8(addr, 7) != addr) { Serial.println("CRC is not valid!"); return; } Serial.println(); // the first ROM byte indicates which chip switch (addr) { case 0x10: Serial.println(" Chip = DS18S20"); // or old DS1820 type_s = 1; break; case 0x28: Serial.println(" Chip = DS18B20"); type_s = 0; break; case 0x22: Serial.println(" Chip = DS1822"); type_s = 0; break; default: Serial.println("Device is not a DS18x20 family device."); return; } ds.reset(); ds.select(addr); ds.write(0x44, 1); // start conversion, with parasite power on at the end delay(1000); // maybe 750ms is enough, maybe not // we might do a ds.depower() here, but the reset will take care of it. present = ds.reset(); ds.select(addr); ds.write(0xBE); // Read Scratchpad Serial.print(" Data = "); Serial.print(present, HEX); Serial.print(" "); for (i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); Serial.print(data[i], HEX); Serial.print(" "); } Serial.print(" CRC="); Serial.print(OneWire::crc8(data, 8), HEX); Serial.println(); // Convert the data to actual temperature // because the result is a 16 bit signed integer, it should // be stored to an "int16_t" type, which is always 16 bits // even when compiled on a 32 bit processor. int16_t raw = (data << 8) | data; if (type_s) { raw = raw << 3; // 9 bit resolution default if (data == 0x10) { // "count remain" gives full 12 bit resolution raw = (raw & 0xFFF0) + 12 - data; } } else { byte cfg = (data & 0x60); // at lower res, the low bits are undefined, so let"s zero them if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms //// default is 12 bit resolution, 750 ms conversion time } celsius = (float)raw / 16.0; fahrenheit = celsius * 1.8 + 32.0; Serial.print(" Temperature = "); Serial.print(celsius); Serial.print(" Celsius, "); Serial.print(fahrenheit); Serial.println(" Fahrenheit"); }

Пора переходить к чему-нибудь более полезному в хозяйстве. Ну, например, сделать цифровой термометр, что-ли. Тем более, что с Ардуино - это совсем не так сложно, как было в "доконтроллерную эпоху". В те времена электронный термометр представлял собой сложную конструкцию из десятка микросхем, аналогового датчика, который нужно было еще откалибровать, и трансформаторного блока питания на несколько выходных напряжений. Ну, и - соответствующей подготовки радиолюбителя, который задумает все это собрать. Сейчас с этим - все гораздо проще.

Разрешите представить - цифровой датчик температуры буржуинской фирмы "Dallas semiconductor" DS18B20.

Полностью функциональное устройство для точного (до нескольких знаков после запятой) измерения температуры в диапазоне от -55 до +120 градусов Цельсия. Кроме того - имеется даже немного "мозгов" (ячеек памяти) для запоминания чего-нибудь полезного. Но пока что мы ими пользоваться не будем. Как видно на рисунке - выпускается в нескольких вариациях. Самая распространенная и для нас удобная - та, где написано "ТО-92".

Датчик имеет всего 3 вывода, на два из которых подается напряжение питания 5в, а средний вывод - для передачи данных. Все управление датчиком (подача на него команд, считывание измеренной температуры) идет по единственному проводнику, поэтому вся эта технология и протокол приема-передачи называется "1-Wire" или "One-Wire".

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

Каждый сеанс передачи или приема данных начинается с команды инициализации. Опять же не будем вдаваться в подробности общения Ардуины с термометром, за нас это сделали посторонние люди (мысленно скажем им спасибо). Просто передадим ей одну команду - "инициализация", и она сама разберется, что надо сделать.

Далее, после инициализации, начинаем подавать управляющие команды. Тут надо заметить, что на одном управляющем проводке, теоретически, может находиться несколько устройств семейства "1-Wire". Причем, не только датчики температуры. Поэтому, есть возможность обращаться к каждому из них по уникальному серийному номеру. Но, поскольку у нас на проводе единственный датчик, то ни к чему другому мы не можем обратиться в принципе. Поэтому эти прелюдии пропускаются командой (передаваемым байтом "0хСС"). Забыл сказать - здесь и далее используется шеснадцатиричная запись двоичных чисел (байтов).

После того, как определились с адресатом - передаем команду "измерить температуру" ("0х44"). После этого нужно оставить датчик в покое примерно на 1 секунду, пока он будет делать свои дела.

За это время "ds-ка" измерит температуру и запишет результаты в два байта, которые нам нужно у нее выудить и привести к человеческому виду. Начинаем, как всегда, с инициализации сеанса связи. Потом снова передаем команду "сброс передачи адреса" ("0хСС"). И тут же следом - сообщаем, что готовы принять результат измерения: ("0хВЕ").

После этого Ардуина получает последовательно 2 байта (или двухбайтное число - кому как нравится) с результатами. Посмотрим, что это за результаты и как нам привести их к удобоваримому виду.

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

Но, довольно слов - пора заняться конструированием. Схема подключения DS18B20 к Ардуине не только проста - а элементарно проста:

Выводы питания датчика подключены к соответствующим выводам Ардуины, а вывод данных - к цифровому выходу "10". Кроме того, вывод данных подключен к шине +5 вольт через резистор 3 - 5 килоом (так называемый "подтягивающий" резистор). Заметьте, что цифровой выход "10", хотя он будет работать и на выход, и на вход, нам уже не придется настраивать, как в предыдущем примере со светодиодами. Разработчики библиотеки "1-Wire" заботливо освободили нас от всякой черновой работы. Спасибо им за это!

В-общем, у меня получилось, примерно, так:

Да! Совсем забыл! Библиотека "1-Wire" не входит в базовую поставку Arduino IDE, поэтому ее нужно скачать, например, отсюда . Распакуем архив и положим папку с библиотекой в директорию \libraries, которая находится в папке, где установлена Arduino IDE. При следующем запуске среды разработки - библиотека будет доступна для использования. Вот где ее можно найти:

Однако, не будем использовать скетч из "Образцов", там сильно всего наворочено. Лучше скопируем в Arduino IDE вот такой скетч:

#include

OneWire ds(10); //

void setup(void) {
Serial.begin(9600); //настраиваем последовательный порт для вывода результатов
}

void loop() {
byte data; // объявляем массив из 2-х байт
ds.reset(); // инициализируем датчик
ds.write(0xCC); // пропускаем адресацию к конкретному датчику (у нас он один)
ds.write(0x44); // даем команду измерять температуру
delay(1000); // ждем 1 секунду, пока измеряется температура

ds.reset(); // снова инициализируем датчик
ds.write(0xCC); // снова пропускаем адресацию
ds.write(0xBE); // даем команду готовности считывать температуру
data = ds.read(); //считываем младший
data = ds.read(); // и старший байты
int Temp = (data << 8) + data; // преобразуем считанную информацию
Temp = Temp >> 4; // к нужному виду.
Serial.println(Temp); // выводим результат в последовательный порт.

Что мы тут видим... Сначала к скетчу подключается библиотека "OneWire". Указываем, что наш датчик подключен к выводу "10" Ардуины. Затем настраивается последовательный порт для вывода результатов измерения. Все, подготовительные операции закончены, начинаем измерять. Подготавливаем (резервируем и называем) 2 байта, куда будем записывать результат измерения температуры. Затем - подаем команды, как описывалось выше и, наконец, получаем 2 байта с нашей температурой. Затем происходит преобразование считанной информации и удаление лишних знаков после запятой с тем, чтобы получить целое значение температуры, без десятичных дробей. Эта информация и выводится через последовательный порт. Где мы можем ее увидеть? А вот здесь:

Итак, загружаем этот скетч в Ардуину, открываем "Монитор последовательного порта" и наблюдаем каждую секунду измеренную температуру:

Ура! Заработало! Не будем вдаваться в подробности процесс преобразования полученных от датчика 2-х байт в целое число температуры, это тема для отдельной большой статьи. Скажу только, что полученное число - переменная Temp типа integer. То есть, она может принимать как положительные значения, так и отрицательные. Проверим работу нашего устройства на морозце:

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

В предыдущих уроках мы уже работали с датчиком температуры и влажности DHT11, а также с терморезистором. На этот раз попробуем разобраться ещё с одним популярным датчиком измеряющим температуру — DS18B20. Это устройство позволяет измерять температуру в диапазоне от –55°C до +125°C с точностью ±0.5°C (при температуре от –10°C до +85°C). Питаться DS18B20 может как от 3.3, так и от 5 Вольт. Сам по себе датчик — это микросхема, которая может встречаться в разных корпусах: Также популярными являются готовые модули, на которых размещен датчик, резистор подтяжки и разъем.
Другой вариант — датчик в герметичной стальной капсуле с проводом:

1. Подключение модуля DS18B20-ROC к Ардуино

В этом уроке мы будем работать с модулем датчика температуры, разработанным в RobotClass. Подключать мы его будем к контроллеру Ардуино Уно. Как и DHT11, датчик DS18B20 использует однопроводную шину (1-wire) для обмена данными с контроллером. Так что нам потребуется всего три провода чтобы подключить датчик к Ардуино. Принципиальная схема Внешний вид макета
Примечание. В случае использования не модуля, а отдельной микросхемы, необходимо вывод микросхемы OUT соединить с контактом питания через резистор 4,7 КОм. В указанном выше модуле этот резистор уже установлен.

2. Программа для получения данных с датчика DS18B20

Напишем программу, которая будет каждую секунду считывать показания температуры с датчика и выводить их в COM-порт. #include OneWire ds(2); void setup() { Serial.begin(9600); } void loop() { byte i; byte data; byte addr; float celsius; // поиск адреса датчика if (!ds.search(addr)) { ds.reset_search(); delay(250); return; } ds.reset(); ds.select(addr); ds.write(0x44, 1); // команда на измерение температуры delay(1000); ds.reset(); ds.select(addr); ds.write(0xBE); // команда на начало чтения измеренной температуры // считываем показания температуры из внутренней памяти датчика for (i = 0; i < 9; i++) { data[i] = ds.read(); } int16_t raw = (data << 8) | data; // датчик может быть настроен на разную точность, выясняем её byte cfg = (data & 0x60); if (cfg == 0x00) raw = raw & ~7; // точность 9-разрядов, 93,75 мс else if (cfg == 0x20) raw = raw & ~3; // точность 10-разрядов, 187,5 мс else if (cfg == 0x40) raw = raw & ~1; // точность 11-разрядов, 375 мс // преобразование показаний датчика в градусы Цельсия celsius = (float)raw / 16.0; Serial.print("t="); Serial.println(celsius); } Процедура на первый взгляд может показать совершенно непонятной. На самом деле, все эти 0xBE, 0x44 и т.п. взяты из спецификации к датчику. Для удобства мы можем всю процедуру вычисления выделить в отдельную функцию или даже в отдельный модуль. Загружаем программу на Ардуино и запускаем монитор COM-порта. В окне терминала мы должны увидеть данные о температуре, обновляющиеся раз в секунду: t=23.15 t=23.47 t=23.32 Вот и всё, датчик работает!

Заключение

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

Так исторически сложилось, что на текущий момент одним из самых популярных цифровых температурных датчиков является датчик DS18B20 корпорации Dallas Semiconductor. Конечно же и мы не можем обойти его стороной.

Вся память DS18B20 включает в себя оперативную (SRAM) и энергонезависимую (EEPROM) память. В EEPROM хранятся регистры TH, TL и регистр конфигурации. Если функция тревожного сигнала не используется, то регистры TH и TL могут использоваться как регистры общего назначения. В режиме термостата TH содержит значение верхнего порога температуры, TL соответственно нижнего порога.

Кодинг.

Первым делом нам потребуется библиотека OneWire которая нам очень упростит жизнь. Скачать можно с GitHub или с нашего сайта .

Любое общение с датчиком начинается с команды Reset . То есть МК прижимает шину данных в состояние логический «0» на 480 µs, потом отпускает ее. Датчик отвечает на это сигналом присутствия, после чего мы отправляем команду Skip ROM (0xCC) . Тое сть обратимся ко всем датчика которые присутствуют на шине.

OneWire(uint8_t pin);

Конструктор, Pin – номер вывода, к которому подключен датчик.

uint8_t reset(void);

Инициализация операции на шине. С этой команды должна начинаться любая операция обмена данными. Возвращает:

  • 1 – если устройство подключено к шине (был ответный импульс присутствия);
  • 0 – если устройство отсутствует на шине (ответного импульса не было).
void write(uint8_t v, uint8_t power = 0);

Запись байта. Передает байт в устройство на шине.

Отправим команду 0x44 инициализации измерения температуры.

Пауза 1 сек . Ожидание на время, необходимое для выполнения датчиком преобразования температуры. Это время зависит от выбранной разрешающей способности датчика. Разрешение 12 бит установлено в датчике по умолчанию. Время преобразования для него – 750 мс.

Затем мы отправляем команду Reset , Skip ROM (0xCC) , а замет команду 0xBE чтения памяти датчика.

Вот и сам код из библиотеке:

#include // OneWire DS18S20, DS18B20, DS1822 Temperature Example // // http://www.pjrc.com/teensy/td_libs_OneWire.html // // The DallasTemperature library can do all this work for you! // http://milesburton.com/Dallas_Temperature_Control_Library OneWire ds(10); // датчик на выводе 10 (а резистор 4.7 K является необходимым) void setup(void) { Serial.begin(9600); } void loop(void) { byte i; byte present = 0; //переменные byte type_s; byte data; byte addr; float celsius, fahrenheit; if (!ds.search(addr)) { Serial.println("No more addresses."); Serial.println(); ds.reset_search(); delay(250); return; } Serial.print("ROM ="); for(i = 0; i < 8; i++) { Serial.write(" "); Serial.print(addr[i], HEX); } if (OneWire::crc8(addr, 7) != addr) { Serial.println("CRC недопустимый!"); return; } Serial.println(); // первый байт ROM указывает, какой чип (8 бит код чипа, 48 бит серийный номер, 8 бит CRC) switch (addr) { case 0x10: Serial.println(" Chip = DS18S20"); // or old DS1820 type_s = 1; break; case 0x28: Serial.println(" Chip = DS18B20"); type_s = 0; break; case 0x22: Serial.println(" Chip = DS1822"); type_s = 0; break; default: Serial.println("Не является устройством семейства DS18x20."); return; } ds.reset(); ds.select(addr); ds.write(0x44, 0); // старт преобразования с питание от внешнего источника. delay(1000); // ждем конца преобразования. // we might do a ds.depower() here, but the reset will take care of it. present = ds.reset(); ds.select(addr); ds.write(0xBE); // Читаем память. Serial.print(" Data = "); Serial.print(present, HEX); Serial.print(" "); for (i = 0; i < 9; i++) { // нам нужно 9 байт data[i] = ds.read(); Serial.print(data[i], HEX); Serial.print(" "); } Serial.print(" CRC="); Serial.print(OneWire::crc8(data, 8), HEX); Serial.println(); // Преобразование данных в фактическую температуру //поскольку результатом является 16-разрядное целое число со знаком // ранится в типе "int16_t", который всегда составляет 16 бит // даже при компиляции на 32-битном процессоре. int16_t raw = (data << 8) | data; if (type_s) { raw = raw << 3; // 9 бит разрешение по умолчанию у датчиков DS18S20 or old DS1820 if (data == 0x10) { // "количество остается" дает полное разрешение 12 бит raw = (raw & 0xFFF0) + 12 - data; } } else { byte cfg = (data & 0x60); // при более низком разрешении низкие биты не определены, поэтому давайте обнуляем их. if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms //// default is 12 bit resolution, 750 ms conversion time } celsius = (float)raw / 16.0; fahrenheit = celsius * 1.8 + 32.0; Serial.print(" Temperature = "); Serial.print(celsius); Serial.print(" Celsius, "); Serial.print(fahrenheit); Serial.println(" Fahrenheit"); }

Собственно это библиотека подходить для всех датчиков семейства DS18 (DS18B20, DS18S20, DS1820, DS1822) подключение не чем не отключаются. Ну а некоторые различия можно уже узнать из datesheet к ним.

DS18B20 подключение к Arduino — это фантастический датчик определения температурной составляющей с цифровым интерфейсом в своем составе — следовательно он не требует выполнения калибровки. Поэтому, такие устройства можно подключить одновременно в множественном количестве к одному контакту arduino. Такую возможность предоставляет оригинальный адрес, который был запрограммирован в схему DS18B20 при его изготовлении.

Вот так выглядит эта «супер-сложная» схема DS18B20 подключение к Arduino:

Здесь нужен всего один резистор и больше ничего))). К тому же здесь отсутствуют необходимость в калибровании температуры, а также исключаются возможные неточности при выполнении сборки. Питающее напряжение возможно подавать в диапазоне от 3v до 5v. Все элементарно. А отображение температурного значения - три строки)). Ниже показан образец, все досконально и четко расписано.

Вот отсюда нужно скачать библиотеку:

Тут все аналогично, код в образце Multiple.pde. Разница лишь в том, что применено некоторое количество переменных величин имеющих адреса термометров — следовательно на три датчика три переменные величины со своим адресом и аналогичный код для поиска:

If (!sensors.getAddress(Thermometer1, 0)) Serial.println("Не найден адрес датчика 0"); if (!sensors.getAddress(Thermometer2, 1)) Serial.println("Не найден адрес датчика 1"); if (!sensors.getAddress(Thermometer3, 2)) Serial.println("Не найден адрес датчика 2");

Естественно и вывода температурных составляющих также по три.