Enkoder ve Step Motor Hakkında

Başlatan oguztkn, 12 Kasım 2019, 20:27:15

oguztkn

Merhaba,

 Bir dc motorun motorun arkasındaki enkoderden gelen pulsleri alıp eş zamanlı olarak step motorun devrini ayarlamak istiyorum. Belirli bir süre gelen puls i sayıp dakika ya vurup devir bulsam eş zamanlı senkron çalışmayacak. Senkron çalışması için nasıl bir çözüm bulunabilir ?

İki puls arasındaki süreyi ölçmek aklıma geldi ama ne kadar mantıklı olur ? (Enkoder bir turda 400 puls üretiyor)

Şimdiden Teşekürler....

İlyas KAYA

Step motor sürücü devresinin step girişine encoder i direk bağlayın zaten istediğiniz olur. Izole izin belki bir optocoupler kullansanız fena olmaz.
Göz odur ki dağ ardını görsün,
Akıl odur ki başa geleceği bilsin.!

oguztkn

Cevabınız için teşekkür ederim ama işlemci üzerinden geçirmem gerekiyor çünkü lcd ekrana yazdırmam ve devire göre oran verip step motorun hızını değiştirmem gerekiyor


oguztkn

Hocam Merhaba,

18f45k22 kullanıyorum ve dahili osilator ile 64 mhz de çalıştırıyorum.
Aynı zamanda PORTB değişiklik kesmesi içerisinde portb.5 pininden timer3 için puls girişi yapıyorum.

Forumda sizin kodlarınız gördüm onlara bakarak yapmaya çalıştım ama bir yerde eksiklik var bulamıyorum.

Kodlarım


DEFINE OSC 64

DEFINE LCD_DREG PORTD
DEFINE LCD_DBIT 4
DEFINE LCD_EREG PORTD
DEFINE LCD_EBIT 0
DEFINE LCD_RWREG        PORTD
DEFINE LCD_RWBIT        1
DEFINE LCD_RSREG PORTD
DEFINE LCD_RSBIT 2
DEFINE LCD_BITS 4
DEFINE LCD_LINES 4

OSCCON = %01110100 '16MHz INTERNAL Primary clock
OSCTUNE = %01000000 '%x1xxxxxx = PLL ENABLED
;###############################################################################


temp var byte:x var byte:y var word
z var byte
poz var bit
sure var word
freq var word
peryot var word
frekans var word
baslangic var byte
durum var byte
;===============================================================================
TRISA=0:
TRISB=%11110100
TRISC=%00000000
TRISD=0
TRISE=0
PORTA=0:PORTB=0:PORTC=0:PORTD=0:PORTE=0                  

ADCON0.0=0
ADCON1=%00001111
ANSELA=0
ANSELB=0
ANSELC=0
ANSELD=0
ANSELE=0          

RCON.7=0
PMD2=%00001111
CM1CON0=0
CM2CON0=0
IOCB=%00100000
SLRCON=0                    

INTCON  = %10001000
INTCON2 = %00000000
INTCON3 = %00000000

T3CON =%10110000
TMR3H=0:TMR3L=0                                      
z=255
;===============================================================================
lcdout $FE,1:pause 300
on interrupt goto Kesme

Basla:        
        lcdout $FE,$80,dec3 z," ",dec5 freq,"  ",dec5 peryot
        lcdout $FE,$C0,dec TMR3H,"  ",dec5 sure
        lcdout $FE,$94,dec TMR3L,"  ",dec INTCON.0
goto Basla



DISABLE
Kesme:
    
if INTCON.0=1 then
    z=z+1 
    
    if z=0 then  
    
    TMR3L=0:TMR3H=0
    T3CON.0=1
    endif
    

    IF Z=1 THEN 

        T3CON.0=0
        sure.lowbyte=TMR3L
        sure.highbyte=TMR3H
    freq=freq+sure
    peryot=freq
    z=255
endif

  
    INTCON.0=0
endif

resume
enable
END


şeklinde amacım iki puls arasındaki süreyi ölçerek frekansa ulaşmak. Sonra buna uygun olarak HPWM kanalından o frekansta pwm sinyali üreteceğim. Onunla da step sürmeyi amaçlıyorum.

