#include <OneWire.h>
// Пример работы с температурным датчиком DS18S20, DS18B20, DS1822 по протоколу OneWire
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// Для выполнения всех этих операций можно использовать библиотеку DallasTemperature!
// http://milesburton.com/Dallas_Temperature_Control_Library
OneWire ds(3); // подключено к пину 3 (необходим резистор 4.7K)
void setup(void) {
Serial.begin(9600); // Инициализация последовательной связи
}
void loop(void) {
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;
if ( !ds.search(addr)) { // Поиск адреса датчика
Serial.println("Больше адресов не найдено."); // Вывод сообщения, если адрес не найден
Serial.println();
ds.reset_search();
delay(250);
return;
}
Serial.print("Адрес устройства =");
for( i = 0; i < 8; i++) { // Вывод адреса найденного датчика
Serial.write(' ');
Serial.print(addr[i], HEX);
}
if (OneWire::crc8(addr, 7) != addr[7]) { // Проверка CRC адреса
Serial.println("CRC недействительный!"); // Вывод сообщения об ошибке CRC
return;
}
Serial.println();
// Первый байт ROM указывает на тип микросхемы
switch (addr[0]) { // Определение типа датчика по первому байту адреса
case 0x10:
Serial.println(" Микросхема = DS18S20"); // или старая DS1820
type_s = 1;
break;
case 0x28:
Serial.println(" Микросхема = DS18B20");
type_s = 0;
break;
case 0x22:
Serial.println(" Микросхема = DS1822");
type_s = 0;
break;
default:
Serial.println("Устройство не является устройством семейства DS18x20."); // Вывод сообщения об ошибке, если датчик не определён
return;
}
ds.reset();
ds.select(addr);
ds.write(0x44, 1); // начать конвертацию, с паразитным питанием в конце
delay(1000); // возможно, 750 мс достаточно, а может быть и нет
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Чтение Scratchpad
Serial.print(" Данные = ");
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); // Проверка CRC данных
Serial.println();
// Преобразование данных в реальную температуру
// потому что результат - это 16-битное знаковое целое число, его нужно
// хранить в типе "int16_t", который всегда 16 бит
// даже при компиляции на 32-битном процессоре.
int16_t raw = (data[1] << 8) | data[0]; // Преобразование данных в температуру
if (type_s) {
raw = raw << 3; // разрешение 9 бит по умолчанию
if (data[7] == 0x10) {
// "count remain" дает полное разрешение 12 бит
raw = (raw & 0xFFF0) + 12 - data[6];
}
} else {
byte cfg = (data[4] & 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 мс
//// по умолчанию разрешение 12 бит, время конвертации 750 мс
}
celsius = (float)raw / 16.0; // Преобразование кельвинов в градусы Цельсия
fahrenheit = celsius * 1.8 + 32.0; // Преобразование градусов Цельсия в градусы Фаренгейта
Serial.print(" Температура = ");
Serial.print(celsius);
Serial.print(" Цельсия, ");
Serial.print(fahrenheit);
Serial.println(" Фаренгейта");
}