encoderli pot, bazen saymıyor veya 1 eksiltiyor

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

eR2

#15
Alıntı yapılan: Tagli - 30 Aralık 2013, 14:04:08
Programda en önemli ve temel bileşeni unutmuşsun: Sonsuz Döngü

Switch bloğunun dışına bir while(1) bloğu koy.

Dediğinizi yaptım fakat olmadı, başlangıç ekranında kalıyor, başlangıç menusune encoder değerini gönderdim, kesmeye hiç girmiyor sanki.. yon bilgisine göre ledi yakıp söndürmek istedim fakat o da olmuyor..

benim anlamadığım ilk sayfadaki kodlarımla program çalışıyor if yerine switch case yapınca program çalışmıyor..

menuye girmek için ayrı bir buton veya kesme kullanmak istiyorum nasıl yapsam bilemedim..

#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(GLOBAL);
   ext_int_edge(L_TO_H);
   set_tris_b(0b00000011);
   lcd_gotoxy(1,1);
   printf(lcd_putc,"    <<MENU>>    ");
   lcd_gotoxy(1,2);
   printf(lcd_putc,"<<geri%ld  ",encoder);
   lcd_gotoxy(10,2);
   printf(lcd_putc,"ileri>>");
   
   if(yon==1) 
   {
   output_high(pin_b7);
   } 

   if(yon==0)
   {
   output_low(pin_b7);
   }
   
      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  Start Delay  ");lcd_gotoxy(1,2);printf(lcd_putc,"<<");delay_ms(300);
      break;
      } 
     
   while(1);

 
 
   
}

Tagli

While(1)'i sona değil, dışa alman gerekiyordu. Şunun gibi:
while(1){
    switch (menu){
        case 1:
        ........
    }
}


Yani kod sürekli dönüp dolaşıp switch satırına tekrar gelmeli. Aksi takdirde o kısım sadece bir kez çalışır, menu değişkeninin değişmesi karşısında tepkisiz kalır.
Gökçe Tağlıoğlu

eR2

Alıntı yapılan: Tagli - 30 Aralık 2013, 15:19:53
While(1)'i sona değil, dışa alman gerekiyordu. Şunun gibi:
while(1){
    switch (menu){
        case 1:
        ........
    }
}


Yani kod sürekli dönüp dolaşıp switch satırına tekrar gelmeli. Aksi takdirde o kısım sadece bir kez çalışır, menu değişkeninin değişmesi karşısında tepkisiz kalır.

çok teşekkür ederim, şimdi oldu,

fakat while(1) yerine (menu tusu olusturmak istedim) while(input(pin_a0)) yazdım, a0 gnd olmasına rağmen bir süre çalışıyor, sonra döngüden çıkıyor..

menuye giriş çıkışları nasıl yapabilirim? işin içinden bir türlü çıkamadım..

Tagli

Menü tuşunun nasıl davranmasını istiyorsun? Basıldığı zaman ne olacak, basılmadığı zaman ne olacak?

Duruma göre dışarıda bir döngü daha olması gerekebilir.
Gökçe Tağlıoğlu

eR2

Alıntı yapılan: Tagli - 30 Aralık 2013, 16:10:58
Menü tuşunun nasıl davranmasını istiyorsun? Basıldığı zaman ne olacak, basılmadığı zaman ne olacak?

Duruma göre dışarıda bir döngü daha olması gerekebilir.

Örneğin menu tuşuna basınca menuye girip, set tuşuna basınca çıkan bir uygulama yapmaya çalışıyorum ama bir türlü beceremedim..
Alttaki kodu ekledim fakat a0 gnd olmasına rağmen hala switch yapısına giriyor bir süre sonra program takılıyor..

      
while(1)
      {
      if (input(pin_a0)==1)
      {
      switch(menu)
      {...}
      }
      }


ete

