Endüktif Sensör Çıkışı Saydırma

Başlatan oongit, 05 Kasım 2017, 23:09:35

oongit

Selam arkadaşlar.

PIC Basic konusuna uzunca bir süre ara vermek durumunda kalmıştım. O yüzden bazı konularda yetersiz kaldığımı biliyorum. Bunun için de siz değerli arkadaşlardan yapmak istediğim devre ve program hakkında tavsiye / yönlerdirme rica ediyorum.

Devrenin ana bileşenleri PIC16F628A, PC817, ve 4x20 LCD, 24V PNP endüktif sensör olacak.

Sorunum şu:
Bir pnömatik pistonun hareket verdiği metal parçaya bağlı olan endüktif sensörden alacağım palsi PIC'e saydırmak ve 1 dakikada kac saykıl yaptığını hesaplamak istiyorum.

Kullanılan endüktif sensör PNP tipinde, 24V ile besleniyor ve metali gördüğünde pozitif çıkış veriyor.
Sensörün metali görme sıklığı dakikada 4 - 20 arası değişiyor.
Sensör toplamda 5 adet. Yani 5 adet pin kullanmam gerekiyor. (16F628A'nın A portunu bu sensörlere ayırdım)
Bazen bütün sensörler aynı anda çıkış verebiliyor

Bu sensörlerden gelen bilgiyi hangi şekilde işlemeliyim ki; LCD ekranda bunu görebileyim.
*     PORTB.4-7 kesmesi mi kullanmam gerekir?
*     PORTA'daki ADC pinlerini mi kullanmalıyım?
*     Ya da ADC'yi iptal edip, pine gelen palsler arasında geçen süreyi mi hesaplamam gerekir?

Bu yöntemlerden hangisi kullanmalıyım? Ya da daha mantıklı fikirleriniz varsa buna da açığım. Yardımcı olabilirseniz çok sevinirim.

Saygılarımla...

Hattuşa

#1
slm öncelikle 628a de adc kanalı yoktur. madem 628a kullanacaksınız o zaman portb 4-7 change kesmesi ve int (portb.0) kesmesini kullanabilirsiniz. burada yapmanız gereken timer0 veya daha hassas olsun istiyorsanız timer1 kesmesini aktif edip, bir zaman oluşturmalısınız. mesela 10mS lik kesme oluşturup sayma işlemi ile zaman oluşturabilirsiniz. bu 10mS lik kesmeden 100 sayım 1 sn, 6000 sayım ise 1 dk ya tekabul eder.
sayacınızı her 6000 sayımda sıfırlarken portb4-7 ve int girişlerindeki kesmeleri sayısını bir değişkende tutarsanız size 5 adet sensörünüzden gelen bilgileri ile 1 dk da hepsinin tek tek kaç kez çıkış vermiş olduğunu öğrenmiş olursunuz.
umarım anlatımım işinize yarar

oongit

Yanıtın için teşekkür ederim Selâmi abi.

16F628A'da ADC modülü olmadığı aklımdan çıkmış, malum uzun zaman oldu. Gerçi işlemci sorun değil, gerekirse farklı kullanırım.
PORTB4-7 ve PORTB.0 kesmelerini aynı anda aktif edebiliyor muyuz? Ve tabi tek TMR1 kesmesi ile aynı anda 5 girişi de okuyabiliyor muyuz?

Saygılarımla...

ete

#3
Benim önerim,
1 adet sensörü PORTB.0 pinine bağlayıp PORTB.0 (INT0) kesmesini aktif etmek.
4 adet sensörüde PORTB 4-7 pinlerine bağlayıp PORTB değişiklik kesmesini aktive etmek. Burada dikkat edilecek husus PORTB pinlerinin PULLDOWN olarak bekletilmesidir. AKtif olan sensör pini HIGH yapacaktır buda kesme oluşmasına sebep olacaktır. INT0 kesmesi için kenar seçme bitini HIGH da tetiklenecek şekilde ayarlaman gerekir. (OPTION_REG.6)
Son olarak da TMR1 sayacını 500 ms için kurup kesmeleri aktif hale getirip iki adet TMR1 kesmesi oluşmasını gözlemleyip her bir sensörün saydığı değerleri ekrana vermek.
TMR1 sayacı için kesme oluşturmaya gerek yoktur. Ancak kesme bayrğını kontrol ederek sonuca ulaşmalısınız.
İşlem sırasını vermek gerekirse;
1. INT0 ve PORTB değişiklik kesmelerini hazır hale getir.
2.TMR1 sayacını aktif et  (T1CON=%00011001):KES=120 vererek 120 kesme sonra 1 dak geçmesini sağlayacaksın
3. ve sayaca 4 mhz için TMR1H=$0B:TMR1L=$DC değerlerini verip kesme bayrağı olan PIR1.0=0 sıfırla.
4. ITCON=%10011000 vererek kesmeleri aktif et.
5. WHILE PIR1.0=0 deyip zaman döngüsünü çalıştır:wend ile bitir
6. Kes=KES-1 ve IF KES>0 THEN 3cü adım diyerek her kesmede 500 ms  geçmesini sağla.
7. buraya geldiğinde 1 dak geçmiş olacak . Kesmeleri kapat (INTCON=0) :T1CON=0
8. Elindeki değerleri Ekrana verip tekrar en baştan devam et.

İşin kritik yanı kesme içinde kimin aktif olduğuna bakmaktır.
Bunun için Kesme oluştuğunda önce PORTB.0 ı test et. IF INTCON.1=1 THEN SAY0=SAY0+1:INTCON.1=0
Daha sonra diğer Pinlere bak;
IF INTCON.0=1 then
  SAY1=SAY1+PORTB.4  (Şayet PORTB.4 pini HİGH ise sayacını 1 artıracak)
  SAY2=SAY2+PORTB.5
  SAY3=SAY3+PORTB.6
  SAY4=SAY4+PORTB.7
  INTCON.0=0:TEMP=PORTB.0
ENDIF
RESUME
ENABLE
şeklinde kesmeden çık.
Bu veridklerim kesmeden en az vakit kaybederek  çıkılmasını sağlayacaktır.
İşin hem temelini anlattım hemde kodun olması gereken şeklinden örneklerde verdim. Bundan sonrasını halledersin sanırım.
Ete

 


oongit

Ete hocam...

Size tek bir cümlem olur:
Allah sizlerden razı olsun...

Akşam eve gidince önerdiğiniz yöntem üzerinde çalışacağım. Sonsuz teşekkürler.

Saygılarımla...

Hattuşa

@ete hocam;
6. maddenizde kesme içerisinde döngüyü bekletmek sağlıklı olurmu? kullanım esnasında ana menude ekran veya diğer işlerin işlenmesinde sıkıntı yaramaz mı?
yani bir saat yazılımı gibi düşünmüştüm ben. timer1 sayıcısı interrupt içerisinde 1 dk oluncaya kadar saymaya devam edecek. 1 dk dolduğunda sayma değeri sıfırlanırken portb.4-7 kesmlerinde ki ve int0 daki sayac değerleri başka bir değişkene alınıp o sayaçlar sıfırlanarak sonsuz bir döngü oluştursak sağlıklı olmaz mı? bu arada ana menude de istenilen diğer işlemlerde yapılabilir diye düşündüm.
gerçi şu var, ilgimi çeken güzel projeler bulamadığımızdan elektronik artık hayatımda yavaş yavaş kenara itiliyor. sizin kadar heyecanlı olabilsek keşke...

ete

Dikkat edersen TMR1 için kesme aktif etmeye gerek yok demiştim. Dolayısıyla kesme içinde bekletme yapmamış oluyorsun işte.
Her bir TMR1 kesme zaman aralığı 500 ms ve bu zaman dilimi epeyce uzun bir süredir. Bu süre içinde yapacağın diğer işleri kolaylıkla yaparsın . TMR1 Kesmesi oluşuncaya kadar demek istiyorum. Kesmesi aktif değil ama kesme bayrağından kesme olup olmadığına bakıyoruz sadece. WHILE PIR1.0=0 ile WEND arasına yapacağın işleri koyarsan PIR1.=1 oluncaya kadar onları yapar.
Bu sistemin temeli yine 1 dak lık zaman dilimi tutmaya dayanıyor. Ama o 1 dakiçinde yapmak istediğin ne var ise onuda yapmana fırsat veriyor.

Ete

Hattuşa

@ozan usta can sıkıntısına bahsettiğin şekilde bir kod yazdım, isisde çalışıyor ve gerçekte de çalışması lazım. ben protonda yazdım incelersen işine yarayan yerleri kullanırsın. şema ve kod ekte;


Device 16F628A
Config BOREN_OFF, CP_OFF, DATA_CP_OFF, PWRTE_OFF, WDT_OFF, LVP_OFF, MCLRE_ON, INTRC_OSC_NOCLKOUT, DATA_CP_OFF, WDT_OFF
Xtal 4

TRISA =%11000000
TRISB =%11110001
PORTA =0
PORTB =0
CMCON =7
Declare All_Digital TRUE

Symbol sIlButOn =PORTA.6
Symbol EnTeR =PORTA.7

Declare LCD_DTPin PORTA.0  ' LCD Data Pin   
Declare LCD_RSPin PORTB.1  ' LCD RS Pin
Declare LCD_ENPin PORTB.2  ' LCD EN Pin
Declare LCD_Lines 2        ' LCD Satır
Declare LCD_Interface 4    ' LCD Data Pin Sayısı 4
Cls
DelayMS 100
OPTION_REG =%10000000

Symbol RBIF = INTCON.0 ' RB Port Interrupt Flag
Symbol INTF = INTCON.1 ' RB0 External Interrupt Flag
Symbol RBIE = INTCON.3 ' RB Port Change Interrupt Enable
Symbol INTE = INTCON.4 ' RB0 External Interrupt Enable
Symbol PEIE = INTCON.6 ' Peripheral Interrupt Enable
Symbol GIE = INTCON.7  ' Global Interrupt Enable
Symbol TMR1IF =PIR1.0
Symbol TMR1IE =PIE1.0

GIE =0
INTE =1
RBIE =1
RBIF =0
INTF =0
PEIE =1
TMR1IE =1
TMR1IF =0
T1CON =%00110001     '1/8 bölme oranı kullanıldı
On_Hardware_Interrupt GoTo KeSMe

Dim SaYaC As Byte       '150 adet saydırdığımızda 1 dk oluşuyor
Dim SeNs1 As Byte       '
Dim SeNs2 As Byte
Dim SeNs3 As Byte
Dim SeNs4 As Byte
Dim SeNs5 As Byte
Symbol dAkIkA =3036    '500mS de bir kesme oluşturma değeri
Dim SeNsOr1 As Byte
Dim SeNsOr2 As Byte
Dim SeNsOr3 As Byte
Dim SeNsOr4 As Byte
Dim SeNsOr5 As Byte


GoSub EkRaN_yEnILe

TMR1L =dAkIkA.LowByte
TMR1H =dAkIkA.HighByte
GIE =1

MaIn:
If sIlButOn =0 Then
   While sIlButOn =0 :Wend
   SeNsOr1 =0
   SeNsOr2 =0
   SeNsOr3 =0
   SeNsOr4 =0
   SeNsOr5 =0
EndIf

Print At 1,3,Dec (SaYaC /2)
Print At 1,9,Dec, SeNsOr1
Print At 1,15,Dec, SeNsOr2
Print At 2,4,Dec, SeNsOr3
Print At 2,9,Dec, SeNsOr4
Print At 2,15,Dec, SeNsOr5

If SaYaC =0 Then Print At 1,3,"   "
DelayMS 100


GoTo MaIn


EkRaN_yEnILe:
Print At 1,1,"T="
Print At 1,6,"S1="
Print At 1,12,"S2="
Print At 2,1,"S3="
Print At 2,6,"S4="
Print At 2,12,"S5="

Return
KeSMe:
Context Save
If TMR1IF =1 Then
    TMR1L =dAkIkA.LowByte
    TMR1H =dAkIkA.HighByte
    TMR1IF =0
    Inc SaYaC
    If SaYaC >=120 Then   '1 dk süre doldu sayac değerlerini değişkene at ve içeriğini temizle
    SeNsOr1 =SeNs1   
    SeNsOr2 =SeNs2 
    SeNsOr3 =SeNs3   
    SeNsOr4 =SeNs4
    SeNsOr5 =SeNs5   
    SeNs1 =0
    SeNs2 =0
    SeNs3 =0
    SeNs4 =0
    SeNs5 =0
    SaYaC =0
    EndIf

EndIf

If INTF =1 Then
    Inc SeNs1
    INTF =0
    EndIf
If RBIF =1 Then
   If PORTB.4 =1 Then Inc SeNs2
   If PORTB.5 =1 Then Inc SeNs3
   If PORTB.6 =1 Then Inc SeNs4
   If PORTB.7 =1 Then Inc SeNs5
RBIF =0
EndIf
Context Restore

End




oongit

#8
Sağolasın Selami Abi, vakit ayırdığın için teşekkürler. Proton dilini bilmediğim için bir yorum yapamıyorum  :)
Ancak; GLCD uygulamaları daha kolay oluyormuş diye okudum. Bir ara kesinlikle ilgileneceğim.
(Edit: Proton Full için bildiğin link varsa bakmak isterim)

