Takometre sorunsalı

Başlatan oguztkn, 26 Temmuz 2016, 22:52:41

oguztkn

Merhaba arkadaşlar ,
Bir elektrikli araba projem için takometre yapmak istiyorum.16f628a kullanmaya karar verdim şemam ektedir.Şöyle bir sıkıntım var PORTB.0 kesmesini kuruyorum aynı zamanda da timer0 ı 1sn lik ayarlıyorum 1sn boyunca portb.0 dan gelenleri toplayıp 60 ile çarpıyorum sonra bunu teker katsayısı ile çarpacağım ama şimdilik devir bilgisini bulmaya çalışıyorum.12 volt dc 1500 rpm motorun ucuna mıknatıs bağladım denemeleri onunlar yapıyorum ama program eksik sayıyor bir anlık çalışmıyor gibi hızlı değişmiyor devir bilgisi bunun nedeni nedir acaba neyi yanlış yapıyorum yoksa komple mi yanlış yoldayım bir yardım edebilirmisiniz
Şimdiden Teşekkür Ederim...

DEFINE LCD_DREG PORTB 'LCD data bacakları PortB de bağlı
DEFINE LCD_DBIT 4 'LCD data bacakları 4. bitten başlıyor
DEFINE LCD_EREG PORTB 'LCD Enable Bacağı PortB de bağlı
DEFINE LCD_EBIT 3 'LCD Enable Bacağı 3. bite bağlı
DEFINE LCD_RSREG PORTA 'LCD RS Bacağı PortB de bağlı
DEFINE LCD_RSBIT 4 'LCD RS bacağı 1. Bite bağlı
DEFINE LCD_BITS 4 'LCD 4 bit olarak bağlı
DEFINE LCD_LINES 2 'LCD 2 sıra olarak çalışıyor.
   
sayac var word
sayi var word
rpm var word

Comm_Pin1   VAR PortA.3
Busy        VAR BIT
HAM         VAR WORD
ISI         VAR WORD
TEMP        VAR word
Float       VAR WORD

ON INTERRUPT GoTo KESME   'kesme oluşursa KESME adlı etikete git.
OPTION_REG=%11000101   'Pull up dirençleri İPTAL- Bölme oranı 1/64.
INTCON=%10110000  'Kesmeler aktif ve TMR0 kesmesi aktif
TMR0=0
CMCON=7
TRISA=0
TRISB=%00000001
clear
pause 200
Basla: 
     'gosub sensor_oku
    ' gosub gonder
     Lcdout $FE,$80,"AREL"
     Lcdout $FE,$C0," UNIV."
     Lcdout $FE,$8A," KM/H"
     Lcdout $FE,$C7,"Pil:"         
     Lcdout $FE,$CB,DEC ISI,",",Dec FLoat,"C"   
    goto basla

