Rotary Pot'ta sadece yön bilgisini okuma

Başlatan blueboard, 28 Eylül 2022, 14:58:55

ete

Yeni işlemcin port tanımlamalarında farklı özelliklere sahip.
Eskisi olan 16F628A da Porttan çıkış yapmak için örneğin PORTA.2 den HIGH çıkarmak için PORTA.2=1 yazman yeterli iken yenisi olan 16F1827 bu işi LATA registeri yapmaktadır. Bu durumda LATA.2=1 yazman gerekir.

Eskisinde Port değişiklik kesmesi INTCON.3 biti set edilerek açılır yenisinde de aynı şekilde açılır. Ancak yenisinde değişikliğin yükselen kenarda mı yoksa düşen kenardamı olduğunu da seçmek gerekiyor. Eskisinde bu özeellik yok idi. Yenisinde bu işi IOCBP (Interrup On Change PORTB Positive) yani yükselen kenarda kesme oluşturma registeri ayarlıyor. Benzer şekilde IOCBN buda düşen kenarda kesme oluşturma registeridir. Senin kesmeler,in yükselen kenarda olacak o halde IOCBP ye değer vermen gerekir.

Programın yanında şema vermemişsin. Programa bakınca giriş ayarlaması olarak TRISB=%00110000 görüyorum. Bu bana PORTB.4 ve PORTB.5 pinlerinin giriş diğerlerinin çıkış olacağını gösterir.
Ancak programa bakınca ;
-if portb.2=0
-if portb.3=0
komut satırlarını görüyorum bu satırlar PORTB.2 ve PORTB.3 pinlerinde giriş kontrolü yapıyor ama tanımlama kısmında bu pinleri giriş yapmamışsın. Şemanı görsem hiç sormaz bunları düzenlerdim. Ama bu durumda kendin karar vermen gerekecek. Şayet bu pinlerde birer giriş pini ise;
TRISB=%00111100 şeklinde giriş ayarlaması yapman gerekir.

Kesme kullanılan programlarda pause kullanılması çok sakıncalıdır. Kullanılmaması gerekir. İlla bir gecikme yaratılacak ise döngüsel gecikme (senin programında DELAY alt programı gibi) yaratılmalıdır. Böylece gecikme dilimlere bölünmüş Pause yada Pauseus ler ile halledilerek programın kesme oluştuğunda anında kesme etiketine gitmesi sağlanır. AKsi halde oraya koyduğun PAUSE 1000 komutu işlenip bitinceye kadar program kesmeye gidemez. Buda sana algılamada 1 sn lik bir gecikme yaratırki sistemin doğru çalışmadığını hemen hissedersin.

Programı olması gereken şekle soktum aşağıdadır.

Ete

'device 16F1827

#CONFIG
  __config _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_ON & _FCMEN_ON
  __config _CONFIG2, _WRT_ALL & _PLLEN_OFF & _STVREN_ON & _LVP_OFF & _BORV_19 
#ENDCONFIg

define OSC 4
OSCCON      =%01101000      '%0xxxx000 ,1111=16mHZ, 1110=8mHZ, 1101=4mHZ. 16MHz internal osilatör frekansı seçildi
OSCSTAT     =%00000000      'Timer1 Osilatör kullanıma hazır,4xPLL KAPALI
OSCTUNE     =0 

ANSELA=0:TRISA=%00100000:LATA=0:PORTA=0:WPUA=%00100000 'MCLR PİNİ DAİMA GİRİŞ OLARAK AYARLANMALI !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ANSELB=0:TRISB=%00111100:LATB=0:PORTB=0:WPUB=%00110000
   
CM1CON0.7=0
CM2CON0.7=0
DACCON0=0
CPSCON0=0
FVRCON=0
SSP1CON1.5=0 
   
CCP1CON = %00000000
CCP2CON = %00000000
CCP3CON = %00000000
CCP4CON = %00000000
CCPTMRS  =0
APFCON0=0
APFCON1=0

OPTION_REG.7 = 0
OPTION_REG.6 = 1

'--------------------------------------------------------------------------
ONAY VAR BYTE                                                                     
TEMP VAR BYTE
ESKI var byte
YENI var byte
W    VAR WORD
YON  var BYTE
ONCEKI VAR BYTE
 
