Rotary encoderde hız ?

Başlatan KAZIMUGUR, 07 Ocak 2008, 09:54:52

z

CHA ve CHB sinyallerinin exorlanması sonucu oluşan sinyali işlemcinin int girişine bağlarsan encoderde değişim olduğu anda işlemci int rutinine girer.

Int rutininde programda yaptığın gibi sayma işlemini yaparsın. Programın ana döngüsünde ise ister LCDye isterse seri porta data basabilirsin.

Yanlız ana döngü içinde kullandığın komut ext interruptlara yasak getirmemeli.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

KAZIMUGUR

Dediğiniz şekilde oluyor , ama yön bilgisini kaybediyorum.
Kesme içerisinde yön bilgisi hesaplarken vakit geçiyor.
Lcd ye veya diğer pice bilgi yollarken kesme oluşsada o andaki komutu bitirmek için oyalanınca yine kaçırıyor.
Hatta isisde farkına vardım , yüksek hızda bilgi gelirken , programın başlayıp,portlara bakmasına kadar ,hıza bağlı belirli sayıda işareti kaçıyor, o sayı kadar farkla doğru göstersede , bu önemli değil elbette.

arslan74

Merhaba,

Ben yıllar önce Rotary encoderle ile konum okuma projesi yapmıştım. Hata düzgün çalıştırana kadar bir cok yolu denemiştim.

İlk denediğim en basit olan yol ise, PIC kendi iç timerlerini harici olarak tetiklemekti. Timer1'in puls girişini harici harici yaptım. A veya B ucundan birini bağladığında. Üretiği pulsla timer sayacını artırdım. Z (sıfır geciş) ucunuda INT0 bağladım. her interrupta timeri sıfırlıyordum. İlk Başlarda düzgün çalışmaya bağladı ama bazen sapitiyordu. O zaman nedeni bulamadığım için bundan vaz gectim ve başka yollar denemeye karaverdim. Bu devrenin tek kusuru yön tayını yoktu. Encoder kaclık puls üretyorsa, bunu dört katına cıkarma imkanınız yoktu.

Sonra başka bir yol denemeye kara verdim. Bunun için birden fazla harici interupta ihtiyacım vardı. 16F serileri harici interrupt tek olduğu için 18F serisinden bir PIC kullandım. 18F252 harici 3 tane interupt var. Ben Z bağlantısı değiştirmedim, Sadece A veya B ucunu diğer interupta verdim. PIC18 serisinde 2 seviyeli interrupt öncelikleri ayarı var. Hangi interruptun öncelik seviyesinin ne olacağını belirleyebiliyorsunuz. Z 1.ci , A yı 2.ci seviyeye aldım.  A interuptunda sayac değiştekini bir artıb sonra konum bilgisini okuyorum. Z interruptunda ise sayac değişkenini sıfırlıyorum. Bu yöntem harici timer yönteminden daha sağlıklı çalıştı ancak. Bununda yön tayini yoktu. sistem sadece tek yönde döndüğü için gerek duymadım ve bu şeklide kullandım.

Ama kendim boş durmayıb başka denemelerda yaptım. Burada bir arkadaşımın dediği gibi RB4-RB7 bacakları Portchange interuptunun kullanarakta encoder okuma devresini yaptım. Denemelerim gayet güzel sonuc verdi. Bu yöntemle 100 pulslık encoderi 400 pulslık hassasiyette ve yön tayini yaparak okuyabiliyordum. Z yine int0 bağlı bıraktım.

Yeniden böyle bir proje yapmam gerek. Şimdi daha iyi ve güzel bir devre üzerine çalışıyorum ancak çalışmalarım daha bitmedi. Microchip'in Motor control entegreleri var örneğin PIC18F4431 gibi piclerde donanımsal encoder girişi var. Onunla direkt konum, yön ve hiz bigisini alabiliyorsun.
Ama bu picleri temini zor olduğu için Microchip firmanın AN696 anplicatin boardundaki devreyi yapmayı düşünüyorum. Bu devrenin proteus simulasyonunda proteus için de hazır var. Onu denedkten sonra sonucu yazarım.

Selamlar

Prof.EleCTroN

