DS18B20 – digitální teploměr pro Arduino

Digitální teplotní čidlo DS18B20 je taková malá klasika mezi Arduino senzory. Není to žádná novinka, ale pořád se používá hodně často, protože je jednoduché, levné a připojuje se jen přes jednu datovou linku.

Mám tu dvě varianty. Jednu obyčejnou v pouzdru TO-92, která vypadá jako malý tranzistor, a druhou vodotěsnou variantu v kovové sondě na kabelu. Obě uvnitř fungují stejně, ale každá se hodí na trochu jiné použití.

V článku ukážu základní zapojení, rozdíly mezi pouzdry, klasické i parazitní napájení a přidám několik testovacích programů. Jeden bude používat pevně zadanou adresu čidla, druhý si čidlo najde automaticky a třetí bude jednoduchý 1-Wire scanner, který vypíše nalezená čidla i s adresou a teplotou.

Oba druhy čidla

Co je DS18B20

DS18B20 je digitální teploměr komunikující po sběrnici 1-Wire. To znamená, že pro komunikaci používá jednu datovou linku a zem. Každé čidlo má vlastní unikátní 64bitovou adresu, takže můžeš mít na jednom datovém vodiči víc čidel najednou a program je dokáže rozlišit.

Podle datasheetu měří v rozsahu -55 °C až +125 °C, má nastavitelné rozlišení převodu 9 až 12 bitů a v rozsahu -10 °C až +85 °C je uváděná přesnost ±0,5 °C. Napájecí napětí je 3,0 až 5,5 V, takže se dá bez problémů použít nejen s klasickým Arduinem, ale i s deskami pracujícími na 3,3 V, jako je ESP8266, ESP32 nebo Raspberry Pi.

Jen je potřeba dát pozor na pull-up rezistor datové linky. U Arduina napájeného 5 V může být pull-up na 5 V, ale u ESP a Raspberry Pi musí být datová linka vytažená na 3,3 V, protože jejich GPIO piny nejsou určené pro 5V logiku.

Výhoda proti obyčejnému analogovému teplotnímu čidlu je v tom, že Arduino nemusí měřit analogové napětí. Čidlo pošle rovnou digitální hodnotu teploty. Díky tomu není měření tolik závislé na analogovém převodníku Arduina, rušení na analogovém vstupu nebo přesnosti referenčního napětí.

Maximální rozlišení 12 bitů znamená krok 0,0625 °C. To ale neznamená, že čidlo je absolutně přesné na setiny stupně. Znamená to jen jemnost výstupní hodnoty. Přesnost jako taková je podle datasheetu horší než rozlišení, což je u měřicích čidel normální. Datasheet také uvádí, že převod při 12bitovém rozlišení může trvat až 750 ms.

Použitý hardware

  • Arduino UNO / Nano / Mega – pro test stačí libovolné běžné Arduino
  • DS18B20 v pouzdru TO-92 – malá obyčejná varianta
  • DS18B20 ve vodotěsném pouzdru – kovová sonda na kabelu
  • Rezistor 4,7 kΩ – pull-up rezistor mezi datovou linku a napájení
  • Nepájivé pole a propojovací vodiče

Pro test používám datový pin D2. V programu ho jde samozřejmě změnit.

Varianty pouzdra

DS18B20 se dá koupit jako samotná součástka v pouzdru TO-92 nebo jako hotová sonda na kabelu. Na první pohled je vodotěsná sonda praktičtější, ale není automaticky lepší pro všechno.

DS18B20 v pouzdru TO-92

Pouzdro TO-92 je malé plastové pouzdro se třemi nožičkami. Výhodou je hlavně malá velikost a rychlejší reakce na změnu teploty. Když čidlo držím v ruce, ohřeje se poměrně rychle. Když ho dám k nějaké součástce nebo do krabičky, bude reagovat rychleji než velká kovová sonda.

čidlo v pouzdru TO-92

Nevýhoda je jasná. Není vodotěsné, nemá kabel a je mechanicky méně odolné. Na pokusy na stole je super, ale venku, ve vodě nebo někde v trubce by se muselo pořádně zaizolovat.

Výhody TO-92:

  • Malé rozměry
  • Rychlejší reakce na změnu teploty
  • Levné provedení
  • Dobré pro měření vzduchu, teploty v krabičce nebo u elektroniky
  • Snadno se zapojí do nepájivého pole