KOnu CCS başlığı altında açıldığı için pek yanıt vermek istemedim. Ama hemen belirteyimki bu pot tipi encoderleri güç kaynağımda akım ve volt set değerlerini aayrlamak için kullanıyorum. Pek çok farklı projede yine menü seçme ve bir takım değer girişleri içinde kullandım. Ben sorun yaşamıyorum. Yardımı olacak ise aşağıda kendi kullandığım bir kod örneği vereyim.
Bunu bir alt program gibi düşünün. Aynı şekilde bu iş kesme yardımı ilede yapılabilr.
Program satırlarının yanına gerekli açıklamaları yazdım.
ENCODER: 'ENCODER A=PORTB.6 da bağlı, ENCODER B=PORTB.7 de bağlı
ESKI= PORTB & %11000000  'encoder portunu okuyoruz
TEKRAR:
YENI = PORTB & %11000000  'Yeniden okuyoruz. 
IF YENI = ESKI Then        'ilk okunan ile son okunan eşit ise encoder dönmemiş demektir
  SURE=SURE+1              'bu testi 100 defa yap hala encoder dönmemiş ise demekki duruyor o halde
  if SURE=100 then RETURN  'geri dön ve diğer işlere bak
  goto TEKRAR              '100 defa okuma yapmak için yeniden bak
endif 
SURE=0                    'program bu satıra gelmiş ise encoder dönmüş demektir.

YON=ESKI.6 ^ YENI.7       'o halde yön tayini yap
IF YONV=1 then 'yön=1 ise 
  IF NEW=%11000000 THEN SAYI=SAYI+1   've okunan değer %11 ise  sayı değerini bir artır
  IF SAYI>UST_LIMIT then SAYI=USTLIMIT 
else
  IF NEW=%11000000 THEN SAYI=SAYI-1   'değilse sayı değerini bir eksilt                 '
  if SAYI> UST_LIMIT then SAYI=0
endif
RETURN


Encoder okuması basittir. İki okuma arasındaki fark olması temeline dayalıdır. İki okumada aynı değeri veriyorsa encoder dönmüyor demektir. Encoder dönmüyor ise dönmesini beklemeninde bir anlamı yoktur. O halde belirli bir süre yada sayaç belirleyip en azından sayaç değerine gelinceye kadar okumaya devam edilmeli hala dönmüyorsa okuma işinde vaz geçip geri dönülmelidir. Tabiiki kesme kullanırsanız program yalnızca encoder döndüğü zaman kesme kısmına gireceği için ayrıca sayac kontrolüne gerek kalmaz.
Örnek kod içinde okunan değerlerin (A ve B hattı) ikiside "1" ise sayac değerini artırıyorum. İstenirse bu özellik %01 veya %10 veya %00 olarak da değiştirilebilir. Bu şartı koymazsanız pot çevrilirken iki tık arasındaki değerlerde de artış yada azalış sağlayabilirsiniz.

Ete

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

eR2

#21
Alıntı yapılan: ete - 30 Aralık 2013, 17:08:33

Encoder okuması basittir. İki okuma arasındaki fark olması temeline dayalıdır. İki okumada aynı değeri veriyorsa encoder dönmüyor demektir. Encoder dönmüyor ise dönmesini beklemeninde bir anlamı yoktur. O halde belirli bir süre yada sayaç belirleyip en azından sayaç değerine gelinceye kadar okumaya devam edilmeli hala dönmüyorsa okuma işinde vaz geçip geri dönülmelidir. Tabiiki kesme kullanırsanız program yalnızca encoder döndüğü zaman kesme kısmına gireceği için ayrıca sayac kontrolüne gerek kalmaz.
Örnek kod içinde okunan değerlerin (A ve B hattı) ikiside "1" ise sayac değerini artırıyorum. İstenirse bu özellik %01 veya %10 veya %00 olarak da değiştirilebilir. Bu şartı koymazsanız pot çevrilirken iki tık arasındaki değerlerde de artış yada azalış sağlayabilirsiniz.

Ete

