encoderli pot, bazen saymıyor veya 1 eksiltiyor

Başlatan eR2, 24 Aralık 2013, 15:39:29

eR2

merhabalar, ccs kodlarım aşağıdadır, rb4-7 kesmesini kullanarak encoderli pot ile sayıcı yaptım, fakat sorunum başlıkta belirttiğim gibi bazen 1 tık saymıyor bazen de 1 eksiltiyor..nerede hata yapıyorum? acaba encoderli pot da mı sorun var?..portb de dahili pull up olmasına rağmen 10dk dirençle bacakları pull up yapmazsam hata oranı artıyor..

kodları buradan referans aldım http://www.ccsinfo.com/forum/viewtopic.php?t=23340&postdays=0&postorder=asc&start=15

#include <18f4550.h> 
#use delay(clock=4M) 
#fuses XT, NOWDT,  NOPROTECT, NOBROWNOUT, NOPUT, NOLVP,NODEBUG,NOWRT,NOCPD 
//#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7)
#use fast_io(B) 
/* 
RB4,RB5=quadrature inputs 
*/ 
signed int32 position; 
//Note using int32, otherwise routine will run off the end very quickly. 
//Also 'signed', so the unit can handle the shaft rotating backwards at 
//the start... 
#byte portb=0xF81 
#bit  bchanged=0xFF2.0 
#include <lcd.c>

#int_global 
void myint(void) { 
   static int old; 
   static int new; 
   static int value; 
   //Here I have an edge on one of the quadrature inputs 
   new=portb; 
   /*Now I have to decode the quadrature changes. There are four 
   possibilities: 
   I can have a rising or falling edge, on each of the two inputs. I have to 
   look at the state of the other bit, and increment/decrement according to 
   this. */ 
   value=new^old; 
   //'value', now has the bit set, which has changed 
   if (value & 0x10) { 
      //Here the low bit has changed 
      if (new & 0x10) { 
         //Here a rising edge on A 
         if (new & 0x20) --position; 
         else ++position; 
      } 
    } 
 
   old=new; 
   bchanged=0; 
#asm 
   //Here the 'fast' exit. 
  RETFIE  1 
#ENDASM 
} 

//Main code loop 
void main(void) { 
   signed int32 lastpos; 
   port_b_pullups(true); 
   //Note that many of the quadrature encoders _require_ pull-ups on 
   //their lines, having open collector outputs. 
   setup_adc_ports(NO_ANALOGS); 
   setup_spi(FALSE); 
   set_tris_B(0x30);  //Input on bit 4,5 for quad 
   enable_interrupts(INT_RB); 
   enable_interrupts(global); 
   lastpos=position; 
   lcd_init();
   while (true) { 
      if(lastpos!=position){ 
         lastpos=position; 
         //printf("\fcount = %5ld",lastpos);
        
         printf(lcd_putc,"\fcount = %Ld",lastpos);
         delay_us(20);
         //I would recommend a delay here. The interrupt will still keep 
         //counting edges, but without a delay, the string will be 'non stop' 
         //for any reasonable movement rate. 
      } 
   } 
}



ek olarak bir de bunu yaptım, sola giderken hiçbir sorun yok ama sağa çevirirken bazen sol görüyor..

#include <16f877a.h> 
#use delay(clock=4M) 
#fuses HS, NOWDT,  NOPROTECT, NOBROWNOUT, NOPUT, NOLVP,NODEBUG,NOWRT,NOCPD 
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7)
#use fast_io(B) 


long encoder, encoder_eski, yon;

#int_ext
void ext_kesmesi()
{
   if (input(pin_b1)==0)
   {
      yon=1;
      encoder++;
   }
   if (input(pin_b1)==1)
   {
      yon=0;
      encoder--;
   }
   
}


#include <lcd.c>
void main()
{
   lcd_init();



   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);

   //TODO: User Code
   
   if (yon==1)
   {
      printf(lcd_putc,"\fSAG:%ld", encoder); 
   }
   if (yon==0)
   {
      printf(lcd_putc,"\fSOL:%ld", encoder);
   }
}

Kabil ATICI