KAZIMUGUR hocam,
RB Change kesmesini kullanacağımızı düşünelim,
PIC de kesme kullanabilmek için GIE bitini "1" yapmamız gerekiyor. Ayrıca kullanmak istediğimiz kesme türü RB Change olduğu için bunu kullanmak içinde ilgili bit olan RBIE bitini "1" yapmalıyız. Böylece RB4:7 arası değişim olduğu zaman mikrodenetleyici ana programdan çıkıp kesme programına gidecektir. RB4:7 arası değişim algılandığında RBIF biti "1" değerini alacaktır. Bunu kesme programının sonunda yazılımsal olarak "0" yapmalıyız. Ayrıca başlangıçtada bu biti sıfırlayabiliriz. Bu bitlerin hepsi INTCON kaydedicisindedir.
Örneğin:
/*Donanim Kurma Programı*/
void Donanim_Kur(void) {
	PORTB=0x00;
	PORTD=0x00; //Tüm portlar sıfırlandı.
	ADCON1=0x06;//Tüm pinler sayısal.
	TRISB=0xFF; //B portu giriş.
	TRISD=0x00; //D portu çıkış.
	/* Kesme Ayarları */
	RBIF=0;
	RBIE=1;
	GIE=1;
}


Mikrodenetleyici kesme olunca ana programından kesme programına atlar. Burada RBIF biti "1" ise encoder konum değiştirmiştir. (RB4 ve RB5 uçlarına encoder bağlandığını farz ediyoruz.) Buna göre önceki konum ile şimdiki konum verilerini değerlendirerek istenenleri elde ediyoruz. En sonda yazılımsal olarak RBIF bitini "0" yapıyoruz.
Örneğin:
void interrupt Kesme (void) {
	if (RBIF) { // RB Change kesmesi.
		KodlayiciCikisi=((PORTB&0b00110000)>>4);
		switch (SonKodlama) 
		{
			case 0b00000000: // Son kodlamanın 00 olma durumu.
			switch (KodlayiciCikisi) 
			{
				case 0b00000000: // Kodlayıcı çıkışı 00 ise.
				// İşlem yok.
				break;
				case 0b00000001: // Kodlayıcı çıkışı 01 ise.
				KonumSayaci+=1; // Geri yöne dönüş.
				break;
				case 0b00000010: // Kodlayıcı çıkışı 10 ise.
				KonumSayaci-=1;
				break;
				case 0b00000011: // Kodlayıcı çıkışı 11 ise.
				// İşlem yok.
				break;
			}
			break;
			case 0b00000001: // Son kodlamanın 01 olma durumu.
			switch (KodlayiciCikisi) 
			{
				case 0b00000000: // Kodlayıcı çıkışı 00 ise.
				KonumSayaci-=1;
				break;
				case 0b00000001: // Kodlayıcı çıkışı 01 ise.
				// İşlem yok.
				break;
				case 0b00000010: // Kodlayıcı çıkışı 10 ise.
				// İşlem yok.
				break;
				case 0b00000011: // Kodlayıcı Çıkışı 11 ise.
				KonumSayaci+=1; // Geri yöne dönüş.
				break;
			}				
			break;
			case 0b00000010: // Son kodlamanın 10 olma durumu.
			switch (KodlayiciCikisi) 
			{
				case 0b00000000: // Kodlayıcı çıkılı 00 ise.
				KonumSayaci+=1; // Geri yöne dönüş.
				break;
				case 0b00000001: // Kodlayıcı çıkışı 01 ise.
				// İşlem yok.
				break;
				case 0b00000010: // Kodlayıcı çıkışı 10 ise.
				// İşlem yok.
				break;
				case 0b00000011: // Kodlayıcı Çıkışı 11 ise.
				KonumSayaci-=1;
				break;
			}
			break;
			case 0b00000011: // Son kodlamanın 11 olma durumu.
			switch (KodlayiciCikisi) 
			{
				case 0b00000000: // Kodlayıcı çıkışı 00 ise.
				// İşlem yok.
				break;
				case 0b00000001: // Kodlayıcı çıkışı 01 ise.
				KonumSayaci-=1;
				break;
				case 0b00000010: // Kodlayıcı çıkışı 10 ise.
				KonumSayaci+=1; // Geri yöne dönüş.
				break;
				case 0b00000011: // Kodlayıcı çıkışı 11 ise.
				// İşlem yok.
				break;
			}
			break;
		}
		SonKodlama=KodlayiciCikisi;			
		RBIF=0; // Kesme bayrağı temizlenir.
	} // RBChange kesme programı sonu. 
} // Kesme fonksiyonunun sonu.


