MicroPython Kesmeler Kullanımı ESP32 ve ESP8266

MicroPython Kesmeler Kullanımı ESP32 ve ESP8266 micropython kesmeler

Bu yazımızda, mikrodenetleyici programlamanın en kritik konularından biri olan MicroPython kesmeler (interrupts) konusunu tüm detaylarıyla ele alıyoruz. Bu rehberdeki adımları ve kodları doğrudan uygulayabilmek için ESP32 veya ESP8266 kartınızda MicroPython belleniminin (firmware) yüklü olması gerekmektedir. Ayrıca hazırladığımız kodları karta yüklemek için bir geliştirme ortamına (IDE) ihtiyacınız olacak. Bu amaçla Thonny IDE veya uPyCraft IDE kullanmanızı tavsiye ederiz. Kurulum adımları için aşağıdaki rehberlerimizden faydalanabilirsiniz:

Thonny IDE Kaynakları

uPyCraft IDE Kaynakları

Kesmeler (Interrupts) Nedir ve Neden Kullanılır?

Kesmeler, mikrodenetleyici tabanlı sistemlerde belirli olayların (event) anında algılanarak asenkron bir şekilde işlenmesini sağlayan donanımsal mekanizmalardır. Kesmeler sayesinde zamanlama (timing) ve kaynak yönetimi problemleri çok daha efektif bir şekilde çözülür.

Geleneksel yöntemlerde (polling), ilgili pinin durumunu kontrol etmek için sürekli bir döngü çalıştırılması gerekir. Bu durum hem işlemciyi gereksiz yere meşgul eder hem de anlık sinyal değişimlerinin kaçırılmasına yol açabilir. Kesmelerde ise durum farklıdır: Pin üzerinde bir sinyal değişimi algılandığında donanım seviyesinde bir olay tetiklenir ve özel bir fonksiyon çağrılır. Bu fonksiyona Kesme Servis Rutini (Interrupt Service Routine – ISR) adı verilir.

Bir kesme sinyali oluştuğunda, işlemci o anda yürüttüğü ana program akışını geçici olarak durdurur (askıya alır), kesmeye özel ISR kodunu çalıştırır ve bu işlem tamamlandıktan sonra aşağıdaki şemada gösterildiği gibi ana program akışına kaldığı yerden devam eder:

MicroPython Kesmeler Kullanımı ESP32 ve ESP8266
MicroPython Kesmeler Kullanımı ESP32 ve ESP8266

Bu mimari; özellikle bir butona basılması, bir sensörden (örneğin PIR hareket sensörü) anlık veri gelmesi veya acil durdurma (emergency stop) gibi senaryolarda pini sürekli tarama ihtiyacını ortadan kaldırarak maksimum enerji tasarrufu ve hassasiyet sağlar.

ESP32 Kesme Pinleri: GPIO 6 ve GPIO 11 (dahili flaş bellek ile paylaşıldığı için) hariç tüm GPIO pinlerini donanımsal kesme pini olarak yapılandırabilirsiniz.

ESP8266 Kesme Pinleri: Donanımsal yapısı gereği GPIO 16 hariç tüm GPIO pinlerini kesme pini olarak kullanabilirsiniz.

MicroPython’da Kesme Yapılandırması

MicroPython platformunda donanımsal bir kesme tanımlamak için sırasıyla şu adımları izlemeniz gerekir:

1. Kesme Servis Rutini (ISR) Fonksiyonunun Tanımlanması: ISR fonksiyonları olabildiğince hafif, optimize ve hızlı çalışacak şekilde yazılmalıdır. Böylece işlemci gecikme yaşamadan ana döngüye geri dönebilir. En ideal yaklaşım, ISR içerisinde ağır işlemler yapmak yerine sadece global bir bayrağı (flag) değiştirmek ve ana kodun bu bayrağı işlemesini sağlamaktır. MicroPython’da kesme fonksiyonu, tetikleyici olan pini temsil eden bir Pin nesnesi parametresini (Örn: pin) kabul etmek zorundadır.

def handle_interrupt(pin):
    # Kesme algılandığında yapılacak işlemler

2. Giriş Pininin Tanımlanması: Kesme sinyalini dinleyeceğimiz pini standart giriş pini olarak tanımlıyoruz:

pir = Pin(14, Pin.IN)

3. irq() Metodu ile Kesmenin Etkinleştirilmesi: Giriş pini üzerinden irq() metodunu çağırarak kesme mekanizmasını aktif hale getiriyoruz:

pir.irq(trigger=Pin.IRQ_RISING, handler=handle_interrupt)

irq() metodu temelde şu parametreleri kabul eder:

  • trigger: Kesmenin hangi sinyal değişiminde tetikleneceğini belirler. 3 farklı tetikleme modu vardır:
    • Pin.IRQ_FALLING: Pin lojik YÜKSEK (3.3V) seviyesinden DÜŞÜK (GND) seviyesine geçtiğinde kesmeyi tetikler (Düşen Kenar tetiklemesi).
    • Pin.IRQ_RISING: Pin lojik DÜŞÜK seviyesinden YÜKSEK seviyesine geçtiğinde kesmeyi tetikler (Yükselen Kenar tetiklemesi).
    • Pin.IRQ_CHANGE: Pindeki her türlü lojik seviye değişiminde kesmeyi tetikler.
  • handler: Kesme olayı gerçekleştiğinde arka planda çağrılacak olan ISR fonksiyonunu işaret eder.

Uygulama Projesi: PIR Hareket Sensörlü Akıllı Aydınlatma

Öğrendiğimiz kesme mimarisini test etmek için pratik bir proje gerçekleştireceğiz. Bu projede, bir PIR hareket sensörü hareket algıladığında kesme tetiklenecek ve bağlı olan LED’i 20 saniye boyunca yakacaktır.

ESP32 ESP8266 MicroPython Kesme Devresi

Gerekli Donanım Bileşenleri

  • ESP32 veya ESP8266 Geliştirme Kartı
  • 5mm veya 3mm LED
  • 330Ω Direnç (Akım sınırlayıcı)
  • PIR Hareket Sensörü (Örn: Mini AM312)
  • Breadboard (Devre Tahtası)
  • Bağlantı Kabloları (Jumper)

ESP32 İçin Bağlantı Şeması

ESP32 geliştirme kartını kullanıyorsanız devrenizi bu şemaya göre kurun:

ESP32 MicroPython PIR Kesme Bağlantısı

ESP8266 İçin Bağlantı Şeması

Eğer ESP8266 NodeMCU kartı kullanıyorsanız devrenizi bu şemaya göre kurun:

ESP8266 MicroPython PIR Kesme Bağlantısı

Önemli Teknik Detay: Bu projede kullandığımız kompakt Mini AM312 PIR sensörü doğrudan 3.3V gerilim ile çalışır. Ancak endüstride yaygın bulunan standart HC-SR501 sensörleri 5V beslemeye ihtiyaç duyar. HC-SR501 kullanıyorsanız, sensörün VCC pinini kartın 5V (Vin / VU) pinine bağlamanız veya sensörü 3.3V ile çalışacak şekilde modifiye etmeniz gerekmektedir.

Aşağıda Mini AM312 modelinin bacak bağlantı şemasını paylaşıyoruz. Farklı bir sensör kullanıyorsanız devreyi enerjilendirmeden önce mutlaka veri kataloğunu (datasheet) inceleyin.

AM312 PIR Sensör Pin Çıkışları

MicroPython Kaynak Kodu

Hareketi kesme kullanarak algılayan ve çıkış pini üzerindeki LED’i kontrol eden ortak MicroPython kodu şu şekildedir. Bu kod hem ESP32 hem de ESP8266 mimarileriyle tam uyumludur:

from machine import Pin
from time import sleep

motion = False

def handle_interrupt(pin):
    global motion
    motion = True
    global interrupt_pin
    interrupt_pin = pin

led = Pin(12, Pin.OUT)
pir = Pin(14, Pin.IN)

pir.irq(trigger=Pin.IRQ_RISING, handler=handle_interrupt)

while True:
    if motion:
        print('Hareket tespit edildi! Kesmeyi tetikleyen pin:', interrupt_pin)
        led.value(1)
        sleep(20)
        led.value(0)
        print('Hareket sonlandı.')
        motion = False

Kodun Teknik Analizi ve Satır Açıklamaları

İlk aşamada donanımsal kontrol için machine modülünden Pin sınıfını dahil ediyoruz. Süre gecikmeleri oluşturmak amacıyla da time kütüphanesinden sleep fonksiyonunu çağırıyoruz:

from machine import Pin
from time import sleep

Hareket durumunu ana kod akışına haber vermek için boolean yapıdaki motion adında global bir bayrak değişkeni oluşturuyoruz. Başlangıçta hareket olmadığı için değerini False olarak atıyoruz:

motion = False

Kesme anında donanımın çağıracağı ISR fonksiyonunu yazıyoruz:

def handle_interrupt(pin):
    global motion
    motion = True
    global interrupt_pin
    interrupt_pin = pin

PIR sensörü hareket algılayıp çıkış pinini lojik-1 seviyesine çektiğinde bu fonksiyon otomatik olarak yürütülür. Fonksiyona parametre olarak gelen tetikleyici pin nesnesi (pin), global olarak tanımlanan interrupt_pin değişkenine atanır. Bu yöntem, birden fazla kesme pini tanımlandığı durumlarda kesmenin tam olarak hangi pin üzerinden geldiğini ayırt edebilmek açısından kritik öneme sahiptir.

Önemli Uyarı: Kesme servis rutinleri içerisinde kesinlikle print(), sleep() veya yoğun döngü gerektiren yavaş kod blokları çalıştırılmamalıdır. Bu tür yavaş işlemler bellek taşmalarına (memory overflow) ve mikrodenetleyicinin kilitlenmesine neden olabilir. Bu yüzden sadece global bayrağı True yapıp çıkıyoruz.

LED için GPIO 12’yi çıkış, PIR sensör verisi için ise GPIO 14’ü giriş pini olarak tanımlıyoruz:

led = Pin(12, Pin.OUT)
pir = Pin(14, Pin.IN)

PIR sensörünün giriş pinine, yükselen kenar (lojik 0’dan 1’e geçiş) tetiklemeli kesmeyi ekliyoruz:

pir.irq(trigger=Pin.IRQ_RISING, handler=handle_interrupt)

Ana döngü içerisinde sürekli olarak motion bayrağını takip ediyoruz. Eğer bayrak True olduysa (yani kesme fonksiyonu çalıştıysa), LED’i yakıyor, terminale bilgi yazdırıyor ve 20 saniye bekledikten sonra LED’i söndürüp bayrağı tekrar False değerine çekiyoruz:

if motion:
    print('Hareket tespit edildi! Kesmeyi tetikleyen pin:', interrupt_pin)
    led.value(1)
    sleep(20)
    led.value(0)
    print('Hareket sonlandı.')
    motion = False

Burada sistemi basit tutmak adına 20 saniyelik beklemeyi sleep() fonksiyonu ile gerçekleştirdik. Ancak daha kararlı ve işlemciyi bloke etmeyen profesyonel projelerde zamanlama yönetimi için donanımsal zamanlayıcıları (Timer) veya millis tabanlı sayaç kontrol yöntemlerini kullanmanız tavsiye edilir.

Projenin Çalıştırılması

Devre kurulumunu yaptıktan sonra kodu Thonny veya uPyCraft IDE üzerinden ESP kartınıza yükleyin. Sensörün önünde bir hareket algılandığı anda kesme anında tetiklenecek, LED yanacak ve IDE arayüzündeki konsola (Shell) tetiklenme detayları yazdırılacaktır.

MicroPython Kesme Konsol Çıktısı

20 saniyelik süre tamamlandığında ise LED otomatik olarak sönecektir.

Teknik Dipnot: Mini AM312 sensörünün dahili donanımsal tetiklenme süresi varsayılan olarak 8 saniyedir. Bu nedenle sensör, ilk hareket algılandıktan sonraki 8 saniye boyunca yeni bir hareket algılaması yapmaz ve çıkışını lojik-1 seviyesinde tutmaya devam eder.

Genel Değerlendirme

Bu rehberimizde, MicroPython platformunda kesme mimarisini donanımsal hareket algılama projesi üzerinden detaylıca inceledik. Burada öğrendiğiniz kesme yapısını buton algılama, enkoder okuma, optik sensörler gibi hız ve hassasiyet gerektiren her türlü senaryoya kolaylıkla uyarlayabilirsiniz.

ESP32 ve ESP8266 kartlarını MicroPython ile kodlamaktan keyif alıyor ve daha derinlemesine projelere imza atmak istiyorsanız, sitemizdeki zengin içerik arşivini inceleyebilirsiniz:

ESP32 ve ESP8266 Geliştirici Kütüphanesi

Yorum yapma özelliği, forum tarafından gelen istek sebebiyle kapatılmıştır. Lütfen tartışmalar ve sorularınız için topluluk forumumuza katılın.