Bu aletlerin buton pek farkı yoktur. Yani iletime geçme ve çıkma anında parazit üretir. bu nedenle bu paraziti bastıracak önlemler alman gerekebilir. (Kondansatör bağlama veya gecikme kullanma gibi)
Butonlardaki tuş sıçramalarını önleme ile ilgili konuları inceleyebilirsin...
ambar7

eR2

teşekkür ederim yardımlarınız için, pot uçlarında 100nf var, yazılımsal olarak kesme içinde delay kullanmak istemedim, başka yolu varmıdır?

Kabil ATICI

Söze edilen hata çok hızlı hareket ettirildiği zaman çıkıyorsa, kondansatör fazla (değeri büyük) geliyor olabilir.
Düşük hızlarda da ortaya çıkıyorsa alet üzerinde dikkat etmen gereken özellikle belirli bir noktada ortaya çıkıyorsa encoder'de mekaniksel bir sıkıntı olabilir.
ambar7

F.T

bende aynı sorunu yaşadım.A,B fazlarına  1 er adet 100nf kapasite ile idare edecek şekle geldi ama sorunumu tam çözemedim.yüksek ihtimal encoder kontak sıçramaları ile alakalı.
Hakk şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.

Kabil ATICI

işlemci girişinde schmitt trigger özellikli bir entegre kullanılarak olaya bir noktada çözüm getirebilir...(74hc14 gibi- bu entegre çıkışa girişe göre NOT yapar.)
ambar7

eR2

74hc14 ü deneyeceğim hocam elimde var inşallah düzelir, sanırım bu mekaniksel bir sorun, yavaş döndürürken problem oluyor, bir de kaliteli birşey alıp deneyeceğim..

Mucit23

Timer1 ile puls sayarsan bence parazit kaynaklı sorunlar Yaşamazsın. Ben denedim.  Fakat söyle bir problem var. Potu çok hızlı çevirince puls atlıyor. Yani bir turda 30 pals verecekse 25 pals felan veriyor.  Normal olduğunu düşünüyorum çünkü mekanik bir alet.

ete

Encoder pot lar her kesin düşündüğünün aksine her tık'da yada  iki tık arasında %00 %10 %11 %01 şeklinde 4 ayrı konum bilgisi vermektedir. Ara geçişler çok kısa aralıklı olduğu için genellikle atlamalar olabiliyor koda bağlı tabiiki.
Bu tür encoderlar ile çalışmanın en güzel yönü her tık da bir saydırmaktır. Bunu sağlamak için yazdığınız kod da özel tedbir almanız gerekir. Genelde her tık sonunda hangi konumda kalıyor ise onu baz alabilirsiniz.
Sorunun ana kaynağının bu olduğunu düşünüyorum.

Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

Kabil ATICI

Yazılım açısından biraz sıkıntılı olabilir.
Atmel işlemcilerinde seri port ,vs gibi donanımlarda gelen sinyalin ne olduğu;
gelen sinyalden 3 tane örnek alıyor, bunlardan 2 tanesi aynı olan sinyal hangisi ise o lojik seviye olarak kabul ediliyor.

örneğin 1-0-0 şeklinde bir örnekleme yapıldıysa  bu sinyal lojik-0 olarak kabul ediliyor.
ambar7

sadogan

Alıntı yapılan: eR2 - 24 Aralık 2013, 17:33:57
teşekkür ederim yardımlarınız için, pot uçlarında 100nf var, yazılımsal olarak kesme içinde delay kullanmak istemedim, başka yolu varmıdır?
Rotary encoder pic ile olan bağlantı şemasını  görebilirmiyiz.
Bortb deki harici int0 int1 int2 leri kullanıyormusunuz bunlar boş ise bunları kullanmak
çok daha uygun.

eR2

Alıntı yapılan: ete - 25 Aralık 2013, 09:41:16
Encoder pot lar her kesin düşündüğünün aksine her tık'da yada  iki tık arasında %00 %10 %11 %01 şeklinde 4 ayrı konum bilgisi vermektedir. Ara geçişler çok kısa aralıklı olduğu için genellikle atlamalar olabiliyor koda bağlı tabiiki.
Bu tür encoderlar ile çalışmanın en güzel yönü her tık da bir saydırmaktır. Bunu sağlamak için yazdığınız kod da özel tedbir almanız gerekir. Genelde her tık sonunda hangi konumda kalıyor ise onu baz alabilirsiniz.
Sorunun ana kaynağının bu olduğunu düşünüyorum.

