Bir ESP32 DS18B20 MQTT kurulumu, tek bir GPIO pininin çok sayıda su geçirmez sıcaklık probunu okumasını ve her birini kendi topic'ine yayınlamasını sağlar. Bu eğitimde birden fazla DS18B20 sensörünü tek bir 1-Wire hattına bağlayacak, onları ROM adresleriyle tanımlayacak, MQTT istemcisini bloklamadan okuyacak ve prob başına bir topic ile broker.connectmq.com'a yayınlayacaksınız.
DS18B20 Çok Noktalı İzleme İçin Neden İdealdir
DS18B20, fabrikada yakılmış benzersiz 64 bitlik bir ROM adresine sahip dijital bir sıcaklık sensörüdür. Her probun kendi adresi olduğu için düzinelercesi aynı üç kabloyu paylaşabilir: güç, toprak ve veri. Bu da onu şu işler için ideal kılar:
- Bir ısıtma sistemindeki gidiş ve dönüş sıcaklıkları.
- Bir buzdolabındaki veya soğuk odadaki birkaç raf.
- Tek bir denetleyiciden akvaryum, havuz ve ortam havası ölçümleri.
- Batarya paketi veya kabin içi sıcak nokta izleme.
Paslanmaz çelik su geçirmez sürümler ucuz ve dayanıklıdır; tipik aralıkta yaklaşık yarım derecelik bir doğruluğa sahiptir. Bedeli hızdır: tam 12 bitlik bir dönüşüm 750 ms'ye kadar sürer; bu yüzden MQTT devreye girdiğinde bloklamayan okumalar önem kazanır.
Parçalar ve Kütüphaneler
- Bir ESP32 geliştirme kartı.
- İki veya daha fazla DS18B20 sensörü (TO-92 veya su geçirmez prob).
- Hat pull-up'ı için bir adet 4,7 kOhm direnç.
- esp32 kart paketiyle Arduino IDE 2.x.
- Kütüphaneler: OneWire (Paul Stoffregen'in veya ESP32 için paketlenen bakımlı fork'u), Miles Burton'ın DallasTemperature kütüphanesi ve PubSubClient.
Birden Fazla Probu Tek Bir ESP32 Pinine Bağlamak
Tüm problar paralel bağlanır:
| Prob kablosu (tipik renkler) | Bağlandığı yer | Notlar |
|---|---|---|
| Kırmızı (VDD) | ESP32 3V3 | Parazit modu değil, normal güç kullanın |
| Siyah (GND) | ESP32 GND | |
| Sarı (DATA) | ESP32 GPIO 4 | Tüm hat için DATA'dan 3V3'e bir adet 4,7 kOhm direnç |
Hat için yalnızca bir pull-up direnci kullanın ve onu ESP32'nin yakınına yerleştirin. Kablo renkleri tedarikçiye göre değişir; bu yüzden problarınızın veri sayfasını kontrol edin. Birkaç metreden uzun hatlarda bükümlü çift kablo kullanın, yıldız yerine doğrusal bir hat yapısı koruyun ve 2,2 kOhm gibi daha güçlü bir pull-up düşünün.
Prob Başına Topic Düzeni
Her prob, ROM adresini içeren bir topic'e yayın yapar; böylece hattın hangi sırayla taranacağından bağımsız olarak topic'ler sabit kalır:
| Topic | Retained | Örnek payload |
|---|---|---|
connectmq/demo/dsb2q6h/ds18b20/28ff641e8316034f/temperature |
Evet | 21.62 |
connectmq/demo/dsb2q6h/ds18b20/summary |
Hayır | {"28ff641e8316034f":21.62,"28aa1b2c3d4e5f60":4.12} |
connectmq/demo/dsb2q6h/status |
Evet | online / offline |
Prob başına topic'ler retained'dır; böylece daha sonra açılan bir dashboard her probun son değerini anında gösterir. Özet topic'i, döngü başına tek bir mesaj isteyen tüketiciler için kullanışlıdır. Her ikisi de herkese açık alanda izin verilen sekiz topic seviyesi sınırının içinde kalır.
ESP32 DS18B20 MQTT Sketch'i
#include <WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
const char* WIFI_SSID = "YOUR_WIFI_SSID";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";
const char* MQTT_HOST = "broker.connectmq.com";
const uint16_t MQTT_PORT = 1883;
const char* PREFIX = "connectmq/demo/dsb2q6h"; // kendi rastgele kimliğinizi kullanın
const uint8_t ONE_WIRE_PIN = 4;
const uint8_t MAX_PROBES = 10;
const uint32_t INTERVAL_MS = 10000;
const uint32_t CONVERSION_MS = 750; // 12 bit çözünürlük
OneWire oneWire(ONE_WIRE_PIN);
DallasTemperature sensors(&oneWire);
WiFiClient net;
PubSubClient mqtt(net);
DeviceAddress probes[MAX_PROBES];
char probeIds[MAX_PROBES][17];
uint8_t probeCount = 0;
String clientId, topicStatus;
unsigned long lastRequest = 0;
bool conversionPending = false;
void addressToHex(const DeviceAddress addr, char* out) {
for (uint8_t i = 0; i < 8; i++) sprintf(out + i * 2, "%02x", addr[i]);
out[16] = '\0';
}
void discoverProbes() {
sensors.begin();
probeCount = 0;
uint8_t found = sensors.getDeviceCount();
for (uint8_t i = 0; i < found && probeCount < MAX_PROBES; i++) {
if (sensors.getAddress(probes[probeCount], i)) {
sensors.setResolution(probes[probeCount], 12);
addressToHex(probes[probeCount], probeIds[probeCount]);
Serial.printf("Probe %u: %s\n", probeCount, probeIds[probeCount]);
probeCount++;
}
}
sensors.setWaitForConversion(false); // bloklamadan kendimiz bekliyoruz
Serial.printf("%u probe(s) found\n", probeCount);
}
void connectWifi() {
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) delay(400);
Serial.printf("Wi-Fi OK, IP %s\n", WiFi.localIP().toString().c_str());
}
void connectMqtt() {
while (!mqtt.connected()) {
if (mqtt.connect(clientId.c_str(), topicStatus.c_str(), 1, true, "offline")) {
mqtt.publish(topicStatus.c_str(), "online", true);
Serial.println("MQTT connected");
} else {
Serial.printf("MQTT failed, state %d\n", mqtt.state());
delay(5000);
}
}
}
void publishReadings() {
String summary = "{";
for (uint8_t i = 0; i < probeCount; i++) {
float c = sensors.getTempC(probes[i]);
bool valid = (c != DEVICE_DISCONNECTED_C) && (c != 85.0f); // 85.0 = açılış değeri
String topic = String(PREFIX) + "/ds18b20/" + probeIds[i] + "/temperature";
char value[16];
if (valid) snprintf(value, sizeof(value), "%.2f", c);
else snprintf(value, sizeof(value), "error");
mqtt.publish(topic.c_str(), value, true);
if (i) summary += ",";
summary += "\"" + String(probeIds[i]) + "\":" + (valid ? String(value) : String("null"));
}
summary += "}";
String topic = String(PREFIX) + "/ds18b20/summary";
mqtt.publish(topic.c_str(), summary.c_str());
Serial.println(summary);
}
void setup() {
Serial.begin(115200);
discoverProbes();
clientId = "esp32-ds18b20-" + String((uint32_t)ESP.getEfuseMac(), HEX);
topicStatus = String(PREFIX) + "/status";
connectWifi();
mqtt.setServer(MQTT_HOST, MQTT_PORT);
mqtt.setBufferSize(1024); // 10 proba kadar özet için yer
connectMqtt();
}
void loop() {
if (WiFi.status() != WL_CONNECTED) connectWifi();
if (!mqtt.connected()) connectMqtt();
mqtt.loop(); // dönüşümler sırasında çalışmaya devam eder
unsigned long now = millis();
if (!conversionPending && now - lastRequest >= INTERVAL_MS) {
sensors.requestTemperatures(); // tüm problarda dönüşümü aynı anda başlatır
lastRequest = now;
conversionPending = true;
}
if (conversionPending && now - lastRequest >= CONVERSION_MS) {
conversionPending = false;
publishReadings();
}
}
Probları Test Etmek
Tüm öneke subscribe olun:
mosquitto_sub -h broker.connectmq.com -p 1883 -i ds-view-2q6h -t "connectmq/demo/dsb2q6h/#" -v
Bir probu elinizde tutun ve diğerleri sabit kalırken onun topic'inin yükselişini izleyin. Bu aynı zamanda hangi fiziksel probun hangi ROM adresine sahip olduğunu bulmanın en hızlı yoludur: ilerledikçe her kabloyu etiketleyin. Herkese açık test alanının herkes tarafından görülebildiğini unutmayın; gerçek izlemeden çok denemeler için uygundur. Sınırları için ücretsiz herkese açık MQTT broker sayfasına bakın.
Bloklamayan Okuma Nasıl Çalışır
requestTemperatures() her proba aynı anda tek bir "dönüştür" komutu gönderir; bu yüzden on prob, bir probla aynı 750 ms'yi alır. setWaitForConversion(false) ile çağrı hemen döner ve problar çalışırken döngü mqtt.loop() çağırmaya devam eder. Sketch, her probu adresiyle ancak dönüşüm süresi geçtikten sonra okur; bu da prob başına birkaç milisaniye sürer.
0,0625 derecelik adımlara ihtiyacınız yoksa çözünürlüğü düşürün. 10 bitte dönüşüm yaklaşık 188 ms sürer ve adım boyutu 0,25 derece olur; bu da oda veya buzdolabı izleme için fazlasıyla yeterlidir.
Problara Anlaşılır İsimler Vermek
ROM adresleri sabittir ancak okunabilir değildir. İki yaklaşım iyi çalışır:
- Firmware'de eşleme.
flow,returnveyafreezergibi adres-isim eşlemesini içeren küçük bir tablo tutun ve ismi topic'te kullanın. Basittir, ancak her prob değişikliği firmware'in yeniden yüklenmesi anlamına gelir. - Sonraki katmanda eşleme. Adresi topic'te tutun ve örneğin bir Node-RED akışı veya dashboard gibi tüketicinin adresleri isimlere çevirmesine izin verin. Bu durumda bir probu değiştirmek firmware'i değil, tek bir eşlemeyi düzenlemek demektir.
İkinci yaklaşım daha iyi ölçeklenir. Ayrıca bir Modbus RS485 gateway'inin genellikle ham register kimliklerini yayınlayıp anlam atamayı daha üst bir katmana bırakma biçimiyle de örtüşür.
Arızalı veya Eksik Bir Probu Tespit Etmek
Sessizce rapor vermeyi bırakan bir prob, hata bildiren bir probdan daha kötüdür; çünkü retained bir topic son iyi değeri sonsuza kadar göstermeye devam eder. Sketch bunu iki şekilde ele alır. Birincisi, okuma -127 veya 85 döndürdüğünde probun retained topic'ine error string'ini yayınlar; böylece bayat sayının üzerine yazılır. İkincisi, özet mesajı o prob için null içerir; çoğu tüketici bunu sıfır değil bir boşluk olarak değerlendirir.
Daha da ileri giderek açılışta bulunan prob sayısını örneğin retained bir ds18b20/count topic'ine yayınlayabilir ve dashboard'unuzda beklenen sayıyla karşılaştırabilirsiniz. Bir kablo kesilirse sayı bir sonraki yeniden keşifte düşer ve fark açıkça görülür. Kritik kullanımlar için mesaj yaşını da izleyin: bir prob topic'i üç aralık boyunca değişmediyse, durumu hâlâ online görünse bile cihazı sağlıksız kabul edin.
Sorun Giderme Kontrol Listesi
| Belirti | Neden | Çözüm |
|---|---|---|
| 0 prob bulundu | Eksik pull-up veya yanlış pin | DATA ile 3V3 arasına 4,7 kOhm ekleyin, ONE_WIRE_PIN değerini kontrol edin |
| -127 okuması | Prob bağlantısı kopuk veya gürültülü hat | Bağlantı noktalarını kontrol edin, kabloyu kısaltın, pull-up değerini düşürün |
| 85.0 okuması | Dönüşüm bitmeden okundu veya güç dalgalanması | 750 ms beklemeyi koruyun, normal güç kullanın |
| Uzun hatlarda bazı problar eksik | Yıldız bağlantı veya fazla kapasitans | Bükümlü çiftle doğrusal bir hat kullanın |
| Özet mesajı eksik | Payload tampondan büyük | setBufferSize değerini artırın |
| Problar yalnızca yeniden başlatmadan sonra bulunuyor | Çalışırken takılan prob | discoverProbes() fonksiyonunu periyodik olarak veya komutla çağırın |
Production Kurulumu
Problar dondurucu gibi önemli bir şeyi koruyorsa kimlik doğrulamalı bir broker'a geçin. app.connectmq.com adresinde bir tane oluşturun, ISRG Root X1 sertifikasıyla 8883 portunda WiFiClientSecure kullanmaya geçin ve YOUR_CLIENT_ID, YOUR_USERNAME ve YOUR_PASSWORD ile bağlanın. ConnectMQ portalında dondurucu probunun topic'ine bir eşik uyarı kuralı ekleyin; böylece backend kodu yazmadan temel bir aşırı sıcaklık alarmınız olur. Sıcaklığın yanında güç de ölçüyorsanız SCT-013 enerji izleyici uyumlu bir düzende yayın yapar; ESP32 DHT22 projesi ise tek bir noktada nem ölçümü ekler.
ConnectMQ ile Başlayın
Çok problu izleme, bir prob eşiği aştığında her zaman yerinde olan bir broker gerektirir. ConnectMQ; TLS, retained mesajlar, canlı topic gezgini ve uyarı kuralları sunan tam yönetilen bir MQTT servisidir ve ücretsiz Serverless plan kredi kartı gerektirmez. Bu sketch'i kendi broker'ınıza yönlendirin ve bir sonraki proje için ESP32 IoT eğitimi merkezine göz atın.
Sık Sorulan Sorular
Bir ESP32 pini kaç DS18B20 sensörünü yönetebilir?
Protokol hat başına çok sayıda cihaza izin verir ve iyi kablolama ile normal güçle on ila yirmi cihaz güvenilir şekilde çalışır. Adres alanından çok daha önce kablo uzunluğu ve topoloji sizi sınırlar.
Bir DS18B20 neden bazen 85 derece okur?
85.0, scratchpad'in açılış (power-on reset) değeridir. Okuma bir dönüşüm tamamlanmadan önce gerçekleştiğinde, genellikle bir güç dalgalanmasından sonra ortaya çıkar. Bunu bir hata olarak değerlendirin.
Her probun kendi MQTT topic'i olmalı mı?
Prob başına retained topic'ler dashboard'ları basitleştirir ve son değeri erişilebilir tutar. Döngü başına bir özet mesajı, tüm değerleri bir arada isteyen tüketiciler için yararlı bir eklemedir.
Bir kablodan tasarruf etmek için parazit güç kullanabilir miyim?
Kullanabilirsiniz, ancak uzun hatlarda ve çok sayıda probla daha az güvenilirdir. Mümkün olduğunda üç kablolu normal güç kullanın.



