Temeller · 10 dk okuma

I2C Nedir? SDA, SCL, Pull-up Direnci ve Arduino I2C Tarayıcı

I2C nedir, nasıl çalışır? SDA ve SCL hatları, 7 bit adresler, pull-up direnci hesabı, I2C tarayıcı kodu, adres çakışması ve Uno, ESP32, Pico pinleri.

I2C (Inter-Integrated Circuit), yalnızca iki sinyal kablosuyla (SDA ve SCL) bir mikrodenetleyicinin onlarca sensör, ekran ve modülle konuşmasını sağlayan seri haberleşme protokolüdür. "I-kare-C" diye okunur; bazı veri sayfalarında IIC ya da TWI (Two Wire Interface) olarak geçer. Arduino projelerinde kullandığın I2C LCD ekran, OLED ekran, MPU6050 ivmeölçer, BMP280 basınç sensörü ve DS1307 saat modülü bu protokolle çalışır; hepsini aynı iki kabloya paralel bağlayabilir, her birine kendi adresiyle ulaşabilirsin.

Bu rehberde I2C'nin elektriksel olarak nasıl çalıştığını, adreslerin ne anlama geldiğini, pull-up direncinin neden şart olduğunu ve değerinin nasıl hesaplandığını öğreneceksin. Ardından Arduino Uno, ESP32 ve Raspberry Pi Pico için pin tablosunu, hattaki cihazları bulan I2C tarayıcı kodunu, kütüphanesiz yazmaç okuma örneğini ve adres çakışması gibi sık karşılaşılan sorunların çözümlerini adım adım göreceksin.

PCF8574 yongalı I2C LCD adaptör modülü
I2C LCD adaptörü: LCD'nin arkasına lehimlenen PCF8574 yongası, 16 pinli LCD'yi yalnızca dört kabloya (GND, VCC, SDA, SCL) indirir ve genellikle 0x27 ya da 0x3F adresinden cevap verir.

I2C nedir, nasıl çalışır?

I2C, 1982'de Philips (bugünkü NXP) tarafından aynı devre kartı üzerindeki yongaların az kabloyla haberleşmesi için geliştirildi. Hatta iki rol vardır: iletişimi başlatan ve saati üreten denetleyici (controller, eski adıyla master) ve ona cevap veren hedef cihazlar (target, eski adıyla slave). Arduino projelerinde denetleyici neredeyse her zaman Arduino, ESP32 ya da Pico'dur; sensörler ve ekranlar ise hedef cihazdır.

  • SDA (Serial Data): Verinin iki yönde de taşındığı hat. Denetleyici adres ve komut gönderir, sensör ölçüm sonucunu aynı hattan geri yollar.
  • SCL (Serial Clock): Saat hattı. Her saat darbesinde SDA üzerindeki bir bit okunur; saati denetleyici üretir.
  • GND (ortak toprak): Sinyallerin referansı. Ayrı beslenen modüllerde bile tüm GND'ler birleştirilmelidir.

Hatlar açık akaçlı (open-drain) çalışır: hiçbir cihaz hattı 1'e sürmez, yalnızca 0'a çeker. Hattı 1 seviyesinde tutan şey, SDA ve SCL'yi besleme gerilimine bağlayan pull-up dirençleridir. Bu sayede iki cihaz aynı anda konuşmaya çalışsa bile kısa devre oluşmaz; birinin 0'a çektiği hattı herkes 0 olarak görür. Bir I2C mesajı şu sırayla ilerler:

  1. START: SCL 1 iken denetleyici SDA'yı 1'den 0'a çeker; hattaki tüm cihazlar dinlemeye başlar.
  2. Adres ve yön biti: 7 bitlik adres, ardından okuma (1) ya da yazma (0) biti gönderilir.
  3. ACK: Adres kendisine ait olan cihaz 9. saat darbesinde SDA'yı 0'a çekerek "buradayım" der. Kimse çekmezse buna NACK denir.
  4. Veri baytları: Her bayt 8 bit olarak gönderilir ve alıcı her birinin ardından ACK verir. Çoğu sensörde ilk bayt, okunacak ya da yazılacak yazmacın (register) numarasıdır.
  5. STOP: SCL 1 iken SDA 0'dan 1'e çıkar ve hat serbest kalır. Okuma işlemlerinde STOP yerine tekrarlı START (repeated start) kullanılarak hat bırakılmadan yön değiştirilir.

I2C'yi Arduino dünyasındaki diğer iki yaygın protokolle karşılaştırmak, hangi durumda tercih edileceğini netleştirir:

ÖzellikI2CSPIUART (Seri)
Sinyal kablosu2 (SDA, SCL)3 ortak (MOSI, MISO, SCK) + her cihaza ayrı CS2 (TX, RX)
Cihaz sayısıAynı hatta 100'den fazla adresBoş CS pini kadarGenellikle 2 cihaz
Tipik hız100 kHz, 400 kHz, 1 MHz10 MHz ve üzeri9600 – 115200 baud
Cihaz seçimiAdresleCS pini ileYok, noktadan noktaya
Tipik kullanımSensör, saat, küçük ekran, EEPROMSD kart, TFT ekran, RFIDGPS, Bluetooth, bilgisayar bağlantısı

