Підключення ds18b20 до ардуїно. Датчик температури DS18B20, Arduino та бібліотека OneWire

У попередніх уроках ми вже працювали з датчиком температури та вологості 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); ds.reset(); .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 – це цифровий датчик температури. Датчик дуже простий у використанні.

По-перше, він цифровий, а по-друге - у нього лише один контакт, з якого ми отримуємо корисний сигнал. Тобто ви можете підключити до одного Arduino одночасно величезну кількість цих сенсорів. Пінов буде більш ніж достатньо. Мало того, ви навіть можете підключити кілька сенсорів до одного пін на Arduino! Але про все по порядку.

DS18B20 має різні форм-фактори. Отже, вибір, який саме використовувати, залишається за вами. Доступно три варіанти: 8-Pin SO (150 mils), 8-Pin µSOP, та 3-Pin TO-92. Серфінг eBay або Aliexpress показує, що китайці пропонують версію TO-92 у вологозахищеному корпусі. Тобто ви можете сміливо занурювати подібне диво у воду, використовувати під дощем і т.д. і т.п. Ці сенсори виготовляються з трьома вихідними контактами (чорний – GND, червоний – Vdd та білий – Data).

Різні форм-фактори датчиків DS18B20 наведені нижче.

Модель DS18B20 у вологозахищеному корпусі:


DS18B20 зручний у використанні. Запитати його можна через контакт data (у такому разі ви використовуєте всього два контакти з трьох для підключення!). Сенсор працює в діапазоні напруг від 3.0 до 5.5 і вимірює температуру в діапазоні від -55°C до +125°C (від -67°F до +257°F) з точністю ±0.5°C (від -10°C до +85°C).

Ще одна крута фіча: ви можете підключити паралельно до 127 датчиків! та зчитувати показання температури з кожного окремо. Не зовсім зрозуміло, в якому проекті подібне може знадобитися, але підключити два сенсори та контролювати температуру в холодильнику та морозильній камері можна. При цьому ви залишите вільними купу пінів на Arduino... Загалом фіча приємна.

Що вам знадобиться для контролю температури за допомогою Arduino та DS18B20

Програмне забезпечення

  • Звичайно, вам потрібна Arduino IDE;
  • Бібліотека OneWire library, яка значно полегшує роботу з Arduino та датчиком DS18B20;
  • Скетч...

Завантажуємо скетч на Arduino

Скетч, який представлений нижче, є у бібліотеці OneWire, у категорії examples. Перейдіть до "File" - "Examples" - "OneWire" і виберіть приклад "DS18x20_Temperature". Код програми наведено нижче.

Даний приклад використовує бібліотеку OneWire Library, щоб зібрати дані з усіх підключених датчиків температури DS28B20 (як підключити кілька сенсорів описано в кінці статті) та відобразити їх у вікні серійного монітора Arduino IDE.

У вікні серійного монітора ви побачите приблизно таке:

ROM = 28 88 84 82 5 0 0 6A

No more addresses.

ROM = 28 88 84 82 5 0 0 6A

Data = 1 56 1 4B 46 7F FF A 10 D1 CRC=D1

Температура = 21.37 Celsius, 70.47 Fahrenheit

No more addresses.

ROM = 28 88 84 82 5 0 0 6A

Data = 1 56 1 4B 46 7F FF A 10 D1 CRC=D1

Температура = 21.37 Celsius, 70.47 Fahrenheit

No more addresses.

Переконайтеся, що ви вказали правильні піни!

У рядку 10, де вказано "OneWire ds(2);" встановлюється пін, якого підключений контакт data з сенсора.

У цьому прикладі використаний пін 2, але значення стандартного піна в прикладі OneWire стоїть на 10. Можна використовувати і його.

#include <OneWire.h>

// Приклад використання бібліотеки OneWire DS18S20, DS18B20, DS1822

OneWire ds(2); // на піні 10 (потрібний резистор 4.7 кому)