Ana programda ise sürekli olarak LCD ye güncel değerleri yazdırıyoruz.

Bu yöntem ile harici bir elemana gerek kalmadan çözme işlemi yapabiliyoruz. rree arkadaşımız da dediği gibi harici elemanlar ile denetleyici biraz daha az meşgul olabilir. Seçim denetleyicinin üstlendiği göreve ve çevre birimlere göre değişebilir. (Mesela 1200 d/dk dönen ASM u 400 çözünürlüklü encoderdan okuma,  LCD de istenen ve okunan değerleri gösterme, tuş takımı okuma, seri port gönderme işlemlerini PIC16F877 ile yapıyor ve kontrol için seri porttan belli aralıklarla gelen verileri işlemesi için PIC18 serisini kullanıyordum. Encoder okuma yöntemim RB Change değil zamanlayıcı taşma tabanlıydı.)

KAZIMUGUR

İşlerim dolayıdsıyla biraz ara verdim ama azıcıkda derslerime çalıştım.

Öneriler doğrultusunda RB.4-7 kesmelerine baktım.
Hazır bir kaç kod buldum.
Ölçebildiğim kadarı ile en hızlı çalışan 2 adedi aşağıda.
Dosyalarıda ekli.Uygulamada da aynı sonuçları verdiler.

Göstermede bir sorunum var.Lcd başka bir picde ve ona değerleri yollarken en fazla 256 yazabiliyor ve sonra 0 dan devam ediyor.

Encoderin bağlı olduğu picde eski örneklerdeki gibi hem sayıp hemde lcd ye yollasam sorun olmuyordu.Bir picden diğerine 256 dan büyük değeri sürekli olarak nasıl yollarım bilmiyorum.2 porta yayılabilirmi ?Tabii bu arada enkoderi kaçırmamakda gerekli.2 picde 256 dan sonrasına devam etmek için bir şeyler denedim.Ama pek beceremedim.

CC5X li olanda aynı pic ile lcd ye yazmaya çalışacağım bakalım yapabilecekmiyim.

// Rotary Encoder inkrementale Drehgeber
// Rotary-Encoder Drehimpulsgeber


#include <16F871.H>
#include <int16CXX.H>
// Speicherschutz12,13,4,5=aus,Debug11=aus,ProgrammFlash9=an,EEpromRead8=an,NiedervoltProgr7=aus
// NiederVoltReset6=an,EinschaltTimer3=an,WachDogTimer2=aus,Oszillator0,1=XC
#pragma config |= 0b.11.111101.11.00.10
#pragma bit En1 @ PORTB.7
#pragma bit En2 @ PORTB.6


#pragma origin 4
bit n1,n2;
char Enkoder;

//***************** Interrupt ****************************************
interrupt int_server( void)
{
    int_save_registers          // W, STATUS (and PCLATH)
    if ( RBIF)                  // Am port B hat sich etwas geändert
    {

        if (En1!=n1)            // Wenn es vom Eingang1 kamm dann wurde Drehimpulsgeber gedreht.
        {
            if (En2==n1)        // Wenn, wehrend Eingang1 geändert wurde, Eingang2 alte Signal hat, dann
            {
                Enkoder--;      // war das Drehung nach Links
                if (Enkoder==14)Enkoder=15;     // Untergrenze des Einstellwertes setzen
            }
            else                // Ansonsten war das Drehung nach Rechts
            {
                Enkoder++;
                if (Enkoder==41)Enkoder=40;     // Obergrenze des Einstellwertes setzen
            }
            n1=En1;             // Zuschtand merken
            n2=En2;
        }

        W = PORTB;              // clear mismatch
        RBIF = 0;               // reset flag

    }
    int_restore_registers       // W, STATUS (and PCLATH)
}
//****************************************************************************

void main(void)
{

    TRISB=0b.1100.0000;     // RB6->En2, RB7->En2 Eingänge zum Drehimpulsgeber
    TRISD=0b.0000.0000;     // 
    PORTD=0;

    GIE=1;       // Interrupts erlauben
    RBIE=1;      // Interrupt von PORTB erlauben

    while(1)
    {
        PORTD=Enkoder;      // Ständige Ausgabe

    }
}