I2C hızları ve teknik sınırlar

ModEn yüksek hızEn uzun yükselme süresiNerede kullanılır?
Standart mod (Sm)100 kHz1000 nsVarsayılan, uzun kablolar
Hızlı mod (Fm)400 kHz300 nsOLED, MPU6050, BMP280
Hızlı mod artı (Fm+)1 MHz120 nsPico ve bazı yeni sensörler
Yüksek hız modu (Hs)3,4 MHz80 ns (400 pF), özel sürücü gerekirHobi projelerinde nadiren

Arduino'nun Wire kütüphanesi varsayılan olarak 100 kHz ile başlar; sensörlerin çoğu 400 kHz'i de destekler ve Wire.setClock(400000) satırıyla bu hıza geçebilirsin. Hızı yükseltmek ekranların daha akıcı yenilenmesini sağlar ama hattı kablo uzunluğuna ve pull-up direncine karşı daha hassas hale getirir. Standarda göre hattın toplam kapasitansı (kablolar ve cihaz pinleri) 400 pF'ı geçmemelidir. Sıradan jumper ve şerit kablolar metre başına 50–100 pF, her cihaz pini de 10 pF'a kadar kapasitans ekler; bu yüzden I2C aynı kart üzerinde ya da birkaç on santimlik kablolarla çalışmak için tasarlanmıştır. 1 metreyi aşan mesafelerde hızı düşürmek, daha güçlü pull-up kullanmak ya da P82B715 gibi hat uzatıcılar eklemek gerekir.

I2C adresleri: 7 bit, 8 bit ve ayrılmış adresler

Hattaki her cihazın 7 bitlik bir adresi vardır; bu da teorik olarak 128 adres eder. 0x00–0x07 ve 0x78–0x7F aralıkları özel işler için ayrıldığından kullanılabilecek adresler 0x08 ile 0x77 arasındaki 112 adrestir. Adres genellikle yonganın üreticisi tarafından sabitlenir; birçok modülde ise A0, A1, A2 ya da AD0 gibi lehim köprüleri ve pinlerle adresin son bitlerini değiştirebilirsin.

Kafa karıştıran nokta şudur: bazı veri sayfaları ve modüllerin arkasındaki yazılar adresi yön bitiyle birlikte 8 bit olarak verir. Örneğin OLED kartının arkasında "0x78" yazar ama koddaki adres 0x3C'dir; LCD modülünde 0x4E yazıyorsa koddaki karşılığı 0x27'dir. Kural basittir: 8 bitlik değeri 2'ye böl (bir bit sağa kaydır), 7 bitlik adresi bulursun. Arduino, ESP32 ve MicroPython kütüphanelerinin hepsi 7 bitlik adres bekler.

ModülYongaVarsayılan adresDeğiştirilebilir mi?
I2C LCD modülü (16x2, 20x4)PCF8574 / PCF8574A0x27 / 0x3FA0–A2 köprüleriyle 0x20–0x27 ya da 0x38–0x3F
0,96 inç OLEDSSD13060x3CArkadaki dirençle 0x3D
İvmeölçer ve jiroskopMPU60500x68AD0 = 1 ise 0x69
Gerçek zamanlı saatDS1307 / DS32310x68Hayır
Basınç ve sıcaklıkBMP280 / BME2800x76 ya da 0x77SDO pinine göre
Işık şiddetiBH17500x23ADDR = 1 ise 0x5C
16 bit ADCADS11150x48ADDR pini ile 0x48–0x4B
16 kanallı servo ve PWM sürücüPCA96850x40A0–A5 köprüleriyle 0x40'tan başlayan onlarca adres
EEPROM bellekAT24C32 / AT24C2560x50A0–A2 ile 0x50–0x57
I2C çoklayıcıTCA9548A0x70A0–A2 ile 0x70–0x77
Tiny RTC (DS1307) modülleri tarandığında 0x68'in yanında 0x50 adresi de görünür; bu bir hata değil, modülün üzerindeki AT24C32 EEPROM belleğidir. DS3231'li ZS-042 modüllerinde aynı bellek 0x57 adresinden cevap verir.

Pull-up dirençleri: neden gerekli ve değeri nasıl seçilir?

I2C hatlarında cihazlar yalnızca 0'a çekebildiğinden 1 seviyesini pull-up dirençleri sağlar. Direnç çok büyük olursa hat kapasitansı yüzünden 0'dan 1'e geçiş yavaşlar, sinyalin köşeleri yuvarlanır ve yüksek hızda bitler yanlış okunur. Direnç çok küçük olursa cihazın hattı 0'a çekerken akıtması gereken akım artar; standart, bir cihazın 0,4 V'ta en az 3 mA akıtabilmesini şart koşar; bu yüzden pull-up direnci hat akımını bu değerin altında tutmalıdır.