void setup(void) (

Serial.begin(9600);

void loop (void) (

byte present = 0;

float celsius, fahrenheit;

if (!ds.search(addr)) (

Serial.println("No more addresses.");

Serial.println();

ds.reset_search();

Serial.print("ROM =");

Serial.write(" ");

Serial.print(addr[i], HEX);

if (OneWire::crc8(addr, 7) != addr) (

Serial.println("CRC is not valid!");

Serial.println();

// Перший байт визначає чіп

Serial.println(" Chip = DS18S20"); // або старіший DS1820

Serial.println(" Chip = DS18B20");

Serial.println(" Chip = DS1822");

Serial.println("Device is not a DS18x20 family device.");

ds.select(addr);

delay(1000); // 750 може бути достатньо, а може і не вистачить

// ми могли б використовувати тут ds.depower(), але reset подбає про це

present = ds.reset();

ds.select(addr);

Serial.print("Data=");

Serial.print(present, HEX);

Serial.print(" ");

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

if (data == 0x10) (

raw = (raw & 0xFFF0) + 12 - 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 мс

//// Роздільна здатність за замовчуванням дорівнює 12 біт, час перетворення - 750 мс

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");

Як підключити декілька сенсорів DS18B20 до Arduino?

Можна підключити кілька цифрових датчиків температури DS18B20 паралельно. При цьому бібліотека OneWire library дозволить вам зчитувати дані з усіх датчиків одночасно.

Нижче описано два методи підключення сенсорів.

Для великої кількості сенсорів (більше 10), треба використовувати резистори з меншим опором (наприклад, 1.6 кім або навіть менше).

Крім того, якщо ви підключаєте паралельно більше 10 датчиків, можуть виникнути проблеми (похибки під час знімання показань). Тому рекомендується встановлювати додатковий резистор опором 100...120 Ом між контактом data на Arduino та data на кожному сенсорі!

Результат роботи попереднього скетчу з двома підключеними сенсорами може виглядати приблизно так:

ROM = 28 88 84 82 5 0 0 6A

Data = 1 51 1 4B 46 7F FF F 10 FE CRC = FE

Температура = 21.06 Celsius, 69.91 Fahrenheit

ROM = 28 DA CA 27 5 0 0 49

Data = 1 4E 1 4B 46 7F FF 2 10 D9 CRC=D9

Температура = 20.87 Celsius, 69.57 Fahrenheit

No more addresses.

Вибираємо правильний сенсор

Було б непогано знати, з якого сенсора ви отримуєте дані, коли ви використовуєте паралельно кілька датчиків. Як це зробити?

Серійний номер

Так як цифрові датчики, у кожного з них є індивідуальний серійний номер, який можна використовувати для розпізнавання того чи іншого сенсора. Начебто все просто. Але... адже нам треба попередньо визначити ці серійні номери, перш ніж використовувати їх для впізнавання сенсора, правильно?

Ви могли звернути на прикладах вище, що скетч видає нам дані у вигляді 64-бітового серійного номера – значення “ROM”. Наприклад:

28 88 84 82 5 0 0 6A або 28 DA CA 27 5 0 0 49 у прикладі вище.

Не забувайте, якщо ви використовуєте одночасно велику кількість датчиків (10 і більше), треба додати резистори 100...120 Ом між контактами data із сенсора DS18B20 та піном data на Arduino (для кожного датчика!).

Нижче показано схему паралельного підключення кількох сенсорів з використанням трьох контактів.


Залишайте Ваші коментарі, питання та поділіться особистим досвідом нижче. У дискусії часто народжуються нові ідеї та проекти!

В асортименті нашого магазину з'явився датчик температури DALLAS 18B20 у вологозахищеному корпусі з широким діапазоном температур від -55 до +125°С. Дані про вологозахищеність і максимальну температуру +125 градусів відразу наштовхнули на думки про екстремальне тестування в киплячій воді. Цим ми й займемося.

Компоненти для повторення (купити у Китаї):

Даний датчик працює по шині 1-Wire.

Кожен такий пристрій містить унікальний 64-бітний "ROM" код, що складається з 8 бітів, що визначають код серії, 48 біт унікального номера та 8 біт завадостійкого CRC коду.

Інформація про виміряну температуру зберігається в оперативній пам'яті датчика, що складається з 9 байт.

1 і 2 байти зберігають інформацію про температуру.

3 і 4 байти зберігають відповідно верхній та нижній межі температури.

5 і 6 байти зарезервовані.

7 і 8 байти використовуються для надточного вимірювання температури.

9 байт зберігає завадостійкий CRC код попередніх 8 байт.

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

search(addressArray)

Виконує пошук наступного 1-Wire пристрою, якщо пристрій знайдено, то в 8-байтний масив addressArray записується його ROM код, інакше повертає false.

reset_search()

Виконує новий пошук із першого пристрою.

reset()

Виконує скидання шини, необхідно перед зв'язком із датчиком.

select(addressArray)

Виконує вибір пристрою після скидання, передається ROM Код пристрою.

write(byte)

Передає інформаційний байт на пристрій

write(byte, 1)

read()

Зчитує інформаційний байт із пристрою

crc8(dataArray, length)

Обчислює CRC код байтів з масиву dataArray, довжиною length

За допомогою команди write ми можемо передавати керуючі команди на датчик у вигляді байтів, розглянемо основні з них:

0x44- провести вимірювання температури та записати дані в оперативну пам'ять

0x4E- записати 3 байти в 3-й, 4-й і 5-й байти оперативної пам'яті

0x48- скопіювати 3-й і 4-й байти оперативної пам'яті в EEPROM

0xB8- скопіювати дані з EEPROM У 3-й і 4-й байти оперативної пам'яті

Підключення до Arduino

З датчика виходять три дроти:

Червоний:"+" харчування.

Чорний:"-" харчування

Білий:Виведення вихідного сигналу

Підключення датчика:

Червоний:на + 5 Вольт Arduino.

Чорнийна будь-який з GND пінів--- Arduino.

Білийбудь-який цифровий вхід Arduino (у прикладі D10).

Для роботи датчика необхідно з'єднати сигнальний провід із проводом живлення резистором номіналом 4.7 кОм.

Для початку розглянемо найкорисніший приклад для роботи з датчиком – виведення показань температури у монітор порту.

Приклад програмного коду

#include OneWire ds(10); // підключений до 10 піну (резистор на 4.7к обов'язковий) void setup(void) ( Serial.begin(9600); ) void loop(void) ( byte i; byte present = 0; byte type_s; byte data; float celsius, fahrenheit; if (!ds.search(addr)) ( Serial.println("No more addresses."); Serial.println(); ds.reset_search(); delay(250); return; ) Serial. print("ROM =");< 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); // начало коммуникации delay(1000); 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(); // Преобразуем получненный данные в температуру // Используем int16_t тип, т.к. он равен 16 битам // даже при компиляции под 32-х битный процессор int16_t raw = (data << 8) | data; if (type_s) { raw = raw << 3; if (data == 0x10) { raw = (raw & 0xFFF0) + 12 - data; } } else { byte cfg = (data & 0x60); if (cfg == 0x00) raw = raw & ~7; else if (cfg == 0x20) raw = raw & ~3; else if (cfg == 0x40) raw = raw & ~1; } 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"); }

Dallas18B20 екстремальне тестування

Як уже говорилося, ми вирішили влаштувати датчику екстремальне тестування, але просто опускати датчик у окріп це не цікаво. Помістимо датчик у склянку і прокип'ятимо. Для наочності монітор порту будуть виводитися значення температури. На прикріпленому нижче відео видно плавне наростання температури. Хочеться відзначитищо температура води при нормальному атмосферному тиску не може бути вищою за 100 °С. При тестуванні датчика в окропі, максимально зафіксована нами температура склала 99.87°С. Тест можна вважати успішним.

У схему було додано реле для автоматичного відключення кип'ятильника при температурі 99.5°С. Щоб не різати дроти на кип'ятильнику, підключимо через розетку, всередині якої знаходиться вищезгадане реле.

Важливо

Датчик температури знаходиться в металевому корпусі, перехід від металу на кабель ізольований термозбіжною трубкою. На металі трубка прилягає дуже щільно, на кабелі слабше, через це місце може, хоч і мала, просочитися вода. З метою уникнення цієї ситуації ми рекомендуємо не занурювати датчик у воду повністю. Якщо у вас все-таки є така необхідність, ми рекомендуємо заізолювати цю ділянку більш ретельно.

Код прикладу

#include OneWire ds(10); // підключений до 10 піну (резистор на 4.7к обов'язковий) void setup(void) ( Serial.begin(9600); pinMode(3, OUTPUT); // Включаємо кип'ятильник digitalWrite(3, LOW); ) void loop(void) ( byte i; byte present = 0; byte type_s; byte data ; byte addr ; ); ds.reset_search(); delay(250);< 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); // начало коммуникации delay(1000); 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(); // Преобразуем получненный данные в температуру // Используем int16_t тип, т.к. он равен 16 битам // даже при компиляции под 32-х битный процессор int16_t raw = (data << 8) | data; if (type_s) { raw = raw << 3; if (data == 0x10) { raw = (raw & 0xFFF0) + 12 - data; } } else { byte cfg = (data & 0x60); if (cfg == 0x00) raw = raw & ~7; else if (cfg == 0x20) raw = raw & ~3; else if (cfg == 0x40) raw = raw & ~1; } 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"); // Если температура достигает температуры кипения (с погрешностью), отключаем кипятильник if (celsius >99.5) (digitalWrite(3, HIGH); ))

#include

OneWire ds(10); // Підключаємо датчик до 10 цифрового піна

void setup(void) (
Serial.begin(9600);
pinMode(3, OUTPUT);
// Включаємо окроп
digitalWrite(3, LOW);
}

void loop (void) (
byte i;
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;
}

// Перевіряємо, чи не було перешкод при передачі
if (OneWire::crc8(addr, 7) != addr) (
Serial.println("CRC is not valid!");
return;
}
Serial.println();

// Визначаємо серію датчика
switch (addr) (
case 0x10:
Serial.println(" Chip = DS18S20");
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(0xBE); // Зчитуємо оперативну пам'ять датчика

for (i = 0; i< 9; i++) {
data[i] = ds.read(); // Заповнюємо масив ліченими даними
}

// Дані про температуру містяться у перших двох байтах, переведемо їх в одне значення і перетворимо на шістнадцятирозрядне число
int16_t raw = (data<< 8) | data;
if (type_s) (
raw = raw<< 3;
if (data == 0x10) (
raw = (raw & 0xFFF0) + 12 - data;
}
}
else (
byte cfg = (data & 0x60);
if (cfg == 0x00) raw = raw & ~7;
else if (cfg == 0x20) raw = raw & ~3;
else if (cfg == 0x40) raw = raw & ~1;
}
celsius = (float) raw / 16.0;
fahrenheit = celsius * 1.8 + 32.0;
Serial.print("Temp = ");
Serial.print(celsius);
Serial.print("C,");
Serial.print(fahrenheit);
Serial.println("F");

// Якщо температура досягає температури кипіння (з похибкою), відключаємо кип'ятильник
if (celsius > 99.5)
{
digitalWrite(3, HIGH);
}
}

Купити в Росії

Час переходити до чогось кориснішого в господарстві. Ну, наприклад, зробити цифровий термометр, чи що. Тим більше, що з Ардуїно - це зовсім не так складно, як було у "доконтролерну епоху". У ті часи електронний термометр був складною конструкцією з десятка мікросхем, аналогового датчика, який потрібно було ще відкалібрувати, і трансформаторного блоку живлення на кілька вихідних напруг. Ну і - відповідної підготовки радіоаматора, який задумає все це зібрати. Зараз із цим – все набагато простіше.

Дозвольте уявити цифровий датчик температури буржуїнської фірми "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. Тобто вона може набувати як позитивних значень, так і негативних. Перевіримо роботу нашого пристрою на морозці:

Ну що ж, показує і негативні температури. Навіть одразу зі знаком. Надалі, коли ми виводитимемо температуру на різні індикатори, треба буде запам'ятати цю особливість нашої програми. І передбачити додатково індикацію символу плюсової температури. Але про те – вже у наступних статтях.

У процесі вивчення мікроконтролерів рано чи пізно виникає необхідність виміру такого метеорологічного параметра навколишнього середовища, як його температура. Сучасний світовий ринок електронних комплектуючих пропонує широкий асортимент датчиків температури. Основні відмінності між ними складаються в діапазоні вимірюваної температури, напрузі живлення, області застосування, габаритних розмірах, способах перетворення температури, інтерфейсом для взаємодії з керуючою системою. Так історично склалося, що на даний момент одним із найпопулярніших температурних датчиків є датчик DS18B20корпорації Dallas Semiconductor. Про нього така розповідь.

DS18B20– цифровий датчик температури з програмованою роздільною здатністю перетворення.

Відмінні риси:

1) Використання інтерфейсної шини даних 1-Wire для взаємодії з керуючою системою;
2) Наявність унікального 64-бітного послідовного ідентифікаційного коду, розташованого у внутрішній ROM-пам'яті та призначеної для багатоточкових систем, де необхідно адресувати конкретний датчик;
3) Напруга живлення становить 3-5,5В, що дозволяє використовувати його не тільки в 5-вольтових системах, а й у 3,3 (більшість мікроконтролерів);
4) Діапазон вимірюваної температури становить -55 ... +125 про З;
5) Точність в ±0,5 про З, щоправда це вірно лише з діапазону -10…+85 про З;
6) Дозвіл перетворення визначається користувачем і становить 9…12 біт;
7) Має внутрішні регістри тригерів верхнього та нижнього порогів спрацьовування з виробленням сигналу тривоги для систем, які використовують термостатичну логіку роботи;
8) Ці датчики програмно сумісні з DS1822та широко застосовуються у промислових термостатичних регуляторах, індустріальних системах, у споживчій електроніці та інших термочутливих системах.

