Timer1 kesmesi (enkoder okuma) --Çözüldü--

Başlatan Eski Klasör, 17 Ocak 2016, 15:19:37

Eski Klasör

Arkadaşlar merhabalar,


Bir projem var ve bunun için enkoder (değerleri değişiklik gösterebiliyor) okumam gerekiyor.

Bu işlemi bu şekilde yapabliyorum.

#include <16f887.h>
 #fuses xt,nowdt,noprotect,nobrownout,nolvp,noput,nowrt,nodebug,nocpd
 
 #use delay (clock=4000000)
 
#use fast_io(b)
#use fast_io(a)
#define LCD_ENABLE_PIN PIN_B0
#define LCD_RS_PIN PIN_B1
#define LCD_RW_PIN PIN_B2
#define LCD_DATA4 PIN_B4
#define LCD_DATA5 PIN_B5
#define LCD_DATA6 PIN_B6
#define LCD_DATA7 PIN_B7
#include <lcd.c>
#define sen1 pin_A3

unsigned int16 x;


void main()

{
   set_tris_a(0b11111111);
   set_tris_b(0b00000000);

   lcd_init();
   x=0;
printf(lcd_putc,"\fokuma");
while(1)
{



   if(input(sen1))
   {
   x=x+1;
   printf(lcd_putc,"\fx=%lu",x);
   while(input(sen1));
   }
}
}
   



Ancak işin içerisine biraz hız girdiğinde kaçırmalar pulslerde atlamalar oluyor yani her saydırdığımda farklı sonuçlar alıyorum.

Kitaplarda ve netteki örnek uygulamalara baktığımda timer 1 kesmesi ile verilerin okunabildiğini hemde arka planda çalıştığı için başka işlemler (gelen verileri hesaplama gibi) yapılabiliyor.

Çok yazılıma hakim olmağım için (hatam varsa affola) bu şekilde yazdım.

#include <16f887.h>
#fuses xt,nowdt,noprotect,nobrownout,nolvp,noput,nowrt,nodebug,nocpd
 
#use delay (clock=4000000)
 
#use fast_io(d)
#use fast_io(c)
#define LCD_ENABLE_PIN PIN_D0
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7

#include <lcd.c>

unsigned int16 x=0;
#int_timer1 

void sayma()
{
set_timer1(65535);
x=x+1;
}


void main()
{  
   
   setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);
   set_timer1(65555);
   enable_interrupts(INT_timer1);
   enable_interrupts(GLOBAL);
   
   lcd_init();
  
while(1)
   {
     
      printf(lcd_putc,"\fx=%lu",x);
   
   }
}



Ancak derlediğimde sadece ekranda;



bu şekilde görüyorum herhangi bir değişiklik olmuyor.

Yardımlarınız için şimdiden teşekkürler   :) :)

mehmet

Enkoder tek uçlu mu? Genelde iki olmaz mı?
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr
https://creativecommons.org/licenses/by/4.0/deed.tr "CC BY"

sadogan

Tmr1 kullanma şeklin doğru deyil.
Amacın birim zamandaki devir sayısınımı  ölçmek yoksa o anki pozisyonumu görmek.
Amacın sadece enkoderin artışını görmek ise harici kesme kullanarak yapmak veya tmr1 kesmesini
kapatıp get_timer1(); ile tmr1 içerigini okuyarak bu nu lcd de gösterebilirsin.
harici kesme ile yapmak istersen
#int_ext
void harici0_int(void)
{
   disable_interrupts(INT_EXT);
   x++;
   enable_interrupts(INT_EXT);
}
tmr1 kesmesine yazdığın kodla bunu değişip kulanabilirsin

Eski Klasör

#3
Alıntı yapılan: sadogan - 17 Ocak 2016, 20:20:41
Tmr1 kullanma şeklin doğru deyil.
Amacın birim zamandaki devir sayısınımı  ölçmek yoksa o anki pozisyonumu görmek.
Amacın sadece enkoderin artışını görmek ise harici kesme kullanarak yapmak veya tmr1 kesmesini
kapatıp get_timer1(); ile tmr1 içerigini okuyarak bu nu lcd de gösterebilirsin.
harici kesme ile yapmak istersen
#int_ext
void harici0_int(void)
{
   disable_interrupts(INT_EXT);
   x++;
   enable_interrupts(INT_EXT);
}
tmr1 kesmesine yazdığın kodla bunu değişip kulanabilirsin

Amacım enkoderden aldığım veri ile step motor kontrol etmek. Bunun içinde inkjet yazıcılardan söktüğüm enkoderler var. 2 adet cıkış veriyor 4013 ile yönünü tespit edip sinyalin birinden timer için ek alıp kaç puls olduğu sayıp sonucu step motora aktarmayı düşünüyorum