İki sınırı veren formüller şunlardır: en küçük direnç R(min) = (VCC − 0,4 V) / 3 mA, en büyük direnç ise R(max) = t(yükselme) / (0,8473 × C(hat)). 5 V için R(min) = 4,6 V / 0,003 A ≈ 1,53 kΩ, 3,3 V için ≈ 0,97 kΩ çıkar. 100 pF kapasitanslı kısa bir hatta 100 kHz için R(max) ≈ 11,8 kΩ, 400 kHz için ≈ 3,5 kΩ olur. Bu yüzden pratikte 100 kHz için 4,7 kΩ, 400 kHz ve kalabalık hatlar için 2,2 kΩ en sık kullanılan değerlerdir. Direncin renk kodunu çözmek için Direnç Renk Kodu, direnç ve kapasitansın oluşturduğu gecikmeyi görmek için RC Zaman Sabiti araçlarını kullanabilirsin.

DurumÖnerilen pull-upNot
Tek modül, kısa kablo, 100 kHz4,7 kΩ – 10 kΩModüllerin çoğunda zaten vardır
Birkaç modül, 400 kHz2,2 kΩ – 4,7 kΩModüllerdeki dirençler paralel bağlanır
50 cm'den uzun kablo2,2 kΩ ve 100 kHzSDA ve SCL'yi birbiriyle bükme; her birini GND ile bük
3,3 V hat (ESP32, Pico)2,2 kΩ – 4,7 kΩDirençleri 5 V'a değil 3,3 V'a bağla
Modüllerin çoğunun üzerinde zaten 4,7 kΩ ya da 10 kΩ pull-up dirençleri vardır ve aynı hatta bağlanan modüllerin dirençleri paralel hale gelir. Üç modülde de 4,7 kΩ varsa toplam yaklaşık 1,57 kΩ olur; 5 V'ta bu, 3 mA sınırının hemen altıdır. Dört beş modülü bir araya getireceksen bazılarının üzerindeki pull-up dirençlerini sökmen ya da lehim köprüsünü kesmen gerekebilir.

Arduino Uno'da Wire.begin() çağrıldığında ATmega328P'nin 20–50 kΩ'luk dahili pull-up dirençleri de açılır. Bu dirençler tek bir modül ve 10–20 cm'lik kabloyla çoğu zaman yeter ama güvenilir değildir; harici direnç her zaman daha iyidir. Üzerinde pull-up olmayan çıplak bir sensör kartı kullanıyorsan SDA ve SCL'den VCC'ye birer 4,7 kΩ direnç eklemeyi unutma.

I2C pinleri: Arduino Uno, Mega, ESP32, ESP8266 ve Pico

KartSDASCLNot
Arduino Uno / NanoA4A5Uno R3'te AREF yanındaki SDA ve SCL pinleri A4/A5 ile aynı hattır
Arduino Mega 25602021Mega'da A4 ve A5 I2C değildir
Arduino Leonardo / MicroD2D3Dijital pinlerdir
ESP32 (DevKit)GPIO 21GPIO 22Wire.begin(SDA, SCL) ile başka pinler seçilebilir; ikinci hat Wire1
ESP8266 NodeMCUD2 (GPIO 4)D1 (GPIO 5)Yazılımsal I2C, pinler değiştirilebilir
Raspberry Pi PicoGP4 (I2C0)GP5 (I2C0)I2C0 ve I2C1 birçok pin çiftinde kullanılabilir
Arduino Uno 5 V, ESP32, ESP8266 ve Pico ise 3,3 V seviyesinde çalışır. 3,3 V'luk bir karta bağladığın modül 5 V ile besleniyor ve pull-up dirençleri 5 V'a bağlıysa SDA ve SCL hatları 5 V'a çıkar ve 5 V'a dayanıklı olmayan pinlere zarar verir. Modülü 3,3 V ile besle ya da iki gerilim arasında BSS138 transistörlü çift yönlü bir seviye dönüştürücü kullan.

Adım adım: I2C tarayıcı kodu ile adres bulma

Yeni bir modül aldığında ilk iş, hattaki cihazların adreslerini öğrenmektir. I2C tarayıcı, 0x08'den 0x77'ye kadar her adrese boş bir mesaj gönderir ve ACK veren adresleri listeler. Böylece hem modülün doğru bağlandığını hem de kodda hangi adresi yazman gerektiğini aynı anda öğrenirsin.

  1. Modülün GND'sini Arduino'nun GND'sine, VCC'sini 5V'a (yalnızca 3,3 V destekleyen modüllerde 3.3V'a) bağla.
  2. SDA'yı A4'e, SCL'yi A5'e bağla. Birden fazla modül varsa hepsinin SDA'larını ve SCL'lerini breadboard üzerinde birleştir.
  3. Aşağıdaki kodu yükle ve Seri Monitör'ü 115200 baud hızında aç.
  4. Listelenen adresleri not al. Hiçbir şey çıkmıyorsa kabloları, ortak GND'yi ve pull-up dirençlerini kontrol et.
  5. Modülleri tek tek çıkarıp takarak hangi adresin hangi cihaza ait olduğunu doğrula; tarayıcı her 5 saniyede bir yeniden tarar.