list p=16f628
;**************************************************************
;*  	Pinbelegung
;*	----------------------------------	
;*	PORTA: 	0 < rotary encoder - B Pin4
;*		1 < rotary encoder - A Pin5
;*		2 -
;*		3 -
;*		4 -
;*		5 -
;*		6 -
;*		7 -
;*
;*	PORTB:	0 > LED
;*		1 > LED
;*		2 > LED
;*		3 > LED
;*		4 > LED
;*		5 > LED
;*		6 > LED
;*		7 > LED
;*	
;**************************************************************
;
;sprut (zero) Bredendiek 01/2003
;
; Rotary-Encoder mit LED Zeile
;
; Prozessor 16F628 
;
; Prozessor-Takt 10 MHz
;
; Rotary Encoder am PortA 0 & 1
; LED-Zeile am PortB
;
;**************************************************************
; Includedatei für den 16F628 einbinden

	#include <P16f628.INC>

	ERRORLEVEL      -302    	; SUPPRESS BANK SELECTION MESSAGES


; Configuration festlegen:
; Power on Timer, kein Watchdog, HS-Oscillator, kein Brown out, kein LV-programming
	__CONFIG	_PWRTE_ON & _WDT_OFF & _HS_OSC & _BODEN_OFF & _LVP_OFF

; Constanten festlegen
#define	encoder	PORTA
#define	LED	PORTB

; Variable festlegen
temp	equ	0x20			; Arbeitsregister 
counter	equ	0x21			; Zählstand
alt	equ	0x22			; alte Rotor-Position
neu	equ	0x23			; aktuelle Rotorposition

;**************************************************************
; Programmanfang

	org	0

;**************************************************************
; Initialisierung *********************************************

init
	bsf     STATUS, RP0		; Bank 1
	clrf	OPTION_REG 
	movlw	B'00000000'		; PortB alle outputs 
	movwf	TRISB
	bcf     STATUS, RP0		; Bank 0
	clrf	PORTB			; LEDs aus
	clrf	INTCON        		; Interupt disable


; 16F628 alle Comparatoreingänge auf Digital umschalten
	BSF	CMCON, CM0
	BSF	CMCON, CM1
	BSF	CMCON, CM2

	clrf	counter
	movfw	encoder
	movwf	alt			; aktuelle encoder-Stellung lesen
	movlw	B'00000011'
	andwf	alt, f			; nur 2 LSB stehen lassen

;Hauptprogrammschleife
loop
	call	read_encoder		; Rotary Encoder abfragen
	movfw	counter
	movwf	LED			; Zählerstand anzeigen
	goto	loop


;**************************************************************
; Test des Encoders auf Verdrehung ****************************

read_encoder
	movfw	encoder
	movwf	neu			; aktuelle encoder-Stellung nach new
	movlw	B'00000011'	
	andwf	neu, f			; nur 2 LSB stehen lassen
	movfw	neu			; wurde der encoder bewegt?
	movwf	temp
	movfw	alt
	xorwf	temp, w			; ist neu = alt?
	bz	ende			; ja: nicht verdreht, also nichts tun
					; nein: encoder verdreht, aber in welche Richtung?
					; drehen wir mal Bit0 des alten werts zum Vergleich 
					;  nach links
	bcf	alt, 1
	clrc				; Carry-Flag löschen
	rlf	alt, f			; alten Encoder-Stand um 1 Stelle nach links drehen
	movfw	neu
	xorwf	alt, f			; falls xorf >1 ergibt, dann war es eine Rechtsdrehung
	bz	links			; links:  decrement counter
	decf	alt, f
	bz	links			; links:  decrement counter
rechts
	incf	counter, f		; rechts:  increment counter
	goto	weiter
links
	decf	counter, f		; links:  decrement counter
weiter
	movfw	neu
	movwf	alt			; neu für nächsten Vergleich als alt speichern
ende
	return

	end



http://www.4shared.com/file/35934740/3a3c5ff/Ek_2.html

arslan74

Merhaba,

Rotary encoder ile ilgili benim bitmiş şekilde yaptığım proje var bu forumdada yayınladım. 100 pulslik bir encoderi 400 pulslik bir hassasiyete okuyabiliyorsunuz. Hemde yönde tayınıde yapabiliyor. Projenin içinde Program, PCB ve Simülasyon dosyaları mevcud.