;*******************************************************************************
Sensor_Oku:              ;/*****************************************************
           OWOUT   Comm_Pin1, 1, [$CC, $44] ;***********************************
Bekle1:                  ;******************************************************
           OWIN    Comm_Pin1, 4, [Busy]     ;***********************************
           IF      Busy = 0 THEN Bekle1     ;***********************************
           OWOUT   Comm_Pin1, 1, [$CC, $BE] ;***********************************
           OWIN    Comm_Pin1, 2, [HAM.Lowbyte, HAM.Highbyte]  ;*****************
           GOSUB   Hesapla1                 ;***********************************
           RETURN        ;******************************************************
Hesapla1:                ;******************************************************
    ISI=HAM*10/16        ;******************************************************
    FLOAT = ISI//10      ;******************************************************
    ISI=ISI/10           ;******************************************************
    RETURN               ;****************************************************** 
;*******************************************************************************
DISABLE                  ;******************************************************
KESME:                   ;******************************************************
    if INTCON.1=1 then   ;******************************************************
    rpm=rpm+1            ;******************************************************
    INTCON.1=0           ;******************************************************
    endif                ;******************************************************
    if INTCON.2=1then    ;******************************************************
        sayac=sayac+1    ;******************************************************
        if sayac=61 then ;******************************************************
                         ;******************************************************
            sayac=0      ;******************************************************
            sayi=rpm*60  ;******************************************************
            Lcdout $FE,$87,dec sayi     
            rpm=0        ;******************************************************
            endif        ;******************************************************
        endif            ;******************************************************
        TMR0=0
        INTCON.2=0       ;******************************************************
                   ;******************************************************
        resume           ;******************************************************
;*******************************************************************************
    end



İşlemci bilgilerin tanımlı değil derseniz programda, 64 bit pc de sıkıntı olduğundan programlayıcıdan seçiyorum sigorta ayarlarını dahili osilatör kullanıyorum.

ete

İki ayrı kaynaktan kesme kullanınca bunları programda iyi izole etmek gerekir. Bir TMR0 kesmesi oluşunca B0 kesmesini ve onun parametrelerini etkilememeli ve benzer şekilde B0 kesmesi oluşuncada TMR0 kesmesini etkilememesi gerekir.
Sen Kesme alt programına bir bak bakalım yada birlikte bakalım.

DISABLE                  ;****************************************************** 
KESME:                   ;******************************************************
    if INTCON.1=1 then   ;***portb.0 kesmesi***************************************************
      rpm=rpm+1          ;******************************************************
      INTCON.1=0         ;******************************************************
    endif                ;******************************************************
    if INTCON.2=1then    ;****tmr0 kesmesi**************************************************
        sayac=sayac+1    ;******************************************************
        if sayac=61 then ;******************************************************
                         ;******************************************************
            sayac=0      ;******************************************************
            sayi=rpm*60  ;******************************************************
            Lcdout $FE,$87,dec sayi     
            rpm=0        ;******************************************************
            endif        ;******************************************************
        endif            ;******************************************************
        TMR0=0
        INTCON.2=0       ;******************************************************
                   ;******************************************************
        resume           ;

PORTB.0 kesmesi oluştuğunda ;
      rpm=rpm+1 
      INTCON.1=0 
işlemlerini yapıp sonraki if satırı atlanarak program son kısıma gelmekte orada;
        TMR0=0
        INTCON.2=0
komutlarıda icra edilerek RESUME komutuna gelmekte. Burada TMR0=0 komutuna dikkatini çekerim. PORTB.0 kesmesi oluştuğunda sen TMR0 değerinide sıfırlıyorsun bu gerekli mi sence. Bu durumda program doğru zamanı nasıl sayacak?
Ayrıca RESUME demişsin ama kesmeleri ENABLE etmemişsin. Resume altına birde ENABLE eklemen gerekecek. Zira baştaki DISABLE kesmeleri iptal eder alttaki enablede tekrar açar.
İki kaynaktan kesme yaratan bir programda kaynağın birisi if komutu ile test edilerek yakalanmaya çalışılır.
Diğeri için ayrıca if kullanmaya gerek yoktur. Zira biri değilse diğeridir mantığını işletmek gerek burada. Yani kesme PORTB.0 kesmesi değil ise mutlaka TMR0 kesmesidir diye düşünmek gerekir. Bu size İkinci kesmeyi test eden İF ve Endif satırlarından kurtarır. Kesme kısmının doğru şekli aşağıdaki gibi olmalı.
DISABLE                  ;****************************************************** 
KESME:                   ;******************************************************
    if INTCON.1=1 then   ;****PORTB.0 kesmesi**********************************************
      rpm=rpm+1          ;******************************************************
      INTCON.1=0         ;******************************************************
      GOTO CIK
    endif                ;******************************************************
   
        sayac=sayac+1    ;******************************************************
        if sayac=61 then ;******************************************************
                         ;******************************************************
            sayac=0      ;******************************************************
            sayi=rpm*60  ;******************************************************
            Lcdout $FE,$87,dec sayi     
            rpm=0        ;******************************************************
        endif        ;******************************************************
        TMR0=0       ;******************************************************
        INTCON.2=0       ;*****TMR0 kesme bayrağı*************************************************
       
CIK:                           
        resume           ;******************************************************
        ENABLE
;*******************************************************************************
    end

Diğer bir konuda kesme özel bir durumdur. Program oraya bir amaçla girer ve mümkün olan en kısa sürede oradan da çıkmak gerekir. Hele iki ayrı kesme kaynağı olan bir programda kesme içinde oyalanmak çok yanlıştır.
Sen ise bütün işi kesme içinde yapmışsın.
           sayi=rpm*60  ;******************************************************
            Lcdout $FE,$87,dec sayi     
            rpm=0
komutları ana program bölümünde olmalı orada değil. Bunu sağlayacak değişikliği düşünü uygulamalısın. Özellikle LCD komutları epeyce gecikme yaratır ve programın aksamasına sebep olur bunu unutma. Ama bu işleri ana program kısmında yaparsan etkilenmezsin.
Programın başında sistemin hangi frekansta çalıştığı belirtilmemiş. Programın başına DEFINE OSC x komtunu da eklemek gerekir.
Sigorta ayarları hiç bir zaman sıkıntı olma. Doğru şekilde kullanırsan elbette. Bununla ilgli detaylı açıklamalar sitede Önemli bilgiler başlığı altında verilmiştir. Okuyup uygulamanı öneririrm. Çok kolaydır. Sadece ne yaptığını bilmen gerekiyor o kadar.

Ete



oguztkn

Hocam cevabınız için teşşekür ediyorum gösterdiğiniz yoldan giderek şöyle birşey yaptım.Baştan timer kesmesini kapadımPortb.0 kesmesi geldiği anda timer i başlattım ve kesme yi bu haliyle işledim. Şuan programım gayet güzel çalışıyor tekrardan teşşekür ederim.Şimdide şöyle birşey aklıma geldi bu okuduğum devir sayısına göre 7 kademeli led eklemek istiyorum yani araba 100 devirde iken ilk led 150 deyken 1ve2. led .... diye bunu 7 kademe yapmak istiyorum.Bunun hakkındada fikrinizi alabilirmiyim okuma işi tamam ama kademeli vumetre gibi bu ışıkları nasıl yapabilirim if sorgularıylamı yapmalıyım ?

Şimdiden Teşekkürler...

ete

#3
Led yakılması bir formüle dayandırılmalıdır. Bu iş için maksimum devir ne ise o 8 led yanmasına tekabül etmelidir. Bu işte min değil maksimum devir sayısına göre hareket edilir. Senin hesabına göre 7 led 400 devirde yanar. Araçtan söz ediyor isek devir sayıları daha yüksek olmalı değilmi.
Örnek hesap vereyim sen kendine uyarla. Maksimum devri 1000 kabul edelim. Portun birini bu işe verecek isen yada bir 74hc595 kullanacak ise. Led adedi 8 olmalıdır. 1000 devirde 8 led yanacak sonra azalan devirlerde led sayısıda lineer şekilde azalacak diyelim. Önce sabit çarpanımızı bulmamız gerekir. Bunun için 32 bit matematik den yararlanacağız.
8/1000= 0,008 x 256=2,048. Bu rakamı 2048 olarak kullanıp çıkan sayıyı ayrıca 1000 e böleceğiz. Formülümüz şöyle olmalı,
Led=Devir */2048)/1000
Bu işlemde kullanılan */ operatörü devir sayısı ile 2048 i çarpıp önce 256 ya bölerek bize sonuç verir. Onuda 1000 e böldükmü tam sonucu bulmuş oluruz.
Çıkan led sayısı yanacak led adedini verir. Hemen bir örnek yapalım. Devir sayımız 800 olsun.
Led=(800 *2048)/256/100=6 sayısı yanacak led sayısıdır.
Şimdi bu sayıyı nasıl kullanalımki bize 6 ledi yanık olarak versin. 6 adet ledin yanması için porta,
1+2+4+8+16+32=63 sayısını vermek gerekiyor. O halde öyle bir formül bulmamız lazım ki 6 sayısından bize 63 rakamını hesaplasın. Aslında çok kolay. Basic de  DCD isimli bir komut var. Bu decoded bit hesabını veriyor. Led=dcd 6. Hesabı bize 64 sayısını verir. O halde bu sayıdan 1 çıkartırsak bize 63 sayısını verecektir. O halde işi toparlayacak olursak;
TEMP=(DEVIR*/2048)/1000
LED=(DCD TEMP)-1
PORT=LED dediğiniz zaman devir sayısına bağlı led adedi yanacaktır.

Ete


Powered by EzPortal