Arduino (C++)
1#include <Wire.h>
2
3void printHex(byte addr) {
4  Serial.print(F("0x"));
5  if (addr < 16) Serial.print('0');    // tek haneliye sıfır ekle / pad single digit
6  Serial.print(addr, HEX);
7}
8
9void setup() {
10  Serial.begin(115200);
11  Wire.begin();                         // Uno: A4 = SDA, A5 = SCL
12#if defined(ARDUINO_ARCH_AVR)
13  Wire.setWireTimeout(3000, true);      // AVR (Uno, Nano, Mega): hat kilitlenirse 3 ms sonra kurtar / recover a stuck bus after 3 ms
14#endif
15  Serial.println(F("I2C tarayici / I2C scanner"));
16}
17
18void loop() {
19  byte found = 0;
20  for (byte addr = 0x08; addr <= 0x77; addr++) {   // geçerli 7 bit adresler / valid 7-bit addresses
21    Wire.beginTransmission(addr);
22    byte err = Wire.endTransmission();             // 0 = cihaz ACK verdi / device acknowledged
23    if (err == 0) {
24      Serial.print(F("Bulundu / found: "));
25      printHex(addr);
26      Serial.println();
27      found++;
28    } else if (err == 4 || err == 5) {
29      Serial.print(F("Hat hatasi / bus error at "));
30      printHex(addr);
31      Serial.println();
32    }
33  }
34  if (found == 0) {
35    Serial.println(F("Cihaz yok: kablolari ve pull-up'lari kontrol et / no devices: check wiring and pull-ups"));
36  } else {
37    Serial.print(found);
38    Serial.println(F(" cihaz bulundu / device(s) found"));
39  }
40  Serial.println();
41  delay(5000);                          // 5 sn sonra yeniden tara / rescan after 5 s
42}
endTransmission() sonucuAnlamıNe yapmalı?
0Cihaz adresini tanıdı (ACK)Bu adresi kodunda kullan
1Veri tampona sığmadıTarayıcıda görülmez; Uno'da tek seferde 32 bayttan fazla yazma
2Adrese NACK geldiO adreste cihaz yok, tarama sırasında normaldir
3Veriye NACK geldiCihaz komutu reddetti; yazmaç numarasını kontrol et
4Diğer hat hatasıKısa devre, eksik pull-up ya da gürültü
5Zaman aşımıHat kilitlendi; kabloları ve beslemeyi kontrol et

Koddaki setWireTimeout satırı önemlidir: SDA ya da SCL kısa devre olduğunda veya bir cihaz hattı 0'da bırakıp takıldığında, Uno'nun Wire kütüphanesi varsayılan ayarla sonsuza kadar bekleyip programı dondurabilir. Zaman aşımı açıkken kütüphane 3 ms sonra pes eder, I2C donanımını sıfırlar ve tarayıcı sorunu hata koduyla raporlar. Bu satır yalnızca AVR tabanlı kartlarda (Uno, Nano, Mega) derlensin diye #if ile korunmuştur; ESP32 ve ESP8266'nın Wire kütüphaneleri zaten kendi zaman aşımı korumasıyla gelir, bu yüzden aynı kod üç platformda da değiştirmeden derlenir ve çalışır.

Kütüphanesiz I2C: yazmaç okuma ve yazma

Kütüphaneler işi kolaylaştırır ama arka planda hepsi aynı şeyi yapar: cihaza yazmaç numarasını gönderir, sonra o yazmaçtan bayt okur ya da yazar. Bunu bir kez kendin yapmak, yeni bir sensörün veri sayfasını okuyup kütüphane olmadan da kullanabilmeni sağlar. Aşağıdaki örnek MPU6050 sensörünü uyku modundan çıkarır, kimlik yazmacını (WHO_AM_I) okur ve ardından sıcaklık ile Z ekseni ivmesini ham değerlerden hesaplar.