Опис та принцип роботи пристрою:

У статті я опишу приклад роботи з датчиком, виконаним у корпусі TO-92.

Виглядає він таким чином:

Усередині ця штуковина влаштовано дуже просто, погляньте самі:

Розглянемо детальніше цю блок-схему.

Однак живлення в такий спосіб вносить деякі обмеження на часові параметри датчика. Утримання лінії даних деякий час розрядить конденсатор, що призведе до знеструмлення лінії INTERNAL Vdd, відповідно і датчика в цілому. Тому в час, що не використовується, на лінії DQ повинен підтримуватися високий логічний рівень. Слід зазначити одне важливе зауваження. При операціях перетворення температури та копіювання даних з Scratchpad в EEPROM (в один з регістрів), споживаний лінією INTERNAL Vdd струм може досягати 1,5мА, що непосильно внутрішньому конденсатору, а на резисторі підтяжки буде велике падіння напруги, що неприпустимо позначиться на роботі пристрою загалом. Для цього необхідно організувати лінії DQ схему потужної підтяжки, що реалізується за такою схемою:

Після видачі команди ConvertT або CopyScratchpad необхідно включити потужну підтяжку MOSFET-транзистором лінії DQ не пізніше 10мкс(макс.), як стверджують розробники датчика, після чого почекати час перетворення (Tconv) або час передачі даних (Twr=10мс), причому в цей час жодних дій при включеній потужній підтяжці на лінії DQ не повинно бути!