Şimdiden Teşekkürler...

ete

#4
Sigorta ayarların neden eksik bilmiyorum ama programınbaşına şunları eklemende fayda var.
ASM
    __CONFIG _CONFIG1H, _FOSC_INTIO67_1H  & _PLLCFG_ON_1H & _PRICLKEN_OFF_1H & _FCMEN_OFF_1H & _IESO_OFF_1H        
    __CONFIG _CONFIG2L, _PWRTEN_ON_2L & _BOREN_OFF_2L & _BORV_285_2L 
    __CONFIG _CONFIG2H, _WDTEN_ON_2H & _WDTPS_32_2H                                                                                    
;    __CONFIG _CONFIG3H, _CCP2MX_PORTB3_3H & _PBADEN_OFF_3H & _CCP3MX_PORTE0_3H & _HFOFST_OFF_3H & _T3CMX_PORTB5_3H & _P2BMX_PORTC0_3H & _MCLRE_INTMCLR_3H
    __CONFIG _CONFIG3H, _PBADEN_OFF_3H & _HFOFST_OFF_3H & _T3CMX_PORTB5_3H & _P2BMX_PORTC0_3H & _MCLRE_INTMCLR_3H
    __CONFIG _CONFIG4L, _STVREN_OFF_4L & _LVP_OFF_4L & _XINST_OFF_4L & _DEBUG_OFF_4L
    __CONFIG _CONFIG5L, _CP0_ON_5L & _CP1_ON_5L    
    __CONFIG _CONFIG5H, _CPB_ON_5H & _CPD_ON_5H
    __CONFIG _CONFIG6L, _WRT0_OFF_6L & _WRT1_ON_6L 
    __CONFIG _CONFIG6H, _WRTC_ON_6H & _WRTB_ON_6H & _WRTD_OFF_6H ; epromun yazma koruması WRTD dir OFF olmalı
    __CONFIG _CONFIG7L, _EBTR0_ON_7L & _EBTR1_ON_7L
    __CONFIG _CONFIG7H, _EBTRB_ON_7H 
endasm

OSCON register gurubunu aşağıdaki gibi ayarla;
OSCCON =%01111010
OSCCON2=%10000000
OSCTUNE=%01000000
Bana kalırsa z değişkenini bit değişkeni şeklinde kullan ve programa Z=0 ile başla ve aşağıdaki şekilde olsun
lcdout $FE,1:pause 300
on interrupt goto Kesme
T3CON =%10110001
TMR3H=0:TMR3L=0                                      
z=0
Kesme kısmında başka kesme kaynağın olmadığına göre IF ile başlaman gerekmiyor.Bu nedenle kesme kısmını aşağıdaki şekilde değiştir
DISABLE
Kesme:        
    if z=0 then      
      TMR3L=0:TMR3H=0
      T3CON.0=1
    endif    
    IF Z=1 THEN 
      T3CON.0=0
      sure.lowbyte=TMR3L
      sure.highbyte=TMR3H
      freq=freq+sure
      peryot=freq      
    endif  
    z=1-Z
    INTCON.0=0

resume
enable
END
bu şekilde dene bakalım. Z yi bit değişkenine çevirmeyi unutma.
Diğer taraftan frekans hesabını pek anlamadım. Timer'ı 1/8 bölme oranı ile kullanıyorsun. Yani her 8 pulsde sayacın 1 artacak demektir. Böylece bir peryotta yakaladığın puls adedini 8 ile çarpman gerekecek. Bu sana her bir konuma kaç pals denk geldiğini gösterecek. Bir puls süresi 0,0625 olduğu için bu rakamla puls adedini çarpacaksın. Böylece her bir konum için gerçek zamanı bulacaksın. İki konum sürelerini toplayınca Toplam peryodu bulacaksın. Bunu 1000.000'a bölersende frekansı HZ olarak bulacaksın.
İşi formülize edersek peryot=Sure*0,5  (0,5=8*0,0625 dir) Bunuda Sure*5/10 şeklinde yapabilirsin.
Bu hesapları ana program kısmında yapmanda yarar var.
Ayrıca bu sürekli çalışn bir sistem olacağına göre Her z=0 olduğu konumda Freq değerini ve peryot değerini sıfırlamanda gerekir. Yoksa üst üste sayıları toplayıp gider program.
Frekans peryot ilişkisi şöyledir. Peryot=HIGH_Süresi+Low_Süresi , Freq=1.000.000/Peryot(us) , sonuç HZ bulunur.
Yada Freq=1000/Peryot(us) sonuç Khz Bulunur.
Ete