MPU-6050 ivmeölçer ve jiroskop modülü
MPU-6050 modülü: VCC, GND, SCL ve SDA pinleriyle I2C hattına bağlanır; AD0 pini adresi 0x68 ile 0x69 arasında seçer.
Arduino (C++)
1#include <Wire.h>
2
3const byte MPU_ADDR = 0x68;             // AD0 GND'de; AD0 = 3.3V ise 0x69 / AD0 low; 0x69 if AD0 high
4
5void writeReg(byte reg, byte value) {
6  Wire.beginTransmission(MPU_ADDR);
7  Wire.write(reg);                      // önce yazmaç adresi / register address first
8  Wire.write(value);                    // sonra veri / then the data
9  Wire.endTransmission();               // STOP gönder / send STOP
10}
11
12int16_t readWord(byte reg) {
13  Wire.beginTransmission(MPU_ADDR);
14  Wire.write(reg);
15  Wire.endTransmission(false);          // STOP yok, tekrarlı START / no STOP, repeated START
16  Wire.requestFrom(MPU_ADDR, (byte)2);  // 2 bayt iste / request 2 bytes
17  uint8_t hi = Wire.read();
18  uint8_t lo = Wire.read();
19  return (int16_t)(((uint16_t)hi << 8) | lo);
20}
21
22void setup() {
23  Serial.begin(115200);
24  Wire.begin();
25  Wire.setClock(400000);                // hızlı mod 400 kHz / fast mode 400 kHz
26  writeReg(0x6B, 0x00);                 // PWR_MGMT_1: uykudan uyandır / wake up from sleep
27  Wire.beginTransmission(MPU_ADDR);
28  Wire.write(0x75);                     // WHO_AM_I yazmacı / WHO_AM_I register
29  Wire.endTransmission(false);
30  Wire.requestFrom(MPU_ADDR, (byte)1);
31  Serial.print(F("WHO_AM_I = 0x"));
32  Serial.println(Wire.read(), HEX);     // 68 beklenir / expect 68
33}
34
35void loop() {
36  int16_t raw = readWord(0x41);         // TEMP_OUT_H ve TEMP_OUT_L / TEMP_OUT_H and TEMP_OUT_L
37  float tempC = raw / 340.0 + 36.53;    // veri sayfasındaki formül / datasheet formula
38  int16_t az = readWord(0x3F);          // Z ekseni ivmesi / Z-axis acceleration
39  Serial.print(F("Sicaklik / temp: "));
40  Serial.print(tempC, 1);
41  Serial.print(F(" C   AccZ: "));
42  Serial.println(az / 16384.0, 2);      // +-2g aralığında 16384 = 1 g / 16384 = 1 g at +-2g
43  delay(500);
44}

Okuma fonksiyonundaki endTransmission(false) satırına dikkat et: STOP göndermeden tekrarlı START ile yön değiştirir, böylece başka bir cihaz araya giremez ve sensör hangi yazmacın istendiğini unutmaz. WHO_AM_I değeri 0x68 çıkıyorsa iletişim kusursuzdur. Ucuz klon modüllerde bu değer 0x70 ya da başka bir sayı olabilir; bu, yonganın MPU6500 gibi uyumlu ama farklı bir model olduğunu gösterir ve bazı hazır kütüphanelerin "sensör bulunamadı" demesinin sebebi budur. Sıcaklık formülü (ham değer / 340 + 36,53) doğrudan MPU6050 veri sayfasından gelir; ivme için ±2 g aralığında 16384 ham değer 1 g'ye karşılık gelir, yani masada düz duran sensör Z ekseninde yaklaşık 1,00 gösterir.

Aynı hatta birden fazla cihaz ve adres çakışması

I2C'nin en büyük avantajı, adresleri farklı olduğu sürece cihazları aynı iki kabloya paralel bağlayabilmendir. Örneğin bir LCD (0x27), bir OLED (0x3C), bir BMP280 (0x76) ve bir DS3231 saat (0x68) aynı A4 ve A5 pinlerini sorunsuz paylaşır; her kütüphane kendi adresine konuşur, diğer cihazlar sessizce dinler. Sorun, iki cihaz aynı adrese sahip olduğunda başlar: ikisi birden ACK verir, gönderdikleri veriler karışır ve genellikle ikisi de çalışmaz. Çözüm yolları şunlardır:

  • Adres pinini değiştir: MPU6050'de AD0 pinini 3,3 V'a bağlarsan adres 0x69 olur ve DS3231 (0x68) ile çakışma biter.
  • Lehim köprülerini kullan: LCD modüllerindeki A0–A2 köprüleri 8, ADS1115'in ADDR pini 4 farklı adres sunar.
  • İkinci I2C hattı aç: ESP32'de Wire1, Pico'da I2C1 ile çakışan cihazı ayrı pinlere taşı.
  • I2C çoklayıcı ekle: TCA9548A tek adresten (0x70) sekiz ayrı alt hat açar; aynı adresli sekiz OLED'i bile bağlayabilirsin.
  • Adresi sabit cihazlar: DS1307 ya da HTU21D gibi bazı yongaların adresi hiç değişmez; bunlarda yalnızca ayrı hat ya da çoklayıcı çözüm olur.

ESP32 ile I2C: istediğin pinler ve iki ayrı hat

ESP32'de I2C donanımı pinlere esnek biçimde yönlendirilebilir. Varsayılan pinler GPIO 21 (SDA) ve GPIO 22 (SCL)'dir, ama Wire.begin(SDA, SCL) ile neredeyse istediğin iki GPIO'yu seçebilirsin. Klasik ESP32 ve ESP32-S3'te iki I2C denetleyicisi bulunduğu için aynı adresli iki sensörü iki ayrı hatta çalıştırabilirsin; ESP32-C3'te ise tek denetleyici vardır. GPIO 34–39 yalnızca giriş olduğundan I2C için kullanılamaz. Kartın tam pin haritası için Pinout aracına, ESP32'ye genel bir giriş için ESP32 Nedir? yazısına bakabilirsin.

