IOC interrupta while döngüsü okumama sorunu

Başlatan bladekel, 19 Şubat 2019, 17:50:09

bladekel

Öncelikle herkese merhabalar.

16f1824 kullanarak encoder okuduğum bir projem var.

Encoderi RA5 pininde interrupt ile okuyorum.

Devremde butonlarım da var bunları normal bir şekilde interruptsız okumaya çalışıyorum.

Encoderden veri gelmezken while(1) döngüsü içerisinde kontrol ettiğim butonları okuyabilirken encoder çalışırken bu kontrolleri yapamıyorum.

enable_interrupts(GLOBAL);
enable_interrupts(INT_RA5);


ile interrupt aktivasyonunu sağlıyorum.


#INT_RA

başlığıyla interrupt fonksiyonunu yazıyorum.


   while(TRUE)
   {
      ileri_oku();
      geri_oku();
      sw_oku();
   }

   
şeklinde de while döngüsünde kontrolleri yapıyorum.

Nerede hata yapıyorum ve/veya ne yapmam gerekir.

Şimdiden yardımlarınız için çok teşekkürler....

MB_77

#1
bu mesaj tarafımdan silinmiştir.

bladekel

Alıntı yapılan: MB_77 - 19 Şubat 2019, 22:52:01
selam,
açıkcası verdiğiniz kod çok fazla yorum yapmaya yeterli değil. ancak en olası sebep bence kesmeye gidince geri dönememekten kaynaklanıyor gibi. kesme rutini içerisinde bir bayrak işaretleyin ve ana rutinde bu bayrak işaretliyse bir led yakın. böylece kesmeye girdiğini ve çıktığını kolayca doğrularsınız.

Aslında sorun dediğiniz gibi. Kesmeye girince ana döngüyü kontrol etmiyor.
Kesmede encoder kontrolü yaptığımdan dolayı ortlama 60Hz'lik bir döngüde kesmenin içerisinde işlem yapılıyor ve bu esnada da ana döngüyü hiçbir şekilde kontrol edemiyor.

Kod aslında uzun ve karışık olabilceğini düşünerekten eklemedim.

Mantık olarak yönlendirme yapılabilirse aslında çözerim diye düşünüyorum.... 

MB_77

#3
bu mesaj tarafımdan silinmiştir.





bladekel

Alıntı yapılan: MB_77 - 20 Şubat 2019, 10:54:21
ana mantık; kesmenin çok kısa sürede tamamlanıp ana döngüye dönmesini sağlamak olmalıdır.

buton kaçırdığına göre en az 50-100ms sürüyor olmalı kesme rutini. tabi rutinin doğru çalıştığını varsayıyorum. doğru mu çalışıyor anlamak kolay aslında. sürekli basılı tutun butona. kesmede hata yoksa eninde sonunda butonu algılamalı.

sensörden gelen sinyal düzeni nedir ki kesmede çok uzun süre kalması gerekiyor.
kesme rutinini eklerseniz daha somut konuşmak mümkün olur.

aşağıdaki enkoder örneği  fikir verebilir;

https://etepic.com/index.php/topic,4024.0.html

Öncelikle alakanız için teşekkürler....


#INT_RA // Encoder kesmeleri
void  RA_isr(void)
{               
   if(sw_durumu == 1)enc_ilerleme = 0;
   
   enc_yeni_okuma = input(enc);
     
   if(enc_eski_okuma == 0 && enc_yeni_okuma == 1)
   {
      enc_pulse_okundugu_an = timer2_cnt; //  Pulse gelmeme kontrolü için
      enc_ilerleme = enc_ilerleme + enc_artim; // Yön bulunduktan sonra sayaç normal şekilde çalışıyor
      enc_kaydet();
     
      #if serial_aktif == 1
      if(enc_ilerleme %50 == 0) printf("M= %Ld %c",enc_ilerleme,alt_satir);
      #endif     
   }
   
   if(motor_calisma_durumu == 1)
   {
      if(motor_yonu == 1 && enc_ilerleme == acilacak_mesafe_pulse)
      {
         #if serial_aktif == 1
         printf("ilerlerken mesafeye ulasildi %Ld %c",enc_ilerleme,alt_satir);
         #endif   
         
         sistem_kapat();     
      }
     
      if(motor_yonu == 0 && sw_durumu == 1)
      {         
         #if serial_aktif == 1
         printf("Gerilerken mesafeye ulasildi %Ld %c",enc_ilerleme,alt_satir);
         #endif 
         
         sistem_kapat();
      }
   }   
   
   enc_eski_okuma = enc_yeni_okuma;
}


Sistem şöyle çalışıyor:
- 1 adet hall effect sensörümüz var ve kontrol ettiği milin üzerinde bir adet mıknatıs. Her dönüşünde encoder(çakma encoder oluyor tabiki) sayacı 1 artıyor.
- Gerekli şartlar oluştuğunda da (ya mesafe tamamlanacak, ya switch değecek ya da sistemdeki çalışmayı sağlayan butona bir kere daha basılacak) sistem_kapat adlı fonksiyondan motoru durduruyoruz.

Bu şekliyle sadece mesafeye ulaşınca duruyor, butonu veya switch'i okumuyor....

MB_77

#5
bu mesaj tarafımdan silinmiştir.

bladekel

Alıntı yapılan: MB_77 - 20 Şubat 2019, 17:29:33
selamlar,

öncelikle kesme olduğuna göre pulse gelmiş demektir;

kesme içinde ioc pinin durumunu kontrol edip buna göre işlem yapmak doğru değil. çünkü zaten değişiklik olmuş ki kesmeye girilmiş. ioc pini sadece yükselen kenarda aktif ederseniz size kesme içinde sayacı bir artırmak kalır.

