DS18B20 khác hoàn toàn DHT11/DHT22 ở một điểm cốt lõi: nó dùng chuẩn 1-Wire của Maxim (nay là Analog Devices), cho phép nhiều sensor trên cùng 1 dây mà vẫn phân biệt được từng cái. Lý do chọn DS18B20 thay vì DHT: khi cần đo nhiệt độ chất lỏng, đất, hoặc môi trường khắc nghiệt — nơi sensor phải nhúng trực tiếp vào môi trường đo.
Nguyên Lý Hoạt Động
1. Đo Nhiệt Độ — Silicon Bandgap Reference
DS18B20 dùng nguyên lý bandgap temperature sensing thay vì NTC thermistor:
Trong transistor BJT, hiệu điện thế base-emitter (V_BE) phụ thuộc nhiệt độ theo:
VBE(T) = Vg0 × (1 – T/T₀) + V_BE(T₀) × (T/T₀) – (nkT/q) × ln(T/T₀)
Trong đó V_g0 ≈ 1.205V là bandgap silicon ở 0K. IC đo tỷ lệ giữa 2 transistor hoạt động ở mật độ dòng khác nhau → lấy được nhiệt độ tuyệt đối với độ chính xác cao, không cần calibrate từng con chip.
Ưu điểm so với NTC thermistor:
- Tuyến tính theo nhiệt độ trong dải rộng (-55°C đến 125°C)
- Không cần calibrate (tolerance do IC handle)
- Không bị drift theo tuổi thọ như thermistor
2. Chuẩn 1-Wire — Nhiều Sensor, 1 Dây
Đây là công nghệ đặc trưng của Maxim/Dallas. Giao thức 1-Wire sử dụng chỉ 1 đường dữ liệu (cộng GND) nhưng có thể kết nối nhiều thiết bị (DS18B20, DS2431, DS2413…) trên cùng một dây.
Mỗi DS18B20 có ROM code 64-bit duy nhất (laser-engraved khi sản xuất):
ROM 64-bit:
┌──────────────────────────────────────────────────────────┐
│ 8-bit Family Code │ 48-bit Serial Number │ 8-bit CRC │
│ 0x28 │ (unique per chip) │ (checksum) │
└──────────────────────────────────────────────────────────┘
Family code 0x28 là định danh của dòng DS18B20 — khi master đọc ROM, nó biết đây là thermometer, không phải DS2431 (EEPROM) hay thiết bị 1-Wire khác.
Các lệnh 1-Wire quan trọng:
| Lệnh | Mã | Chức năng |
|---|---|---|
| SKIP ROM | 0xCC | Phát lệnh tới TẤT CẢ sensor (chỉ dùng khi có 1 sensor) |
| MATCH ROM | 0x55 | Chọn sensor theo ROM address 64-bit |
| SEARCH ROM | 0xF0 | Tìm kiếm tất cả ROM trên bus |
| READ ROM | 0x33 | Đọc ROM (chỉ khi 1 sensor trên bus) |
| CONVERT T | 0x44 | Bắt đầu chuyển đổi nhiệt độ |
| READ SCRATCHPAD | 0xBE | Đọc 9 byte bộ nhớ (gồm kết quả đo) |
3. Scratchpad Memory — 9 Byte Kết Quả
Sau khi lệnh CONVERT T hoàn thành, kết quả lưu trong Scratchpad (bộ nhớ tạm 9 byte):
| Byte | Nội dung |
|---|---|
| 0 | Nhiệt độ LSB |
| 1 | Nhiệt độ MSB |
| 2 | Ngưỡng cao TH (user-programmable) |
| 3 | Ngưỡng thấp TL (user-programmable) |
| 4 | Configuration register (độ phân giải) |
| 5–7 | Reserved |
| 8 | CRC của byte 0–7 |
Ví dụ đọc nhiệt độ 25.0625°C:
- Byte 0: 0x91 = 1001 0001
- Byte 1: 0x01 = 0000 0001
- Ghép: 0x0191 = 401 → 401 × 0.0625 = 25.0625°C
Độ phân giải cấu hình được (Configuration Register):
| Bit R1:R0 | Độ phân giải | LSB | Thời gian chuyển đổi |
|---|---|---|---|
| 00 | 9-bit | 0.5°C | 93.75ms |
| 01 | 10-bit | 0.25°C | 187.5ms |
| 10 | 11-bit | 0.125°C | 375ms |
| 11 | 12-bit | 0.0625°C | 750ms |
Mặc định: 12-bit (750ms conversion time). Nếu cần đọc nhanh hơn, giảm xuống 9-bit (93ms) nhưng mất độ chính xác.
4. Parasite Power Mode — Không Cần Dây VCC
DS18B20 có chế độ đặc biệt: Parasite Power — lấy điện từ đường DATA (qua tụ bên trong, nạp khi bus ở mức HIGH). Chỉ cần 2 dây: DATA và GND.
Parasite Power:
MCU ─── [R 4.7kΩ] ─── DATA ─── DS18B20 pin DATA + VDD
DS18B20 pin GND ─── GND
(VDD nối với DATA, không nối VCC riêng)
Khi nào dùng parasite power: Dây cáp dài, khó kéo 3 dây. Nhưng có hạn chế: không dùng SKIP ROM với nhiều sensor, không đo chính xác > 100°C.
Thông Số Kỹ Thuật
| Thông số | Giá trị |
|---|---|
| Điện áp (VDD) | 3.0V – 5.5V |
| Điện áp Parasite | 3.0V – 5.5V (từ DQ) |
| Dòng tiêu thụ (active) | 1.5mA |
| Dòng tiêu thụ (standby) | 750nA |
| Dải nhiệt độ | -55°C – 125°C |
| Độ chính xác (±0.5°C) | -10°C – 85°C |
| Độ phân giải | 9–12-bit (cấu hình được) |
| Thời gian chuyển đổi (12-bit) | ≤ 750ms |
| ROM Code | 64-bit laser-engraved unique |
| Số sensor trên 1 bus | Nhiều (giới hạn bởi pull-up capacity) |
| Kích thước TO-92 (bare) | 4.4 × 3.7 × 2.8mm |
| Kích thước đầu dò chống nước | Thường ∅6mm × 30mm (tùy loại) |
| Chiều dài cáp đầu dò | 1m, 2m, 3m (tùy loại, màu đen) |
Sơ Đồ Chân (Pinout)
DS18B20 TO-92 (Bare Sensor)
Nhìn từ mặt phẳng (mặt có chữ):
GND DQ VDD
│ │ │
(1) (2) (3)
────────────
DS18B20
TO-92
| Chân | Tên | Chức năng |
|---|---|---|
| 1 | GND | Đất |
| 2 | DQ | Data / 1-Wire bus (cần pull-up 4.7kΩ lên VDD) |
| 3 | VDD | Nguồn 3.0V – 5.5V (hoặc nối GND cho parasite mode) |
Cách nhận biết chiều chân TO-92: Giữ sensor nhìn từ mặt phẳng (chữ hướng về phía bạn), chân trái là GND, giữa là DQ, phải là VDD.
Đầu Dò Chống Nước (Waterproof Probe)
Cáp 3 màu:
Đỏ → VDD (3.3V hoặc 5V)
Vàng → DQ (Data — cần pull-up)
Đen → GND
Đầu dò kim loại (thường là inox 304) bọc epoxy chống nước. Thực chất bên trong là DS18B20 TO-92 + R 4.7kΩ pull-up tích hợp trong vỏ nhựa đầu cáp.
Các Biến Thể Cùng Dòng
| Model | Đặc điểm | Dùng khi |
|---|---|---|
| DS18B20 TO-92 | Bare sensor nhỏ | Hàn trực tiếp PCB, prototype |
| DS18B20Z SOIC-8 | SMD package | PCB sản xuất hàng loạt |
| DS18B20 waterproof probe | Đầu dò kim loại, cáp 1–3m | Đo nhiệt độ nước, đất, chất lỏng |
| DS18S20 | Chỉ 9-bit, không cấu hình được | Đời cũ, không khuyến nghị dùng mới |
| MAX31820 | Tương thích 1-Wire, 3.3V | Dùng khi nguồn 3.3V đơn thuần |
Lưu ý DS18B20 giả (fake): Thị trường có nhiều DS18B20 không chính hãng. Dấu hiệu nhận biết: ROM không hợp lệ, đọc sai CRC, không hoạt động ở 3.3V, độ chính xác kém. Mua từ nhà phân phối uy tín.
Kết Nối Phần Cứng
Kết Nối với ESP32 DevKit V1
ESP32 DevKit V1 DS18B20
───────────────────── ─────────────────
3V3 ─────────────────→ VDD (chân 3)
GND ─────────────────→ GND (chân 1)
GPIO4 ────────────────→ DQ (chân 2)
Pull-up:
3V3 ──[R 4.7kΩ]──────→ DQ (chân 2)
Resistor pull-up 4.7kΩ BẮT BUỘC nếu dùng bare sensor. Module có sẵn thường đã tích hợp. Không có pull-up → bus luôn LOW → không đọc được.
Nhiều sensor trên 1 dây:
GPIO4 ──[R 4.7kΩ]── DQ ─┬─ DS18B20 #1 (DQ)
3V3 ─────────────────────┤
├─ DS18B20 #2 (DQ)
└─ DS18B20 #3 (DQ)
Tất cả GND nối chung, tất cả VDD nối chung với 3V3.
Kết Nối với Arduino Uno
Arduino Uno DS18B20
───────────────────── ─────────────────
5V ─────────────────→ VDD (chân 3)
GND ─────────────────→ GND (chân 1)
Pin 4 ────────────────→ DQ (chân 2)
5V ──[R 4.7kΩ]────────→ DQ (chân 2)
Code Arduino IDE
Cài Library
| Board | Library 1 | Library 2 |
|---|---|---|
| Arduino Uno + ESP32 | OneWire by Paul Stoffregen | DallasTemperature by Miles Burton |
Cả hai cần cài đặt. Trong Library Manager tìm “DallasTemperature” → Install → khi hỏi về dependency chọn “Install All” (tự cài OneWire).
Code cho Arduino Uno (1 Sensor)
/*
* DS18B20 - Đọc nhiệt độ 1 sensor
* Board: Arduino Uno
* Library: OneWire + DallasTemperature
* Kết nối: DQ → Pin 4, R 4.7kΩ từ DQ lên 5V, VDD → 5V, GND → GND
*/
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_PIN 4 // Chân DQ kết nối vào Arduino pin 4
// Khởi tạo bus 1-Wire trên pin 4
OneWire oneWire(ONE_WIRE_PIN);
// Khởi tạo DallasTemperature dùng bus 1-Wire vừa tạo
DallasTemperature sensors(&oneWire);
void setup() {
Serial.begin(9600);
sensors.begin(); // Quét bus 1-Wire, tìm các sensor DS18B20
// In số sensor tìm được trên bus
Serial.println("=== DS18B20 Test - Arduino Uno ===");
Serial.print("Số sensor tìm thấy: ");
Serial.println(sensors.getDeviceCount());
// Cấu hình độ phân giải 12-bit (mặc định) — 0.0625°C, 750ms
// Giảm xuống 9-bit nếu cần đọc nhanh hơn (93ms, 0.5°C resolution)
sensors.setResolution(12);
}
void loop() {
// Gửi lệnh CONVERT T tới TẤT CẢ sensor trên bus
// Dùng SKIP ROM → tất cả đồng thời chuyển đổi → tiết kiệm thời gian
sensors.requestTemperatures();
// Chờ đủ thời gian chuyển đổi (750ms cho 12-bit)
// Thư viện tự xử lý nếu không dùng setWaitForConversion(false)
delay(1000); // Dư giờ để chắc chắn
// Đọc nhiệt độ sensor đầu tiên (index = 0)
float tempC = sensors.getTempCByIndex(0);
// Kiểm tra lỗi: DEVICE_DISCONNECTED_C = -127.0
if (tempC == DEVICE_DISCONNECTED_C) {
Serial.println("LỖI: Không tìm thấy DS18B20!");
Serial.println(" → Kiểm tra: dây kết nối, R pull-up 4.7kΩ, chiều chân TO-92");
return;
}
Serial.print("Nhiệt độ: ");
Serial.print(tempC, 2); // 2 chữ số thập phân: "25.06 °C"
Serial.println(" °C");
Serial.println("---");
}
Code cho Arduino Uno (Nhiều Sensor — Dùng ROM Address)
/*
* DS18B20 - Đọc nhiều sensor trên cùng 1 dây
* Board: Arduino Uno
* Kết nối: Tất cả DQ nối chung vào Pin 4, R 4.7kΩ pull-up
*/
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_PIN 4
OneWire oneWire(ONE_WIRE_PIN);
DallasTemperature sensors(&oneWire);
// Mảng lưu địa chỉ ROM của từng sensor (8 byte mỗi sensor)
DeviceAddress sensorAddresses[10]; // Tối đa 10 sensor
int sensorCount = 0;
void setup() {
Serial.begin(9600);
sensors.begin();
sensorCount = sensors.getDeviceCount();
Serial.print("Tìm thấy ");
Serial.print(sensorCount);
Serial.println(" sensor DS18B20:");
// Lấy và in ROM address của từng sensor
for (int i = 0; i < sensorCount; i++) {
if (sensors.getAddress(sensorAddresses[i], i)) {
Serial.print(" Sensor ");
Serial.print(i);
Serial.print(": ROM = ");
// In ROM code dạng hex
for (int j = 0; j < 8; j++) {
if (sensorAddresses[i][j] < 0x10) Serial.print("0");
Serial.print(sensorAddresses[i][j], HEX);
if (j < 7) Serial.print(":");
}
Serial.println();
}
}
sensors.setResolution(12);
}
void loop() {
sensors.requestTemperatures(); // Đo tất cả cùng lúc
delay(1000);
for (int i = 0; i < sensorCount; i++) {
// Đọc theo ROM address — chính xác sensor nào là sensor nào
float tempC = sensors.getTempC(sensorAddresses[i]);
Serial.print("Sensor ");
Serial.print(i);
Serial.print(": ");
if (tempC == DEVICE_DISCONNECTED_C) {
Serial.println("NGẮT KẾT NỐI");
} else {
Serial.print(tempC, 2);
Serial.println(" °C");
}
}
Serial.println("---");
}
Code cho ESP32
/*
* DS18B20 - Đọc nhiệt độ
* Board: ESP32 DevKit V1
* Library: OneWire + DallasTemperature (cùng library với Arduino Uno)
* Kết nối: DQ → GPIO4, R 4.7kΩ từ DQ lên 3V3, VDD → 3V3, GND → GND
*
* Ưu điểm ESP32: có thể đọc DS18B20 không blocking nhờ millis()
*/
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_PIN 4 // GPIO4 — an toàn, không phải strapping pin
OneWire oneWire(ONE_WIRE_PIN);
DallasTemperature sensors(&oneWire);
// Biến cho non-blocking conversion
bool conversionRequested = false;
unsigned long conversionStartTime = 0;
const unsigned long CONVERSION_TIME_MS = 750; // 750ms cho 12-bit
void setup() {
Serial.begin(115200);
sensors.begin();
sensors.setResolution(12);
// Tắt blocking mode — requestTemperatures() trả về ngay, không chờ 750ms
// Phải tự chờ CONVERSION_TIME_MS trước khi đọc
sensors.setWaitForConversion(false);
Serial.println("=== DS18B20 Test - ESP32 ===");
Serial.printf("Số sensor: %d\n", sensors.getDeviceCount());
}
void loop() {
unsigned long now = millis();
// Bắt đầu chuyển đổi nếu chưa yêu cầu, hoặc đã qua đủ 1 chu kỳ
if (!conversionRequested) {
sensors.requestTemperatures(); // Không blocking vì setWaitForConversion(false)
conversionStartTime = now;
conversionRequested = true;
}
// Chờ đủ 750ms kể từ khi request (không dùng delay — không blocking)
if (conversionRequested && (now - conversionStartTime >= CONVERSION_TIME_MS)) {
conversionRequested = false; // Reset để chu kỳ tiếp theo request lại
// Đọc kết quả
float tempC = sensors.getTempCByIndex(0);
if (tempC == DEVICE_DISCONNECTED_C) {
Serial.println("LỖI: DS18B20 không kết nối!");
return;
}
Serial.printf("Nhiệt độ: %.2f °C\n", tempC);
// Ứng dụng: cảnh báo khi nhiệt độ vượt ngưỡng
if (tempC > 80.0f) {
Serial.println(" ⚠ CẢNH BÁO: Nhiệt độ quá cao!");
} else if (tempC < 0.0f) {
Serial.println(" ⚠ CẢNH BÁO: Nhiệt độ dưới 0°C!");
}
Serial.println("---");
// Chờ 1 giây trước chu kỳ tiếp theo (millis-based, không blocking)
delay(1000); // Đơn giản hóa — dùng millis() trong project thực
}
}
Kết Quả Mong Đợi
=== DS18B20 Test - ESP32 ===
Số sensor: 1
Nhiệt độ: 25.06 °C ← 12-bit resolution: bước 0.0625°C
---
Nhiệt độ: 25.13 °C
---
Khi nhúng vào nước lạnh: giá trị giảm dần trong 5–10 giây (thời gian đáp ứng phụ thuộc vỏ bọc đầu dò).
Ứng Dụng Thực Tế
| Ứng dụng | Tại sao DS18B20 | Ghi chú |
|---|---|---|
| Đo nhiệt độ nước | Đầu dò chống nước, 125°C | Không dùng DHT |
| Đo nhiệt độ đất | Đầu dò inox chống ăn mòn | Soil temp cho nông nghiệp |
| Nhiệt độ dầu máy | 125°C max — đủ cho nhiều ứng dụng | |
| Nhiều điểm đo (1 dây) | 1 GPIO cho nhiều sensor | Tòa nhà, nhà kính |
| Tủ đông / kho lạnh | -55°C — đo được âm sâu | |
| Kiểm soát nhiệt độ aquarium | Không rò điện, chính xác |
Lưu Ý Khi Sử Dụng
1. Pull-up 4.7kΩ là bắt buộc
1-Wire là open-drain — DS18B20 chỉ kéo bus xuống LOW, không đẩy lên HIGH. Không có pull-up → bus luôn LOW → không đọc được bất kỳ dữ liệu nào. Nếu dùng nhiều sensor hoặc cáp dài, giảm pull-up xuống 2.2kΩ để tăng tốc độ sườn lên (rise time).
2. Thời gian chờ 750ms
Ở độ phân giải 12-bit, DS18B20 cần 750ms để hoàn thành chuyển đổi. Đọc trước 750ms → nhận giá trị không hoàn chỉnh. Dùng setWaitForConversion(false) + millis() để không blocking toàn bộ chương trình.
3. Phân biệt nhiều sensor
Khi có nhiều sensor, đọc theo ROM address (không phải index). Index có thể thay đổi tùy thứ tự tìm kiếm trên bus. ROM address không thay đổi. Lần đầu chạy: in ROM của từng sensor → gắn nhãn vật lý → hardcode ROM vào code.
4. DS18B20 giả (clone) phổ biến
Dấu hiệu sensor giả: đọc -127°C, -127.00, hoặc 85°C (giá trị reset mặc định). Thử test với 5V (dù chạy ở 3.3V) — sensor giả thường không hoạt động ở 3.3V.
5. Cáp dài > 10m
Cần giảm pull-up xuống 1–2kΩ, thêm tụ 100nF từ DATA xuống GND tại điểm cuối dây để chống nhiễu. Cáp > 30m: cân nhắc dùng DS2482 (I2C to 1-Wire bridge).


