Bu içeriğimizde, Arduino IDE kullanarak ESP8266 kesmeleri ve zamanlayıcıları nasıl kullanacağınızı öğreneceksiniz. Kesmeler, mevcut değerini sürekli olarak kontrol etmenize gerek kalmadan GPIO durumundaki değişiklikleri algılamanıza olanak tanır. Kesmeler, bir değişiklik algılandığında bir olay tetiklenir (bir işlev çağrılır).
Örnek olarak, bir PIR hareket sensörü kullanarak hareketi algılayacağız: hareket algılandığında, ESP8266 bir zamanlayıcı başlatır ve önceden tanımlanmış sayıda saniye boyunca bir LED’i açar. Zamanlayıcı geri sayımı bitirdiğinde LED otomatik olarak kapanır.
Bir kesme oluşturmak için, AttachInterrupt()‘u çağırırız ve argüman olarak GPIO kesme pinini, ISR’yi (çağrılacak fonksiyon) ve modu iletiriz. ISR işlevi, ICACHE_RAM_ATTR özniteliğini bildirmiş olmalıdır. Mod, DEĞİŞİM(CHANGE), YÜKSELEN(RISING) veya DÜŞEN(FALLING) olabilir.
attachInterrupt(digitalPinToInterrupt(GPIO), ISR, mod);
Bu eğiticiye devam etmeden önce, Arduino IDE’nizde ESP8266 eklentisinin kurulu olması gerekir. Henüz yapmadıysanız, bu içeriğe göz atın: ESP8266’yı Arduino IDE’ye Kurmak
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.
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.
Arduino IDE’de bir kesme ayarlamak için, argüman olarak kabul eden attachInterrupt() işlevini kullanırsınız: GPIO kesme pini, yürütülecek işlevin adı ve mod:
attachInterrupt(digitalPinToInterrupt(GPIO), ISR, mode);
İlk argüman bir GPIO kesmesidir. GPIO’yu bir kesme pini olarak ayarlamak için digitalPinToInterrupt(GPIO) kullanmalısınız. Örneğin, GPIO 14’ü kesme olarak kullanmak istiyorsanız, şunu kullanın:
digitalPinToInterrupt(14)
ESP8266, GPIO16 dışında herhangi bir GPIO’daki kesmeleri destekler.
attachInterrupt() işlevinin ikinci argümanı, kesme her tetiklendiğinde çağrılacak işlevin adıdır – kesme hizmeti rutini (interrupt service routine – ISR).
ISR 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öner.
En iyi yaklaşım, genel bir değişken kullanarak ve loop() içinde kesmenin gerçekleştiğini ana koda bildirmek ve bu bayrağı kontrol edip temizlemek ve kodu yürütmektir.
ISR’lerin RAM’de kesme kodunu çalıştırabilmesi için işlev tanımından önce ICACHE_RAM_ATTR‘ye sahip olması gerekir.
Üçüncü argüman moddur ve 3 farklı mod vardır:
Örneğimiz için RISING modu kullanılacaktır, çünkü PIR hareket sensörü hareket algıladığında bağlı olduğu GPIO DÜŞÜK’ten YÜKSEK’e geçer.
Bu içerik için zamanlayıcıları kullanacağız. Hareket algılandıktan sonra LED’in önceden belirlenmiş bir süre boyunca açık kalmasını istiyoruz. Kodunuzu engelleyen ve belirli bir saniye boyunca başka bir şey yapmanıza izin vermeyen bir delay() işlevi kullanmak yerine bir zamanlayıcı kullanacağız.
delay() işlevi, bağımsız değişken olarak tek bir int sayısını kabul eder. Bu sayı, programın bir sonraki kod satırına geçene kadar beklemesi gereken süreyi milisaniye cinsinden temsil eder.
delay(milisaniye cinsinden beklenecek süre);
delay(1000)’i kullandığınız zaman programınız 1 saniyeliğine durur. delay() aslında bir engelleme işlevidir. Engelleme işlevleri, bir programın söz konusu görev tamamlanana kadar başka bir şey yapmasını engeller. Aynı anda birden fazla görevin gerçekleşmesi gerekiyorsa, delay()‘i kullanamazsınız. Çoğu proje için gecikmeleri kullanmaktan kaçınmalı ve bunun yerine zamanlayıcıları kullanmalısınız.
millis() adlı bir işlevi kullanarak, programın ilk başlamasından bu yana geçen milisaniye sayısını döndürebilirsiniz.
millis();
Bu işlev neden yararlıdır? Çünkü biraz matematik kullanarak, kodunuzu engellemeden ne kadar zaman geçtiğini kolayca doğrulayabilirsiniz.
millis() işlevine aşina değilseniz, bu bölümü okumanızı öneririz. Zamanlayıcılara zaten aşina iseniz, PIR hareket sensörü projesine geçebilirsiniz.
Aşağıdaki kod parçası, led yakmak için millis() işlevini nasıl kullanabileceğinizi gösterir. 1000 milisaniye boyunca bir LED’i açar ve ardından kapatır.
const int ledPini = 26;
int ledDurumu = LOW; // ledDurumu ledin yanıp yanmayacağına karar verir
unsigned long oncekiMillis = 0; // LED'in en son güncellendiği zamanı saklar
const long sure = 1000; // yanıp sönme süresi (milisaniye)
void setup() {
pinMode(ledPini, OUTPUT);
}
void loop() {
unsigned long simdikiMillis = millis();
if (simdikiMillis - oncekiMillis >= sure) {
// LED'i en son ne zaman yaktığınızı kaydeder
oncekiMillis = simdikiMillis;
// LED kapalıysa aç ve açıksa kapa:
if (ledDurumu == LOW) {
ledDurumu = HIGH;
} else {
ledDurumu = LOW;
}
// LED'i değişkenin ledDurumu ile ayarlama:
digitalWrite(ledPini, ledDurumu);
}
}
Delay() işlevi olmadan çalışan led yakıp söndürme koduna daha yakından bakalım :
Temel olarak, bu kod önceki kaydedilen zamanı (oncekiMillis) şimdiki zamandan (simdikiMillis) çıkarır. Kalan aralıktan daha büyükse (bu durumda 1000 milisaniye), program öncekiMillis değişkenini geçerli zamana günceller ve LED’i açar veya kapatır.
if (simdikiMillis - oncekiMillis >= sure) {
// LED'i en son ne zaman yaktığınızı kaydeder
oncekiMillis = simdikiMillis;
Bu kod engelleyici olmadığından, ilk if ifadesinin dışında bulunan herhangi bir kod normal şekilde çalışmalıdır.
Artık loop() işlevinize başka görevler ekleyebileceğinizi ve kodunuz her saniye LED’i yanıp sönmeye devam edeceğini anlayabilmelisiniz.
Test etmek için bu kodu ESP8266’nıza yükleyebilirsiniz. Yerleşik LED her saniye yanıp sönmelidir.
Ufak bir seri iletişim ile her 1000 milisaniyede hazırladığımız sayaçların durumunuda kontrol edebilirsiniz.
Bu bölümde, kodunuzdaki kesmeler, ve zamanlayıcıları kullanarak bir PIR hareket sensörüyle hareketi nasıl algılayacağınızı öğreneceksiniz.
Bu öğreticiyi tamamlamak için gereken parçaların listesi:
PIR hareket sensörünü ve bir LED’i ESP8266’nıza bağlayın. LED’i GPIO 12’ye (D6) ve PIR hareket sensörü veri pinini GPIO 14’e (D5) bağlayın.
Önemli: Bu projede kullanılan Mini AM312 PIR Hareket Sensörü 3.3V ile çalışmaktadır. Ancak, HC-SR501 gibi başka bir PIR hareket sensörü kullanıyorsanız, 5V’da çalışır. 3.3V’da çalışacak şekilde değiştirebilir veya Vin pinini kullanarak basitçe çalıştırabilirsiniz.
Aşağıdaki şekil AM312 PIR hareket sensörü pin çıkışını göstermektedir.
Devreyi şematik diyagramda gösterildiği gibi bağladıktan sonra, verilen kodu Arduino IDE’nize kopyalayın.
Kodu olduğu gibi yükleyebilir veya hareket algıladıktan sonra LED’in yanacağı saniye sayısını değiştirebilirsiniz. Basitçe sureSaniye değişkenini istediğiniz saniye sayısıyla değiştirin.
#define sureSaniye 10
const int led = 12;
const int hareketSensoru = 14;
//timer kismi
unsigned long simdi = millis();
unsigned long sonTetiklenme = 0;
boolean sayaciBaslat = false;
// Hareketin algılanıp algılanmadığını kontrol eder, LED'i YÜKSEK olarak ayarlar ve bir zamanlayıcı başlatır
ICACHE_RAM_ATTR void hareketTespitEt() {
Serial.println("Hareket Tespit Edildi!!!");
digitalWrite(led, HIGH);
sayaciBaslat = true;
sonTetiklenme = millis();
}
void setup() {
Serial.begin(115200);
pinMode(hareketSensoru, INPUT_PULLUP);
// hareketSensoru pinini interrupt olarak ayarlar, interrupt fonksiyonunu atayıp RISING modunu ayarlar
attachInterrupt(digitalPinToInterrupt(hareketSensoru), hareketTespitEt, RISING);
pinMode(led, OUTPUT);
digitalWrite(led, LOW);
}
void loop() {
// simdiki zaman
simdi = millis();
// sureSaniye değişkeninde tanımlanan saniye sayısından sonra LED'i kapatır
if (sayaciBaslat && (simdi - sonTetiklenme > (sureSaniye * 1000))) {
Serial.println("Hareket durur...");
digitalWrite(led, LOW);
sayaciBaslat = false;
}
}
Şimdi koda bir göz atalım:
led ve hareketSensoru değişkenlerine iki GPIO pini atayarak başlıyoruz:
const int led = 12;
const int hareketSensoru = 14;
Ardından, hareket algılandıktan sonra LED’i kapatmak için bir zamanlayıcı ayarlamanıza izin verecek değişkenler oluşturun.
unsigned long simdi = millis();
unsigned long sonTetiklenme = 0;
boolean sayaciBaslat = false;
simdi değişkeni geçerli süreyi tutar. sonTetikleme değişkeni, PIR sensörünün hareketi algıladığı zamanı tutar. sayaciBaslat, hareket algılandığında zamanlayıcıyı başlatan bir boole değişkenidir.
setup() Kısmı
setup() kısmında, seri bağlantı noktasını 115200 baud hızında başlatıyoruz.
Serial.begin(115200);
PIR Hareket sensörünü INPUT_PULLUP olarak ayarlıyoruz:
pinMode(hareketSensoru, INPUT_PULLUP);
PIR sensör pinini bir kesme olarak ayarlamak için, daha önce açıklandığı gibi attachInterrupt() işlevini kullanıyoruz.
attachInterrupt(digitalPinToInterrupt(hareketSensoru), hareketTespitEt, RISING);
Hareketi algılayacak olan pin GPIO 14’tür ve RISING modundayken hareketTespitEt() fonksiyonunu çağırır.
LED, durumu DÜŞÜK durumda başlayan bir ÇIKIŞ olarak ayarlarız:
pinMode(led, OUTPUT);
digitalWrite(led, LOW);
loop() Kısmı
loop() işlevi sürekli olarak tekrar tekrar çalışır. Her döngüde, simdi değişkeni geçerli zamanla güncellenir.
simdi = millis();
loop() içinde başka hiçbir şey yapılmaz. Ancak, hareket algılandığında, setup() içinde daha önce bir kesme ayarladığımız için hareketTespitEt() işlevi çağrılır.
hareketTespitEt() işlevi, Seri Monitörde bir mesaj yazdırır, LED’i açar, sayaciBaslat boolean değişkenini true olarak ayarlar ve sonTetiklenme değişkenini geçerli zamanla günceller.
ICACHE_RAM_ATTR void hareketTespitEt() {
Serial.println("Hareket Tespit Edildi!!!");
digitalWrite(led, HIGH);
sayaciBaslat = true;
sonTetiklenme = millis();
}
Bu adımdan sonra kod, loop()‘a geri döner. Bu sefer sayaciBaslat değişkeni doğru olur. Yani saniye cinsinden tanımlanan süre geçtiğinde (hareket algılandığından beri), aşağıdaki if ifadesi doğru olacaktır.
if (sayaciBaslat && (simdi - sonTetiklenme > (sureSaniye * 1000))) {
Serial.println("Hareket durdu...");
digitalWrite(led, LOW);
sayaciBaslat = false;
}
“Hareket durdu…” mesajı Seri Monitörde yazdırılır, LED kapanır ve sayaciBaslat değişkeni false olarak ayarlanır.
Kodu ESP8266’nıza yükleyin. Doğru kartın ve COM bağlantı noktasının seçili olduğundan emin olun.
115200 baud hızında Seri Monitörü açın.
Elinizi PIR sensörünün önüne getirin. LED yanmalıdır ve Seri Monitörde “Hareket Tespit Edildi!!!” diyen bir mesaj yazdırılır. 10 saniye sonra LED sönmelidir.
Özetlemek gerekirse, kesintiler bir GPIO durumundaki bir değişikliği tespit etmek ve anında bir işlevi tetiklemek için kullanışlıdır.