Kısa Not:
Ozan değil abi, Özgür, Teknoloji ekibinden beni hatırlarsın sanmıştım  ;)

Akşam hastanede biraz koşturmak durumunda kaldığımız için Ete hocanın bahsettiği şekilde çalışamadım. İnşaallah bu akşam dediklerini uygulamaya çalışacağım.

Saygılarımla...

ete

Özgür,
Selami bir şeyler karalamış, çalışıyor da, mantık da doğru ancak benim  mantığımında doğru olduğunu göstermek açısından birşeylerde bende karalayım istedim. Yaptığım örnekden mantığımı daha iyi anlayacaksınız.
İlişiktedir. Sensör girişlerinden birisine 100Hz lik clk bağladım butona basılınca sensör girişinin ne hızla sayabildiğine bakmanızı isterim.
Önceden de belirttiğim üzere KESME işini yalnızca sensör girişlerine ayırdım. Üstelik burada sayac hızlansın diye kim kesme yaratmış buna bile bakmıyorum. Zira girişlerden hangisi High ise  onun ilgli sayacı bir artırmasını hedefledim. Güzelde çalışıyor.
Bu program, INT0 kesmesi ile PORTB değişiklik kesmesinin birlikte kullanılmasına ve buna ilave olarak TMR1 kesmesini aktif etmeden oluşturacağı kesmeden nasıl yararlanabileceğimize güzel bir örnek olacak.
Unutmayın işlemcide kesme kaynakları aslında sürekli aktiftirler. Siz gereken bitleri set ederseniz yada bayrak bitlerine bakarsanız onların kesme oluştuğu anda set edildiğini görebilirsiniz. Ama kullanımda ancak ilgili kesmeyi aktif ederseniz bayrak bir işe yarar değilse öyle set edilmiş kalır yerinde.