https://www.picproje.org/index.php/topic,18953&highlight=encoder


Ayrıca başka başlık altında da bu konu işlenmiştir.

https://www.picproje.org/index.php/topic,9726&highlight=encoder

Selamlar

Macera

Evvelden foruma yazmıştım ama şimdi bulamadım neyse kodu tekrar veriyim.
Gerçek anlamda aşağıdaki kod çalışıyor ama yüksek devirde denemedim.
Alıntı Yap/*  
   3 Agustos 2005
   enkoder denemesi test edildi onaylandı.
   port b.0 dan enkoder girişi
   port b.1 dan enkoder yönü
   olacak şekilde ayarlanacak
   enkoderin iki girişi xorlanıp port b.0 a girecek
   enkoderin bir girişide b.1 e girecek
*/
#pragma chip PIC16F877A
#pragma bit dir    @ PORTB.1
#pragma bit pulse   @ PORTB.0
#include "int16CXX.H"


#pragma origin 4
static int16 counter;
uns8 dir1;
interrupt int_server( void)
{
   int_save_registers    // W, STATUS (and PCLATH)
//   swPCLATH = PCLATH;
   if ( INTF)  
   {
       INTEDG=!INTEDG;/* bu bana 3 ay kaybettirdi*/
       dir1=counter.low8 & 0x02;
       if ((PORTB & 0x02)==dir1) counter++;
           else counter--;  
       INTF = 0;  /* reset flag */
    }
   int_restore_registers // W, STATUS (and PCLATH)
 //  PCLATH = swPCLATH;
}
#include "Stdio.c"
void main( void)
{
   int16 oldcount;
   GIE = 1;    /* interrupts allowed */
   INTE= 1;
   PORTB = 0b00000000;
   TRISB = 0b00000011;
   counter =0;
   if (pulse)  INTEDG  =1;
   else
       {
           INTEDG = 0;
           ++counter;
       }
   if (dir) {
           ++counter;
           ++counter;
           }
   PORTC   = 0b.0000.0000;
   TRISC   = 0b.1000.0000;//Input RC7 - Incoming Data RX
   SPBRG   = 129; //20MHz for 9600 baud rate
   TXSTA   = 0b.0010.0100; //8-bit asych mode, high speed uart enabled
   RCSTA   = 0b.1001.0000; //Serial port enable, 8-bit asych continous receive mode
   oldcount=0;
   while(1)
   {  
       if (counter != oldcount)
       {
       printf(" %h ",counter.high8);
       printf(" %h \n",counter.low8);
       oldcount=counter;
       }
   }
       
}
"Art without engineering is dreaming; engineering without art is calculating." -- Steven K. Roberts

KAZIMUGUR

@Macera hocam , aşağıdaki başlıkta görmüştüm.
Derlemeye çalışırken stdio.c hatası verince o dosyayı internette arayıp buldum,bu sefer windows.h hatası verdi,onu bulamadım ,çok adı geçiyor ama dosya olarak bulamadım.Sonrasında onun içerisindede bir şeyler varsa ve açamazsa diye peşini bırakmıştım.
Bunlar herhalde borland ya da visuel c gibi gibi programların içerisinde var.
Dolayısı ile derleyemeyince deneyemedim. :oops:

https://www.picproje.org/index.php/topic,9882

Macera

#include "Stdio.c"
printf(" %h ",counter.high8);
printf(" %h \n",counter.low8);
satırlarını silersen gayet güzel çalışır.
Oda olmazsa stdio.c için link
Kodu CC5X de derledim.
"Art without engineering is dreaming; engineering without art is calculating." -- Steven K. Roberts

KAZIMUGUR

Biraz tembelim,süre uzadı ama derslerime çalıştım.

Yeteri kadar hızlı çalışıyor artık.
Set ayarları yapılırken bile kaçırmadan saymaya devam ediyor.Yüksek hızlar da(>10k), lcd , göstermek de azıcık gecikse de doğruyu gösteriyor.

Hocalarımın hepsine teşekkür ederim.
Dediğiniz gibi, işi çözen RB4-7 oldu.

