Arkadaşlar merhaba, bu yazıda Arduino’da kesme(interrupt) nedir, nerede ve nasıl kullanılır onu anlatmaya çalışacağım. Basitçe kesme, Arduino’da kullanılan işlemcimizin, bizim belirlediğimiz bir anda yapmakta olduğu işi bırakıp, bizim istediğimiz işi yapması ve sonra kaldığı yerden devam etmesidir.
Akıllarda daha iyi otursun diye bir örnek vermek gerekirse; siz belirli aralıklar ile bilgisayarınızda belirli işleri yapıyorsunuz, bilgisayar başında ödevinizi yapıp, ders çalışıyorsunuz , daha sonra düzenlenmesi gereken işleri yapıyorsunuz aniden kapı çalıyor. Ne yaparsınız? Tabiki de yaptığınız işi bırakıp kapıyı açar daha sonra yarım kalan işe geri dönersiniz. İşte bu örnekte, hali hazırda yapmakta olduğunuz iş işlemcinizin içindeki kodda yaptığınız iş. Arduino için örnek vermek gerekirse, void loop() fonksiyonu. Kapının çalması ise kesme yani interrupt.
Yukarıdaki örnekte olduğu gibi kesme işlemi kapının çalması gibi dışarıdan da gelebilir ya da belirli zaman aralıkları ile de oluşabilir. Örneğe sadık kalmak amacı ile, ders çalışırken belirli aralıklar ile hap içmeniz gibi düşünebilirsiniz.
Yukarıda kısaca anlattığım gibi kesmeler Zaman Kesmesi(Timer Interrupt) ve Dış Kesme(External Interrupt) olarak ikiye ayrılır.
Interrupt Neden Kullanılır?
Örneğin bizim arduino’nun interrupt pinlerine bağlı bir butonumuz olsun. Normal şartlarda interrupt kullanmazdan direk buton kodu ile if-else şeklinde butonu kullanmayı denersek kodumuz sadece if kısmı geldiğinde butona basılıp basılmadığını kontrol edecek ve o zaman if’in içine girebilecek. Örneğin 5 saniye yanıp 5 saniye sönen bir led imiz olsun ve butona basıldığında ledin yanıyorsa yönmesini, sönük durumda ise yanmasını isteyelim. Bu durumda koddaki 5 saniyelik delay kısmına butona istediğimiz kadar basalım kod beklemede olduğu için hiç bir işlemi yerine getiremeyecektir.
İşte bu noktada devreye interrupt giriyor. Interrupt, kod delay fonksiyonu içinde bile olsa devreye girip istenilen işlemleri yaptırabiliyor. Yani kısaca interrupt, anlık müdehale yapamız gereken yerlerde kullanılıyor.
Kesme Çeşitleri
1)Dış Kesme(External Interrupt)
Dış kesme, Arduino’nun özel pinlerindeki voltaj değişimlerine göre davranan kesmedir.
Board | Kesme için kullanılabilecek dijital pinler |
Uno, Nano, Mini, other 328-based | 2, 3 |
Mega, Mega2560, MegaADK | 2, 3, 18, 19, 20, 21 |
Micro, Leonardo, other 32u4-based | 0, 1, 2, 3, 7 |
Zero | 4. hariç tüm dijital pinler |
MKR1000 Rev.1 | 0, 1, 4, 5, 6, 7, 8, 9, A1, A2 |
Due | Tüm dijital pinler |
Dış kesme pinleri her Arduino modelinde farklılık göstermektedir. Örneğin, Arduino UNO’nun 3. pinine bir buton bağlayalım ve kesme olarak kullanılacak şekilde ayarlayalım. Bu butona basıldığında kod her nerde olursa olsun bizim istediğimiz işlemleri yapacaktır.
Dış kesme 4 farklı şekilde yapılabilir. Bunlar;
LOW – Dijital pindeki gerilim 0 olduğunda kesmeye girer
CHANGE – Belirli dijital pinde oluşacak her gerilim değişiminde kesmeye girer. Yani pindeki gerilim 0’dan 5’e yükseldiğinde veya 5’ten 0’a düştüğünde kesmeye girer.
RISING – Yükselen kenar olduğunda kesmeye girer. Yani dijital pindeki gerilim 0’dan 5 Volta çıktığında kesmeye girer.
FALLING – Düşen kenar olduğunda kesmeye girer. Yani dijital pindeki gereilim 5’dan 0 Volta çıktığında kesmeye girer.
şeklindeki kesmelerdir.
Arduino da dış kesme AttachInterrupt(); fonksiyonu kullanılarak yapılmaktadır. AttachInterrup fonksiyonu içerisinde 3 adet değişken barındırır.
AttachInterrupt(dijitalPin,kesme fonksiyonu, kesme modu);
Bu değişkenlerin ilki dijitalPin olup Arduino’nun kesme için kullandığımız pinidir. Fakat burada dijital pin olarak Arduino’da kaçıncı pine bağladığımız değil örneğin Arduino UNO da 2. dijital pine bağlı ise 0, 3. dijital pine bağlı ise 1 yazılmalıdır.
Kesme fonksiyonu, kesmeye girildiğinde yapılması gereken işlemlerin içinde bulunduğu fonksiyondur. Void loop’un altına yazılmalıdır.
Kesme modu, kesmeye ne zaman girileceğini gösteren modlar. LOW, RISING vb.
Dış Kesme Örneği:
Dış kesmeyi bir örnek ile pekiştirelim. Örneğimizde bir led, buton ile kontrol edilecektir. Bunun için 1 adet interrupt, CHANGE modunda kullanılmıştır.
int ledPin = 8; boolean led_durumu = LOW; int butonPin = 7; void setup() { pinMode(ledPin, OUTPUT); pinMode(butonPin,INPUT); attachInterrupt(1, goz_kirpmasi, CHANGE); } void loop() { } void goz_kirpmasi() { led_durumu = !led_durumu; digitalWrite(ledPin, led_durumu); }
2)Zaman Kesmesi(Timer Interrupt)
Zaman kesmesi, belirlediğimiz süre sonunda, belirlediğimiz görevleri yapmaya yarayan kesmedir. Örneğin 1 saniyede bir kodda nerede olursak olalım sensörden veri okumak istersek bu kesmeyi kullanabiliriz. Kod o sırada delay fonksiyonu içinde bile olsa sensörden veri almaya devam edecektir.
Timer kullanımı için zaman sayıcısının değerleri ayarlanmalıdır. Zaman sayıcısı, her saat sinyalinde 1 artan sayaç gibi düşünülebilir ve belirli bir değere ulaştığında sürenin dolduğu anlaşılır ve işlemcimiz kesme fonksiyonu içerisine girer.
Örneğin 8 bitlik bir zaman sayıcımız olsun. Sayıcımızın ilk değeri 100 olarak belirlensin. Bu değer her bir saat darbesinde artacak olup 255’i geçtiği anda sıfırlanacaktır ve kesme fonksiyonu içerisine girilecektir. Bu fonksiyon ISR(TIMER1_COMPA_vect) fonksiyonudur.
Zaman kesmesinin frekansı şu formül ile bulunur:
Zaman Kesmesi(Hz) = Arduino’nun kristal Hızı/(Zaman Kesmesinin Çözünürlüğü – Sayıcının Başlangıç Değeri + 1)
Burada Arduino’nun kristal hızı 16MHz olup, zaman kesmesi çözünürlüğü 8 bit olduğu için 255’tir. yani Zaman kesmesinin frekansı maximum 62.500 olabilir.
Zaman Kesmesi Örneği:
Bu örnekte Arduino’yu ilk kullanmaya başladığımızda gördüğümüz led yakıp söndürme işlemini zaman kesmesi kullanarak yapacağız. Kodu Arduino’ya attıktan sonra, 13. pine bağlı olan ledin saniyede bir yanıp söndüğünü göreceğiz.
int ledPin = 13; boolean led_durumu = LOW; void setup(){ pinMode(ledPin,OUTPUT); cli(); // Timer1 kesmesi ayarlanıyor TCNT1 = 0; TCCR1A = 0; TCCR1B = 0; OCR1A = 15624; // 1 saniye çalışması için gerekli zaman kesmesi frekansı TCCR1B |= (1 << WGM12); TCCR1B |= (1 << CS12) | (1 << CS10); TIMSK1 |= (1 << OCIE1A); sei(); } ISR(TIMER1_COMPA_vect){ //Her kesmeye girildiğinde otomatik çalıştırılacak fonksiyon. led_durumu = !led_durumu; digitalWrite(ledPin, led_durumu); } void loop(){ delay(10000); }
Merhaba,
Dış kesme için yazmış olduğunuz kod yanlış sanırım.Buton değişkeninin 7.pine değil 3.pine bağlanması gerekli.
Evet orda bir ayrıntıyı atlamışlar
Makalede uno da 2 ve 3 numaralı pin kullanılabilir demişler ama örnekte 7 kullanılmış.
Bir sorum olacak;
Bir led düşünün ve led yandığında role ve arduino yardımı ile elektrik kesebilecek bir devre lazım çok önemli lütfen böyle biiey mümkünmü ve mümkünse varmı?
Mümkündür. LED’in durumunu Arduino’nun dijital girişlerine bağlayarak okutabilir ve bu duruma bağlı olarak bir röle veya kontaktör ile anahtarlama yapabilirsiniz.
attachInterrupt dış kesme mi yapıyor?
peki kaç tane zaman kesmesi ekleyebilirim bunun bir sınırı varmıdır ?
Zaman kesmesinin sınırı mı varmış?
mantıklı düşünürsek kaç tane timer varsa o kadar kesme yapabiliriz
Merhaba dis kesmeler void loop icinde ayri bir void x acilip onun icinde mi komutlar uygulanmali
Merhabalar, dış kesmeler için ayrı bir fonksiyon oluşturmanız ve kesme koşulunun gerçekleşmesi durumunda yapılacak işlemleri bu fonksiyon içerisine yazmanız gereklidir. Yukarıdaki kodlar arasında void goz_kirpmasi() isimli fonksiyonu örnek olarak kullanabilirsiniz.
Merhaba, sensörden gelen verinin 1 defaya mahsus gelmesini istiyorum ama arduino sürekli güç aldığı ve dolayısıyla çalıştığı için sürekli olarak sensörden değer geliyor. Bunu interrupt ile nasıl yapabilirim? Teşekkürler
Ne tip bir sensör kullandığınızı belirtmemişsiniz, fakat programınızı sensörü bir kere okuyacak şekilde yazmanız interrupt’a gerek kalmadan mümkündür. setup fonksiyonu içerisine yazılan komutlar Arduino ilk çalıştığında bir kereye mahsus gerçekleşir ve daha sonra loop fonksiyonuna geçilerek döngü tekrar etmeye başlar.
İyi günler benim bi sorum var günlerdir uğraşıyorum yapamıyorum. Soru şu elimizde 3 tane void fonsiyonu var bunların sırası ile yapılması gerekiyor mesala void 1, void 2, void 3 bunlar sırasıyla çalıştırılması gerekiyor artı olarak ta void 1 çalıştıktan 1000 saniye sonra void 2, 1000 saniye sonra void 3, 1000 saniye sonra void 1 e donecek bunu delay kullanmadan millis kullanarak yapma şansımız varmı sınır sadece delay kullanılmayacak
İyi günler, buradaki örneği inceleyerek delay kullanmadan bekleme fonksiyonu gerçekleştirebilirsiniz: https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
Merhaba kesmeleri analog sensörde okuma sıklığı için kullanabilir miyiz. Ben saniyede maksimum kaç kez analog sensör okuması yapabilirim.
hocam iyigünler 10 sn veya daha farklı değerlerde zaman kesmeleri için kullanacağımız sayısal ifade nedir nasıl hesaplanır.
merhaba hc sr 04 mesafe seösörü ile 30cm den sonra ledi yakması sonra yine 30cm den sonra ledi söndürmesi mümkün mü acilen lazım
Merhaba, bir if yazarak bunu yapabilirsiniz. Buradaki yazılarımızı inceleyebilirsiniz:
Arduino Dersleri 19: HC-SR04 Ultrasonik Mesafe Sensörü Kullanımı
Arduino ile Basit Park Sensörü Yapımı
Merhaba,
Bu devreyi ve kodları olduğu kopyeledim. tabii ki kesme pinini doğru kodladım ve bağladım. kodları yanlış yorumlamadım ise “butona ilk bas-bırak ta led yanacak, ikinci bas-bırakta led sönecek.” led kararsız çalışıyor. butona basınca, sönükse yanıyor ama bırakınca bazen yanık kalıyor bazende tekrar sönüyor. bende programda serial ekranı aktif ettim ve void goz_kirpmasi() fonksiyonu içine butona basıldığı belli olsun diye Serial.print(“+”) ekledim. serial ekranda gördümki butona bir kere bassam da ekrana birden fazla + yazıyor. bende void goz_kirpmasi() fonksiyonu içine delay(3000) ekledim. şimdilik çözüm oldu gibi. soruma gelince;
1-ledin kararsız çalışması neden oluyor olabilir? normal mi ?
2-ben delay komutu ile engelledim, doğrumu? daha kararlı bir şekilde nasıl engelleyebiliriz ?
Bugüne kadar belki çözüm bulmuşsunuzdur ama ben yine de yazayım. Sizin fiziksel olarak butona basıp çektiğiniz süre sırasında Arduino çok fazla kez çalıştığı için bu kararsızlık oluşuyor. Ben bu durumu “while” kullanarak çözüyorum. Butona basma işlemini while’a koşul olarak verip, while içine herhangi bir şey yazmazsanız butondan elinizi çekene kadar while içinde sonsuz çalışır ve bu kararsızlığı önler.
Mesela şunun gibi:
while(digitalRead(buttonPini,LOW){}
Hocam merhaba anlamadığım bir nokta var .Datasheette focna=16.10^6/2*N*(1+OCR1A) yazıyor .SBuradaki çarpı 2 ifadesi nereye gidiyor?
merhabalr bir peojem var mesafe sensörüne 10 cm yaklaşıldığında olaylar olucak ve bitiğinde durcuk bir dahaki 10 cm uyarsıs gelene kadar yardım edin lütfen
Merhaba,
Timer ile frekansı değişen 3 farklı sinyal (pwm) oluşturmak istiyorum. Oluşturulan sinyallerin herbiri belli bir sürede çalışacak . Timer ISR komutunu her sinyal için farklı bir şekilde nasıl oluşturabilirim?
Birde her değişen frekans değeri için Aynı timer ı nasıl kullabilirm? Oluşturulacak her farklı frekans değeri için timer ile bir fonksiyon mu oluşturmam gerekiyor?
Timer’ı kullanmadan istediğim frekans değerinde sinyal oluşturabilir miyim?
15624’ü ve 62.500’ü nasıl hesapladığınızı detaylı anlatabilir misiniz?
merhaba. Benimde bir sorum olacak. Aurdino ile bir motorun milinin dönüş sayısı anlık olarak (manuel programlama) girilebilirmi?
Anlık programlama mümkünse hangi kartlara ihtiyacım olacaktır?
Merhaba, arduino ile bir rpm sinyali oluşturdum(bir dijital pini aç kapa yaparak bir kare dalga). İsteğim şey bu rpm sinyalini arduino ile sürekli sabit bir frekansta verirken aynı zamanda lcd ekrana bir şeyler yazmak ve bir dijital inputtan gelen değeri kontrol etmek istiyorum bunu yapabilmek arduino ile mümkün mü?
bi projem var yardımcı olabilirmisiniz.
4 led olacak (yeşil kırmızı sarı yeşil)
buton basma hızına göre ledler değişecek
1000 – 101 milisaniye hızda = kırmızı ışık
100 – 76 milisaniye hızda = sarı ışık
75 – 61 milisaniye hızda = yeşil ışık
60 – 51 milisaniye hızda = 2 adet yeşil ışık
0 – 50 mili saniye hızda = 2 adet yeşil ve uyarı veren sarı ışık
Zaman kesmesi ile dht11’den sıcaklık değeri okumak istiyorum. void loop ()’a yazdığımda değeri alabiliyorum fakat kesmeye yazdığımda değeri sürekli 0 okuyor. Yardımcı olabilir misiniz. Baktığım tüm örnekler Led yakma üzerine. Kesme ile sensörlerden veri okuma yapılabilir mi?
dht11 ile zaman kesmesi kullanarak sıcaklık ölçmek istiyorum.
cli();
TCNT1 = 0;
TCCR1A = 0;
TCCR1B = 0;
OCR1A = 15624;
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS12) | (1 << CS10);
TIMSK1 |= (1 << OCIE1A);
sei();
}
ISR(TIMER1_COMPA_vect){
int chk = DHT11.read(DHT11PIN);
float sicaklik=(DHT11.temperature);
Serial.print("Sicaklik (Celcius): ");
Serial.println(sicaklik, 2);
}
ancak sıcaklığı hep sıfır gösteriyor. sıcaklık ölçtüğüm kodları loop() içne yazdığımda sıcaklık değerini veriyor. kesme içinde sıcaklık ölçmemesinin nedeni ne olabilir?
sicaklik degiskeni global olmalıdır. en üst kısımda tanımlayın
zamanı uzat, her saniyede bir o sensörden veri okumak sıkıntı olabilir.
Bu arada şimdi gördüm, sen neyi okudun, hangi değişkene atadın, neyi yazdırdın onlar bir bakmanı tavsiye ederim.
int chk = DHT11.read(DHT11PIN);
float sicaklik=(DHT11.temperature);
Serial.print(“Sicaklik (Celcius): “);
Merhaba kodum çalışmaya başladığı zaman zaman kesmeni geliyor ama içinden çıkamıyor bir sonsuz döngü şeklinde devam ediyor ne yapmam gerekmektedir
led_durumu = !led_durumu; bu kod ne anlama geliyor
Merhabalar;
Ben de GPS ve ivmeölçerden verilerimi alıp SD kart içine kaydetmek istiyorum. GPS verileri saniyede 5 veri alırken ivmeölçer verilerimin kesinti olmadan devam etmesini istiyorum. bu çalışmamı interrupt konutu ile yapabilir miyim?
Bu yaptığınız multi proccesing (çoklu işlem) diye geçmektedir. Eş zamanlı değil, birazcık gecikme ile bunu yapabilirsiniz.