Arduino (C++)
1#include <Wire.h>
2
3// Klasik ESP32'de iki I2C denetleyicisi vardır: Wire ve Wire1 / the classic ESP32 has two I2C controllers: Wire and Wire1
4
5void scan(TwoWire &bus, const char *name) {
6  Serial.printf("%s:\n", name);
7  for (uint8_t addr = 0x08; addr <= 0x77; addr++) {
8    bus.beginTransmission(addr);
9    if (bus.endTransmission() == 0) {
10      Serial.printf("  bulundu / found 0x%02X\n", addr);
11    }
12  }
13}
14
15void setup() {
16  Serial.begin(115200);
17  Wire.begin(21, 22);                   // SDA, SCL: varsayılan pinler / default pins
18  Wire1.begin(32, 33, 400000);          // SDA, SCL, hız: başka iki GPIO / SDA, SCL, speed: any two other GPIOs
19  scan(Wire, "Wire  (SDA 21, SCL 22)");
20  scan(Wire1, "Wire1 (SDA 32, SCL 33)");
21}
22
23void loop() {
24}

Raspberry Pi Pico ile I2C (MicroPython)

Pico'nun RP2040 yongasında I2C0 ve I2C1 adlı iki denetleyici vardır ve her biri birkaç farklı pin çiftine yönlendirilebilir. I2C0 için GP0/GP1, GP4/GP5, GP8/GP9, GP12/GP13, GP16/GP17 ve GP20/GP21; I2C1 için GP2/GP3, GP6/GP7, GP10/GP11, GP14/GP15, GP18/GP19 ve GP26/GP27 çiftleri kullanılabilir. Her çiftte çift numaralı pin SDA, tek numaralı pin SCL'dir. MicroPython'da tarayıcı tek satırdır: i2c.scan() ACK veren adreslerin listesini döndürür. Pico 3,3 V ile çalıştığı için modülleri 3V3(OUT) pininden beslemek en güvenli yoldur; RP2040 1 MHz'lik hızlı mod artıyı da desteklese de breadboard üzerinde 400 kHz'te kalmak daha az sürpriz çıkarır. Pico ile ilk adımlar için Raspberry Pi Pico Nedir? yazısına göz atabilirsin.

MicroPython
1from machine import Pin, I2C
2
3i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=400000)   # I2C0: GP4 = SDA, GP5 = SCL
4devices = i2c.scan()                                 # ACK veren adresler / addresses that ACK
5
6if devices:
7    for addr in devices:
8        print("Bulundu / found:", hex(addr))
9else:
10    print("Cihaz yok / no devices")
11
12# MPU6050 varsa WHO_AM_I yazmacını oku / if an MPU6050 is present, read WHO_AM_I
13if 0x68 in devices:
14    i2c.writeto_mem(0x68, 0x6B, b"\x00")             # uykudan uyandır / wake up
15    who = i2c.readfrom_mem(0x68, 0x75, 1)[0]
16    print("WHO_AM_I:", hex(who))                     # 0x68 beklenir / expect 0x68

I2C ile proje fikirleri

  • Mini hava istasyonu: BMP280 ile basınç ve sıcaklığı ölç, OLED ekranda göster; iki modül aynı iki kabloyu paylaşır.
  • Dijital saat: DS3231 saat modülünden zamanı okuyup I2C LCD ekrana yazdır.
  • Eğim göstergesi: MPU6050 ile açıyı hesapla, sonucu OLED'de bir su terazisi gibi çiz.
  • Wi-Fi sensör düğümü: ESP8266 NodeMCU kartının D1 ve D2 pinlerine bağladığın sensörün değerlerini telefondan izle.
  • 16 servolu robot kol: PCA9685 sürücüsüyle yalnızca iki pinden 16 servoyu kontrol et.
  • Veri kaydedici: AT24C256 EEPROM'a dakikada bir ölçüm yaz; elektrik kesilse bile veriler kaybolmasın.

Sık yapılan hatalar ve çözümleri

BelirtiOlası sebepÇözüm
Tarayıcı hiçbir cihaz bulmuyorSDA ve SCL yer değiştirmiş, ortak GND yok ya da modül beslenmiyorKabloları kontrol et; Uno'da A4 = SDA, A5 = SCL
Tarayıcı donuyor ya da her adreste hata veriyorHat kısa devre ya da pull-up eksiksetWireTimeout ekle; boştaki SDA ve SCL'de besleme gerilimini ölç
Kod derleniyor ama ekran boşKodda yanlış adres (0x27 yerine 0x3F)Tarayıcının bulduğu adresi koda yaz
Kartın arkasında 0x78 yazıyor, kod çalışmıyor8 bitlik adres yazılmış2'ye böl: 0x78 → 0x3C
İki sensör birlikte çalışmıyorAdres çakışmasıAdres pinini değiştir, ikinci hat ya da TCA9548A kullan
Rastgele donmalar, motor çalışınca bozulmaUzun kablo, gürültü ya da zayıf beslemeKabloları kısalt, hızı 100 kHz'e düşür, modüllere 100 nF kondansatör ekle
ESP32 ya da Pico pini zarar gördü5 V'a bağlı pull-up 3,3 V pine bağlanmışModülü 3,3 V ile besle ya da seviye dönüştürücü kullan
I2C sorunlarında multimetre en iyi dostundur: güç açıkken ve iletişim yokken SDA ve SCL hatlarının ikisinde de besleme gerilimini (5 V ya da 3,3 V) ölçmelisin. 0 V görüyorsan bir cihaz hattı kısa devre etmiş ya da takılı kalmış demektir. Kart beslemesizken SDA ile VCC arasındaki direnci ölçerek hattaki toplam pull-up değerini de yaklaşık olarak bulabilirsin.