ALDI var bit   

 
INTCON=%10001000  'KESME DERSİNİZDE INTCON registerinden hem global kesmeler hemde PORTB.0 kesmesi bitleri aktif edilir.
                    'Bit7=Global kesme biti , Bit4=PortB.0 Kesme bitidir.
                     'INTCON=%10010000    yazmıştınız ancak burada daha önce  " INTCON=%10001000   "  yazdınız.	                        
IOCBP=%00110000                     
ON INTERRUPT GOTO KESME'KESME OLUŞUNCA TEKRAR ADLI ETİKETE  GİDİLECEK
PAUSE 200
YON=0:ALDI=0
ESKI=PORTB & %00110000 
BASLA:
 
      if PORTB.4=0  then
        LATA.2=1
        WHILE PORTB.4=0:WEND
        GOSUB DELAY
      ENDIF 
 
      if portb.2=0 then          
        LATA.1= 1
        WHILE portB.2=0:WEND
        LATA.1 = 0
        GOSUB DELAY
      ENDIF 
 
      if portb.3=0 then          
        LATA.0 = 1
        WHILE portB.3=0:WEND
        LATA.0 = 0
        GOSUB DELAY
      ENDIF 
 
      IF YON=1 AND ALDI=1 THEN 
         LATA.2=1
         pause 1000
         LATA.2=0
         GOSUB DELAY
      ENDIF
 
      IF YON=0 AND ALDI=1 THEN      
         LATA.3=1
         GOSUB DELAY
         GOSUB DELAY
         LATA.3=0
         GOSUB DELAY
      ENDIF
      LATA=0  
  
      goto basla
 
DELAY:
      FOR W=0 TO 15000
      PAUSEUS 5
      NEXT
      ONAY=0
      ALDI=0
      RETURN 
 
DISABLE  ' DEĞİŞİKLİK KESMESİ İÇİN GEREKLİ
KESME:
       YENI=PORTB & %00110000 
       IF YENI=ESKI THEN CIK  'POT DÖNMÜYORSA ÇIKIŞA GİT BİR ŞEY YAPMA
       YON=ESKI.5 ^ YENI.4  ' YÖNÜ BELİRLE 
       ALDI=1   'BU SADECE BİR TEDBİR BİTİ LEDLER POT DÖNMEDEN YANMASIN DİYE
       ESKI=YENI 'BU ESKİ OKUMA OLACAK
CIK:
    INTCON.0=0 'KESME BAYRAĞINI SIFIRLADIK
    IOCBF=0  'Kesme bayrağı sıfırlanıyor yeniden kesme oluşabilmesi için
    RESUME
    ENABLE    
   
END

blueboard

Alıntı yapılan: ete - 29 Eylül 2024, 08:40:22Yeni işlemcin port tanımlamalarında farklı özelliklere sahip.
Eskisi olan 16F628A da Porttan çıkış yapmak için örneğin PORTA.2 den HIGH çıkarmak için PORTA.2=1 yazman yeterli iken yenisi olan 16F1827 bu işi LATA registeri yapmaktadır. Bu durumda LATA.2=1 yazman gerekir.

Eskisinde Port değişiklik kesmesi INTCON.3 biti set edilerek açılır yenisinde de aynı şekilde açılır. Ancak yenisinde değişikliğin yükselen kenarda mı yoksa düşen kenardamı olduğunu da seçmek gerekiyor. Eskisinde bu özeellik yok idi. Yenisinde bu işi IOCBP (Interrup On Change PORTB Positive) yani yükselen kenarda kesme oluşturma registeri ayarlıyor. Benzer şekilde IOCBN buda düşen kenarda kesme oluşturma registeridir. Senin kesmeler,in yükselen kenarda olacak o halde IOCBP ye değer vermen gerekir.

Programın yanında şema vermemişsin. Programa bakınca giriş ayarlaması olarak TRISB=%00110000 görüyorum. Bu bana PORTB.4 ve PORTB.5 pinlerinin giriş diğerlerinin çıkış olacağını gösterir.
Ancak programa bakınca ;
-if portb.2=0
-if portb.3=0
komut satırlarını görüyorum bu satırlar PORTB.2 ve PORTB.3 pinlerinde giriş kontrolü yapıyor ama tanımlama kısmında bu pinleri giriş yapmamışsın. Şemanı görsem hiç sormaz bunları düzenlerdim. Ama bu durumda kendin karar vermen gerekecek. Şayet bu pinlerde birer giriş pini ise;
TRISB=%00111100 şeklinde giriş ayarlaması yapman gerekir.