Enkoderi balkondaki gariban frezeye takmayı düşündüm,belki seneye biter.Bir şekilde enerji kesilirse filan diye düşünerek konum değerini hafızaya almak istedim.Böylece eeproma yazma - okuma öğrendim.
Bunları bir de Hi-Tech için yazmaya çalışacağım.Ne yapalım , ustalarımız onu öğren dedi.

Bakalım geçer not alabilecekmiyim. :)

#include "C:\aa\CCS\877yeni\877yeni.h"
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
#use fast_io(e) 

#include <lcdn.c>       //entegreterbiyecisi'ne teşekkür

int32 konum,hedef;
int1  yon,eskia,eskib,yenia,yenib;
int8  x3,x2,x1,x0;
int   i,j;

#int_RB        
void  RB_isr(void){
     yenia=input(pin_b6);
     yenib=input(pin_b7);  
       yon=eskia^yenib;
     konum=konum+(2*yon)-1 ; 
     eskia=yenia;
     eskib=yenib;}          //@ETE hocam sen çok yaşa        
void main(){            
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   enable_interrupts(INT_RB);
   enable_interrupts(GLOBAL);
      set_tris_a(0b00000);
      set_tris_b(0b11000000);
      set_tris_c(0b00000000);          
      set_tris_d(0b11110000);
      set_tris_e(0b000); 
   x0=read_eeprom(10);
   x1=read_eeprom(20);
   x2=read_eeprom(30);
   x3=read_eeprom(40); 
  konum=make32(x3,x2,x1,x0);
     #define sec   pin_d4
     #define arti  pin_d5
     #define eksi  pin_d6    
     #define kayit pin_d7     
  lcd_init();
 while(true){
    LCDkonum(bir+0); 
     printf(lcdyaz,"\KONUM(mm)=%5Ld ",konum);
    LCDkonum(iki+0);                
     printf(lcdyaz,"\HEDEF(mm)=%5Ld ",hedef);
//hedefi arttırmak için    
 if((input(sec))&&(input(arti))){{     
   i++;}         
 if(i<10){
   hedef++;
   delay_ms(200);}        
 else{   
   i=10;    
   hedef++;}}
 else{
   i=0;}
//hedefi azaltmak için       
 if((input(sec))&&(input(eksi))){{     
   j++;}         
 if(j<10){
   hedef--;
   delay_ms(200);}        
  else{   
   j=10;    
   hedef--;}}
  else{
   j=0;}
//karşılaştırma
  if(konum>hedef)
    output_high(pin_d0);
  else
    output_low(pin_d0);
  if(konum==hedef)
    output_high(pin_d1);
  else
    output_low(pin_d1);
  if(konum<hedef)
    output_high(pin_d2);
  else
  output_low(pin_d2);
 //kayıt
  if((input(sec))&&(input(kayit))){
    x0=make8(konum,0);
    x1=make8(konum,1);
    x2=make8(konum,2);
    x3=make8(konum,3);    
        write_eeprom(10,x0);
        write_eeprom(20,x1);
        write_eeprom(30,x2);
        write_eeprom(40,x3);
}}}




http://www.4shared.com/file/56577881/b43d2717/877yeni.html

kamoz

Sayın Kazım bey:
Vermiş oldugunuz dosyadaki uygulamayı gerçekleştirdim.Lakin similasyondaki hızlara çıkmak ne mümkün.1000 palslik bir enkoder kullanıyorum 1 turu  20- 30 saniyenin üstünde kat edersem hatalar başlıyor.C dili kulanmadıgım için programada fazla müdahele edmedim.Lakin c ile istedigim hıza çıkmış olsa idi hemen c diline dönecektim.......Lütfen projenizin gerçek uygulamada başarılı olup olmadıgın bildirirmisiniz. Kamil Özduyucu

 lcd fonksiyonun iptal ederek çalıştırıyorum hızı farkedilir şekilde artdı.Yardımınız için tşk

arslan74

Alıntı yapılan: "kamoz"Sayın Kazım bey:
Vermiş oldugunuz dosyadaki uygulamayı gerçekleştirdim.Lakin similasyondaki hızlara çıkmak ne mümkün.1000 palslik bir enkoder kullanıyorum 1 turu  20- 30 saniyenin üstünde kat edersem hatalar başlıyor.C dili kulanmadıgım için programada fazla müdahele edmedim.Lakin c ile istedigim hıza çıkmış olsa idi hemen c diline dönecektim.......Lütfen projenizin gerçek uygulamada başarılı olup olmadıgın bildirirmisiniz. Kamil Özduyucu