Про стандартне харчування потрібно мало що сказати, адже тут все просто, і навіть MOSFET зовсім не потрібен:

Підсистема "64-BIT ROM AND 1-Wire PORT" містить унікальний 64-бітний послідовний ідентифікаційний код, розташований в енергонезалежній пам'яті ROM, також в цьому вузлі розташований інтерфейс взаємодії з керуючою системою 1-Wire. Підсистема «Memory Control Logic» здійснює передачі даних між підсистемою інтерфейсу 1-Wire і пам'яттю типу Scratchpad, яка, у свою чергу, має доступ до регістрів температурного датчика, регістрів установки верхнього і нижнього порогів спрацьовування сигналу тривоги, регістру конфігурації і регістру генератора 8- бітної контрольної суми для захисту системи від неправильних даних.

При включенні живлення за замовчуванням датчик має роздільну здатність перетворення 12 біт, і одразу входить у режим зниженого енергоспоживання. Для ініціювання перетворення провідний пристрій має передати команду ConvertT . Після перетворення температури в цифровий код цей код розташовується в Scratchpad-пам'яті у вигляді двобайтного слова, і датчик знову переходить в енергозберігаючий режим.

Перетворення температури.

Тепер розберемося, як перетворюється температура датчика. По суті, всередині самого температурного сенсора розташовується АЦП, і вихідні дані, розташовані в регістрі температури, переносяться в Scratchpad-пам'ять. Дані про температуру мають такий формат:

Прапор S - прапор знака, використовується для вказівки знака числа (S = 0 - число, що міститься в бітах 10-0 позитивно, і S = 1, якщо число, що міститься в тих же бітах, негативно, тобто в даному випадку температура представляється у додатковому коді (коді доповнення до двох)).

При налаштуванні дозволу перетворення 12 біт все 12 біт (bit 11- bit 0) задіяні і містять достовірні дані. При налаштуванні на дозвіл 11 біт вміст біта 0 не слід брати до уваги, при налаштуванні на 10 біт не слід брати до уваги біти 0 і 1 і т.д.

Сигнал тривоги – це функція термостата.

Для цього передбачено 2 8-бітові регістри, Th і Tl. Th містить значення верхнього порогу температури, а Tl – відповідно нижнього. Якщо температура вище значення Th або нижче за Tl встановлюється прапор тривоги. Цей прапор тривоги виявляється провідним пристроєм у вигляді видачі команди Alarm Searchна лінію DQ. Прапор тривоги оновлюється після кожної операції перетворення температури. До речі, лише біти з 11 по 4-й регістру температури використовують у порівнянні з регістром Th або Tl, звідси випливає, що функція термостата працює тільки для цілих значень температури. Реєстри фізично є пам'яттю EEPROM, тому вони зберігають свої значення при вимкненні живлення. Самі регістри аналогічні регістру температури, тільки вони 8-бітові, прапор S має абсолютно таке ж значення, як і в попередньому випадку:

Цей код, як зазначалося раніше, необхідний для ідентифікації кожного пристрою лінії в системах багатоточкового вимірювання температури.

Формат цієї пам'яті такий:

Молодші 8 біт відводяться для позначення сімейства і містять значення 0х28. Наступні 48 біт містять унікальний серійний номер пристрою. Найстарший байт містить значення контрольної суми CRC, яка розраховується для молодших 56 біт ROM-пам'яті.

Організація пам'яті.

Пам'ять датчика складається з простору пам'яті блокнотного типу (Scratchpad) та EEPROM-пам'яті для зберігання даних конфігурації та значень регістрів верхнього та нижнього порогів сигналу тривоги.

При вимиканні живлення дані байта 2, 3 і 4 зберігають своє значення EEPROM. Ну а при включенні значення у них залишаються незмінними. Байт 0 і 1 містять значення перетвореної температури, байти 5, 6, 7 зарезервовані для внутрішнього використання і не можуть бути доступні користувачеві для його потреб.

8-й байт містить значення, що генерується вбудованою логікою формування CRC-коду для байтів з 0 по 7, що зводить до мінімуму можливість помилкового визначення температури в кінцевому підсумку.

Слід зазначити, що якщо функція термостата не використовується, то регістри Th і Tl можуть використовуватися як пам'ять загального призначення – у них можна зберігати будь-яку інформацію.

Дані записуються в байти 2, 3 і 4 починаючи з молодшого біта 2 байта за допомогою команди Write Scratchpad. Для перевірки цілісності записаних даних можна їх прочитати, для чого необхідно передати датчику команду Read Scratchpad, після чого провідний пристрій повинен приймати дані з молодшого біта байта 0.

Для збереження даних старшого, молодшого регістрів термостата або регістра конфігурації в EEPROM-пам'яті, провідний пристрій повинен передати датчику команду. Copy Scratchpad.

Як зазначалося раніше, дані, які вже записані в EEPROM, при вимиканні живлення зберігаються. Але при включенні живлення з відповідних EEPROM-осередків значення автоматично завантажуються у відповідні регістри пам'яті scratchpad. Зручно, чи не так?:)

Крім того, дані, записані в EEPROM, у будь-який час можуть бути перезаписані в scratchpad-пам'ять. Це потрібно наприклад у тому, коли змінили конфігурацію у процесі роботи, та був вам треба стати «штатний режим роботи», тобто. повернути ту конфігурацію роботи, яка була до зміни вмісту регістрів пам'яті scratchpad. Ось власне для цього провідний пристрій має передати датчику команду Recall E2 .

У регістрі конфігурації користувачем можуть визначатися лише 2 біти: R0 та R1. Ці біти визначають дозвіл перетворення температури, і по дефолту встановлені в 1, що визначає початкову налаштування на 12-бітове дозвіл перетворення.

Всі можливі конфігурації цих бітів та відповідні дозволи представлені у таблиці нижче. Слід зазначити, що чим більша роздільна здатність перетворення, тим більше час перетворення, наприклад, для 12-бітного роздільна здатність час перетворення становить 750мс (макс.).