Hocam çok teşekkür ederim, çok güzel anlatmışsınız fakat ben beceremedim, şu şekilde yazdım ama hocalarım yardım ederseniz çok sevinirim..

#include <16f877.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>
#define A pin_b0
#define B pin_b1

long yon;
int menu=0,encoder=0,ESKI,YENI,SURE=0;


void read_encoder()

{
   
   ESKI = A & 0b11000000;
   //TEKRAR:
   YENI = B & 0b11000000;
     // if(yeni==eski)
      //sure=sure+1;
     // if(sure==100)
      //goto tekrar;
      //sure=0;
   
   YON=ESKI^YENI;
   IF( YON==1 )
    {
    if (YENI==0b11000000)
    encoder=encoder+1;
    else
    encoder=encoder-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(GLOBAL);
   ext_int_edge(L_TO_H);

  
   
   
   if (yon==1)
   {
      printf(lcd_putc,"\fSAG:%d", encoder);
      
   }
   if (yon==0)
   {
      printf(lcd_putc,"\fSOL:%d", encoder);
      
   }
   
   
   
}




Alıntı yapılan: Tagli - 30 Aralık 2013, 16:10:58
Menü tuşunun nasıl davranmasını istiyorsun? Basıldığı zaman ne olacak, basılmadığı zaman ne olacak?

Duruma göre dışarıda bir döngü daha olması gerekebilir.


hocam şu şekilde bir kod yazdım switch case ile yapamadım ekran donup kalıyor, a0 (menuac butonu) butonuna basılıyken menuye giriyor, menude gezinmeler yapabiliyorsunuz fakat basılı tutmanız gerekiyor..
benim istediğim a0 butonuna basınca (basılı tutmadan) menuye giriş ve set butonuna basınca değerleri kaydedip menuden çıkmak.. Nasıl yapabilirim?

Bakmak isterseniz proteus simulasyonunu ekledim hocam...

http://s3.dosya.tc/server15/AzRRyC/rotenc_menu.rar.html

#include <16f877.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>
#define       menuac input(pin_A0)     //Sağ
#define       sag input(pin_A1)     //Sol
#define       sol input(pin_A2)     //Ac
#define       menukapa input(pin_A3)     //Kapa
long encoder, yon;
int m,k,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_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);
   ext_int_edge(L_TO_H);


   
   while(1)
   {
   
   
      if(menuac==0)
   {
    
   if (menu==0)
   {
   printf(lcd_putc,"\f   <<MENU>>    ");
   lcd_gotoxy(1,2);
   printf(lcd_putc,"<<geri   ");
   lcd_gotoxy(10,2);
   printf(lcd_putc,"ileri>>");delay_ms(300);
   }
   if (menu==1)
   {
   printf(lcd_putc,"\f  Temperature  ");lcd_gotoxy(15,2);printf(lcd_putc,">>");delay_ms(300);
   }
   if (menu==2)
   {
   printf(lcd_putc,"\f     Timer     ");lcd_gotoxy(1,2);printf(lcd_putc,"<<");lcd_gotoxy(15,2);printf(lcd_putc,">>");delay_ms(300);
   }
   if (menu==3)
   {
   printf(lcd_putc,"\f     Speed     ");lcd_gotoxy(1,2);printf(lcd_putc,"<<");lcd_gotoxy(15,2);printf(lcd_putc,">>");delay_ms(300);
   }
   if (menu==4)
   {
   printf(lcd_putc,"\f  Start Delay  ");lcd_gotoxy(1,2);printf(lcd_putc,"<<");delay_ms(300);
   }

   }     
     
 
   if(menuac==1)
   {
      menu=0;
      if (yon==1)
      {
      printf(lcd_putc,"\fSAG:%ld",encoder);
      delay_ms(300);
      }
      if (yon==0)
      {
      printf(lcd_putc,"\fSOL:%ld",encoder);
      delay_ms(300);  
      }
   }
    
   
       
   }
   
}