Kesme kullanılan programlarda pause kullanılması çok sakıncalıdır. Kullanılmaması gerekir. İlla bir gecikme yaratılacak ise döngüsel gecikme (senin programında DELAY alt programı gibi) yaratılmalıdır. Böylece gecikme dilimlere bölünmüş Pause yada Pauseus ler ile halledilerek programın kesme oluştuğunda anında kesme etiketine gitmesi sağlanır. AKsi halde oraya koyduğun PAUSE 1000 komutu işlenip bitinceye kadar program kesmeye gidemez. Buda sana algılamada 1 sn lik bir gecikme yaratırki sistemin doğru çalışmadığını hemen hissedersin.

Programı olması gereken şekle soktum aşağıdadır.

Ete

'device 16F1827

#CONFIG
  __config _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_ON & _FCMEN_ON
  __config _CONFIG2, _WRT_ALL & _PLLEN_OFF & _STVREN_ON & _LVP_OFF & _BORV_19 
#ENDCONFIg

define OSC 4
OSCCON      =%01101000      '%0xxxx000 ,1111=16mHZ, 1110=8mHZ, 1101=4mHZ. 16MHz internal osilatör frekansı seçildi
OSCSTAT     =%00000000      'Timer1 Osilatör kullanıma hazır,4xPLL KAPALI
OSCTUNE     =0 

ANSELA=0:TRISA=%00100000:LATA=0:PORTA=0:WPUA=%00100000 'MCLR PİNİ DAİMA GİRİŞ OLARAK AYARLANMALI !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ANSELB=0:TRISB=%00111100:LATB=0:PORTB=0:WPUB=%00110000
   
CM1CON0.7=0
CM2CON0.7=0
DACCON0=0
CPSCON0=0
FVRCON=0
SSP1CON1.5=0 
   
CCP1CON = %00000000
CCP2CON = %00000000
CCP3CON = %00000000
CCP4CON = %00000000
CCPTMRS  =0
APFCON0=0
APFCON1=0

OPTION_REG.7 = 0
OPTION_REG.6 = 1

'--------------------------------------------------------------------------
ONAY VAR BYTE                                                                     
TEMP VAR BYTE
ESKI var byte
YENI var byte
W    VAR WORD
YON  var BYTE
ONCEKI VAR BYTE
 
ALDI var bit   

 
INTCON=%10001000  'KESME DERSİNİZDE INTCON registerinden hem global kesmeler hemde PORTB.0 kesmesi bitleri aktif edilir.
                    'Bit7=Global kesme biti , Bit4=PortB.0 Kesme bitidir.
                     'INTCON=%10010000    yazmıştınız ancak burada daha önce  " INTCON=%10001000   "  yazdınız.                            
IOCBP=%00110000                     
ON INTERRUPT GOTO KESME'KESME OLUŞUNCA TEKRAR ADLI ETİKETE  GİDİLECEK
PAUSE 200
YON=0:ALDI=0
ESKI=PORTB & %00110000 
BASLA:
 
      if PORTB.4=0  then
        LATA.2=1
        WHILE PORTB.4=0:WEND
        GOSUB DELAY
      ENDIF 
 
      if portb.2=0 then          
        LATA.1= 1
        WHILE portB.2=0:WEND
        LATA.1 = 0
        GOSUB DELAY
      ENDIF 
 
      if portb.3=0 then          
        LATA.0 = 1
        WHILE portB.3=0:WEND
        LATA.0 = 0
        GOSUB DELAY
      ENDIF 
 
      IF YON=1 AND ALDI=1 THEN 
         LATA.2=1
         pause 1000
         LATA.2=0
         GOSUB DELAY
      ENDIF
 
      IF YON=0 AND ALDI=1 THEN      
         LATA.3=1
         GOSUB DELAY
         GOSUB DELAY
         LATA.3=0
         GOSUB DELAY
      ENDIF
      LATA=0  
  
      goto basla
 
DELAY:
      FOR W=0 TO 15000
      PAUSEUS 5
      NEXT
      ONAY=0
      ALDI=0
      RETURN 
 