Nevýhody TO-92:

  • Není vodotěsné
  • Nožičky se dají snadno ohnout nebo ulomit
  • Pro venkovní použití se musí chránit
  • Na delší vzdálenost se musí řešit kabel nebo vlastní mechanické uchycení.

Vodotěsná varianta na kabelu

Vodotěsná varianta má čidlo zalité v kovové trubičce a vyvedené na kabelu. Hodí se tam, kde se měří teplota vody, zeminy, potrubí, venkovní teplota nebo něco, kam se samotné TO-92 pouzdro nehodí.

čidlo ve vodotěsné variantě

Je ale potřeba počítat s tím, že kovová sonda je větší a má větší tepelnou setrvačnost. To znamená, že na změnu teploty reaguje pomaleji. Když sondu přendáme ze studené vody do teplé, hodnota se nezmění okamžitě. Chvilku trvá, než se ohřeje kovové pouzdro, zalévací hmota uvnitř a teprve potom samotné čidlo.

To není chyba. Pro měření vody v akváriu, boileru, venku nebo v zemi to většinou vůbec nevadí. Naopak je výsledek klidnější a méně skáče. Pro rychlé změny teploty je ale lepší malé pouzdro TO-92.

Výhody vodotěsné sondy:

  • Dá se použít ve vodě nebo venku
  • Má hotový kabel
  • Lépe se mechanicky umisťuje
  • Vhodná pro akvária, nádrže, potrubí, zeminu nebo venkovní měření
  • Díky větší tepelné setrvačnosti méně reaguje na krátké teplotní výkyvy

Nevýhody vodotěsné sondy:

  • Pomalejší reakce na změnu teploty
  • Větší rozměry
  • U levných sond nemusí být jistá kvalita zalití
  • Barvy vodičů nemusí být u všech výrobců stejné
  • U levných kopií nemusí fungovat všechno stejně jako u originálního čidla

Zapojení klasickým způsobem

Nejspolehlivější je běžné třívodičové zapojení:

DS18B20Arduino
GNDGND
DQ / DATAD2
VDD5 V

Mezi DQ / DATA a 5 V se připojí rezistor 4,7 kΩ. To je pull-up rezistor datové linky. Sběrnice 1-Wire ho potřebuje, protože datový výstup čidla je typu open-drain a linka se bez pull-upu sama nevrátí do logické jedničky.

U TO-92 pouzdra je pinout při pohledu na plochou stranu zepředu a nožičky dolů:

PinFunkce
LevýGND
ProstředníDQ / DATA
PravýVDD

Toto zapojení odpovídá pinoutu v datasheetu pro TO-92 pouzdro.

U vodotěsné sondy se často používá následující barevné značení. Platí pro mnou použité čidlo:

VodičFunkce
ČervenýVDD
ČernýGND
Žlutý DATA

U levných čidel bych ale barvám nevěřil naslepo. Pokud je možnost, je dobré si zapojení ověřit podle prodejce nebo popisu konkrétní sondy.

Parazitní napájení

DS18B20 umí ještě jednu zajímavou věc. Může fungovat v režimu parazitního napájení. V tom případě se nepoužije samostatný vodič VDD. Čidlo si bere energii z datové linky DQ. Podle datasheetu je při parazitním napájení potřeba jen DQ a GND a pin VDD se připojuje na GND.

Zapojení pak vypadá takto:

DS18B20Arduino
GNDGND
DQ / DATAD2
VDDGND

Mezi DQ / DATA a 5 V zůstává pull-up rezistor.

Na papíře to vypadá krásně. Místo tří vodičů stačí dva. Jenže v praxi to nemusí být vždycky tak jednoduché. Při měření teploty potřebuje čidlo víc proudu a datová linka musí být po dobu převodu dostatečně tvrdě vytažená nahoru. Datasheet kvůli tomu popisuje požadavek na silný pull-up během převodu teploty.

U originálního čidla to může fungovat dobře, ale u levných čínských kopií a hlavně u vodotěsných sond z neznámého zdroje bych s parazitním napájením moc nepočítal. Některé kusy se sice jako DS18B20 tváří, ale parazitní režim nemusí fungovat vůbec, nebo může fungovat jen nespolehlivě.

