ESP32 ile DHT11 Sensörü ve OLED Ekran Kullanımı

Giriş

Bu rehber, ESP32 geliştirme kartı kullanarak DHT11 sıcaklık ve nem sensöründen okunan verileri SSD1306 OLED ekran üzerinde görüntüleme işlemini adım adım açıklar. I2C iletişim protokolü ile OLED ekranın kontrol edilmesi ve DHT kütüphanesi ile sensör verilerinin okunması prensibine dayanan bu proje, sensör entegrasyonu, harici kütüphane kullanımı ve grafik ekran programlama konularını öğrenmek için temel bir uygulamadır.

Adım 1 – Bileşenleri Tanıyın

DHT11 Sıcaklık ve Nem Sensörü

DHT11, ortam sıcaklığını ve bağıl nem oranını ölçebilen dijital bir sensördür. Dört bağlantı ucu bulunur (bazı modüllerde üç pin bulunur):

  • VCC: Güç beslemesi (3.3V veya 5V)
  • GND: Toprak bağlantısı
  • DATA: Tek hat üzerinden dijital veri çıkışı
  • NC: Bağlantısız pin (kullanılmaz)

Sensör, sıcaklık ölçüm aralığı 0-50°C (±2°C hassasiyet), nem ölçüm aralığı %20-90 (±5% hassasiyet) değerlerine sahiptir.

SSD1306 OLED Ekran (i2c)

SSD1306 sürücülü OLED ekran, düşük güç tüketimi ve yüksek kontrast oranı ile karakter ve grafik görüntüleme için uygun bir display modülüdür. I2C iletişim protokolü kullanır ve dört bağlantı ucu bulunur:

  • VCC: Güç beslemesi (3.3V veya 5V)
  • GND: Toprak bağlantısı
  • SCL: I2C saat sinyali (Clock)
  • SDA: I2C veri sinyali (Data)

Ekranda 128×64 piksel çözünürlük bulunur ve I2C adresi genellikle 0x3C veya 0x3D’dir.

SSD1306 OLED Ekran (SPI)

Bu ekran türü boyut olarak i2c OLED ile aynıdır. Ancak pin sayısı 6 veya 7 olabilmektedir. Temelde haberleşme yöntemi değişmektedir. Ancak kodlarda büyük bir değişiklik olmamaktadır.

Bu ekran için <SPI.h> kütüphanesi kurulmalıdır. Bazen SCK – SDA yerine D0-D1 yazabilir bu durumda aşağıdaki resim dikkate alınmalıdır.

Gerekli Kütüphaneler

Projede kullanılan kütüphaneler:

  • Wire.h: ESP32’nin dahili I2C iletişim kütüphanesi
  • Adafruit_GFX.h: Grafik çizim fonksiyonlarını sağlayan temel kütüphane
  • Adafruit_SSD1306.h: SSD1306 OLED ekran sürücü kütüphanesi
  • DHT.h: DHT11/DHT22 sensörleri için okuma fonksiyonları içeren kütüphane

Kütüphaneye SSD1306 kurulumu yapılmalıdır. Versiyon farklılıkları olabilir.

Adım 2 – GPIO Pin Atamaları

Projede kullanılan pin atamaları:

  • GPIO 2: DHT11 sensör DATA pini için dijital giriş/çıkış pini
  • GPIO 21 (SDA): OLED ekran I2C veri pini (ESP32 varsayılan I2C SDA)
  • GPIO 22 (SCL): OLED ekran I2C saat pini (ESP32 varsayılan I2C SCL)

Not: ESP32’de I2C pinleri yazılımsal olarak herhangi bir GPIO’ya atanabilir; bu projede varsayılan pinler kullanılmıştır.

Adım 3 – Devre Bağlantısı

Eğer ekranınız SPI ise aşağıdaki gibi OLED bağlantısı yapabilirsiniz. Bu durumda DHT11 bağlantılarında bir değişiklik olmayacaktır. Bazı OLED ekranları 6 pinlidir. 6 pinli olanlarda genellikle CS ucu bulunmaz. Bu uç boş bırakılabilir.

DHT11 Sensör Bağlantısı:

  1. DHT11 VCC pinini ESP32 3.3V pinine bağlayın.
  2. DHT11 GND pinini ESP32 GND pinine bağlayın.
  3. DHT11 DATA pinini ESP32 GPIO 2 pinine bağlayın.
  4. Opsiyonel: DATA ve VCC arasına 10kΩ pull-up direnç ekleyin (bazı modüllerde dahili bulunur).

SSD1306 OLED Ekran Bağlantısı:

  1. OLED VCC pinini ESP32 3.3V pinine bağlayın.
  2. OLED GND pinini ESP32 GND pinine bağlayın.
  3. OLED SCL pinini ESP32 GPIO 22 (SCL) pinine bağlayın.
  4. OLED SDA pinini ESP32 GPIO 21 (SDA) pinine bağlayın.

Not: OLED ekranın I2C adresini kontrol etmek için I2C Scanner sketch’i kullanılabilir. Varsayılan adres 0x3C’dir; çalışmazsa 0x3D deneyin.

Not: Eğer SPI Oled varsa üstte verilen şekildeki bağlantı kurulabilir.

Adım 4 – Arduino IDE Hazırlığı

Arduino IDE’yi açın ve aşağıdaki kütüphaneleri Kütüphane Yöneticisi üzerinden yükleyin:

  • Adafruit SSD1306: “Adafruit SSD1306” araması ile yükleyin
  • Adafruit GFX Library: “Adafruit GFX Library” araması ile yükleyin (SSD1306 bağımlılığı)
  • DHT sensor library: “DHT sensor library” araması ile yükleyin (Adafruit versiyonu)
  • Adafruit Unified Sensor: “Adafruit Unified Sensor” araması ile yükleyin (DHT bağımlılığı)

Ayrıca aşağıdaki kart ayarlarını kontrol edin:

  • Board: ESP32 geliştirme kartınızın modeli (Örn: DOIT ESP32 DEVKIT V1)
  • Port: ESP32’nin bağlı olduğu COM portu
  • ESP32 Paketi: Board Manager’dan “esp32” paketinin yüklü olduğundan emin olun

Adım 5 – Kodu Yükleyin

Aşağıdaki kodu Arduino IDE editörüne yapıştırın ve ESP32 kartınıza yükleyin. Bu kod i2c ekranlar için uygundur.

#include <Wire.h> // Wire kütüphanesi: I2C iletişim protokolü için dahili ESP32 kütüphanesi
#include <Adafruit_GFX.h> // Grafik çizim fonksiyonları (yazı, şekil, bitmap) sağlar
#include <Adafruit_SSD1306.h> // SSD1306 sürücülü OLED ekranları kontrol eder

// DHT kütüphanesi: DHT11/DHT22 sensörlerinden sıcaklık ve nem okuma fonksiyonları içerir
#include <DHT.h>

// OLED ekranın piksel çözünürlük değerlerini tanımla
#define SCREEN_WIDTH 128  // OLED ekran genişliği: 128 piksel
#define SCREEN_HEIGHT 64  // OLED ekran yüksekliği: 64 piksel

#define DHT11_PIN 2  // GPIO2 pini DHT11 sensör veri hattına bağlanır

// Parametreler: genişlik, yükseklik, I2C nesnesi (&Wire), reset pini (-1 = yok)
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); // oled nesnesi oluştur

// Parametreler: veri pini, sensör tipi (DHT11 veya DHT22) // DHT nesnesi oluştur
DHT dht11(DHT11_PIN, DHT11);

// Sıcaklık ve nem verilerini saklamak için String değişkenleri tanımla
String temperature;  // Sıcaklık değerini metin olarak tutar
String humidity;     // Nem değerini metin olarak tutar

// Kurulum fonksiyonu: reset atıldığında bir kez çalışır
void setup() {
  // Serial iletişim hızını 9600 baud olarak başlat

  Serial.begin(9600);

  // OLED ekranı I2C üzerinden başlat
  // Parametreler: voltaj kaynağı (SSD1306_SWITCHCAPVCC), I2C adresi (0x3C)
  // begin() fonksiyonu false döndürürse ekran bulunamadı demektir
  if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    // OLED başlatılamadıysa Serial Monitor'e hata mesajı yaz
    Serial.println(F("SSD1306 allocation failed"));
    // Sonsuz döngü ile programı burada durdur (hatanın devam etmemesi için)
    while (true)
      ;
  }

  // OLED ekranın tamamen açılması ve stabilize olması için 2 saniye bekle
  delay(2000);

  // OLED ekranın tampon belleğini temizle (ekranı boşalt)
  oled.clearDisplay();

  // Metin boyutunu ayarla: 1=normal, 2=2x büyük, 3=3x büyük vb.
  oled.setTextSize(3);

  // Metin rengini beyaz (WHITE) olarak ayarla
  // OLED monokrom olduğu için sadece WHITE veya BLACK kullanılabilir
  oled.setTextColor(WHITE);

  // İmleç konumunu ayarla: (x=0, y=10) koordinatlarından itibaren yazmaya başla
  oled.setCursor(0, 10);

  // DHT11 sensörünü başlat ve okumaya hazırla
  dht11.begin();

  // String değişkenleri için hafızada önceden yer ayır
  temperature.reserve(10);
  humidity.reserve(10);
}

// Ana döngü fonksiyonu: sürekli tekrarlanır
void loop() {
  // DHT11 sensöründen bağıl nem değerini oku (float tipinde, % cinsinden)
  float humi = dht11.readHumidity();

  // DHT11 sensöründen sıcaklık değerini oku (float tipinde, Celsius cinsinden)
  float tempC = dht11.readTemperature();

  // Okuma işleminin başarılı olup olmadığını kontrol et
  // isnan(): "is not a number" - geçersiz/okunamayan değer için true döner
  if (isnan(humi) || isnan(tempC)) {
    // Okuma başarısızsa ekranda "Failed" mesajı göster
    temperature = "Failed";
    humidity = "Failed";
  } else {
    // Sıcaklık değerini String'e dönüştür: 1 ondalık basamak ile for
    temperature = String(tempC, 1);
    // Sıcaklık değerine derece sembolü (°) ekle: char(247) = ASCII derece karakteri
    temperature += char(247);
    // Sıcaklık birimi olarak "C" (Celsius) ekle
    temperature += "C";

    // Nem değerini String'e dönüştür: 1 ondalık basamak ile formatla
    humidity = String(humi, 1);
    // Nem değerine yüzde işareti (%) ekle
    humidity += "%";
  }

  // Sıcaklık ve nem değerlerini Serial Monitor'e yazdır
  Serial.print(tempC);      // Sıcaklık sayısal değerini yaz
  Serial.print("°C | ");    // Birim ve ayraç ekle
  Serial.print(humi);       // Nem sayısal değerini yaz
  Serial.println("%");      // Birim ekle ve satır sonu yap

  // OLED ekranda sıcaklık ve nem değerlerini merkezli olarak görüntüle
  oledDisplayCenter(temperature, humidity);
}

// OLED ekranda metinleri yatay ve dikey olarak ortalamak için yardımcı fonksiyon
// Parametreler: temperature (sıcaklık metni), humidity (nem metni)
void oledDisplayCenter(String temperature, String humidity) {
  // Metin sınırlarını ve boyutlarını saklamak için değişkenleri tanımla
  int16_t x1;      // Metin başlangıç X koordinatı (kullanılmıyor)
  int16_t y1;      // Metin başlangıç Y koordinatı (kullanılmıyor)
  uint16_t width_T;  // Sıcaklık metninin piksel cinsinden genişliği
  uint16_t height_T; // Sıcaklık metninin piksel cinsinden yüksekliği
  uint16_t width_H;  // Nem metninin piksel cinsinden genişliği
  uint16_t height_H; // Nem metninin piksel cinsinden yüksekliği

  // Sıcaklık metninin boyutlarını hesapla
  // getTextBounds(): Metnin kapladığı alanı piksel cinsinden döndürür
  oled.getTextBounds(temperature, 0, 0, &x1, &y1, &width_T, &height_T);

  // Nem metninin boyutlarını hesapla
  // Not: Orijinal kodda sıcaklık metni tekrar hesaplanmış; burada humidity kullanılmalı
  oled.getTextBounds(humidity, 0, 0, &x1, &y1, &width_H, &height_H);

  // OLED tampon belleğini temizle: Önceki içeriği sil, yeni içeriğe hazırla
  oled.clearDisplay();

  // Sıcaklık metnini yatay ve dikey olarak ekranın üst yarısında ortala
  // Yatay ortalama: (Ekran genişliği - Metin genişliği) / 2
  // Dikey konum: Ekran yüksekliği / 2 - metin yüksekliği - 5 piksel ofset
  oled.setCursor((SCREEN_WIDTH - width_T) / 2, SCREEN_HEIGHT / 2 - height_T - 5);
  oled.println(temperature);  // Sıcaklık metnini tampona yaz

  // Nem metnini yatay ve dikey olarak ekranın alt yarısında ortala
  // Yatay ortalama: (Ekran genişliği - Metin genişliği) / 2
  // Dikey konum: Ekran yüksekliği / 2 + 5 piksel ofset
  oled.setCursor((SCREEN_WIDTH - width_H) / 2, SCREEN_HEIGHT / 2 + 5);
  oled.println(humidity);  // Nem metnini tampona yaz

  // Tampon bellekteki içeriği fiziksel OLED ekrana yansıt
  // display() çağrılana kadar değişiklikler ekranda görünmez
  oled.display();
}

SPI ekranlar için aşağıdaki gibi bir uygulama yapabilirsiniz.

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <SPI.h>

// Ekran boyutları
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

// SPI Pin Tanımlamaları
#define OLED_MOSI   23  // SDA ucu buraya
#define OLED_CLK    18  // SCK ucu buraya
#define OLED_DC      2  // DC ucu buraya
#define OLED_CS      5  // CS ucu (varsa) buraya, yoksa 5 kalsın sorun olmaz
#define OLED_RESET   4  // RES ucu buraya

// Ekran objesini SPI modunda başlatıyoruz
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

void setup() {
  Serial.begin(115200);
  Serial.println("OLED Baslatiliyor...");

  // Ekranı başlat (SPI ekranlarda I2C adresi kullanılmaz)
  if(!display.begin(SSD1306_SWITCHCAPVCC)) {
    Serial.println(F("SSD1306 bulunamadi! Baglantilari kontrol et."));
    for(;;); // Hata varsa burada kalsın
  }

  // Başlangıç animasyonunu temizle
  display.clearDisplay();
  
  // Ekrana yazı yazalım
  display.setTextSize(1);           // Küçük yazı
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0,0);
  display.println("ESP32 + SPI OLED");
  
  display.setTextSize(2);           // Orta boy yazı
  display.setCursor(0, 25);
  display.println("CALISIYOR!");

  // Çizgi çizelim (Görsel test için)
  display.drawLine(0, 50, 127, 50, SSD1306_WHITE);

  // ÖNEMLİ: Bu komut olmadan ekrana hiçbir şey gelmez!
  display.display();
  
  Serial.println("Ekran basariyla acildi.");
}

void loop() {
  // Burası boş kalabilir, setup ekranı açmaya yeterlidir.
}

SPI haberleşmeli örnek i2c için yazdığım örnekten farklıdır. Geçişi siz sağlayabilirsiniz.

Kod Nasıl Çalışır

Kütüphane ve Tanımlar

  • #include direktifleri ile gerekli kütüphaneler projeye dahil edilir; I2C, grafik çizim, OLED sürücü ve sensör okuma fonksiyonları sağlanır.
  • #define direktifleri ile ekran çözünürlüğü ve sensör pini sabit olarak tanımlanır; kodun okunabilirliği ve bakımı kolaylaşır.
  • Adafruit_SSD1306 oled(...) ve DHT dht11(...): OLED ekran ve sensör için nesne örnekleri oluşturulur.

Setup Fonksiyonu

  • Serial.begin(9600): Serial iletişim başlatılır; sensör verilerini izlemek ve hata ayıklama için kullanılır.
  • oled.begin(...): OLED ekran I2C üzerinden başlatılır; başlatma başarısız olursa hata mesajı Serial Monitor’e yazılır ve program durur.
  • oled.setTextSize(), setTextColor(), setCursor(): OLED ekranında kullanılacak metin stil parametreleri yapılandırılır.
  • dht11.begin(): DHT11 sensörü okumaya hazırlanır.
  • temperature.reserve(), humidity.reserve(): String değişkenleri için önceden hafıza ayrılır; dinamik bellek kullanımında parçalanma riski azaltılır.

Loop Fonksiyonu

  • dht11.readHumidity() ve dht11.readTemperature(): DHT11 sensöründen nem ve sıcaklık değerleri okunur.
  • isnan() kontrolü: Okuma işlemi başarısız olursa ekranda “Failed” mesajı gösterilir.
  • String(tempC, 1): Sayısal değerler 1 ondalık basamakla formatlanarak metne dönüştürülür.
  • char(247): ASCII kodu 247 olan derece sembolü (°) sıcaklık değerine eklenir.
  • Serial.print/println: Gerçek zamanlı veri izleme için değerler Serial Monitor’e yazdırılır.
  • oledDisplayCenter(): Sıcaklık ve nem metinleri OLED ekranda ortalanarak görüntülenir.

oledDisplayCenter Fonksiyonu

  • getTextBounds(): Metnin piksel cinsinden genişlik ve yükseklik değerlerini hesaplar; ortalama işlemi için gereklidir.
  • oled.clearDisplay(): Önceki ekran içeriği temizlenir; yeni veriler için alan hazırlanır.
  • oled.setCursor((SCREEN_WIDTH - width) / 2, ...): Metin, ekran genişliği ve metin genişliği farkının yarısı kadar X ekseninde kaydırılarak yatay olarak ortalanır.
  • oled.println(): Metin OLED tampon belleğine yazılır; henüz ekranda görünmez.
  • oled.display(): Tampon bellekteki tüm değişiklikler fiziksel OLED ekrana yansıtılır; kullanıcı tarafından görülebilir hale gelir.