DISABLE  ' DEĞİŞİKLİK KESMESİ İÇİN GEREKLİ
KESME:
       YENI=PORTB & %00110000 
       IF YENI=ESKI THEN CIK  'POT DÖNMÜYORSA ÇIKIŞA GİT BİR ŞEY YAPMA
       YON=ESKI.5 ^ YENI.4  ' YÖNÜ BELİRLE 
       ALDI=1   'BU SADECE BİR TEDBİR BİTİ LEDLER POT DÖNMEDEN YANMASIN DİYE
       ESKI=YENI 'BU ESKİ OKUMA OLACAK
CIK:
    INTCON.0=0 'KESME BAYRAĞINI SIFIRLADIK
    IOCBF=0  'Kesme bayrağı sıfırlanıyor yeniden kesme oluşabilmesi için
    RESUME
    ENABLE    
   
END
Teşekkür ederim.

blueboard

#17
Ete Hocam, 16F1827 ile Rotary Encoder 'de sadece yön bilgisini okuma yaparken sıklıkla hatalı okuma yapılıyor. Encoder'i saat yönüne de çevirsem, saatin ters yönüne de çevirsem sanki hep aynı yöne çeviriyormuşum gibi çıkış veriyor. Bir de dikkatimi çeken isisi ilk çalıştırdığımda GND(Şase) uçlarının bağlı olduğu yerler mavi renkli değil de sarı renkli oluyor. Simulasyonda ebcoderi çevirdikten sonra mavi renge dönüyor. Yardımcı olabilir misiniz. Proteus versiyonum 8.5 'tir. Gerçek devrede encoder ayakları ile şase arasına 100 nf kondansatör de bağladım. Normalde encoderde bulunan push butonları da kullanacağım ancak programın daha sade olması için onları şu an simulasyona ve programa ilave etmedim.


ete

İşlemci değişince yeni işlemciye göre bazı eklemeler yapılması gerekirdi.
Bunların başında hem düşen kenear kesmesi hemde yükselen kenar kesmesi açık olmalı.
Aşağıdaki programı bir dene bakalım.

ete,
device 16F1827
#CONFIG
  __config _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_ON & _CPD_ON & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_ON & _FCMEN_ON
  __config _CONFIG2, _WRT_ALL & _PLLEN_OFF & _STVREN_ON & _LVP_OFF & _BORV_19 & _LVP_OFF 
#ENDCONFIG

define OSC 4
OSCCON      =%01101000      '%0xxxx000 ,1111=16mHZ, 1110=8mHZ, 1101=4mHZ. 16MHz internal osilatör frekansı seçildi
OSCSTAT     =%00000000      'Timer1 Osilatör kullanıma hazır,4xPLL KAPALI
OSCTUNE     =0 
  
ANSELA=0:TRISA=%00100000:LATA=0:PORTA=0:WPUA=%00100000 'MCLR PİNİ DAİMA GİRİŞ OLARAK AYARLANMALI !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ANSELB=0:TRISB=%00111100:LATB=0:PORTB=0:WPUB=%00110000

CM1CON0.7=0
CM2CON0.7=0
DACCON0=0
CPSCON0=0
FVRCON=0
SSP1CON1.5=0 
   
CCP1CON = %00000000
CCP2CON = %00000000
CCP3CON = %00000000
CCP4CON = %00000000
CCPTMRS  =0
APFCON0=0
APFCON1=0

OPTION_REG.7 = 0
OPTION_REG.6 = 1

'--------------------------------------------------------------------------
ONAY VAR BYTE                                                                     
TEMP VAR BYTE
ESKI var byte
YENI var byte
W    VAR WORD
YON  var BYTE 56
ONCEKI VAR BYTE
 
ALDI var bit                 
                       
PAUSE 200
INTCON=%10001000  
 
IOCBN=%00110000                     
IOCBP=%00110000                 
ON INTERRUPT GOTO KESME'KESME OLUŞUNCA TEKRAR ADLI ETİKETE  GİDİLECEK
YON=0:ALDI=0
ESKI=PORTB & %00110000 

BASLA:
 
      
   IF YON=1 AND ALDI=1 THEN 
      PORTA.2=1
      GOSUB DELAY
    ENDIF

    IF YON=0 AND ALDI=1 THEN      
      PORTA.3=1
      GOSUB DELAY
    ENDIF
    PORTA=0  
  
    goto basla