Взаємодія з системою, що управляє.

DS18B20, як зазначалося раніше, для зв'язку з веденим пристроєм використовують інтерфейсну шину даних 1-Wire. Тому для його підключення система керування повинна забезпечувати вихід з відкритим стоком або з Hi-Z станом лінії.

Внутрішня конфігурація інтерфейсу датчика показана нижче:

У неактивному стані (у стані простою) лінія DQ підтягнута резистором до «+» живлення. Таким чином, між транзакціями (передачами даних) ця лінія завжди повинна утримуватися в цьому стані. Якщо з будь-якої причини транзакції повинні бути припинені, лінія DQ повинна утримуватися у високому логічному рівні, якщо ця передача буде відновлена. У процесі зупинки транзакції ми скільки завгодно довго можемо тримати лінію DQ у високому логічному рівні, починаючи з 1мкс. Але якщо шина даних буде утримана в низькому логічному рівні довше 480мкс, відбудеться повне скидання всіх датчиком, присутніх на цій шині.

Послідовність операцій обміну.

Щоразу при зверненні керуючої системи до датчика повинна бути дотримана наступна послідовність дій:

1) Ініціалізація;
2) Команда ROM (за яким слідує необхідний обмін даними);
3) Функціональна команда датчика (за якою слідує необхідний обмін даними).

Якщо будь-який крок при зверненні до датчика відсутній, датчик не буде реагувати. Виняток становлять команди SearchROM [ F0 h] і AlarmSearch [ ECh] , після їх виконання майстер повинен повернутися до першого кроку послідовності, що управляє.

Отже. Усі транзакції розпочинаються з ініціалізації. Ця операція супроводжується виробленням провідним пристроєм імпульсу скидання, який ведені пристрої (в даному випадку датчик(-и)) передають ведучому імпульс присутності, які дають йому знати, що датчики підключені і готові до роботи.

Взагалі інтерфейсна шина 1-Wire, реалізована в датчику, визначає кілька типів сигналів лінії даних: імпульс скидання, імпульс присутності, запис 0, запис 1, читання 0, читання 1. Всі ці операції реалізує провідний пристрій, за винятком імпульсу присутності. Його формує лише датчик(-и).

Отже, для початку провідний пристрій переходить в режим передавача і встановлює лінію DQ в 0 на час не менше 480мкс (виділено жирним чорним кольором). Це скидає датчик. Потім лінію необхідно відпустити, і перевести провідний пристрій режим приймача, при цьому підтягуючий резистор встановить лінію даних у високий логічний рівень (виділено тонким чорним кольором). Після того, як датчик почує наростаючий фронт, датчик вичекає час 15-60мкс і своїм апаратним інтерфейсом скине лінію даних 0, і її триматиме протягом 60-240мкс. Після цього датчик відпустить лінію і вона встановиться в рівень логічної 1 протягом не менше 480мкс після виявлення датчиком імпульсу скидання.

Тепер поговоримо у тому, як здійснюється процес передачі. Взагалі передачі біта. Справа в наступному. Береться відрізок часу, і протягом цього часу майстер дивиться, що там у нас на лінії, припустімо 1 означає записали 1, якщо 0 означає записали нуль. Але це лише абстрактне пояснення. Насправді там є деякі нюанси, пов'язані з тимчасовими рамками цієї справи.

Дивимося картинки:

Все починається з того, що ведучий має опустити лінію даний у низький логічний рівень, і з цього моменту починається слот запису/читання 1/0, що триває від 60 до 120мкс. Між слотами запису/читання лінія даних обов'язково має встановитися в 1 на час, не менше часу відновлення (1мкс). Для організації слота запису 0 необхідно весь час слота тримати лінію даних 0, якщо необхідно записати в датчик 1, то спочатку скидаємо лінію даних 0, потім чекаємо не менше 1мкс і відпускаємо лінію 1, протягом слота запису 1 (60- 120мкс) буде записана 1 датчик (див. верхній правий малюнок).

Власне кажучи, якщо протягом 15-60мкс після старту буде виявлено 1 лінії даних, то запишеться 1, а якщо протягом 60-240мкс виявиться 0 - то і запишеться 0.