oguztkn

#5
Hocam verdiğiniz sigorta ayarları pbp nin klasörü içerisinde ki işlemcinin inc dosyasında mevcut oradan aldığından bir kez daha programın başına eklemedim.

OSCON register gurubunu aşağıdaki gibi ayarla;
OSCCON =%01111010
OSCCON2=%10000000
OSCTUNE=%01000000

verdiğiniz bu satırları daha önce bende denedim. Fakat işlemci bu ayarları verince düzgün çalışmıyor. Basit bir kod ile 1 ledi 1sn yakıp söndürüyorum fakat yaklaşın 40 sn ye de bir yanıp sönüyor. Nedenini bilmiyorum ama aynı kodlar

OSCCON = %01110100
OSCTUNE = %01000000

sadece bu iki satırı yazınca normal çalışıyor. Pause süresi normale dönüyor.


Kesme bölümüne gelirsek z bit bit olarak değiştirdim simulasyonda değil gerçek devrede deniyorum ekrana TMR3L ve TMR3H ı da yazdırmama rağmen değerler sürekli 0 olarak kalıyor. Z değerini de ekrana yazdırdım o sürekli toggle oluyor. Sinyali resimdeki modül ile PORTB.5 bacağından veriyorum.

Timer bölme oranında ise 1/8 kullanmamın bir nedeni olmalı mı bilmiyorum dediğim gibi amacın sürekli olarak frekansı ölçmek açıkçası ne olması gerektiğini bilmiyorum

Kodların son hali ise:


DEFINE OSC 64

DEFINE LCD_DREG		PORTD
DEFINE LCD_DBIT		4
DEFINE LCD_EREG		PORTD
DEFINE LCD_EBIT		0
DEFINE LCD_RWREG        PORTD
DEFINE LCD_RWBIT        1
DEFINE LCD_RSREG	PORTD
DEFINE LCD_RSBIT	2
DEFINE LCD_BITS		4
DEFINE LCD_LINES	4


'OSCCON =%01111010
'OSCCON2=%10000000
'OSCTUNE=%01000000


OSCCON = %01110100
OSCTUNE = %01000000
;###############################################################################

temp var byte:x var byte:y var word
z var bit
poz var bit
sure var word
freq var word
peryot var word
frekans var word
baslangic var byte
durum var byte
periyot var word
;===============================================================================
TRISA=0:TRISB=%11110100:TRISC=%00000000:TRISD=0:TRISE=0
PORTA=0:PORTB=0:PORTC=0:PORTD=0:PORTE=0                   

ADCON0.0=0:ADCON1=%00001111
ANSELA=0:ANSELB=0:ANSELC=0:ANSELD=0:ANSELE=0          

RCON.7=0:PMD2=%00001111:CM1CON0=0
CM2CON0=0:IOCB=%00100000:SLRCON=0                     
              
INTCON  = %10001000
INTCON2 = %00000000
INTCON3 = %00000000
         
T3CON =%10110000
TMR3H=0:TMR3L=0                                       
z=0
;===============================================================================
lcdout $FE,1:pause 300
on interrupt goto Kesme

Basla:
         peryot=Sure*5/10
         lcdout $FE,$80,"Z:",dec z," F:",dec5 freq," P:",dec5 peryot
         lcdout $FE,$C0,"TMR3H: ",dec TMR3H
         lcdout $FE,$94,"TMR3L: ",dec TMR3L
                
                 
goto Basla


DISABLE
Kesme:
    
   
    if z=0 then
    freq=0
    peryot=0       
    TMR3L=0:TMR3H=0
    T3CON.0=1
    endif
    

    IF Z=1 THEN 
         T3CON.0=0
         sure.lowbyte=TMR3L
         sure.highbyte=TMR3H
    freq=freq+sure
    peryot=freq