Pro běžné domácí pokusy bych proto doporučil klasické třívodičové zapojení. Parazitní napájení je zajímavé, ale pokud není nutné šetřit jeden vodič, je lepší čidlo napájet normálně.

Porovnání napájení

ZapojeníVýhodyNevýhody
Klasické napájení VDD + DATA + GNDSpolehlivější, vhodné pro více čidel, lepší pro delší kabely, jednodušší laděníPotřebuje tři vodiče
Parazitní napájení DATA + GNDStačí dva vodiče, zajímavé pro jednoduchou kabelážMůže být nespolehlivé, potřebuje dobrý pull-up, horší s delšími kabely a více čidly, u kopií nemusí fungovat
Klasické zapojení dvou čidel na nepájivém poli

Instalace knihoven

V Arduino IDE je potřeba nainstalovat dvě knihovny:

  • OneWire
  • DallasTemperature

V Arduino IDE otevřeme Manažéra knihoven, vyhledáme DallasTemperature a nainstalujeme ji. Knihovna DallasTemperature sama v dokumentaci uvádí, že je potřeba doinstalovat také knihovnu OneWire od Paula Stoffregena.

Knihovna OneWire slouží pro samotnou komunikaci po 1-Wire sběrnici. Knihovna DallasTemperature nad tím přidává jednodušší práci s teplotními čidly, takže není potřeba ručně řešit všechny příkazy DS18B20.

Program 1: 1-Wire scanner s výpisem adresy a teploty

První program je nejužitečnější při ladění. Prohledá 1-Wire sběrnici, vypíše nalezená čidla, jejich adresy a aktuální teplotu.

Hodí se hlavně ve chvíli, kdy máme víc čidel, nebo když chceme zjistit adresu konkrétního kusu pro pevně zadaný program.

#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 2

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void printAddress(const uint8_t address[8]) {
for (uint8_t i = 0; i < 8; i++) {
if (address[i] < 16) Serial.print("0");
Serial.print(address[i], HEX);
if (i < 7) Serial.print(":");
}
}

void scanOneWire() {
uint8_t address[8];
int pocet = 0;

Serial.println();
Serial.println("Hledam zarizeni na 1-Wire sbernici...");

oneWire.reset_search();

while (oneWire.search(address)) {
pocet++;

Serial.print("Zarizeni ");
Serial.print(pocet);
Serial.print(": ");

printAddress(address);

if (OneWire::crc8(address, 7) != address[7]) {
Serial.println(" CRC chyba");
continue;
}

Serial.print(" typ: ");

if (address[0] == 0x28) {
Serial.print("DS18B20");
} else if (address[0] == 0x10) {
Serial.print("DS18S20 / DS1820");
} else if (address[0] == 0x22) {
Serial.print("DS1822");
} else {
Serial.print("neznamy 1-Wire prvek");
}

Serial.print(" teplota: ");

sensors.requestTemperaturesByAddress(address);
float teplota = sensors.getTempC(address);

if (teplota == DEVICE_DISCONNECTED_C) {
Serial.println("chyba cteni");
} else {
Serial.print(teplota, 2);
Serial.println(" °C");
}
}

if (pocet == 0) {
Serial.println("Nenalezeno zadne 1-Wire zarizeni");
}

oneWire.reset_search();
}

void setup() {
Serial.begin(9600);
sensors.begin();

Serial.println("1-Wire scanner pro DS18B20");
}

void loop() {
scanOneWire();
delay(5000);
}

Výstup může vypadat třeba takto:

výpis ze scanneru

Adresu pak stačí opsat do programu s pevně zadanou adresou ve tvaru:

DeviceAddress cidlo = { 0x28, 0xFF, 0x64, 0x1E, 0x5B, 0x8A, 0x58, 0x00 };

Program 2: měření s pevně zadanou adresou

Každé čidlo DS18B20 má vlastní adresu. Pokud máme na jedné sběrnici víc čidel, je nejlepší používat adresy. Program pak přesně ví, které čidlo čte.

Adresu zjistíme scannerem, který je výše v článku. Potom ji jen zkopírujeme do tohoto programu.

#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 2

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// Sem vlož adresu svého čidla ze scanneru
DeviceAddress cidlo = { 0x28, 0xFF, 0x64, 0x1E, 0x5B, 0x8A, 0x58, 0x00 };

void printAddress(DeviceAddress deviceAddress) {
  for (uint8_t i = 0; i < 8; i++) {
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
    if (i < 7) Serial.print(":");
  }
}

