5. ünite / 10 · yaklaşık 5 saat
Sensörler ve veri yolları: 1-Wire, I²C, SPI
DS18B20 ve CRC, I²C adresleri ve i2cdetect, SPI ile MCP3008 analog okuma; config.txt ayarları.
Bu ünitenin sonunda
- config.txt ve raspi-config ile I²C, SPI ve 1-Wire arayüzlerini açmak
- DS18B20'yi 1-Wire üzerinden okuyup CRC'yi denetlemek
- I²C yolundaki cihazları i2cdetect ile bulmak ve adres çakışmasını çözmek
- Pi'nin olmayan analog girişini SPI'lı bir ADC (MCP3008) ile eklemek
Ders notları
Sensörler Pi'ye üç yaygın veri yoluyla bağlanır. Hepsi /boot/firmware/config.txt satırlarıyla ya da raspi-config ile açılır: dtparam=i2c_arm=on, dtparam=spi=on, dtoverlay=w1-gpio.
1-Wire: DS18B20
Tek veri hattı (varsayılan GPIO4) ve 4,7 kΩ pull-up. Her cihazın 64 bitlik benzersiz kimliği vardır; aynı hatta onlarca sensör olabilir. Çekirdek sürücüsü ölçümü w1_slave dosyasına yazar: ilk satır sonunda YES yoksa CRC tutmamıştır ve ölçüm atılır. Ham değer 1/16 °C birimindedir.
I²C: adresli yol
İki hat (SDA GPIO2, SCL GPIO3), Pi'de dahili 1,8 kΩ pull-up. Her cihazın 7 bit adresi vardır: BME280 0x76/0x77, SSD1306 0x3C, MPU6050 0x68/0x69. i2cdetect -y 1 yolu tarar. İki cihaz aynı adresteyse (MPU6050 ile DS3231 ikisi de 0x68) birinin adres pini değiştirilir ya da bir I²C çoklayıcı (TCA9548A) kullanılır.
SPI: hızlı ve tam çift yönlü
Dört hat (SCLK, MOSI, MISO, CE). Adres yok: her cihaza ayrı seçim (CE) hattı. Pi'nin ADC'si olmadığından potansiyometre ya da analog sensör için MCP3008 kullanılır: 3 bayt gönderilir, dönen son iki bayttan 10 bitlik değer çıkar.
Simülasyon
Sensör veri yolları: 1-Wire, I²C ve SPI
DS18B20'nin w1_slave dosyasını CRC ile çözümle, I²C yoluna cihaz ekleyip adres çakışmasını gör, MCP3008'e SPI ile giden ve gelen baytları izle.
$ cat /sys/bus/w1/devices/28-0316a2794c5f/w1_slave
4b 01 4b 46 7f ff 05 10 e1 : crc=e1 YES 4b 01 4b 46 7f ff 05 10 e1 t=20687
Kendin dene
1-Wire sekmesinde sıcaklığı değiştir ve w1_slave satırlarını izle; "CRC bozuk" kutusunu işaretleyince okuyucunun ölçümü neden reddettiğini açıkla. I²C sekmesinde MPU6050 ve DS3231'i birlikte ekle, çakışmayı MPU6050'nin AD0 pinini değiştirerek çöz. SPI sekmesinde 2,5 V için giden ve gelen baytları yaz. Terminalde i2c-tools kurup i2cdetect -y 1 çalıştır.
Kod
from pathlib import Path
from smbus2 import SMBus
import spidev
def ds18b20() -> float | None:
dev = next(Path("/sys/bus/w1/devices").glob("28-*")) # aile kodu 28 = DS18B20
l1, l2 = (dev / "w1_slave").read_text().strip().splitlines()
if not l1.endswith("YES"):
return None # CRC tutmadı: yeniden oku
return int(l2.split("t=")[1]) / 1000
with SMBus(1) as bus: # /dev/i2c-1
chip = bus.read_byte_data(0x76, 0xD0) # kimlik yazmacı
print("BME280" if chip == 0x60 else f"? 0x{chip:02x}")
spi = spidev.SpiDev(); spi.open(0, 0) # SPI0, CE0
spi.max_speed_hz = 1_000_000
rx = spi.xfer2([0x01, (0x08 | 0) << 4, 0x00]) # başla, tek uçlu, kanal 0
value = ((rx[1] & 0x03) << 8) | rx[2]
print(f"CH0 = {value} -> {value * 3.3 / 1024:.2f} V, T = {ds18b20()} C")Sık yapılan hatalar
- Arayüzü config.txt'de açıp yeniden başlatmamak: /dev/i2c-1 oluşmaz.
- DS18B20'yi pull-up dirençsiz bağlamak: 85 °C ya da hiç cihaz görünmez (85 °C, dönüşüm yapılmamış açılış değeridir).
- 5 V I²C modülünü seviye dönüştürücüsüz bağlamak: modül kendi pull-up'larıyla hatları 5 V'a çeker.
- I²C kablolarını uzun tutmak: yol kapasitesi artar, kenarlar yavaşlar, iletişim kopar.
Yazılım mühendisliği bağlantısı
Sensör okuyucuyu bir arayüzün arkasına koy: read() → float | None.
- None, "bu ölçüm geçersiz" demektir; çağıran yeniden dener ya da son geçerli değeri kullanır.
- Kayıtlı w1_slave örnekleriyle (biri bozuk CRC) çözümleyiciyi birim testinde sına.
Kendini sına
w1_slave dosyasının ilk satırı "crc=e1 NO" ile bitiyorsa ne yapılmalı?
I²C yolunda MPU6050 (0x68) ve DS3231 (0x68) birlikte çalışmıyor. Çözüm?
Pi'de potansiyometre okumak için ne gerekir?
SPI'da birden fazla cihaz nasıl seçilir?
Bu üniteden sonra bitirme projesinde
- Donanım katmanı: hw.py: motor, enkoder, ultrasonik ve sıcaklık sınıfları; sahte (fake) karşılıklarıyla pytest testleri.