mesaj birleştirme:: 17 Ocak 2016, 22:15:17

Alıntı yapılan: mehmet - 17 Ocak 2016, 19:50:52
Enkoder tek uçlu mu? Genelde iki olmaz mı?


2 ucu var sadecr birindeki sinyali sayıp yön tayinini 4013 ile yapmayı planlıyorum.

dursuncemal

isin ne kada hassas bilmiyorum ama her palste interrupta gitmek yerine  T0CKI den tmr saydirsan cok mu zaman kaybedersin?
:=

Eski Klasör

Alıntı yapılan: dursuncemal - 17 Ocak 2016, 23:47:05
isin ne kada hassas bilmiyorum ama her palste interrupta gitmek yerine  T0CKI den tmr saydirsan cok mu zaman kaybedersin?

Tam olarak anladım sayılmaz fazla iyi değilim yazılımda (yeni yeni sağdan soldan kod inceleyerek öğreniyorum).

Yapmak istediğim tam olarak;

Enkoderden veri geldiğinde bu veriyi okuyup gerekli formüllerle step motorda göndermek. örn:Basit olarak anlatmam gerekirse enkoderden (yönüne göre) 1 puls okuduğumda step motor 3 adım gidicek. 

Ancak puls kaçırmamam lazımsorunum burada kesme ve if ile yaptığımda hız faktörü adım kaçırmama sebep oluyor. Yani 1000 pulslik enkoderi hızlı döndürürsem 500-1000 arası bir değer görüyorum. Hiçbir seferde birbirini tutmuyor gelen veriler.


Bir nevi bu işlei yapmak istiyorum ama display yerine step motor kullanmak istiyorum
https://www.youtube.com/watch?v=8PZaDNG1YQs
https://320volt.com/encoder-kullanimi-aci-olcumu-ve-ccs-c-pic16f628-ornek-uygulama/

Mucit23

Alıntı yapılan: Eski Klasör - 18 Ocak 2016, 14:02:55
Tam olarak anladım sayılmaz fazla iyi değilim yazılımda (yeni yeni sağdan soldan kod inceleyerek öğreniyorum).

Yapmak istediğim tam olarak;

Enkoderden veri geldiğinde bu veriyi okuyup gerekli formüllerle step motorda göndermek. örn:Basit olarak anlatmam gerekirse enkoderden (yönüne göre) 1 puls okuduğumda step motor 3 adım gidicek. 

Ancak puls kaçırmamam lazımsorunum burada kesme ve if ile yaptığımda hız faktörü adım kaçırmama sebep oluyor. Yani 1000 pulslik enkoderi hızlı döndürürsem 500-1000 arası bir değer görüyorum. Hiçbir seferde birbirini tutmuyor gelen veriler.


Bir nevi bu işlei yapmak istiyorum ama display yerine step motor kullanmak istiyorum
http://www.youtube.com/watch?v=8PZaDNG1YQs
https://320volt.com/encoder-kullanimi-aci-olcumu-ve-ccs-c-pic16f628-ornek-uygulama/


Puls kaçırmamak istiyorsan Timer kullanmak en sağlamı. İnterrupt ve diğer yöntemlerde eğer enkoder çözünürlüğü çok yüksek ise yüksek hızlarda puls kaçırmamak elde değil.

Şurada ben timer ile açı ölçmüştüm. Muhtemelen işini görecektir.
http://arectron.com/microchip/pic16f628_ile_aci_olcer.html

https://www.youtube.com/watch?v=Bfqe2k-uq38

Eski Klasör

Alıntı yapılan: Mucit23 - 18 Ocak 2016, 14:10:20
Puls kaçırmamak istiyorsan Timer kullanmak en sağlamı. İnterrupt ve diğer yöntemlerde eğer enkoder çözünürlüğü çok yüksek ise yüksek hızlarda puls kaçırmamak elde değil.

Şurada ben timer ile açı ölçmüştüm. Muhtemelen işini görecektir.


Gökte ararken yerde buldum hocam sizi :D

Timer kullanmak istiyorum ama ayarlarında mı nerede problem yaşıyorsam çözemedim birtürlü değeri arttıramıyorum.
Birde basitçe anlatabilirseniz fazla teknik kullanmadan timer1 kesmesini göremedim yazılımda

Galiba bütün olay burada bitiyor.

