MicroPython Kesmeler Kullanımı ESP32 ve ESP8266

Bu yazımızda MicroPython kesmeler kullanımına göz atıyoruz. İçeriktekileri eksiksiz takip etmek için ESP32 veya ESP8266’nızda MicroPython bellenimine(firmware) ihtiyacınız var. Ayrıca kodu yazıp karta yüklemek için bir IDE’ye ihtiyacınız var. Thonny IDE veya uPyCraft IDE kullanmanızı öneririz:

Thonny IDE

uPyCraft IDE

Kesmelere/Interrupts Giriş

Kesmeler, mikrodenetleyici programlarında işlerin otomatik olarak gerçekleşmesi için yararlıdır ve zamanlama sorunlarının çözülmesine yardımcı olabilir.

Kesintilerle mevcut pin değerini sürekli kontrol etmeniz gerekmez. Bir değişiklik algılandığında, bir olay tetiklenir – bir işlev çağrılır. Bu işleve kesme servis rutini (ISR) denir.

Bir kesinti olduğunda, işlemci bir görevi yürütmek için ana programın yürütülmesini durdurur ve ardından aşağıdaki şekilde gösterildiği gibi ana programa geri döner.

MicroPython Kesmeler Kullanımı ESP32 ve ESP8266 micropython kesmeler

Bu, özellikle, hareket algılandığında veya pin durumunu sürekli kontrol etmeye gerek kalmadan bir düğmeye basıldığında bir eylemi tetiklemek için kullanışlıdır.

ESP32 kesme pinleri: GPIO 6 ve GPIO 11 hariç tüm GPIO’ları kesme olarak kullanabilirsiniz.

ESP8266 kesme pinleri: GPIO 16 hariç tüm GPIO’ları kesme olarak kullanabilirsiniz.

MicroPython’da Kesme Ayarlama

MicroPython’da kesme ayarlamak için sonraki adımları izlemeniz gerekir:

1. Bir kesme işleme işlevi tanımlayın: Kesme işleme işlevi mümkün olduğunca basit olmalıdır, böylece işlemci ana programın yürütülmesine hızlı bir şekilde geri dönebilir. En iyi yaklaşım, örneğin genel bir değişken kullanarak kesintinin gerçekleştiğini ana koda bildirmektir. Kesinti işleme işlevi, Pin türünde bir parametre kabul etmelidir. Bu parametre geri arama işlevine döndürülür ve kesintiye neden olan GPIO’ya başvurur.

def handle_interrupt(pin):

2. Giriş olarak bir kesme pini görevi görecek GPIO’yu ayarlayalım. Örneğin:

pir = Pin(14, Pin.IN)

3. irq() yöntemini çağırarak bu pine bir kesme ekleyelim:

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

irq() yöntemi aşağıdaki bağımsız değişkenleri kabul eder:

  • trigger: bu tetikleme modunu tanımlar. 3 farklı koşulu vardır:
    • Pin.IRQ_FALLING: Pin YÜKSEK’ten DÜŞÜK’e gittiğinde kesmeyi tetikler.
    • Pin.IRQ_RISING: Pin DÜŞÜK’ten YÜKSEK’e gittiğinde kesmeyi tetiklemek için.
    • Pin.IRQ_CHANGE: Kesmeyi her iki kenarda tetiklemek için kullanılır (bu, herhangi bir değişiklik algılandığında anlamına gelir)
  • handler: Kesme algılandığında çağrılacak bir işlevdir, kodumuzda handle_interrupt() işlevi kullanılır.

PIR Hareket Sensörlü Proje Örneği

Kesmeleri nasıl ele alınacağını göstermek için PIR hareket sensörü ile basit bir proje oluşturacağız. Hareket algılandığında 20 saniye boyunca bir LED yakacağız.

MicroPython Kesmeler Kullanımı ESP32 ve ESP8266 micropython kesmeler

Gerekli Malzemeler

  • ESP32 ya da ESP8266
  • 5mm LED ya da 3mm LED
  • 330Ω direnç
  • PIR Hareket Sensörü
  • Devre tahtası
  • Bağlantı kabloları

Devre Şeması – ESP32

ESP32 kartı kullanıyorsanız bu şematik diyagramı kullanın:

MicroPython Kesmeler Kullanımı ESP32 ve ESP8266 micropython kesmeler

Devre Şeması – ESP8266

Eğer ESP8266 kartı kullanıyorsanız bu şematik diyagramı kullanın:

MicroPython Kesmeler Kullanımı ESP32 ve ESP8266 micropython kesmeler

Önemli: Bu projede kullandığımız Mini AM312 PIR Hareket Sensörü 3,3V’ta çalışır. Ancak, HC-SR501 gibi başka bir PIR hareket sensörü kullanıyorsanız 5V’ta çalışır. 3,3V’ta çalışacak şekilde değiştirebilir veya Vin pinini kullanarak basitçe çalıştırabilirsiniz.

