Цифровой датчик температуры DS18B20
Цифровой датчик температуры DS18B20, работает по протоколу 1-Wire. Используется при разработке домашней метеостанции на Arduino.
Описание датчика DS18B20
DS18B20 — цифровой термометр с программируемым разрешением от 9 до 12 битов, которое может сохраняться в памяти EEPROM прибора. DS18B20 обменивается данными по шине 1-Wire и при этом может быть как единственным устройством на линии, так и работать в группе. Все процессы на шине управляются центральным микропроцессором.
Диапазон измерений датчика: от –55 до +125 °C и точностью 0,5 °C в диапазоне от –10 до +85 °C. В дополнение DS18B20 может питаться напряжением линии данных при отсутствии внешнего источника напряжения.
Каждый датчик типа DS18B20 имеет уникальный 64-битный последовательный код, который позволяет общаться с множеством датчиков DS18B20, установленных на одной шине. Первые 8 битов — код серии (для DS18B20 — 28h), затем 48 битов уникального номера, и в конце 8 битов CRC-кода. Такой принцип позволяет использовать один микропроцессор, чтобы контролировать множество датчиков DS18B20, распределенных по большому участку.
Характеристики датчика DS18S20:
- интерфейс 1-Wire;
- измеряемая температура от –55 до +125 °C;
- точность 0,5 °C в диапазоне от –10 до +85 °С;
- температура считывается 9-ю битами данных;
- время на конвертацию температуры — 750 ms (максимальное).
![]() |
|
Датчик DS18B20 |
Данные о температуре хранятся в оперативной памяти датчика. Память состоит из оперативной ROM и энергонезависимой EEPROM:
первые два байта — содержат данные об измеренной температуре;
третий и четвертый байты хранят верхний (TH) и нижний (TL) пределы температуры;
пятый и шестой — не используются;
седьмой и восьмой — байты-счетчики. Они могут использоваться для более точного измерения температуры;
девятый байт хранит CRC-код предыдущих восьми.
![]() |
Карта памяти DS18B20 |
Кроме общих команд для всех типов устройств 1-Wire, представленных в таблице, датчик может выполнять следующие команды:
Alarm Search [ECh] — операция этой команды идентична операции поиска адресов [F0h], за исключением того, что в данном случае ответят только те датчики, у которых при последнем измерении температура вышла за установленные пре- делы (выше TH или ниже TL);
Convert T [44h] — конвертировать температуру. Датчик произведет измерение и запись данных о текущей температуре. Если ведущее устройство будет за этой командой слать тайм-слоты чтения, то пока конвертация не закончена, DS18S20 будет выдавать в линию "0", а после завершения конвертации "1".
Write Scratchpad [4Eh] — запись в память. Эта команда позволяет записать 3 байта в память датчика. Первый байт запишется в TH, второй — в TL, а третий байт запишется в пятый байт памяти — это байт конфигурации;
Read Scratchpad [BEh] — чтение памяти. Команда позволяет нам считать память датчика. В ответ на эту команду датчик вернет 9 байтов своей памяти, начиная с 0-го байта TEMPERATURE LSB и заканчивая восьмым — CRC;
Copy Scratchpad [48h] — копировать память. Датчик скопирует содержимое ОЗУ — TH и TL в EEPROM.
Последовательность команд для получения данных от датчика о температуре:
Произвести RESET и поиск устройств на линии 1-Wire.
Выдать команду 0x44, чтобы запустить конвертацию температуры датчиком.
Подождать не менее 750 ms.
![]() |
Подключение датчика DS18B20 к Arduino |
Выдать команду 0xBE, чтобы считать ОЗУ датчика (данные о температуре будут в первых двух байтах).
Датчик может запитываться двумя способами: внешним питанием (3 провода) или паразитным (питание от шины, 2 провода).
Использование библиотеки OneWire
Для работы с датчиками с интерфейсом 1-Wire можно использовать библиотеку OneWire.
Cкетч получения данных с датчика температуры DS18B20 и вывода данных в последовательный порт с помощью библиотеки OneWire представлен в примере
Скачать библиотеку OneWire.h: OneWire.h.zip
Sketch code
#include <OneWire.h>
OneWire ds(10); // линия 1-Wire будет на pin 10
void setup(void)
{
Serial.begin(9600);
}
void loop(void)
{
byte i;
byte present = 0; byte data[12]; byte addr[8];
if ( !ds.search(addr)) { Serial.print("No more addresses.\n"); ds.reset_search();
return;
}
if ( OneWire::crc8( addr, 7) != addr[7]) { Serial.print("CRC is not valid!\n"); return;
}
if ( addr[0] != 0x28) {
Serial.print("Device is not a DS18B20 family device.\n"); return;
}
ds.reset(); ds.select(addr);
ds.write(0x44,1); // запускаем конвертацию delay(750); // ждем 750ms
present = ds.reset(); ds.select(addr);
ds.write(0xBE); // считываем ОЗУ датчика
for ( i = 0; i < 9; i++) { // обрабатываем 9 байт data[i] = ds.read();
Serial.print(data[i], HEX); Serial.print(" ");
}
// высчитываем температуру :)
int HighByte, LowByte, TReading, Tc_100; LowByte = data[0];
Serial.print("LB= ");Serial.print(LowByte,HEX); HighByte = data[1];
Serial.print(" HB= ");Serial.print(HighByte,HEX); TReading = (HighByte << 8) + LowByte;
Tc_100 = TReading/2;
Serial.print(" T = ");Serial.print(Tc_100); Serial.println();
}
Библиотека DallasTemperature
Специально для температурных датчиков Dallas (DS18S20, DS18B20, DS1822) создана Arduino-библиотека DallasTemperature, скачать которую можно со страницы https://github.com/milesburton/Arduino-Temperature-Control-Library.
Cкетч получения данных с датчика температуры DS18B20 и вывода данных в последовательный порт с помощью библиотеки DallasTemperature представлен на примере
![]() |
Схема подключения датчика DS18B20 к Arduino |
Скачать библиотеку DallasTemperature.h: DallasTemperature.h.zip
Пример программы
#include <DallasTemperature.h>
DallasTemperature tempSensor;
void setup(void){
Serial.begin(9600);
tempSensor.begin(10); // Датчик на 10 порт
}
void loop(void){
switch(tempSensor.isValid())
{
case 1:
Serial.println("Invalid CRC");
tempSensor.reset(); // сбросить девайс
return;
case 2:
Serial.println("Invalid device");
tempSensor.reset(); // сбросить девайс return;
}
Serial.print(" T = ");
Serial.print(tempSensor.getTemperature()); // отправить температуру
Serial.println(); // перенос строки
}
S2
#include <OneWire.h> #include <DallasTemperature.h> // Data wire is plugged into pin 2 on the Arduino #define ONE_WIRE_BUS 2 // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs) OneWire oneWire(ONE_WIRE_BUS); // Pass our oneWire reference to Dallas Temperature. DallasTemperature sensors(&oneWire); void setup(void) { // start serial port Serial.begin(9600); Serial.println("Dallas Temperature IC Control Library Demo"); // Start up the library sensors.begin(); // IC Default 9 bit. If you have troubles consider upping it 12. Ups the delay giving the IC more time to process the temperature measurement } void loop(void) { // call sensors.requestTemperatures() to issue a global temperature // request to all devices on the bus Serial.print("Requesting temperatures..."); sensors.requestTemperatures(); // Send the command to get temperatures Serial.println("DONE"); Serial.print("Temperature for Device 1 is: "); Serial.print(sensors.getTempCByIndex(0)); // Why "byIndex"? You can have more than one IC on the same bus. 0 refers to the first IC on the wire }
S3
// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 10
#define TEMPERATURE_PRECISION 9
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// arrays to hold device addresses
DeviceAddress insideThermometer, outsideThermometer;
void setup(void)
{
// start serial port
Serial.begin(9600);
Serial.println("Dallas Temperature IC Control Library Demo");
// Start up the library
sensors.begin();
// locate devices on the bus
Serial.print("Locating devices...");
Serial.print("Found ");
Serial.print(sensors.getDeviceCount(), DEC);
Serial.println(" devices.");
// report parasite power requirements
Serial.print("Parasite power is: ");
if (sensors.isParasitePowerMode()) Serial.println("ON");
else Serial.println("OFF");
// Assign address manually. The addresses below will beed to be changed
// to valid device addresses on your bus. Device address can be retrieved
// by using either oneWire.search(deviceAddress) or individually via
// sensors.getAddress(deviceAddress, index)
//insideThermometer = { 0x28, 0x1D, 0x39, 0x31, 0x2, 0x0, 0x0, 0xF0 };
//outsideThermometer = { 0x28, 0x3F, 0x1C, 0x31, 0x2, 0x0, 0x0, 0x2 };
// Search for devices on the bus and assign based on an index. Ideally,
// you would do this to initially discover addresses on the bus and then
// use those addresses and manually assign them (see above) once you know
// the devices on your bus (and assuming they don't change).
//
// method 1: by index
if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0");
if (!sensors.getAddress(outsideThermometer, 1)) Serial.println("Unable to find address for Device 1");
// method 2: search()
// search() looks for the next device. Returns 1 if a new address has been
// returned. A zero might mean that the bus is shorted, there are no devices,
// or you have already retrieved all of them. It might be a good idea to
// check the CRC to make sure you didn't get garbage. The order is
// deterministic. You will always get the same devices in the same order
//
// Must be called before search()
//oneWire.reset_search();
// assigns the first address found to insideThermometer
//if (!oneWire.search(insideThermometer)) Serial.println("Unable to find address for insideThermometer");
// assigns the seconds address found to outsideThermometer
//if (!oneWire.search(outsideThermometer)) Serial.println("Unable to find address for outsideThermometer");
// show the addresses we found on the bus
Serial.print("Device 0 Address: ");
printAddress(insideThermometer);
Serial.println();
Serial.print("Device 1 Address: ");
printAddress(outsideThermometer);
Serial.println();
// set the resolution to 9 bit per device
sensors.setResolution(insideThermometer, TEMPERATURE_PRECISION);
sensors.setResolution(outsideThermometer, TEMPERATURE_PRECISION);
Serial.print("Device 0 Resolution: ");
Serial.print(sensors.getResolution(insideThermometer), DEC);
Serial.println();
Serial.print("Device 1 Resolution: ");
Serial.print(sensors.getResolution(outsideThermometer), DEC);
Serial.println();
}
// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
for (uint8_t i = 0; i < 8; i++)
{
// zero pad the address if necessary
if (deviceAddress[i] < 16) Serial.print("0");
Serial.print(deviceAddress[i], HEX);
}
}
// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{
float tempC = sensors.getTempC(deviceAddress);
Serial.print("Temp C: ");
Serial.print(tempC);
Serial.print(" Temp F: ");
Serial.print(DallasTemperature::toFahrenheit(tempC));
}
// function to print a device's resolution
void printResolution(DeviceAddress deviceAddress)
{
Serial.print("Resolution: ");
Serial.print(sensors.getResolution(deviceAddress));
Serial.println();
}
// main function to print information about a device
void printData(DeviceAddress deviceAddress)
{
Serial.print("Device Address: ");
printAddress(deviceAddress);
Serial.print(" ");
printTemperature(deviceAddress);
Serial.println();
}
/*
* Main function, calls the temperatures in a loop.
*/
void loop(void)
{
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
Serial.print("Requesting temperatures...");
sensors.requestTemperatures();
Serial.println("DONE");
// print the device information
printData(insideThermometer);
printData(outsideThermometer);
}