endif
    z=1-z
    INTCON.0=0

resume
enable

END




ete

INC dosyasında default config ayarları vardır ve sen programa kendi configlerini koyduğun zaman derleyici seninkiler ile INC içindekileri yer değiştirip seninkileri kullanır.
INC dosyasındaki ayarlarda Senin PLL kullanıp kullanmayacağını bilemez. O nedenle kendi ayarlarını programa koyman gerekir.
Yaşadığın sorunların sebebi bu olsa gerek.
Diğer taraftan kullandığın mantığı anlamaya çalışıyorum. Frekansı PORTB.5 den girip kesme yaratıyorsun. İki kesme arasındaki zamanı sayarak peryot hesabı yapacağına göre TMR3 sayacı dahili OSC den puls alıp sayması gerekir. Bu durumda T3CON=%00110000 şeklinde değer alması gerekir.
İlişikteki Programı dene istersen,

Ete



oguztkn

Hocam ekte gönderdiğiniz dosyayı da denedim. Sonrasında PORTB değişiklik kesmesinden çıkarıp puls girişini portb.0 a yapıp o kesmeyi aktif ettim o şekilde denedim fakat sonuç gene aynı oldu. Çok kısa çalışmasını çektim drive'a yükledim . Acaba neden bu şekilde çalışıyor ?

Çalışma Videosu

ete

Sorun aslında değerlerin çok kısa aralıklarla değişmesinden kaynaklanıyor. Timer değerlerini ekrandan kaldırıp yalnızca frekans yada peryot hesabını yazdırmaya çalışsan belki daha iyi sonuç alacaksın.
Peryot ölçerek frekans ölçme işi daha ziyade düşük frekanslarda işe yarıyor. Mesela 500 hz nin altında. Daha büyük frekanslarda zaman tutup giren pulsları saydırmak daha iyi sonuç veriyor.
Peryot ölçme işinide en iyi capture özelliği ile yapabiliyorsun. Bence oraya odaklansan daha uygun olacak. Zira tercih ettiğin yolda çok fazla komut gecikmesi oluyor ve seni yanıltıyor.
Ete

oguztkn

#9
Hocam ekrandaki diğer göstergeleri kaldırarak denedim sonuç aynı birşey değişmedi.

"Peryot ölçerek frekans ölçme işi daha ziyade düşük frekanslarda işe yarıyor. Mesela 500 hz nin altında." demişssiniz ama videoda da görebileceğiniz gibi 10h veriyorum kaynaktan. Bu kadar az frekansta bile bunu yapması pek normal değil gibi sanki ?

Capture yi denemek istedim.
PORTB.5 bu işlemcide CCP3 girişi

 Basla etikentinde önce şu şekilde uyguladım.

 

INTCON  = %11000000
INTCON2 = %00000000
INTCON3 = %00000000

PIE4.0=1
PIR4.0=0
CCP3CON=%00000101         ;rising
;CCP3CON=%00000100         falling
T1CON=%01000000

clear
lcdout $FE,1:pause 300
On interrupt goto Kesme

Basla:
      LCDOUT $FE,$94,"SURE:   :",dec SURE1
      Sure1.lowbyte=TMR1L
      sure1.highbyte=TMR1H
goto basla

Disable
Kesme:
    if PIR4.0=1 then

    if z=0 then
    CCP3CON=%00000100
    TMR1H=0:TMR1L=0    
    T1CON.0=1
    endif
    
    if z=1 then
    T1CON.0=0
    sure1.lowbyte=TMR1L
    sure1.highbyte=TMR1H
    CCP3CON=%00000101
    endif
  
z=1-z
PIR4.0=0
endif

resume
enable

END

Bu şekilde de videodan farksız bir görüntü olmadı.




ete