void setup() {
  Serial.begin(9600);
  sensors.begin();

  sensors.setResolution(cidlo, 12);

  Serial.println("DS18B20 - mereni podle pevne adresy");
  Serial.print("Adresa cidla: ");
  printAddress(cidlo);
  Serial.println();
}

void loop() {
  sensors.requestTemperaturesByAddress(cidlo);

  float teplota = sensors.getTempC(cidlo);

  if (teplota == DEVICE_DISCONNECTED_C) {
    Serial.println("Chyba: cidlo nenalezeno nebo neodpovida");
  } else {
    Serial.print("Teplota: ");
    Serial.print(teplota, 2);
    Serial.println(" °C");
  }

  delay(1000);
}
Výpis teploty ne sériáku

Tahle varianta je vhodná hlavně tehdy, když bude čidlo součástí nějakého trvalého projektu. Třeba když jedno čidlo měří venkovní teplotu, druhé teplotu vody a třetí teplotu uvnitř krabičky. Když jsou adresy pevně zadané, program si je nesplete.

Program 3: automatické vyhledání čidla

Pro první pokusy je pohodlnější neřešit adresu vůbec. Program si najde první dostupné čidlo na sběrnici a začne z něj číst teplotu.

#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 2

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DeviceAddress cidlo;
bool cidloNalezeno = false;

void printAddress(DeviceAddress deviceAddress) {
for (uint8_t i = 0; i < 8; i++) {
if (deviceAddress[i] < 16) Serial.print("0");
Serial.print(deviceAddress[i], HEX);
if (i < 7) Serial.print(":");
}
}

void setup() {
Serial.begin(9600);
sensors.begin();

Serial.println("DS18B20 - automaticke vyhledani");

int pocetCidel = sensors.getDeviceCount();

Serial.print("Pocet nalezenych cidel: ");
Serial.println(pocetCidel);

if (pocetCidel > 0 && sensors.getAddress(cidlo, 0)) {
cidloNalezeno = true;
sensors.setResolution(cidlo, 12);

Serial.print("Pouzivam prvni nalezene cidlo: ");
printAddress(cidlo);
Serial.println();
} else {
Serial.println("Nenalezeno zadne cidlo");
}
}

void loop() {
if (!cidloNalezeno) {
Serial.println("Cidlo neni dostupne");
delay(2000);
return;
}

sensors.requestTemperatures();

float teplota = sensors.getTempC(cidlo);

if (teplota == DEVICE_DISCONNECTED_C) {
Serial.println("Chyba cteni teploty");
} else {
Serial.print("Teplota: ");
Serial.print(teplota, 2);
Serial.println(" °C");
}

delay(1000);
}
výpis na sériáku

Tento program je dobrý na rychlé ověření, že čidlo žije. Stačí připojit jedno DS18B20 a otevřít sériový monitor.

Nastavení rozlišení měření

DS18B20 umožňuje nastavit rozlišení měření od 9 do 12 bitů. Jednoduše řečeno tím nastavíme, jak jemně bude čidlo teplotu měřit a jak dlouho bude převod trvat.

RozlišeníKrok teplotyOrientační doba převodu
9 bitů0,5 °Caž 93,75 ms
10 bitů0,25 °Caž 187,5 ms
11 bitů0,125 °Caž 375 ms
12 bitů0,0625 °Caž 750 ms

Výchozí a nejčastěji používané nastavení je 12 bitů. Čidlo pak vrací nejjemnější hodnotu, ale zároveň měření trvá nejdéle. Pro běžné měření teploty v místnosti, venku nebo ve vodě to vůbec nevadí, protože teplota se většinou nemění tak rychle.

Nižší rozlišení se hodí ve chvíli, kdy potřebujeme měřit rychleji, nebo když stačí hrubší hodnota. Například u jednoduchého termostatu může být rozlišení 10 bitů pořád úplně dostačující.

V knihovně DallasTemperature se rozlišení nastavuje funkcí:

sensors.setResolution(cidlo, 12);   //nastavení rozlišení konkrétního čidla na 12 bitů

Pokud máme na sběrnici jen jedno čidlo nebo chci nastavit stejné rozlišení všem čidlům, jde použít i jednodušší zápis:

sensors.setResolution(12);          //nastavení rozlišení pro všechna čidla