Ete

Hocam nasıl bir yol izleyebilirim, daha önce forumda yazdıklarınızı okudum hatta picbasic kodlarını vermişsiniz, kodları biraz açıklama şansınız olursa yapabilirim sanıyorum..


Alıntı yapılan: sadogan - 25 Aralık 2013, 10:29:59
Rotary encoder pic ile olan bağlantı şemasını  görebilirmiyiz.
Bortb deki harici int0 int1 int2 leri kullanıyormusunuz bunlar boş ise bunları kullanmak
çok daha uygun.


Encoderin bacakları, üstteki kodda rb4 ve rb5 bacaklarına bağlı alttakinde ise rb0 ve rb1 e bağlı, d portunu da lcd için kullanıyorum, diğer bacaklar boş..Simulasyon yapmadığımdan şema elimde yok, dilerseniz proteusda çizebilirim..

Tagli

Bence de ambar7'nin dediği gibi, ilk denenmesi gereken şey Schmitt Trigger. Benzer bir sorunu BLDC hall effect sensörleri ile yaşamıştım, ki onlar mekanik anahtarlara göre daha az sorun çıkarması beklenen cihazlar. Yine de sürekli olarak yalancı kesmeler geliyordu. Schmitt Trigger ve onun çıkışında alçak geçiren filtre ile sorunu çözmüştüm.
Gökçe Tağlıoğlu

eR2

Encoderli potum şu anda eskisine göre çok daha iyi çalışıyor, fakat bir problemle karşılaştım, bu potla menu oluşturmak istiyorum, fakat switch case yapısını kesme içerisine almazsam ekranda hiçbir değişiklik olmuyor.. Kodlarım aşağıdadır..
Ekranda ilk menu ekranı geliyor fakat sonra hiçbir değişiklik olmuyor, nasıl yapabilirim?


#include <16f877a.h> 
#use delay(clock=4M) 
#fuses HS, NOWDT,  NOPROTECT, NOBROWNOUT, NOPUT, NOLVP,NODEBUG,NOWRT,NOCPD 
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7)
#use fast_io(B) 
#include <lcd.c>
long encoder=0,yon;
int menu=0;





#int_ext
void ext_kesmesi()
{
   if (input(pin_b1)==0)
   {
      yon=1;
      encoder++;
      menu++;
      if(menu>=4) menu=4;
   }
   if (input(pin_b1)==1)
   {
      yon=0;
      encoder--;
      menu--;
      if(menu<=1) menu=1;
   }
   


}



void main()
{
   lcd_init();



   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   enable_interrupts(INT_EXT);
   enable_interrupts(INT_RB);
   enable_interrupts(GLOBAL);
   ext_int_edge(L_TO_H);

   lcd_gotoxy(1,1);
   printf(lcd_putc,"    <<MENU>>    ");
   lcd_gotoxy(1,2);
   printf(lcd_putc,"<<geri   ");
   lcd_gotoxy(10,2);
   printf(lcd_putc,"ileri>>");
   
     

      switch(menu)
      {
      case 1:printf(lcd_putc,"\f  Temperature  ");lcd_gotoxy(15,2);printf(lcd_putc,">>");delay_ms(300);
      break;
      case 2:printf(lcd_putc,"\f     Timer     ");lcd_gotoxy(1,2);printf(lcd_putc,"<<");lcd_gotoxy(15,2);printf(lcd_putc,">>");delay_ms(300);
      break;
      case 3:printf(lcd_putc,"\f     Speed     ");lcd_gotoxy(1,2);printf(lcd_putc,"<<");lcd_gotoxy(15,2);printf(lcd_putc,">>");delay_ms(300);
      break;
      case 4:printf(lcd_putc,"\f     Delay     ");lcd_gotoxy(1,2);printf(lcd_putc,"<<");delay_ms(300);
      break;
      } 
     
   


 
 
   
}

Tagli

Programda en önemli ve temel bileşeni unutmuşsun: Sonsuz Döngü

Switch bloğunun dışına bir while(1) bloğu koy.
Gökçe Tağlıoğlu