Ete

oongit

Hocam;

Biliyorum, aramızda oldukça büyük bir mesafe var. Ama izninizle, ben yine de buradan, Bursa'dan ellerinizden öpüyorum.
Kabul edin lütfen.

Saygılarımla...

Hattuşa

@ETE hocam; yanlış anlamayın amacım söylemlerinize alternatif olmak değil, özgürü 5-6 sene öncesinden başka bir siteden tanıyorum. dün oldukça boş vaktim vardı onun için o kodu hazırladım. aslında sizinde benimde yaptığımız işlem aynısı, fark olarak ben zamanın set işlerini kesme işlemi içerisinde gerçekleştirmiş olmamdan kaynaklanıyor. malum ben basic olarak ne öğrendimse sayenizde öğrendim. Ve sizden öğreneceğimiz çok şey var daha...
mesela;
portb portunu neden temp değişkenine aktarırız?

ete

PORTB değişiklik kesmesi portdaki değişikliklere göre kesme oluşturur. Portun son halini kesmeden çıkmadan evvel okumak gerekiyor. Böylece kesmeden sonra portda okunandan farklı bir sonuş çıkar ise hemen yeniden kesme oluşturulur.
Temeli bu düşünceye dayanıyor.
İşlemcilerle çalışırken bazı işlerin zaman kaybetmeden yapılması gerekir. Bu nedenle algoritmalarımızı bu fikre uygun olarak geliştirmemiz gerekiyor.
INT0 - PortB-4-7 kesmesi ve buna birde TMR1 kesmesini eklerseniz 3 kesme içinde işlemcinin isnenleri yeterince hızlı yapmasını bekleyemeyiz. Çünki kovalayacağı iş adedini artırmış oluyoruz.
Bu nedenle TMR1 kesmesini diğer kesmelerin içine dahil etmedim. Yazdıkların yanlış değil bunu söyledim. Ama daha akıllıca yada işlemciyi daha az meşgul edecek bir şey yazmak gerekirse diye benim düşüncemi de oraya ekleyeyim demiştim .

Öğrenmenin sınırı yok elbette. Bende hala yeni yeni şeyler öğreniyorum. Az bildiklerimi pekiştiriyorum.
Öğrenmeyi seviyorum.

Ete

Powered by EzPortal