Je dobré si uvědomit, že větší počet desetinných míst na výpisu neznamená automaticky větší skutečnou přesnost. Rozlišení říká, po jak malých krocích čidlo hodnotu posílá. Skutečná přesnost čidla je ale daná jeho konstrukcí a podle datasheetu je v běžném rozsahu horší než samotný nejmenší krok měření.

Pro běžné pokusy bych nechal 12 bitů. U rychlejšího měření nebo u většího počtu čidel na jedné sběrnici bych zkusil 10 nebo 11 bitů a porovnal, jestli je výsledek pořád dostatečný.

Na co si dát pozor

Nejčastější problém je chybějící pull-up rezistor. Bez něj může čidlo někdy fungovat, někdy ne, nebo se nemusí najít vůbec. Rezistor 4,7 kΩ mezi DATA a napájení je základ.

Další častá chyba je prohozené napájení u TO-92 pouzdra. Při pohledu na plochou stranu jsou nožičky zleva GND, DATA, VDD. U vodotěsných sond je zase potřeba nevěřit naslepo barvám vodičů, protože u levných kusů se značení může lišit.

Pokud čidlo vrací hodnotu -127 °C, většinou to znamená chybu komunikace nebo že čidlo není nalezené. Pokud se objeví 85 °C, často jde o výchozí hodnotu po resetu nebo stav, kdy ještě neproběhlo správné měření.

U delších kabelů se může hodit snížit hodnotu pull-up rezistoru nebo použít kvalitnější kabel. Tady už ale záleží na konkrétní délce, počtu čidel, napájecím napětí a rušení v okolí.

Mně se osvědčilo místo pevného rezistoru při ladění použít trimr, například 10 kΩ, zapojený jako nastavitelný pull-up mezi datovou linku a napájení. Hodnotu pak můžu postupně doladit tak, aby byla komunikace spolehlivá. Když vše funguje, stačí odpojit napájení, změřit nastavený odpor trimru a nahradit ho nejbližší běžnou hodnotou pevného rezistoru.

Je ale potřeba nedotáčet trimr úplně k nule. Pull-up má datovou linku jen vytahovat nahoru, ne ji tvrdě spojit s napájením. U ESP8266, ESP32 nebo Raspberry Pi musí být pull-up samozřejmě připojený na 3,3 V, ne na 5 V.

Co používám v praxi

Na pokusy na stole stačí obyčejné pouzdro TO-92. Je malé, rychlé a dobře se strká do nepájivého pole.

Na měření vody, venkovní teploty nebo teploty v nějaké nádrži už je lepší použít vodotěsnou sondu. Jen je třeba počítat s tím, že nebude reagovat okamžitě. Na pomalé měření je to v pořádku, ale na sledování rychlých změn teploty se moc nehodí.

Napájení používám klasické třívodičové. Parazitní napájení je zajímavé a určitě stojí za zmínku, ale pokud není potřeba šetřit jeden vodič, nevidím důvod si komplikovat život.

Závěr

DS18B20 je jednoduché a praktické teplotní čidlo, které se hodí jak pro první pokusy s Arduinem, tak pro reálné měření v nějakém hotovém projektu. Velká výhoda je digitální komunikace, možnost připojit víc čidel na jednu sběrnici a také to, že každé čidlo má vlastní adresu.

Obyčejné pouzdro TO-92 je vhodné hlavně pro rychlé testy a měření uvnitř zařízení. Vodotěsná varianta je praktičtější do vody, ven nebo k potrubí, ale kvůli většímu pouzdru má větší tepelnou setrvačnost.

Parazitní napájení je pěkná funkce, ale u levných kopií a čínských sond bych s ním raději nepočítal jako se samozřejmostí. Pro spolehlivé měření je lepší použít normální třívodičové zapojení s napájením, zemí, datovou linkou a pull-up rezistorem.

Související články

Další díly ze začátečnické série o modulech najdete zde:

2 komentáře u „DS18B20 – digitální teploměr pro Arduino“

  1. Když už je ten článek o tom čidle tak dlouhý, bylo by fajn také zmínit, jak vnitřně funguje (registry) a na co si dát pozor při výběru (klony).

    1. To by pak mohl být dvakrát takový. Myslím že pro běžné použití s knihovnou není potřeba zacházet do takových detailů. Ale rozhodně by to mohlo být pro někoho zajímavý.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *