Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124

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.
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):
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 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:
Ekranda 128×64 piksel çözünürlük bulunur ve I2C adresi genellikle 0x3C veya 0x3D’dir.

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.

Projede kullanılan kütüphaneler:
Kütüphaneye SSD1306 kurulumu yapılmalıdır. Versiyon farklılıkları olabilir.

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

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.

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.
Arduino IDE’yi açın ve aşağıdaki kütüphaneleri Kütüphane Yöneticisi üzerinden yükleyin:
Ayrıca aşağıdaki kart ayarlarını kontrol edin:
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.
#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.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.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.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.Kod yüklendikten sonra:
Temel işlevi tamamladıktan sonra projeyi aşağıdaki şekilde genişletebilirsiniz:
delay(2000) ekleyerek sensör okuma sıklığını ayarlayın; DHT11 minimum 1-2 saniye aralıkla okuma yapmalıdır.tempF = tempC * 9/5 + 32.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.