DS18B20: цифровой термометр на шине 1-Wire и работа с Arduino

Как устроен датчик DS18B20, чем прямое питание отличается от паразитного и какие функции библиотек OneWire и DallasTemperature нужны для чтения температуры.
Что представляет собой DS18B20
DS18B20 — законченный цифровой термометр в одной микросхеме. Он измеряет температуру от -55 до +125 °C, а разрядность результата настраивается в пределах 9–12 бит. С микроконтроллером или платой Arduino датчик общается по шине 1-Wire, причём каждому экземпляру ещё на заводе присваивается уникальный 64-битный адрес, который не повторяется. Благодаря этому на одну линию данных можно повесить целую группу термометров и опрашивать их по отдельности.
Микросхема выпускается в трёх корпусах: TO-92, SO и uSOP. Для жидких и агрессивных сред существуют исполнения в герметичной гильзе из нержавеющей стали; условие одно — температура среды должна оставаться в пределах диапазона измерения.

| Напряжение питания | 3–5,5 В |
| Интерфейс | 1-Wire |
| Подключение | прямое или с паразитным питанием по линии данных |
| Разрешение | 9–12 бит |
| Диапазон температур | от -55 до +125 °C |
| Время измерения при 12 бит | 750 мс |
| Адресация | уникальный 64-битный адрес |
| Сигнал тревоги | программируемые верхний и нижний пороги |
Внутреннее устройство
Внутри маленького корпуса размещено несколько функциональных блоков. Узел POWER SUPPLY SENSE отвечает за работу от внешнего источника, а PARASIT POWER CIRCUIT с буферным конденсатором Cpp позволяет датчику питаться прямо от линии данных. Блок 64-BIT ROM AND 1-WIRE PORT хранит заводской адрес в энергонезависимой памяти и обслуживает интерфейс. MEMORY CONTROL LOGIC связывает команды шины с внутренней памятью SCRATCHPAD.

Через эту память доступны несколько регистров:
- TEMPERATURE SENSOR — результат преобразования температуры;
- ALARM HIGH TRIGGER и ALARM LOW TRIGGER — верхний и нижний пороги тревоги;
- CONFIGURATION REGISTER — выбор разрешения: 9, 10, 11 или 12 бит, что даёт шаг 0,5; 0,25; 0,125 и 0,0625 °C;
- 8-BIT CRC GENERATOR — формирование контрольной суммы для защиты данных.
Схемы подключения к Arduino
При прямом питании вывод Vdd соединяют с 5 В платы, GND — с общим проводом, а средний вывод данных DQ — с любым свободным входом, например D2 на Arduino Nano; номер вывода затем указывается в скетче. Обязательный элемент схемы — резистор 4,7 кОм между плюсом питания и линией данных. Он подтягивает линию к логической единице, и без него обмен по 1-Wire работать не будет. Номинал не критичен: допустимо отклонение примерно на 2 кОм в любую сторону.

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

В режиме паразитного питания отдельный провод 5 В не нужен: выводы Vdd и GND каждого датчика соединяют между собой, а энергию микросхема получает с линии данных через тот же резистор 4,7 кОм. Такой вариант экономит одну жилу в шлейфе. При качественном экранированном кабеле длина линии может достигать 300 м, для больших расстояний применяют повторители 1-Wire.
Функции библиотеки OneWire
Работать с датчиком можно через готовые библиотеки, напрямую командами или с собственной низкоуровневой реализацией тайм-слотов; последний путь самый трудоёмкий. Чаще всего применяют OneWire.h и надстройку над ней DallasTemperature.h, которая без первой не работает.
Объект шины создаётся конструктором с номером вывода, например OneWire ds(2). Далее используются следующие функции:
- search(addr) — ищет очередное устройство и записывает его адрес в массив из 8 байт; возвращает false, когда устройств нет или все уже перебраны;
- reset_search() — возвращает перебор к началу, вызывается после того, как search вернула false;
- reset() — сброс шины перед каждым сеансом обмена; true означает, что хотя бы один датчик ответил импульсом присутствия;
- select(addr) — выбор датчика по адресу, вызывается после reset; следующий сброс разрывает связь с ним;
- skip() — пропуск выбора, пригоден только при единственном датчике на шине;
- write(byte, powerType) — отправка байта; второй аргумент равен 1 при паразитном питании и 0 (по умолчанию) при внешнем;
- read() — чтение одного байта от датчика;
- crc8(addr, len) — расчёт контрольной суммы для проверки принятых данных.
Как выглядит цикл измерения
Типовой скетч для группы датчиков на выводе D2 действует так. Сначала search находит очередной адрес, он выводится в монитор порта и проверяется по CRC. По нулевому байту адреса определяется тип микросхемы: 0x28 соответствует DS18B20, 0x10 — DS18S20, 0x22 — DS1822. Затем следуют reset, select и команда запуска преобразования 0x44 (для паразитного питания — ds.write(0x44, 1)), после чего выдерживается пауза в одну секунду с запасом к штатным 750 мс.
После повторных reset и select командой 0xBE открывается чтение памяти Scratchpad, из которой забирают 9 байт. Температура лежит в байтах 0 и 1: их объединяют в 16-битное число и делят на 16, получая градусы Цельсия. При пониженном разрешении младшие неопределённые биты обнуляют; преобразование занимает 93,75 мс при 9 битах, 187,5 мс при 10 и 375 мс при 11.
С библиотекой DallasTemperature код заметно короче: создаётся объект sensors со ссылкой на шину, в setup вызывается sensors.begin(), а в цикле — sensors.requestTemperatures() и sensors.getTempCByIndex(0). В комплекте с библиотекой идут 14 документированных примеров.
Типичные вопросы и применение
Если датчик постоянно или время от времени показывает 85 °C, это значение по умолчанию: его возвращают при сбое питания, плохом кабеле, слишком большом удалении от контроллера или неисправности самой микросхемы. Датчики можно разносить и по разным выводам Arduino, создавая для каждой шины свой экземпляр класса.
Точность и надёжность DS18B20 делают его подходящим для инкубаторов, климат-контроллеров теплиц, аквариумов и бытовых помещений.