I2C, iki kabloyla projene ekran, saat, sensör ve bellek eklemenin en pratik yoludur; adresleri, pull-up dirençlerini ve tarayıcı kodunu öğrendiğinde karşılaşacağın sorunların çoğunu birkaç dakikada çözersin. BlueGrays uygulamasında I2C LCD ekran, OLED ekranlı Pong oyunu, DS1307 saatli dijital saat ve ESP32 hava durumu ekranı gibi I2C kullanan projeleri adım adım devre şemaları ve kodlarıyla bulabilirsin.

Sıkça sorulan sorular

I2C ile SPI arasındaki fark nedir?

I2C iki kabloyla adresleme yaparak yüzden fazla cihazı aynı hatta bağlar ama tipik olarak 100–400 kHz ile sınırlıdır. SPI ise üç ortak kablo ve her cihaz için ayrı bir seçim (CS) pini ister; buna karşılık 10 MHz ve üzeri hızlara çıkar. Sensörler ve küçük ekranlar için I2C, SD kart ve renkli TFT ekranlar için SPI tercih edilir.

I2C hattına en fazla kaç cihaz bağlanabilir?

7 bitlik adreslemede kullanılabilir 112 adres vardır. Pratikte sınırı adres sayısından çok hattın kapasitansı (en fazla 400 pF) ve paralel bağlanan pull-up dirençleri belirler; breadboard üzerinde 5–10 cihaz sorunsuz çalışır. Daha fazlası için TCA9548A çoklayıcı ya da ikinci bir I2C hattı kullanılır.

I2C pull-up direnci kaç ohm olmalı?

100 kHz ve kısa kablolar için 4,7 kΩ, 400 kHz ya da birçok cihazın bulunduğu hatlar için 2,2 kΩ en yaygın değerlerdir. 5 V hatta 1,5 kΩ'un, 3,3 V hatta 1 kΩ'un altına inmemelisin. Modüllerin üzerindeki dirençlerin paralel bağlandığını da hesaba kat.

Arduino Uno'da I2C pinleri hangileri?

Arduino Uno ve Nano'da SDA A4, SCL ise A5 pinidir. Uno R3'te AREF pininin yanında SDA ve SCL yazan iki pin daha vardır ama bunlar kart üzerinde A4 ve A5'e bağlıdır, ayrı bir hat değildir. Mega'da I2C pinleri 20 (SDA) ve 21 (SCL)'dir.

I2C kablo uzunluğu en fazla ne kadar olabilir?

I2C kart üzerindeki kısa mesafeler için tasarlanmıştır; 100 kHz'te ve uygun pull-up dirençleriyle 1 metreye kadar genellikle çalışır. Daha uzun mesafelerde hızı düşürmek, bükülü çift kablo kullanmak ya da P82B715 gibi hat sürücülerine geçmek gerekir. Metrelerce uzaklık için RS-485 ya da kablosuz bağlantı daha doğru seçimdir.

I2C tarayıcı cihazımı bulamıyorsa ne yapmalıyım?

Önce SDA ve SCL'nin doğru pinlere takıldığını, ortak GND'nin bağlı olduğunu ve modülün beslendiğini kontrol et. Sonra boştaki SDA ve SCL'de besleme gerilimini ölçerek pull-up dirençlerini doğrula. Hâlâ bulunmuyorsa modülü tek başına, kısa kablolarla ve 100 kHz'te dene; ESP32'de Wire.begin'e doğru pinleri verdiğinden emin ol.

Tüm projeleri gör
I2C İle LCD Ekran Kullanımı
#32Başlangıç
Premium

I2C İle LCD Ekran Kullanımı

I2C modülü sayesinde sadece 2 kablo (SDA, SCL) ile LCD ekranı kontrol ederek mesaj yazdıran proje. I2C protokolü ile pin tasarrufu sağlamayı öğretir.

4.8(53)
69
ESP32 I2C LCD Ekran (16x2)
#119Orta
Premium

ESP32 I2C LCD Ekran (16x2)