DELAY:
      ALDI=0
      FOR W=0 TO 10000
      PAUSEUS 5
      IF ALDI=1 THEN RETURN
      NEXT
      ONAY=0
      
      RETURN 

DISABLE  ' DEĞİŞİKLİK KESMESİ İÇİN GEREKLİ
KESME:
       YENI=PORTB & %00110000 
       IF YENI=ESKI THEN CIK  'POT DÖNMÜYORSA ÇIKIŞA GİT BİR ŞEY YAPMA
       YON=ESKI.5 ^ YENI.4  ' YÖNÜ BELİRLE 
       ALDI=1   'BU SADECE BİR TEDBİR BİTİ LEDLER POT DÖNMEDEN YANMASIN DİYE
       
CIK:
    ESKI=YENI 'BU ESKİ OKUMA OLACAK
    INTCON.0=0 'KESME BAYRAĞINI SIFIRLADIK
    TEMP=PORTB  'PORTU OKUDUK DEĞİŞİKLİK OLURSA KESMEYE GELİNECEK.
    RESUME
    ENABLE    
   
END

blueboard

#19
Ete Hocam, son gönderdiğiniz program sorunsuz çalışıyor. Teşekkür ederim. Sizin yazdığınız programa ilaveler yaptım. Birincisi buton ilavesi yaptım. Buton istediğim şekilde çalışıyor. İkincisi ise mümkün mü bilmiyorum, denedim ancak başarılı olamadım. Yapmak istediğim şu: A1 pinine 0-1 volt arası bir gerilim uygulanırsa a7 pini çıkış verecek. Uygulanan gerilim 1 volttan fazla olursa a7 pini çıkışı kesecek.

Bir de gerek Rotary encoder de gerekse butonda harici pull up direnci yerine dahili pull up dirençlerini kullansam olur mu?

ete

ADC olayına bakacağım.
Dahili Pullup dirençleri 22K civarındadır. Bence zayıf kalır. Bu nedenle harici pullup kullansan daha iyi olur. Çünki Pullup bazen 4K7 olarak gerekebiliyor. Yinede deneyip sonuca bakmanı öneririm.
Sorun olmuyor ise kullanabilirsin.

Ete

mehmet

Parazit durumu söz konusu ise, harici pull-up direnci 1K bile olabilir.
Düşük güç durumları hariç; ben çoğunlukla pot da dahil olmak üzere 1K kullanıyorum.



5000mV ÷ 1023 = 4.888mV
1000mV ÷ 4.888 = 204.5 ADC değeri

205'den küçük ve büyük olma durumuna göre pin konumunu değiştirebilirsiniz.
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
http://www.mehmetbilgi.net.tr
CC BY

ete

Adc ile ilgili bir iki düzeltme yaptım.
Birincisi Define komutlarını 4Mhz e göre değiştirdim.
İkincisi ADCON1 registerini eklememişsin. Bunu ekleyerek sonucu sağa yaslı ve dolayısıyla 0-1023 arasında okunmasını sağlamış oldum.
1V un karşılığı digital olarak 204 dür. Dolayısıyla programın ADC okuma kısmını;
ADCIN 1,HAMa
IF HAMA<204 THEN  
  LATA.7=1
else
  LATA.7=0
ENDIF 
şeklinde değiştirdim.
Bu şekilde çalışıyor sistem.
Dosya ilişiktedir.
Ete



blueboard

Ete Hocam, ellerinize sağlık. Son bir sorum olacak. ADC girişteki gerilimi örneğin 0.5 volt olarak ayarlıyorum. Şart sağlandığı için A7 pinindeki led yanıyor. Ancak yanma sürekli değil, yanma sönme şeklinde oluyor. Bunun sebebi nedir?

ete

#24
PORTA=0 bu komut yüzünden bu söndürüyor ADC okuması yakıyor şeklinde düşünebilirsin.,Çözüm şu;
PORTA=0 (bu komut aslında LATA=0 şeklinde olmalı) yerine yalnızca LATA.2 ve LATA.3'ü söndürecek bir komut yazılmalı. O da şöyle olur;
LATA=LATA & (%11110011)

Ete

blueboard


Powered by EzPortal
▲