dolayısıyla sinyalin gelmeme durumu diye bir şey de söz konusu olmaz, timer2 ile bekleme yapmak da manasızdır. bunu da kaldırmak gerek.

benzer olarak encoder eski okuma gibi bir değişken tutmak ve değerlendirmelere tabi tutmak da gereksizdir. sonuçta kesmedeki değerlendirmeler yükselen kenardan hemen sonra olacağından değer de hep high olacaktır.

yön bilgisini motor yönünden dolaylı olarak belirliyorsunuz bu düşük ataletli sistemlerde işe yarayabilir. hızlı ve yüksek ataletli sistemlerde pals kaçırmaya neden olabilir. sonraki aşamada belki iki sensör koyarak güvenilir hale getirebilirsiniz.

ayrıca kesme içinde lcd yazdırma komutları da iyi bir fikir değil. bu komutlar da oldukca uzun gecikmelere neden olacaktır.

rutin içerisinde switch durumunun kontrol edildiği ve açıkca durdurma komutunun verildiği bir satır göremedim.
başka bir rutin içinde olabilir ve olmalıdır. swtich de yine bir ioc pinine bağlı olmalıdır ve açıldığında motor durdurulmalıdır.

bu dili bilmediğimden kod yazarak örnek veremiyorum.  mantıksal olarak aşağıdaki gibi olmalıdır bence;



kesme rutini: (sensör için)

eğer IOCAF.5=1 ise   (ra5 değişiklik kesmesi oluşmuşsa)

eğer motor yönü 1 ise
enc_ilerleme=enc_ilerleme+1
değilse
enc_ilerleme=enc_ilerleme-1
endif

eğer enc_ilerleme=mesafe1 ise  ' (mesafe1 üst sınır)
motor durdur
bayrak=1     'bayrak işaretlendi. bu bayrak ana döngüde kontrol edilir ve işaretli ise lcd mesaj yazılır.okunduktan sonra silinir.
değilse
eğer enc_ilerleme=mesafe2 ise  ' (mesafe2 alt sınır)
bayrak=2      'ana döngüde lcd mesaj yazılır
endif
endif

IOCAF.5=0   'bayrak temizlendi
endif

temelde kesme rutininde yapılacak işin çekirdeği yazılmalıdır. diğer işler ana döngüye aktarılmalı (lcd gibi)

Öncelikle tekrardan alakanız için teşekkürler....

ioc pin kontrol etmemdeki sebep araştırmalarım ve denemelerim sonucunda oldu diyelim. 16f1824 ioc pinleri yükselen veya düşen kenar kontrolü yapılamıyormuş ( en azından ccs'de). Bu yüzdendir ki böyle bir kontrol yapıyorum.

Timer2'de bekleme yapmıyorum. Pulse geldiği zamanı kontrol ediyorum.

LCD yazdırma kullanmıyorum, bahsettiğiniz printf ile sadece kontrol amaçlı , daha doğrusu bu sorunu çözebilmek için seri porttan okuyabilmek maksatlı bilgiler yazdırıyorum.

Ve hala daha bir çözüm bulamadım. Kesmeyi bekletecek bir durum yok( bağlı bulunan fonksiyonlarda bir delay yok).

Yaptığı şey, kesme içerisindeyken ana döngüyü göremiyor arkadaş....

MB_77

#7
bu mesaj tarafımdan silinmiştir.

fatih88

arkadaşlar kusura bakmayın ama tek hallefect sensörle nasıl yön bilgisi elde edebiliyorsunuz onu anlayamadım ccs c genelde flag ları otomatik siler istemez iseniz kapatırsınız bide butonları okumama sebebi motorun hızından dolayıdır sürekli kesmeye gittiği içindir kesmenin içine koşul komutu konulabilir
bilgi paylaştıkça çoğalır!!

www.fayelektronik.com

MB_77

#9
bu mesaj tarafımdan silinmiştir.

bladekel

Alıntı yapılan: fatih88 - 21 Şubat 2019, 21:17:56
arkadaşlar kusura bakmayın ama tek hallefect sensörle nasıl yön bilgisi elde edebiliyorsunuz onu anlayamadım ccs c genelde flag ları otomatik siler istemez iseniz kapatırsınız bide butonları okumama sebebi motorun hızından dolayıdır sürekli kesmeye gittiği içindir kesmenin içine koşul komutu konulabilir
Yön belirlemeyi sensörle yapmıyorum şuan için. Butondan gelen sinyale göre yapıyorum.

Butonları okuyamama sorunu aynen söylediğiniz sebepten kaynaklanıyor. Deneyeceğim....

bladekel

Alıntı yapılan: MB_77 - 21 Şubat 2019, 14:44:30
daha fazla yorum yapamayacağım ancak kesme konusuna açıklık getirmek isterim.

pic16f1824'de değişiklik kesmesi olarak isterseniz düşen isterseniz yükselen kenar kesmesi yapabilirsiniz. datasheet sayfa 141'i inceleyiniz. ccs'de yapılamaması diye bir durum söz konusu olamaz.

sayfa 141'de belirtildiği üzere genel adımlar;

intcon registerınde IOCIE bitini set ediniz
IOCAP.5    regsterini set ediniz    (negatif kenar için IOCAN regısterı ilgili pin biti kullanılır)

kesme oluştuğunda IOCAF.5 bayrağı otomatik olarak set edilir. kesmeden çıkarken siliniz.

ccs'de bu işlemleri otomatik yapan bir komut olması beklenebilir. bu olmayabilir ancak yukarıdaki registerleri set ederek de yapabilirsiniz.

İlginize çok teşekkürler... Bu dediğinizi deneyeceğim....

Powered by EzPortal