Читання даних супроводжується провідним пристроєм, що він скидає лінію, чекає щонайменше 1мкс, і протягом 15мкс дивиться, що у лінії відбувається: якщо залишився 0, то датчик передає 0, якщо переключилася на 1, - те й передалася 1.

Команди.

ROM-команди.

Ці команди повинні слідувати за послідовністю ініціалізації та містять інструкції пошуку відповідного датчика тощо. Розрядність кожної команди 8біт. Після виконання відповідної команди можна передати функціональну команду датчику.

SEARCH ROM

Коли система спочатку підключена, вона повинна розпізнати всі підключені до шини пристрою. І тому ця команда. Але, оскільки у нас лише один датчик, користуватися цією командою ми не будемо.

READ ROM

Ця команда використовується лише тоді, коли на шині є лише один датчик. Це дозволяє провідному пристрою рахувати вміст 64 біт ROM-пам'яті не використовуючи команду її пошуку. А якщо ви спробуєте використовувати цю команду при підключеній кількості датчиків, більше 1, всі вони почнуть передавати вміст цієї пам'яті, що призведе до небажаних наслідків.

MATCH ROM

Це команда відповідності ROM. Майстер випускає 64 біти відповідної пам'яті ROM підключеного до шини датчика і там вже визначається, що з ним робити (виміряти температуру, і т.д.). Інші датчики на шині в цей час чекатимуть на свою чергу.

SKIP ROM

Це команда пропуску ROM. Не враховує адресу будь-якого конкретного датчика на шині, а звертається відразу до всіх. Після цієї команди можна видати, наприклад, команду перетворення температури, і всі датчики почнуть перетворення. Однак вивести команду читання пам'яті після виклику цієї команди призведе до непередбачуваних результатів (бо відразу всі датчики будуть передавати дані). Значить, лише за одного підключеного датчика можлива така ситуація.

ALARM SEARCH

Ця команда ідентична першої в цій таблиці, за винятком того, що здійснює пошук датчиків на шині з встановленим прапором тривоги.

функціональні команди.

Ці команди здійснюють функціональні операції будь-яких процесів, наприклад, запуск операції перетворення температури, копіювання пам'яті і т.д. Усього команд 6, розрядність кожної 8біт.

CONVERT T

Запуск перетворення температури. Після виконання цієї команди 2-байтні дані заносяться в регістр температури.

WRITE SCRATCHPAD

Записує дані в регістри 2-4 починаючи з другого, молодшим бітом уперед. Під час передачі дані в три регістри необхідно стежити, щоб майстер не скинув датчики, тому що можлива втрата даних.

READ SCRATCHPAD

Ініціює процес передачі всіх регістрів пам'яті scratchpad, починаючи з молодшого біта байта 0 і закінчуючи старшим бітом байта 8 (CRC).

COPY SCRATCHPAD

Ця команда копіює вміст регістрів байта 2, 3 та 4 у відповідні EEPROM-осередки.

RECALL E2

Ця команда копіює дані з EEPROM у відповідні місця у блокнотній пам'яті scratchpad. Як зазначалося раніше, при включенні живлення ця операція відбувається автоматично.

READ POWER SUPPLY

Ось, власне, і вся премудрість роботи з датчиком температури DS18B20. За більш детальною інформацією звертаємось у даташит (). Тепер необхідно всю цю справу реалізувати у залізі.

Принципова схема пристрою:

Складальний креслення друкованої плати (вибачаюсь за якість, робив аби працювало, для налагодження):

Не забудьте правильно віддзеркалити плату

Оскільки це макетка, я витяг її зі старого проекту, тому на платі, наведеній вище – трохи не те, що в мене (на своїй я зараз прибрав усе зайве і воно стало точнісінько як на малюнках вище).

Ось що вийшло у мене:

Вийшов такий собі бутерброд

Вихідний код програми був написаний у середовищі розробки. Я не намагався використовувати максимум готових бібліотек avr-gcc компілятора, а писав усе, як кажуть, «від руки». Моя мета – це не демонстрація віртуозного володіння Сі, а лише приклад, написаний за годину, здатний надати новачкам загальне уявлення щодо роботи з датчиком.
Пристрій призначений для використання у кімнаті, тому не передбачає вимірювання негативних температур.

Завантажити вихідні та друковану плату LAY ви можете нижче

Всі додаткові питання, побажання чекаю на адресу: [email protected]