Aşağıdaki şekilde Mini AM312 PIR hareket sensörünün pin çıkışını sağlıyoruz. Başka bir hareket sensörü kullanıyorsanız, devreyi kurmadan önce mutlaka pin çıkışını kontrol edin.

MicroPython Kesmeler Kullanımı ESP32 ve ESP8266 micropython kesmeler

MicroPython Kodu

İşte hareketi algılayan ve hareket algılandığında LED’i yakan komut dosyası. Bu kod hem ESP32 hem de ESP8266 ile 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, kesme sebebi:', interrupt_pin)
    led.value(1)
    sleep(20)
    led.value(0)
    print('Hareket durdu!')
    motion = False

Kesmeleri kullanmak için machine modülünden pin sınıfını içe aktarın. Ayrıca, komut dosyamıza bir gecikme eklemek için sleep yöntemini time modülünden içe aktarırız.

from machine import Pin
from time import sleep

True ya da False olabilen, hareket adlı bir değişken oluşturuyoruz. Bu değişken, hareketin algılanıp algılanmadığını gösterecektir (bu, kesme işleme işlevinde değiştirilecek olan global değişkendir).

motion = False

Ardından, handle_interrupt adlı bir işlev oluşturuyoruz.

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

Bu fonksiyon her hareket algılandığında çağrılır. handle_interrupt işlevi, kesme gerçekleştiğinde pin sınıfına ait bir nesnenin geçirileceği bir giriş parametresine (pin) sahiptir (kesmeye hangi pinin neden olduğunu gösterir).

Burada kesme neden olan pini interrupt_pin değişkenine kaydediyoruz. Bu durumda sadece bir kesme pinimiz olduğu için pek kullanışlı değildir. Ancak, aynı kesme işleme işlevini tetikleyen birkaç kesmemiz varsa ve kesmeye hangi GPIO’nun neden olduğunu bilmek istiyorsak bu yararlı olabilir.

Örneğimizde, handle_interrupt işlevi, hareket değişkenini True olarak değiştirir ve kesme pinini kaydeder. Kesme işlevlerini mümkün olduğunca kısa tutmalı ve içindeki print() işlevini kullanmaktan kaçınmalısınız. Ardından, ana kod, kesinti gerçekleştiğinde olmasını istediğimiz her şeye sahip olmalıdır.

Not: Hareketin hem işlev içinde hem de kod boyunca kullanılabilir olmasını istediğinizden, hareketin global olarak bildirilmesi gerekir. Aksi takdirde, hareket algılandığında hiçbir şey olmaz, çünkü hareket değişkeni kodun ana gövdesinde değil, işlevin içinde değişir.

Pin nesnesi oluşturmamız gerekiyor. Biri GPIO 12’deki LED için, diğeri GPIO 14’teki PIR hareket sensörü için.

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

Ardından, irq() yöntemini çağırarak pir’de bir kesinti ayarlarız.

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

loop() kısmında, hareket değişkeni True olduğunda, LED’i 20 saniye boyunca açarız ve hareketin algılandığını ve kesintiye hangi pinin neden olduğunu belirten bir mesaj yazdırırız.

if motion:
  print('Hareket tespit edildi, kesme sebebi:', interrupt_pin)
  led.value(1)
  sleep(20)

20 saniye sonra LED’i kapatın ve hareketin durduğunu belirten bir mesaj yazdırırız.

led.value(0)
print('Hareket durdu!')

Son olarak, hareket değişkenini False olarak ayarlarız:

motion = False

Hareket değişkeni, yalnızca hareket algılanırsa ve handle_interrupt işlevi çağrılırsa yeniden True olabilir.

Basit olması için, bu örnekte LED’i 20 saniye boyunca açık tutmak için bir gecikme kullanıyoruz. İdeal olarak, zamanlayıcıları(millis) kullanmalısınız.

Son Hal

Kodu ESP32/ESP8266 kartınıza yükleyin. Hareket algılandığında LED 20 saniye boyunca yanmalı ve Shell’e bir mesaj yazdırılmalıdır.

MicroPython Kesmeler Kullanımı ESP32 ve ESP8266 micropython kesmeler

20 saniye sonra LED söner.

Not: AM312 PIR hareket sensörünün varsayılan gecikme süresi 8 saniyedir. Bu, son tetiklemenin üzerinden 8 saniye geçmeden tetiklenmeyeceği anlamına gelir.

Özetle

Örneğimizde, kesmeyi tetiklemek için bir PIR hareket sensörü kullandık. Ancak sunulan örnek, örneğin bir düğmeye basıldığını algılamak için de kullanılabilir.

ESP32 ve ESP8266 kartlarını MicroPython ile programlamayı seviyorsanız ve daha fazlasını öğrenmek istiyorsanız, aşağıdaki kategori sayfamıza göz atın:

ESP32 ve ESP8266 İçerikleri