#10
Nasıl bir görüntü bekliyorsun bilmiyorum ama amaç burada freq ve peryot hesaplama olduğuna göre görüntüye bakmayacaksın. Tutarlı bir sonuç alıp alamayacağına bakman gerek.
İlişikte ki disyada 628A ile yaptığım capture çalışmasına örnek bir proje var. İncele istersen.
Ayrıca sitede Capture konusunda bir şeyler daha olması gerek. Arama yapıp onlarada bakın lütfen.

Ete

oguztkn

Beklediğim görüntü şu aslında hocam

pedala bağlı bir dc motor var gibi düşünün pedala bastıkça motor hızlanıyor motorun arkasında ki encoder den de puls ler geliyor. Motorun devrini ekranda anlık göstermeye çalışıyorum




ete

Aşağıdaki mantık daha sabit bir görüntü veriyormuş. Bunlar eski çalışmalarım.
#CONFIG
 __config _BODEN_ON & _BOREN_ON & _CP_ON & _PWRTE_ON & _WDT_ON & _LVP_OFF & _MCLRE_OFF & _INTRC_OSC_NOCLKOUT 
#ENDCONFIG
define OSC 4
    TRISA=0
    TRISB=%00001000    
    PORTA=0
    PORTB=0
'@ DEVICE pic16F628A                      'işlemci 16F628                                
'@ DEVICE pic16F628A, WDT_on              'Watch Dog timer açık
'@ DEVICE pic16F628A, PWRT_ON             'Power on timer açık
'@ DEVICE pic16F628A, PROTECT_OFF         'Kod Koruma kapalı
'@ DEVICE pic16F628A, MCLR_OFF             'MCLR pini kullanılıyor.
'@ DEVICE pic16F628A, INTRC_OSC_NOCLKOUT  'Dahili osilatör kullanılacak    
CMCON=7

SURE1  VAR WORD
SURE2  VAR WORD
SURE3  VAR WORD
SURE   VAR WORD
PERYOT VAR WORD
FREQ   VAR WORD

SYMBOL FLAG=PIR1.2
SYMBOL KESME=PIE1.2

DEFINE LCD_DREG     PORTB   'LCD Data bacakları hangi porta bağlı
DEFINE LCD_DBIT     4       'LCD data bacakları hangi bitten başlıyor
DEFINE LCD_EREG     PORTB   'LCD    ENABLE bacağı hangi porta bağlı
DEFINE LCD_EBIT     2       'LCD enable bacağı hangi bite bağlı
DEFINE LCD_RSREG    PORTB   'LCD RS Bacağı hangi bite bağlı
DEFINE LCD_RSBIT    1       'LCD RS bacağı hangi bite bağlı
DEFINE LCD_BITS     4       'LCD 4 BIT MI 8 BIT MI
DEFINE LCD_LINES    2       'LCD KAÇ sıra yazabiliyor
'******************************************************************
lcdout $fe,1
PAuse 500
 
BASLA:
            
      TMR1L=0:TMR1H=0:FLAG=0
      CCP1CON=%00000101:PIR1.0=0:'kesme=1
      T1CON=1:CCPR1L=0:CCPR1H=0:FLAG=0
      WHILE FLAG=0:WEND
      SURE1.BYTE0=CCPR1L
      sure1.BYTE1=CCPR1H    
      CCP1CON=%00000100 
      FLAG=0
      WHILE FLAG=0:WEND
      SURE2.BYTE0=CCPR1L
      SURE2.BYTE1=CCPR1H
      SURE=SURE2-SURE1-1 'LOW SÜRESİ  
      
      CCP1CON=%00000101 
      FLAG=0
      WHILE FLAG=0:WEND      
      sure3.BYTE0=CCPR1L
      SURE3.BYTE1=CCPR1H
      PERYOT=SURE3-SURE2+1  'HIGH SÜRESİ
     
      LCDOUT $FE,$80,"HIGH  :",dec Peryot," us"
      LCDOUT $FE,$C0,"LOW   :",dec SURE  ," us"
      LCDOUT $FE,$94,"PERYOT:",dec (peryot+SURE)," us"
      SURE1=1000**1000
      FREQ=DIV32 (peryot+sure)
      lcdout $fe,$d4,"FREQ  :",DEC FREQ," Hz"
      T1CON=0
      
      GOTO BASLA

Powered by EzPortal