Merhaba 1000pulslik encoder bayacağı yüksek cözünürlüğe sahib. Eğer A B uclarını beraber kullanırsanız bu cözünürlük dört katına cıkmış olur. O zaman da 4000 puls gibi muazzam büyüklükte bir çözünürlük cıkar. Hassas servo motorların coğunda bile bu çözünürlük yok. İşlemcinin bu hıza yetişebilmesi için en yüksek hızda işlemciyi secib en yüksek hızda kullanmanız gerekir.

Selamlar

KAZIMUGUR

İlk deneyleri 100 puls/tur luk enkoder ile yapmıştım.1500 devir/min motorla çevirdiğimde (siemens sürücülü) doğru değerler almıştım.
Cevap gecikti çünkü enkoderi bir yere taktığım için deneyi tekrarlayamadım.
Şimdi elimde olanlar 500 puls/tur ve 5000puls/tur.
İkiside çalışmadı.5000 liği açtığımda moralim bozuldu.40mm çapında 0,3mm kalınlığında krom diske çevrede 5000 yarık açmış ,varmı yokmu az ışık geçmese belli değil.Aynı yarıklardan birde optolara maske yapmış.Tıpkı sinema makinaları gibi.Optoların çapı bildiklerimizden(4mm).
İçlerindeki tüm parçalar yanmış sanki aşırı gerilim dolaşmış.
Belki bir ara yaparım.

Yeniden yazdım.@arslan74 hocamın dosyalarından yararlandım , Allah razı olsun.
Kesmenin içerisinde işi çabuk bitiren , yine @ete hocamın kodları.Önceden çok dolaşmıştım ama o mantık da ve sadelik de başka yok.Kesmeden çabuk çıkmak da önemli.
Evet Lcd kodları içerisinde beklemeler var ve bunlar hızlanınca kesmelerin kaçırılmasına yol açıyor.Çeşitli lcd dosyaları farklı sonuçlar veriyor.İçlerindeki beklemeler azaltılırsa gerçekde bir garip davranıyorlar.

Önceki sayfalardaki deneylerimin birinde enkoderi bir pice lcd yi bir pice bağlamıştım.Kesinlikle hızlanıyor.
Birde önceki deneylerimi yaparken 20MHz kullanamamıştım,çalışmıyordu.Meğer define osc 20 yazmayı bilmiyormuşum. :oops:

Hi-Tide da yazdığım yeni kodlar aşağıda.
Bunları B6-7 uçlarına sinyal vererek denedim (enkoder bağlayamadım).
4000 puls (yaklaşık), 7474 lerden sonra 1000 e düşüyor, ama hem inen hem çıkan değerlendirildiği için sonuc da 4000 okunuyor malum.

#include <htc.h>
#include "delay.h" 
#include "lcd.h" 
#include "stdio.h"

unsigned char outString[17];

long konum,hedef;
bit yon,eskia,eskib,yenia,yenib;

void interrupt Kesme (void) 
{ 	
		   yenia=RB6;
		   yenib=RB7;  
		     yon=eskia^yenib;
	       konum=konum+(2*yon)-1 ; 
		   eskia=yenia;
		   eskib=yenib;             
     RBIF=0; 	
} 
void main(void)
{
	   ADCON1=0x06;         //Tüm pinler sayısal 
	   TRISB=0b11000000;    //B6-7 giriş. 
	   TRISD=0b00000000;    //D portu çıkış. 
	   TRISA=0b00000000;    //A portu çıkış.	   	   
	 RBIF=0; RBIE=1; GIE=1; // Kesme Ayarları
       lcd_init(FOURBIT_MODE);
 while(1)
 {
	 lcd_goto(S1_1); //1.satırının 1.sütününa git
	   sprintf (outString,"HEDEF = %05ld ", hedef);
	   lcd_puts(outString);   
	 lcd_goto(S2_1); //2.satırının 1.sütününa git
	   sprintf (outString,"KONUM = %05ld ", konum );
	   lcd_puts(outString);     
}}




http://www.4shared.com/file/58716657/c86599f6/Enkoder_Hi-Tide.html