Interrupt Problemi (Çözüldü)
  • Arduino mega 2560 R3 de attachInterrupt ile led bile yakamıyorum.

    Bulduğum örneklerde "volatile" diye bir sabit gibi birşey kullanmış bunun tam olarak ne işe yaradığını anlamadım.

    Örnek vermek gerekirse bendeki arduinoda 2, 3, 18, 19, 20 ve 21 nolu bacaklar interrupt pinleri.

    Devreyi if yapısıyla çalıştırıyorum; ancak interrupt ile çalıştıramıyorum.


    //INTERRUPT
    int pin=2;
    int pinled=42;
    volatile int state = LOW;

    void setup()
    {

    pinMode(42, OUTPUT);
    digitalWrite(42, HIGH);
    pinMode(pin, INPUT);
    attachInterrupt(2,led,RISING);

    }

    void loop()
    {

    }

    void led()
    {
    digitalWrite(pinled,LOW);
    delay(5000);
    digitalWrite(pinled,HIGH);

    }

    //IF

    int pin=2;
    void setup()
    {

    pinMode(42, OUTPUT);
    digitalWrite(42, HIGH);
    pinMode(pin, INPUT);

    }

    void loop()
    {

    int x=digitalRead(pin);
    if(x==1)
    { digitalWrite(42, LOW);
    delay(2000);
    digitalWrite(42, HIGH);

    }
    }


  • Kodun sürekli çalışması için loop()'un içine yazılması lazım. Siz INTERRUPT'ta loop()'u boş bırakmışsınız, altta void led() fonksiyonu tanımlamışsınız. O sadece tanım. loop()'un içinde çağırmanız lazım onu.
  • Merhaba,

    Gördüğüm kadarıyla kodda sıkıntı yok. Interrupt yaptırmak için loop'ta çağırmanıza gerek yok.

    Fakat siz interrupt yaptırmak için dışarıdan mı sinyal veriyorsunuz devrenize? Yani interrupt'ı aktif edecek sinyali kod içerisinde mi yoksa dışaran mı üretmek istiyorsunuz?

    Eğer Kod içinden yapacaksanız, Ahmet abinin dediği gibi loop içerisinde, "2" pin'ine giden herhangi başka bir dijital pin'i HIGH yapmanız gerekir.

    Ayrıca pinMode(pin, INPUT); kısmını kaldır, interrupt için gerekmiyor input olması.

    Kendi yazdığım örnek bir kod yükledim, belki yardımcı olur.

    Ayrıca volatile olayı, interrupt fonksiyonun içerisinde tanımladığınız değişkeni , ana loop() fonksiyonu içerisine taşımanıza olanak sağlar.



    int potPin= 0;
    int k=0;

    unsigned long dutycycle;
    volatile int state;

    void setup()
    {

    pinMode(pin2, OUTPUT);
    pinMode(pin3, OUTPUT);
    pinMode(pin4, OUTPUT);
    pinMode(pin5, OUTPUT);

    attachInterrupt(5, Rising, RISING); // Bu pine gelen sinyal HIGH'a geçerse aktif
    attachInterrupt(4, Falling, FALLING); // Bu pine gelen sinyal LOW'a geçerse aktif


    }

    void loop()
    {

    //başka işler yaptırabilirisiniz.

    }

    void Rising()
    {
    digitalWrite(7, HIGH);
    digitalWrite(8, HIGH);

    }

    void Falling()
    {
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    }
  • Sayın alfteam;

    Harici interrupt kullanıyorum. Bunun için tetikleme devresi alttaki linkteki gibidir.
    http://c1212.hizliresim.com/14/k/gztzu.png

    Sizin kodunuzda

    "unsigned long dutycycle;
    volatile int state;"

    kısmında int olarak tanımladığınız "state" değişkeni lokal olarak sadece çalıştığı fonksiyon için değil aynı zamanda loop() fonksiyonu içinde geçerli oluyor. Doğru mu anlamışım?

    Eğer böyle ise neden global değişken olarak tanımlamıyoruz da volatile olarak bir değişken tanımlıyoruz. Interrupt içeren bir proğramda volatile olmasa proğram çalışır mı?

    Teşekkürler.
  • Bir çalışma masası düşünün, üzerinde 2 kat raf var; çalışırken ilk raftan sürekli kitap alıp yerine yenisini koyuyorsunuz, kitabın üzerini çizip, notlar alıp rafın başka bir noktasına koyuyorsunuz. 2. rafta da sizin içindeki notları referans aldığınız bir defter var. Bu defterin içinde bir yeri değiştirirseniz çalışmanız sekteye uğruyor. Burada 2. raf RAM, ilk raf registerlardır. Volatile değişken RAM'den çağırılır.

    Defterdeki bir şeyi değiştirince sekteye uğrama olayı nasıl oluyor diye sorarsanız şöyle açıklanabilir; Arduino'da işlemci programlamanın çok derinine inemiyor olsak da(Arduino bu konuda yüzeysel kalıyor), bir şekilde donanımsal kaynakları kontrol ediyoruz. Donanımsal kaynaklarda aynı anda çalışan bir kaç rutin var. ISR denilen Interrupt Service Routine kod akışına(standart işlemleri kastediyorum) paralel çalışan bir servis. Bunu da iki şeritli bir yola benzetebiliriz, ilk şerit otomobillere, diğeri kamyonlara ayrılmış olsun. Araçlar kendi şeridinden giderken biri diğer şeride geçtiği zaman trafik akışı bozuluyor. İlk şeritte otomobiller küçük ve çevik olduğu için sollama vs. gibi atraksiyonlar yapabiliyorlar. Birinci şeritteki bu hengameye bir kamyon koyarsanız otomobillerin kamyonun hareketini engelleme ihtimali doğar.

    Interrupt içeren bir program volatile olmasa da çalışabilir ama standart işlemlerin ISR'yi nasıl etkileyeceği belli olmadığı için volatile kullanılıyor. Arduino'da volatile dışında bir şey çalışır mı diye denemedim ama muhtemelen interrupt fonksiyonunu yazarken volatile dışındakileri engellemişlerdir.
  • Sayın mekatronik,

    Ahmet Abi'nin dediği doğru, volatile değişkeni ile ancak loop ve interrupt rutini arasında bağ kurabilirsin. Sen bir değişkeni global olarak da tanımlasan, interrupt içerisine çağıramaya bilirisin. Mesela alttaki örneği incelersen state değişkeni ancak volatile ise interrupt içerisinde çalışacaktır.

    Diğer soruna gelince, senin örneğinde de olduğu gibi değişken taşıma gibi bir durum yoksa volatile bir değişken tanımadan da interrupt kullanabilirsin.

    Aklıma gelen şu, Yazılımında
    int pinled=42; yerine
    #define pinled 42 ekler misin kodun başına ?
    Ya da direk kod içine digitalWrite(42, HIGH) yazmayı dener misin?
    Bir de böyle dene istersen. Belki o değişken verisi tam aktarılamadığından sorun oluyordur.

    // toggles LED when interrupt pin changes state

    int pin = 13;
    volatile int state = LOW;

    void setup()
    {
    pinMode(pin, OUTPUT);
    attachInterrupt(0, blink, CHANGE);
    }

    void loop()
    {
    digitalWrite(pin, state);
    }

    void blink()
    {
    state = !state;
    }
  • Sayın aflteam;

    İnterrupt girişini pull up yaptım. Dediğiniz gibi çıkışı define ile tanımladım; ancak yine interrupt devreye girmiyor. Ve yine IF ile devre çalışıyor. Maalesef interrupt çalışmıyor.

    giriş:

    http://www.google.com.tr/imgres?q=pull+up+resistor&um=1&hl=tr&sa=N&tbo=d&biw=1366&bih=643&tbm=isch&tbnid=Y4sUvsW5f5rMFM:&imgrefurl=http://www.madsciencenotebook.com/node/4&docid=ycdOEItDC3YG4M&imgurl=http://www.madsciencenotebook.com/files/pullup.png&w=350&h=350&ei=e6TVUJGyLuaJ4gSa1oDoDQ&zoom=1&iact=hc&vpx=211&vpy=114&dur=2453&hovh=225&hovw=225&tx=115&ty=154&sig=109124288243488075162&page=1&tbnh=145&tbnw=149&start=0&ndsp=24&ved=1t:429,r:2,s:0,i:91

    Kod:

    int pin=2;
    #define pinled 42


    void setup()
    {

    pinMode(pinled, OUTPUT);
    digitalWrite(pinled, HIGH);
    pinMode(pin, INPUT);
    attachInterrupt(2,led,FALLING);


    }

    void loop()
    {
    }

    void led()
    {
    digitalWrite(pinled,LOW);
    delay(5000);
    digitalWrite(pinled,HIGH);

    }
  • Sorunu ancak deneyerek anlayabiliriz, müsait olursam aynı kodu test edicem ama siz şunları bir dener misiniz?

    FALLING yerine RISING yazın,
    2 pini yerine baska bir interrupt pini kullanabilirsiniz,
    Pull-up/down koymadan, arduino'nun kendi 5V'unu direk interrput pini'ne kablo ile sok/çıkarıp basitçe dener misiniz?

    Bir de interrupt fonksiyonu içerisinde delay fonksiyonu çağırmamalısınız. Çünkü o da ayrı bir rutin ile kontrol ediliyor.
    http://arduino.cc/forum/index.php/topic,41819.0.html
  • Sorunu buldum gibi. Zira SerialMonitor ü de kullanarak anladım ki kesme meydana geliyor.Ama bu kezde alt proğramda board kilitleniyor sanki. Tam olarak durumu anlayınca çözümü burada paylaşacağım.
  • Sorun tam olarak şundan dolayı kaynaklanıyormuş. Örneğin 21 nolu bacak INT5 diye geçiyorsa ben attachInterrupt(21, altprogram, RISING); şeklinde yazıyordum. Halbuki hangi interrupt ise onun kodu yazılması lazım imiş. Yani şu şekilde olması lazım imiş. """attachInterrupt(5, altprogram, RISING);"""

    Ancak şimdi de şöyle bir sorunla karşılaştım. O da kesmenin içinde "delay()" fonksiyonunu kullanamamam. Bir link vermişsiniz; ancak tam olarak anlayamadım. Anladığım kadarıyla ayrı bir kütüphane gerekiyor. Eğer böyleyse bu kütüphaneyi nereden ve nasıl ekleyeceğimiz konusunda bir bilginiz var mı? Teşekkürler. İyi günler.
  • kesmenin içerisine genel bir değişken ata bekleme = true; yap.
    sonra onu da if(bekleme) ile loop içerisinde kontrol et. yani gecikme istiyorsan baştan kesmeye işlemini yaptır sonra loop içerisine dönünce kesme varsa if(bekleme) bloğuna girsin. if sonunda da bekleme = false yap olsun bitsin.

    unutmayın ki kesmenin esprisi loop rutinini çalışırken o an delay içerisinde dahi olsa dışarıdan yükselen,düşen,değişen kenar hareketi gelirse kesme işlemine atadığınız loop dışındaki fonksiyon, hızlıca çalışsın ve loop içerisinde kaldığı yere geri dönsün amacıyla kullanılır.

    yani siz gecikmeli bir işlem yapmaya çalıştığınızda bunu kesmesiz de yapabilirsiniz. kesme işleminin hiç bir esprisi kalmamakta.

    kesmeyi makinalardaki acil stop gibi düşünebilirsiniz.

    makina çalışırken bi anda bi komut gelir ve herşeyi bırakır onu yapar. bu acil stop örneğinden bir farkı ise interrupt -yani kesme-, kaldığı yere geri döner ve kalan satırları -yani loop'ta kaldığı yerden- işlemeye devam eder.
  • buraya da kesmeyle ilgili şeker bir örnek bırakalım.

    // pin definitions
    int ledPin = 3;
    int buttonPin = 2;

    // global variables
    int toggleState;
    int lastButtonState = 1;
    long unsigned int lastPress;
    volatile int buttonFlag;
    int debounceTime = 20;

    void setup() {
    // setup pin modes
    pinMode(ledPin, OUTPUT);
    pinMode(buttonPin, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(buttonPin), ISR_button, CHANGE);
    }

    void loop() {
    if ((millis() - lastPress) > debounceTime && buttonFlag)
    {
    lastPress = millis(); //update lastPress
    if (digitalRead(buttonPin) == 0 && lastButtonState == 1) //if button is pressed and was released last change
    {
    toggleState = ! toggleState; //toggle the LED state
    digitalWrite(ledPin, toggleState);
    lastButtonState = 0; //record the lastButtonState
    }

    else if (digitalRead(buttonPin) == 1 && lastButtonState == 0) //if button is not pressed, and was pressed last change
    {
    lastButtonState = 1; //record the lastButtonState
    }
    buttonFlag = 0;
    }
    }

    void ISR_button()
    {
    buttonFlag = 1;
    }

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Login with Facebook
Açık kaynak kültürü gereği, çözdüğünüz problemlerin çözümlerini paylaşmayı lütfen unutmayın.