while(TRUE)
   {
     counter=(get_timer1()%encoder_res);//Timer1 İn modu alınıyor.
 
     if(counter!=old_counter)// Sayaçta Değişim varsa
     {
	    if(counter&lt;old_counter){ //Fark Hesaplanıyor.            fark=(encoder_res-old_counter)+counter;         }else{           fark=counter-old_counter;         }       if(input(yon))//Sağa Dönüyorsa       {          encoder_loc+=fark;         if(encoder_loc&gt;=encoder_res)encoder_loc=encoder_loc-encoder_res;
      }
      else          //Sola Dönüyorsa
      {
        encoder_loc-=fark;
        if(encoder_loc&lt;0)encoder_loc=encoder_res-abs(encoder_loc);       }          old_counter=counter;       angle=(float)(encoder_loc*360.0)/encoder_res;       show_display(angle*10);      }              if(!input(button))      {        while(!input(button))        {          btn_syc2++;           if(btn_syc2&gt;100)
          {
            exit=1;
            break;
          }
         delay_ms(10);
       }
       btn_syc2=0;
       if(!exit)
       {
          encoder_loc=0;
          counter=0;old_counter=0;
          fark=0;
          set_timer1(0);
          angle=(float)(encoder_loc*360.0)/encoder_res;
          show_display(angle*10);
       }
     }


Mucit23

Programda Timer kesmesi kullanmadım. Timer1 kullanılıyor ama sadece sayıcı olarak kullanılıyor. Timer1'in özelliği clock girişinin external olarak ayarlanabilmesi. Yani Encoderden gelen puls ları doğrudan Timer1'in harici clock girişine verip timer1'in otomatikmen enkoderden gelen pulsları saymasını sağladım. Bundan sonrası hesap kitap.

Yalnız bu sisteminde bir eksiği var. Temelde Timer1 sayacının sürekli enkoder çözünürlüğüne modu alınıyor. Eğer enkoder çözünürlüğü 8 in tam katı değilse timer sayacı sıfırlandığında hata yapma olasılığı var. Bunu önlemek için Ekonder 256, 512, 1024 veya 2048 gibi 65536 değerine tam bölünen bir puls değerine sahip olması gerekiyor.

Sebebini tam olarak kavrayabilmek için kodun nasıl çalıştığını iyi anlamak gerekiyor.

Yukarıda verdiğim linkteki proje amatör bir proje olduğu için bu durumu göz ardı ettim.

Eski Klasör

Alıntı yapılan: Mucit23 - 18 Ocak 2016, 15:54:38
Programda Timer kesmesi kullanmadım. Timer1 kullanılıyor ama sadece sayıcı olarak kullanılıyor. Timer1'in özelliği clock girişinin external olarak ayarlanabilmesi. Yani Encoderden gelen puls ları doğrudan Timer1'in harici clock girişine verip timer1'in otomatikmen enkoderden gelen pulsları saymasını sağladım.

Hocam peki bunun için hangi kodlara bakmam hangi kod üzerinden yürümem lazım ccs-c kitabını okudum inceledim ama gözüme böyle bir olay çarpmadı yada dikkat etmedim?

Kod yada hazır program istemiyorum birden çalışsın otursun da istemiyorum öyle olunca unutuyorum öğrenmiyorum birşey aşama aşama kademe kademe gitmek benim için en yararlısı.

Mucit23

CCS için Timer ayarlarını aşağıdaki gibi yapmak yetiyor. Tabi kullanılacak işlemciye göre bu ayarlar değişiklik gösterebilir en iyisi teknik dökümanı incelemek.
setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);
16F628 çin Başkada bir ayarı yok.

Eski Klasör

Alıntı yapılan: Mucit23 - 18 Ocak 2016, 16:28:21
CCS için Timer ayarlarını aşağıdaki gibi yapmak yetiyor. Tabi kullanılacak işlemciye göre bu ayarlar değişiklik gösterebilir en iyisi teknik dökümanı incelemek.
setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);
16F628 çin Başkada bir ayarı yok.
Kusura bakmayın fazla soru soruyorum ama,

get_timer1();  bunun ile timer1 sayılıyor ve bir değişkene atanıyor geriye kalanı formül ve işlem ?



Mucit23

Get_Timer1() fonksiyon timerin değerini getirir.

Diğer işlemler için verdiğim linkte açıklama yapmışım.

Eski Klasör

Alıntı yapılan: Mucit23 - 18 Ocak 2016, 16:50:59
Get_Timer1() fonksiyon timerin değerini getirir.

Diğer işlemler için verdiğim linkte açıklama yapmışım.

setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); 
   lcd_init();
   set_timer1(0);
  
 while(TRUE)
   {
  set_timer1(0);     
  y=get_timer1();      
   printf(lcd_putc,"\fx=%lu",y);
     }
}


gibi mi? (sadece pusleri görmek için)

Mucit23

evet timer değerini o şekilde görebilirsin.