Adım 6 – Test Edin

Kod yüklendikten sonra:

  1. Arduino IDE’de Serial Monitor’ü açın (9600 baud).
  2. OLED ekranın açılışta 2 saniye boş kaldıktan sonra sıcaklık ve nem değerlerini gösterdiğini gözlemleyin.
  3. Serial Monitor’de “XX.X°C | YY.Y%” formatında güncellenen sensör verilerini kontrol edin.
  4. DHT11 sensörüne hafifçe üfleyerek veya elinizle yaklaştırarak sıcaklık/nem değişimini ekranda izleyin.
  5. Ekranda “Failed” yazısı görünüyorsa sensör bağlantılarını, pin atamasını ve güç beslemesini doğrulayın.
  6. OLED ekran açılmıyorsa I2C adresini (0x3C/0x3D) ve SDA/SCL bağlantılarını kontrol edin.

İsteğe Bağlı Geliştirmeler

Temel işlevi tamamladıktan sonra projeyi aşağıdaki şekilde genişletebilirsiniz:

  • Okuma Aralığı: delay(2000) ekleyerek sensör okuma sıklığını ayarlayın; DHT11 minimum 1-2 saniye aralıkla okuma yapmalıdır.
  • Fahrenheit Dönüşümü: Sıcaklık değerini Fahrenheit cinsine dönüştüren bir seçenek ekleyin: tempF = tempC * 9/5 + 32.
  • Grafik Gösterim: Adafruit_GFX çizim fonksiyonları ile sıcaklık/nem değişimini çubuk grafik olarak görselleştirin.
  • Uyarı Sistemi: Belirli sıcaklık/nem eşik değerleri aşıldığında ekranda uyarı mesajı veya renk değişimi gösterin.
  • WiFi Entegrasyonu: ESP32 WiFi özelliği ile sensör verilerini bulut platformuna (ThingSpeak, Blynk vb.) aktarın.

ESP32 DHT11-OLED Projesi SSS

S: OLED ekran açılmıyor, “SSD1306 allocation failed” hatası alıyorum.
C: I2C adresi yanlış olabilir. OLED ekranınızın adresini 0x3D olarak değiştirerek deneyin. Ayrıca SDA (GPIO21) ve SCL (GPIO22) bağlantılarını ve güç beslemesini kontrol edin.

S: DHT11 sürekli “Failed” değeri döndürüyor.
C: DATA pininde pull-up direnç eksik olabilir (10kΩ VCC-DATA arasına ekleyin). Ayrıca sensörün okuma aralığı minimum 1-2 saniyedir; loop() içinde çok hızlı okuma yapmamaya dikkat edin.

S: OLED ekranda metinler kaymış veya bozuk görünüyor.
C: getTextBounds() fonksiyonu metin boyutlarını doğru hesaplamalıdır. Metin ortalama hesaplamasında width_T ve width_H değişkenlerinin doğru metinler için kullanıldığından emin olun.

S: String kullanımı hafıza sorunu yaratır mı?
C: ESP32’de hafıza yönetimi Arduino Uno’ya göre daha esnektir, ancak uzun süreli çalışmalarda dinamik String kullanımı hafıza parçalanmasına neden olabilir. reserve() kullanımı bu riski azaltır. Alternatif olarak char[] dizileri veya String yerine snprintf() kullanılabilir.

S: DHT22 sensörü kullanabilir miyim?
C: Evet. DHT22, DHT11’e göre daha hassas ve geniş ölçüm aralığına sahiptir. Kodda DHT dht11(DHT11_PIN, DHT11) satırını DHT dht22(DHT11_PIN, DHT22) olarak değiştirmeniz yeterlidir.

S: OLED ekranın I2C adresini nasıl öğrenirim?
C: Arduino IDE’de “File > Examples > Wire > i2c_scanner” sketch’ini yükleyerek Serial Monitor’de taranan I2C cihaz adreslerini görebilirsiniz. SSD1306 genellikle 0x3C veya 0x3D adresini kullanır.

S: Derece sembolü (°) ekranda yanlış karakter olarak görünüyor.
C: OLED font setinde char(247) derece sembolünü temsil eder. Farklı karakter görünüyorsa oled.print("C") şeklinde derece sembolü olmadan devam edebilir veya özel font yükleyebilirsiniz.

Leave a Reply

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir