Dersler

View on GitHub

EEM-241 İleri Düzey Programlama

2024-2025 Güz Dönemi

Ders 14 - Raspberry Pi GPIO Programlama

Raspberry Pi GPIO simülatörü: create.withcode.uk

1. Elektriksel güvenlik

Kod yazmadan önce şu kurallar açıklanmalıdır:

Donanım sınırları kullanılan Raspberry Pi modelinin resmi belgelerinden doğrulanmalıdır.

2. Pin numaralandırma

RPi.GPIO iki numaralandırma biçimi sunar:

Bir programda yalnızca biri seçilmeli ve devre şemasıyla aynı sistem kullanılmalıdır. Bu dersteki örneklerde, mevcut simülatör/devrelerle uyum için BOARD kullanılacaktır.

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)

Pin eşlemesini görmek için:

print(GPIO.getmode())

3. Dijital çıkış: LED yakıp söndürme

Bu örnekte fiziksel pin 11 çıkış olarak kullanılmaktadır.

import RPi.GPIO as GPIO
import time

LED_PIN = 11

GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED_PIN, GPIO.OUT, initial=GPIO.LOW)

try:
    while True:
        GPIO.output(LED_PIN, GPIO.HIGH)
        time.sleep(1)
        GPIO.output(LED_PIN, GPIO.LOW)
        time.sleep(1)
except KeyboardInterrupt:
    print("Program kullanıcı tarafından durduruldu.")
finally:
    GPIO.cleanup()

GPIO.cleanup() pinleri güvenli başlangıç durumuna döndürür. Sonsuz döngülü donanım programlarında finally içinde çağrılması özellikle önemlidir.

4. Tekrarı fonksiyonla azaltma

import RPi.GPIO as GPIO
import time

LED_PIN = 11

def led_yak_sondur(pin, bekleme):
    GPIO.output(pin, GPIO.HIGH)
    time.sleep(bekleme)
    GPIO.output(pin, GPIO.LOW)
    time.sleep(bekleme)


GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED_PIN, GPIO.OUT, initial=GPIO.LOW)

try:
    for _ in range(5):
        led_yak_sondur(LED_PIN, 0.5)
finally:
    GPIO.cleanup()

Önce sonlu döngüyle test yapmak, devre doğrulamasını kolaylaştırır.

5. Birden fazla LED: yürüyen ışık

import RPi.GPIO as GPIO
import time

LED_PINLERI = [11, 13, 15, 16, 18, 22]

GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED_PINLERI, GPIO.OUT, initial=GPIO.LOW)

def tek_led_yak(pin, bekleme=0.2):
    GPIO.output(pin, GPIO.HIGH)
    time.sleep(bekleme)
    GPIO.output(pin, GPIO.LOW)


try:
    while True:
        for pin in LED_PINLERI:
            tek_led_yak(pin)

        for pin in LED_PINLERI[-2:0:-1]:
            tek_led_yak(pin)
except KeyboardInterrupt:
    pass
finally:
    GPIO.cleanup()

İkinci döngüde uç LED’lerin iki kez art arda yanmaması için [-2:0:-1] dilimi kullanılmıştır.

6. Dijital giriş: Buton okuma

Harici direnç yerine dahili pull-up direnci kullanılabilir. Bu bağlantıda butona basılmadığında giriş HIGH, basıldığında LOW okunur; buna active-low denir.

import RPi.GPIO as GPIO
import time

LED_PIN = 11
BUTON_PIN = 12

GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED_PIN, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(BUTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)

try:
    while True:
        butona_basildi = GPIO.input(BUTON_PIN) == GPIO.LOW
        GPIO.output(LED_PIN, GPIO.HIGH if butona_basildi else GPIO.LOW)
        time.sleep(0.02)
except KeyboardInterrupt:
    pass
finally:
    GPIO.cleanup()

7. Buton sıçraması (debounce)

Mekanik buton tek basışta kısa süreli çok sayıda geçiş üretebilir. Basit olay algılamada bouncetime kullanılabilir.

import RPi.GPIO as GPIO
import time

BUTON_PIN = 12
sayac = 0

def butona_basildi(kanal):
    global sayac
    sayac += 1
    print("Basılma sayısı:", sayac)


GPIO.setmode(GPIO.BOARD)
GPIO.setup(BUTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(
    BUTON_PIN,
    GPIO.FALLING,
    callback=butona_basildi,
    bouncetime=200
)

try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    pass
finally:
    GPIO.cleanup()

Callback kısa tutulmalıdır; uzun süren işlem ana program akışında yapılmalıdır.

8. Butona göre yürüyen ışık yönü

import RPi.GPIO as GPIO
import time

LED_PINLERI = [11, 13, 15, 16, 18, 22]
BUTON_PIN = 12

GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED_PINLERI, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(BUTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)

def sirayi_oynat(pinler, bekleme=0.15):
    for pin in pinler:
        GPIO.output(pin, GPIO.HIGH)
        time.sleep(bekleme)
        GPIO.output(pin, GPIO.LOW)


try:
    while True:
        if GPIO.input(BUTON_PIN) == GPIO.LOW:
            sirayi_oynat(LED_PINLERI)
        else:
            sirayi_oynat(LED_PINLERI[::-1])
except KeyboardInterrupt:
    pass
finally:
    GPIO.cleanup()

9. PWM ile LED parlaklığı

PWM, dijital çıkışı hızlı biçimde açıp kapatarak ortalama gücü değiştirir. Görev oranı (duty cycle) 0–100 arasındadır.

import RPi.GPIO as GPIO
import time

LED_PIN = 11

GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED_PIN, GPIO.OUT)
pwm = GPIO.PWM(LED_PIN, 1000)
pwm.start(0)

try:
    for gorev_orani in range(0, 101, 5):
        pwm.ChangeDutyCycle(gorev_orani)
        time.sleep(0.1)

    for gorev_orani in range(100, -1, -5):
        pwm.ChangeDutyCycle(gorev_orani)
        time.sleep(0.1)
finally:
    pwm.stop()
    GPIO.cleanup()

PWM her donanım yükünü doğrudan sürmek için uygun değildir. Motor gibi yüklerde uygun sürücü devresi ve geri EMK koruması gerekir.

10. Sınıfla donanım davranışını kapsülleme

import RPi.GPIO as GPIO
import time

class Led:
    def __init__(self, pin):
        self.pin = pin
        GPIO.setup(self.pin, GPIO.OUT, initial=GPIO.LOW)

    def yak(self):
        GPIO.output(self.pin, GPIO.HIGH)

    def sondur(self):
        GPIO.output(self.pin, GPIO.LOW)

    def yanip_son(self, sure=0.5):
        self.yak()
        time.sleep(sure)
        self.sondur()


GPIO.setmode(GPIO.BOARD)
led = Led(11)

try:
    for _ in range(5):
        led.yanip_son(0.2)
finally:
    GPIO.cleanup()

Bu örnek, 9. haftadaki sınıf bilgisini fiziksel bir bileşenle birleştirir.

11. Bütünleştirici uygulama: Trafik lambası

import RPi.GPIO as GPIO
import time

KIRMIZI = 11
SARI = 13
YESIL = 15

GPIO.setmode(GPIO.BOARD)
GPIO.setup([KIRMIZI, SARI, YESIL], GPIO.OUT, initial=GPIO.LOW)

def durum(kirmizi, sari, yesil, sure):
    GPIO.output(KIRMIZI, kirmizi)
    GPIO.output(SARI, sari)
    GPIO.output(YESIL, yesil)
    time.sleep(sure)


try:
    while True:
        durum(GPIO.HIGH, GPIO.LOW, GPIO.LOW, 3)
        durum(GPIO.HIGH, GPIO.HIGH, GPIO.LOW, 1)
        durum(GPIO.LOW, GPIO.LOW, GPIO.HIGH, 3)
        durum(GPIO.LOW, GPIO.HIGH, GPIO.LOW, 1)
except KeyboardInterrupt:
    pass
finally:
    GPIO.cleanup()

Derste uygulama sırası

  1. Devre enerjisizken bağlantıları kurun ve numaralandırmayı doğrulayın.
  2. Tek LED’i sonlu döngüyle sınayın.
  3. try/finally ve kullanıcı kesmesini ekleyin.
  4. LED listesini ve yürüyen ışığı oluşturun.
  5. Buton girişini önce okuyup yazdırarak sınayın.
  6. Butonla LED davranışını birleştirin.
  7. Zaman kalırsa olay algılama ve PWM uygulayın.

Ders sonu alıştırmaları

  1. Üç LED’i ikili sayaç olarak kullanarak 0–7 sayılarını gösterin.
  2. Butona her basıldığında yürüyen ışığın yönünü kalıcı olarak değiştirin.
  3. İki butonla PWM görev oranını artırıp azaltın.
  4. Trafik lambasına yaya butonu ve güvenli geçiş sırası ekleyin.
  5. Led sınıfını birden fazla LED’i yöneten LedGrubu sınıfına genişletin.

Dönem sonu proje önerisi

Bir butonla çalışma modu değişen LED kontrol sistemi tasarlayın. Sistem;