← До всіх проєктів
Сенсори Початковий

Десять термометрів на одному дроті: DS18B20 і шина 1-Wire

Водонепроникні датчики DS18B20 підключаються паралельно до одного GPIO. Міряємо температуру котла, бойлера, вулиці й кімнати одночасно та віддаємо все одним JSON.

Складність
Початковий
Час
1 h
Категорія
Сенсори

Чому DS18B20

  • Точність ±0.5 °C у діапазоні −10…+85 °C, загалом −55…+125 °C.
  • Продається у водонепроникній гільзі з кабелем 1–3 м — можна опускати у воду чи кріпити на трубу.
  • Кожен датчик має унікальну 64-бітну адресу, тому десятки датчиків можуть сидіти на одному дроті даних.

Компоненти

  • ESP32 DevKit
  • 2–10 датчиків DS18B20 (краще у гільзі)
  • Резистор 4.7 кОм — один на всю шину

Підключення

Усі датчики підключаються паралельно:

DS18B20 ESP32
Червоний (VDD) 3V3
Чорний (GND) GND
Жовтий (DATA) GPIO 4 + 4.7 кОм до 3V3

Для кабелів довше 10 м зменште резистор до 2.2 кОм і використовуйте виту пару.

Бібліотеки

  • OneWire
  • DallasTemperature

Код

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

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

const char* WIFI_SSID = "YOUR_SSID";
const char* WIFI_PASS = "YOUR_PASSWORD";

const int ONE_WIRE_PIN = 4;
const int MAX_SENSORS = 10;

OneWire oneWire(ONE_WIRE_PIN);
DallasTemperature sensors(&oneWire);
WebServer server(80);

DeviceAddress addrs[MAX_SENSORS];
float temps[MAX_SENSORS];
int count = 0;
bool converting = false;
unsigned long requestedAt = 0;
unsigned long lastCycle = 0;

String addrToString(const uint8_t *a) {
  char buf[17];
  for (int i = 0; i < 8; i++) sprintf(buf + i * 2, "%02X", a[i]);
  return String(buf);
}

void handleData() {
  String json = "[";
  for (int i = 0; i < count; i++) {
    if (i) json += ",";
    json += "{\"id\":\"" + addrToString(addrs[i]) + "\",\"t\":";
    json += temps[i] == DEVICE_DISCONNECTED_C ? String("null") : String(temps[i], 2);
    json += "}";
  }
  json += "]";
  server.send(200, "application/json", json);
}

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

  count = sensors.getDeviceCount();
  if (count > MAX_SENSORS) count = MAX_SENSORS;
  Serial.printf("Found %d sensor(s)\n", count);

  for (int i = 0; i < count; i++) {
    sensors.getAddress(addrs[i], i);
    sensors.setResolution(addrs[i], 12);   // 0.0625 °C, ~750 мс на вимір
    temps[i] = DEVICE_DISCONNECTED_C;
    Serial.println("  " + addrToString(addrs[i]));
  }
  sensors.setWaitForConversion(false);

  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) delay(500);
  Serial.println(WiFi.localIP());

  server.on("/data", handleData);
  server.begin();
}

void loop() {
  server.handleClient();

  if (!converting && millis() - lastCycle > 5000) {
    sensors.requestTemperatures();   // усі датчики міряють одночасно
    requestedAt = millis();
    converting = true;
  }
  if (converting && millis() - requestedAt > 800) {
    for (int i = 0; i < count; i++) {
      temps[i] = sensors.getTempC(addrs[i]);
      Serial.printf("%s: %.2f °C\n", addrToString(addrs[i]).c_str(), temps[i]);
    }
    converting = false;
    lastCycle = millis();
  }
}

Як дізнатися, де який датчик

Порядок, у якому бібліотека знаходить датчики, не збігається з порядком підключення. Тож:

  1. Підключіть датчики й відкрийте Serial Monitor — там буде список адрес.
  2. Затисніть один датчик у долоні — його температура зросте.
  3. Підпишіть адресу (наприклад, 28FF4A1B... → «котел, подача»).

Надалі в Home Assistant чи іншій системі прив'язуйтеся саме до адрес — вони не змінюються.

Проблеми

  • −127 °C — датчик не відповідає: перевірте контакт і резистор 4.7 кОм.
  • 85 °C одразу після ввімкнення — це значення за замовчуванням, вимір ще не завершився.
  • Знаходить не всі датчики на довгій лінії — зменште резистор, приберіть «зірку» (підключайте ланцюжком).

Ідеї

  • Моніторинг опалення: подача/зворотка котла і різниця температур.
  • Контроль морозильної камери з Telegram-сповіщенням при > −12 °C.
  • Акваріумний термостат з реле обігрівача.