UNAL, Faruk

learn –recursive –force <something>

Development Boards, School Projects

Arduino’da Paralel Çalışan Denetleyici

UYARI: Bu yazıyı Arduino ile yeni yeni çalışır sistemler geliştirmeye başladığımda ve birçok alan terimlerini bilmeden önce yazmıştım, bu nedenle bazı terimlerin ne olduğunun bile farkında olmadan kendimi anlatmaya çalışım. Ancak, geçmişimi de  kabullenmek ve hatırlamak adına onları silmek yerine, parantez içerisinde düzeltmeye çalışacağım. Tabii yine şu anki şuurumla 🙂


Arduino kartını, efpiceyimsi (FPGA kartına benzeteceksek ancak bu şekilde benzeyebilir 😀 ) mantıkla (O zamanlar, arkdaşım FPGA diye bir şey varmış her şeyi paralel işliyormuş demişti, ben de onu böyle sanmışım. Burada bahsedilen durum interrupt veya multiprocess/thread.) kullanabileceğimizi öğrendim bugün. Aslında uzun zamandır aklımdaydı, “Arduino ile paralel işlem yapabilir miyiz?” sorusu. “En azından paralel olarak bazı pinleri denetlesek ya” diyordum. Vaktim olduğunda araştıracaktım ki bugün okulda bitirme projesi için çalışan arkadaşlarım sağolsun, bir konu hakkında benim fikrimi alırlarken böyle bir şey yapmaya çalıştıklarını gördüm ve anahtar kelimeyi hatta hazır gelen fonksiyonu bile bulduklarını gördüm: attachInterrupt().

attachInterrupt için özel pinler var:

Bu fonksiyon şu işe yarıyor, Arduino’muz bir işlem yapıyorken paralel olarak bir yandan da sürekli tanımladığımız bir pini kontrol ediyor, pinde bir değişiklik meydana geldiğinde yine bizim tanımladığımız bir fonksiyona gidiyor. (“How it works” vermişim vay be, temelde iki tür interrupt çalışma yöntemi var diye biliyorum, detaylarını unuttum, araştırdığımda doğrusu hakkında bir yazı yazarım belki.) Şöyle düşünün, engel kontrolü yapıyorsunuz ona göre led yakıyorsunuz veya motor sürüyorsunuz, kontrolü yaptıktan sonra bir yerlere delay() yani gecikme eklediniz, Arduino gecikme içerisindeyken engel ile karşılaşırsa bunu algılamayacaktır, bu da bizi hataya götürecektir. Böyle durumlarda engeli paralel olarak kontrol edebiliriz böylece algoritma içerisindeki delay() satırlarından etkilenmeyiz. Görselleştirelim;

Arduino’nun paralel olarak sürekli pin kontrolü yapması bizi olası engellerden sürekli korur. (..sürekli koruma sağlar, gün boyu hijyende kalırsınız 😀 sabun reklamı vardı sanki böyle, neyse) Bunu yukarıda bahsettiğim attachInterrupt() yardımı ile sağlıyoruz.

Biz örnek olarak led yakıp söndüreceğiz (fakirlik, sürecek motorumuz bile yok 😀 ). Ledimiz 4 saniye delay() ile yanıp sönecek. Biz istiyoruz ki, herhangi bir sensörden veri geldiğinde delay() süresi beklenmeksizin istediğimiz bir şey yaptıralım, motoru durdurmak gibi (tabi ki biz ledi söndüreceğiz 😀 ).

Şimdi burada püf nokta interrupt içeren algoritmayı iyi oluşturmak. Bizim örneğimiz için konuşalım:

  1. Led, 4 saniye delay() ile yanıp sönüyor. Dijital 3. Pinimize giriş geldiğinde ledin durumunu terslemek istiyoruz.
  2. Interrupt fonksiyonunun içinde sadece ledin durumunu belirleyen değişkeni terslersem, değişken o an terslenir ancak delay() devam eder. Interrupt fonksiyonunun içinde delay() süresini de iptal etmem gerekiyor.

Daha iyi anlayabilmek için ikisini de göstereceğim. Önce bağlantıları şematize edeyim:

Koda geçmeden önce Uyarı: Debian ve türevlerinde attachInterrupt() içeren kod, Arduino IDE tarafından derlenirken hata veriyor.

Interrupt Fonksiyonunun İçinde Sadece Led Durumunu Terslersek


const byte ledPin = 13;
const byte interruptPin = 3;
volatile byte state = LOW;

void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, CHANGE);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
}

void loop() {
digitalWrite(ledPin, state);
delay(4000);
}

void blink() {
Serial.println("Interrupt pininde değişim algılandı.");
state = !state;
Serial.print("Led durumu: ");
Serial.println(state);
}

Sonuç:

Bu durumda, dijital 3. Pinde değişiklik olduğunda sadece state=1 ise state=0 olacak. Ancak led yanıyorsa delay() bitene kadar yine yanacak, sönük durumdaysa delay() bitene kadar yine sönük kalacak. Dijital 3. Pin bir acil butonu olsaydı bu delay() bizim için tehlike yaratır. Bu yüzden biz istiyoruz ki, anında tepki alalım, bunun için Interrupt fonksiyonu içerisine tek satırlık bir ekleme yapacağız.

Interrupt Fonksiyonunun İçinde  Led Durumunu Tersleyelim ve Loop Döngüsünü Tetikleyelim


const byte ledPin = 13;
const byte interruptPin = 3;
volatile byte state = LOW;

void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, CHANGE);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
}

void loop() {
digitalWrite(ledPin, state);
delay(4000);
}

void blink() {
Serial.println("Interrupt pininde değişim algılandı.");
state = !state;
Serial.print("Led durumu: ");
Serial.println(state);
loop();
}

Sonuç:

7 Comments

  1. Orçun Polatoğlu

    Çok güzel anlatın teşekürler

  2. Ellerinize sağlık, gerçekten güzel bir anlatım olmuş.

    • unalfaruk

      Teşekkür ederim Emre 🙂 Aslında halen öğreniyorum yeni şeyler ve farkettim ki giriş paragrafında kullandığım terimler hatalı, düzeltmeleri yapacağım 🙂

      • Ziyanı yok, açıkçası hataları fark edemedim bile. Basit bir turnike sistemi hazırlıyordum, işimi fazlası ile gördü. Direk kodlara odaklandığımdan 🙂

  3. Yusuf Cihan

    Merhaba, güzel bir anlatım olmuş, tebrik ederim. Başarılı bir şekilde çalıştırabiliyorum ancak bir sorunum var, delay veya millis fonksiyonlarını eklediğimde çalışmıyor. Detaylı bilgiyi şurada bulundurdum;
    https://www.arduinox.com/konular/interrupt-isleminde-delay-veya-millis-komutlari-calismiyor.1763/
    Bu konuda ne yapabilirim ?

    • unalfaruk

      Merhaba,

      Kesme tetiklendiğinde fonksiyona giriş yapıp bekleme zamanı tamamlanana kadar olası kesmeleri devre dışı bırakmayı deneyebilirsin;

      noInterrupts();
      unsigned long saniye = millis();
      while (millis() – saniye < 2000);
      //kodlar
      interrupts();

      Yukarıdaki kod satırlarıyla yapabilmen lazım, bu kod satırlarının üzerinde biraz çalışırsan bence istediğini elde edersin.

Leave a Reply

Theme by Anders Norén