Bu projede 16x2 karakter LCD ekranı I2C protokolü üzerinden ESP32'ye bağlayarak metin görüntülüyoruz. I2C sayesinde sadece 2 data pini (SDA ve SCL) ile ekranı kontrol edebiliyoruz; klasik paralel bağlantıdaki 6+ pin israfı ortadan kalkıyor. Kod ilk satıra sabit bir mesaj, ikinci satıra ise her saniye artan bir sayaç yazdırıyor. Ayrıca başlangıçta I2C tarayıcı çalıştırarak ekranın adresini Serial Monitor'a yazdırıyoruz (genelde 0x27 veya 0x3F).

4.9(22)
39
ESP32 RTC DS1307 ile Dijital Saat (I2C + LCD)
#120Orta
Premium

ESP32 RTC DS1307 ile Dijital Saat (I2C + LCD)

Bu projede DS1307 gerçek zaman saati (RTC) modülü ile 16x2 I2C LCD ekrana saat ve tarih bilgisi yansıtıyoruz. DS1307 pil destekli bir RTC'dir; ESP32 kapansa bile zamanı korur. Her iki modül de aynı I2C hattını (SDA/SCL) paylaşır, böylece sadece iki sinyal kablosu ile çoklu cihaz kontrolü öğrenmiş oluruz. Bu proje sayesinde I2C haberleşme protokolünü, RTC modüllerinin çalışma prensibini ve LCD ekranda dinamik veri gösterimini pratik bir şekilde öğreneceksiniz.

4.6(26)
40
Arduino I2C Hesap Makinesi
#94Orta
Premium

Arduino I2C Hesap Makinesi

4x4 membran tuş takımı ve 16x2 I2C LCD ekran kullanarak toplama, çıkarma, çarpma ve bölme işlemlerini gerçekleştiren Arduino tabanlı bir hesap makinesi projesidir. I2C sayesinde sadece 2 kablo ile ekran bağlantısı sağlanır, böylece kablo karmaşası azalır ve daha fazla pin kullanıma açık kalır. Ondalıklı sayı girişi ve negatif sayı desteği de bulunmaktadır.

5.0(31)
43
Pong Oyunu - SSD1306
#86Orta
Premium

Pong Oyunu - SSD1306

Arduino ve SSD1306 OLED ekran kullanılarak hazırlanmış; topun hareketlerini anlık olarak takip edip yörüngesine göre tepki veren otonom yapay zeka (CPU) rakibiyle donatılmış ve ses efektleriyle zengin

4.5(47)
65
ESP32 HTTPClient + Hava Durumu API (SSD1306 OLED Ekranlı)
#134İleri
Premium

ESP32 HTTPClient + Hava Durumu API (SSD1306 OLED Ekranlı)

Bu projede ESP32 ile internet üzerinden hava durumu API'sine (wttr.in) `HTTPClient.h` kullanarak REST API çağrısı yapıyoruz. Bir önceki I2C LCD versiyonundan farklı olarak burada SSD1306 OLED (128×64) ekran kullanıyoruz — büyük font, vector ikonlar ve tek ekranda zengin görsel sunum mümkün oluyor. Hava durumu için 7 farklı vector ikon (güneşli, parçalı bulutlu, bulutlu, yağmurlu, karlı, fırtınalı, sisli) runtime'da çiziliyor (bitmap dosyası gerektirmez). Sıcaklık 3x büyük fontla ortada, hava dur

4.3(10)
18
Dot Matrix Saat ve Takvim (MAX7219, DS1307)
#84Orta
Premium

Dot Matrix Saat ve Takvim (MAX7219, DS1307)

DS1307 RTC modülü ile gerçek zamanlı saat ve takvim bilgisini MAX7219 8x32 dot matrix LED ekranda gösteren bir projedir. Saat gösteriminde iki nokta her saniye yanıp sönerek zamanın aktığını yansıtır.

5.0(37)
58
ESP32 Sıcaklık Loglayıcı (DHT22 + DS1307 RTC + microSD + OLED)
#144İleri
Premium

ESP32 Sıcaklık Loglayıcı (DHT22 + DS1307 RTC + microSD + OLED)

ESP32 ile zamanlı sıcaklık ve nem kayıt sistemi kur! Bu projede DHT22 sensörü ile her 10 saniyede sıcaklık/nem okuyup DS1307 RTC modülünden aldığın gerçek zaman etiketiyle microSD karta CSV formatında kaydediyoruz. OLED ekranda büyük font ile son sıcaklık değeri, nem yüzdesi, timestamp ve toplam kayıt sayısı canlı gösterilir. SD kart üzerindeki `/temp_log.csv` dosyası Excel/Google Sheets/Python pandas ile açılıp analiz edilebilir — sera monitörü, ev/oda sıcaklık takibi, laboratuvar veri toplama,

4.7(7)
12

İki kabloyla onlarca sensör ve ekranı aynı hatta bağlamanı sağlayan I2C protokolünü; adresleri, pull-up dirençlerini, I2C tarayıcı kodunu ve en sık hataların çözümünü örneklerle öğren.

I2C Nedir? SDA, SCL, Pull-up Direnci ve Arduino I2C Tarayıcı | BlueGrays