Hacettepe Robot Topluluğu
Makaleler Geri Sayım Cihazı HUNRobotX - Makaleler - Geri Sayım Cihazı
Geri Sayım Cihazı Yazan: Kutluhan Akman, Düzenleyen: Canol Gökel - 22 Ekim 2006 Giriş Hepinizin bazı macera filmlerinden de bildiği gibi bombaları patlatan bir saat vardır :) Bu saat genellikle (1980 den sonra çekilmiş filmlerde) dijital bir geri sayıcıdan oluşur. Saat belirli bir değerden başlar, 0000 oluncaya kadar sayar ve sonra buuum. Yeni nesil Türk dizilerinde de ortada bir bomba varsa bu tür geri sayıcıların örneklerine rastlıyoruz. Bu çalışmamızda da bir geri sayım cihazı yapacağız. Sayıcı 0 değerine ulaştığında bize baştan beri vermekte olduğu +5V seviyesindeki çıkışı kesecek ve hayali bomba düzeneğini ateşleyecek. Cihaza ekşın katmak için de birkaç kablo koyucaz.. tabii ki bazıları sayıcıyı durdururken bazıları ise sayım bitmeden 0 lanmasına yani patlamasına neden olucak. tabii ki bu sayıcı mantığı birçok otomatik kontrol uygulamasında kullanılabilir. Gerçek hayatta da birçok uygulamasını görebilirsiniz. Sayıcıyı yaparken assembly dilini kullandık. Donanımsal programlarda assembly'nin üstünlüğü tartışılmaz biliyoruz. Gecikme yapmak için kontrolcünün iç timer'ı kullanılabilirdi fakat gerek görmedik çünkü işlemcinin tek yapacağı işlem saymak. Kontrolcü olarak 4 Mhz'lik PIC16F84A kullanıldı. Ekran olarak da 3 adet 7 segment LED display kullanıldı. Bir de butonumuz var tabii ki; eğer basılırsa, sayıcıya başlama sinyalini veriyor. Hepinize iyi eğlenceler, doğru kabloyu kesmeniz dileğiyle.. 7 Segment Display'ler Hakkında Genel Bilgi Bu programı hazırlamak için bilmeniz gereken ufak birkaç ayrıntı var arkadaşlar. Bilindiği gibi insan gözü 1 saniye içinde bir görüntüdeki sadece belirli sayıdaki değişmeleri algılayabilir. Mesela sinema perdesindeki resimler saniyede 24 kez değişirler. Ama insan gözü orada hareketli bir görüntü varmış gibi görür ve göz yanılgısı, görüntü değişiminin hızı sayesinde sağlanır. Bizim 7 segment LED display'lerimiz (7SD) de aynı prensibi kullanarak çalışmaktalar. Her bir 7SD'yi sürdüğümüzde (ayrı ayrı sürüldüğünde), her segment için 1 çıkış = 7 çıkışa ihtiyaç vardır. 3 7SD için bu bize 21 adet çıkış gerektiği anlamına geliyor. 16F84'de ise sadece (8 adet PORTB'de, 5 adet PORTA'da olmak üzere) 13 adet giriş/çıkış portu bulunur. Ama biz çoklu bağlama metodu ile hepsini birlikte sürüyor ve göz yanılgısından faydalanarak tam bir görüntü oluşuyor imajını veriyoruz. 7 segment display'in çalışma prensibi de çok basittir. İçinde 7 adet LED var. Her bir LED'i yakmak da tabii ki normal LED'i yakmak gibidir.
f a b c d e f g d.p a b g c d.p + e d Şekil 1: 7 segment display'de 3 sayısının yazdırılması - a b c d e f g d.p Şekil 2: Ortak anotlu display'in iç yapısı a b c d e f g d.p Şekil 3: Ortak katotlu display'in iç yapısı Yukarıdaki resimlerde de görülebileceği gibi LED display'lerin 2 çeşidi mevcuttur: Ortak artılı (common anode) ve ortak eksili (common cathode). Common cathode'ta isminden de anlaşılabileceği gibi (-) ler ortak bağlanmıştır. LED'lerin çalışması diyotların çalışmasından farklı değildir. Anoda + gerilim ve katoda da 0V seviyesi verirseniz iletime geçerler, yani ışık yaymaya başlarlar. (Anot) + - (Katot) 7SD'lerde oluşturulabilecek görüntü şekli azdır ama rakamların tamamını oluşturmak mümkündür. Örneğin 3 rakamını oluşturmak için: 1- Common anode display'lerde: Ortak artıyı +5V'a bağladıktan sonra 3 rakamını oluşturmak için gerekli olan a, b, c, d ve g segment'leri 0V'a (ground) bağlanır. 2- Common cathode display'lerde: Ortak eksiyi 0V a (ground) bağladıktan sonra 3 rakamı oluşturmak için gerekli olan a, b, c, d ve g segmentleri +5V'a bağlanır (bkz: Şekil 1). Tabii ki gerilimi vermeden önce dikkat etmemiz gereken önemli hususlardan birisi LED'in müsaade ettiği maksimum gerilim ve akım değerlerini geçmemektir. Bir de eğer diyodun iletim gerilimi adı verilen gerilimin altında gerilim uygularsak diyot iletime geçmez ve ışık yaymaz. Maksimum akım değerini geçmemek için LED'e seri bir direnç bağlamalıyız.
+5V 0V seri direnç Mesela LED'in maksimum akımı 20mA ise V =I R bağıntısından bağlamamız gereken direnci bulabiliriz. Tabii ki bizim bu devrede asıl dikkat etmemiz gereken husus PIC'ten çekebileceğimiz maksimum akım sınırını geçmemektir. PIC'ten maksimum 25mA çekebileceğimizi kabul edersek (her bir out bacağından), PIC 5V ile çalıştığına göre R=V / I bağıntısından bağlayabileceğimiz en küçük direncin 200 Ohm olduğunu buluruz. Yani 7SD'in her bir segmenti için en az 200 Ohm'luk direnç bağlamalıyız. Biz devremizde 330 Ohm'luk dirençler tercih ettik. +5 330Ω IN 22KΩ 2N4124 Gelelim çoklu calıştırmaya. 7SD'leri çoklu çalıştırmak için transistor kullanacağız. Kullandığımız 7SD'ler ortak eksili oldukları için biz de NPN tipi transistör kullanacağız. NPN transistörün şematik gösterimi yukarıdaki gibidir. Eğer IN e ( base de denir) +5V uygularsak, transistörü anahtar olarak kullanmış oluruz ve LED ışık yayar. Çünkü transistörün LED'e bağlı tarafı (collector) ile toprağa bağlı tarafı (emiter) arasında akım akmaya başlar (collector-emiter arasındaki anahtar açıkmış, IN (base) e +5V verdiğimizde kapanmış gibi düşünebiliriz).
+5 +5 +5 330Ω 330Ω 330Ω IN 22KΩ 2N4124 IN 22KΩ 2N4124 IN 22KΩ 2N4124 Yukarıdaki şekillerde her bir şekil için 3 adet genel bağlantı noktası vardır: 1- +5V 2- IN 3- Ground Yukarıda bahsedildiği gibi eğer IN girişine de +5V verilirse LED ışık verir. Eğer ki sıra ile 3 devrenin de IN girişlerine +5V verilirse üçü de sıra ile yanacaktır. Eğer bu sıra ile yakma işlemi saniyede 20 kereden fazla yapılırsa insan gözü bunların sıra ile yandıklarını fark edemeyecek, sanki aynı anda yanıyorlarmış gibi görecektir. Bizim kullandığımız 7SD tipi common cathode olduğu için biz de display'lerin ground'larına transistör bağlayarak her display'i sıra ile çalıştıracağız. Her display'in a segment'lerini, b segment'lerini ve diğer segment'lerini kendi aralarında birbirlerine bağlayacağız (bkz: Aşağıdaki şekil). Bu şekilde mesela eğer PORTB'den verilen display data'sı 00111111 olduğunda hangi display aktifse (hangisinin anahtarlama transistörü iletimdeyse, hangisinin IN (base) girişine +5V ( yani lojik 1 seviyesi) geliyorsa) o display'de 0 yazısı görülecektir (Verilen 00111111 data'sı 0 sayısına ait data'dır.).
Assembly Programı ve Devre Biz PIC'in PORTB'sinden, gösterilmesini istediğimiz sayıya ait data'yı gönderiyoruz. Mesela eğer ekranımızda 359 yazmasını istiyorsak: 1-1 ler basamağını ilk önce yollayacağız. 1 ler basamağımızda da 9 sayısı var. PORTB den 9 a ait 01101111 data'sını gönderiyoruz (bkz: Şekil 1 ve o konu). Unutmayalım PIC için 0=0V, 1=5V seviyesidir; bir port'un bir bit'ini 0 yaparsak orası ground seviyesine çekilir, 1 yaparsak +5V seviyesine. 2- Sonra o display'e bağlı transistörü aktif etmek için (o anahtarı kapatmak için) PORTA nın 0. bit'ini de 1 seviyesine getiriyoruz. Diğer display'lerde o anda hiçbir segment yanmasın diye (1 ler basamağı hariç diğer display'lerde 9 sayısı gözükmesin diye) PORTA nın 1. ve 2. bit'lerini 0 yapıyoruz. Şu anda en sağdaki display'de 9 sayısı yandı. Sıra ile diğer sayıları da diğer display'lerde yakacağız ve saniyede 50 defa bu işlemi tekrarlayacağız (diğer display'e geçeceğiz) ki gözümüz ekranda 359 yazıyormuş gibi görsün. 3- Şimdi sıra geldi bu işlemleri yaptıktan sonra belirli bir miktar işlemciyi bekletmeye. Saniyede 50 defa display değiştireceğimize göre 20 milisaniyelik bir bekletme işimizi görecektir. Tabii eğer daha az bekletme yaparsak da göz için bir şey değişmez, yeter ki bütün çevrim 70 milisaniyeden daha kısa zamanda tamamlansın. 4- PORTB'deki data'yı 5 sayısını göstermek için değiştirmeden önce 1'ler basamağı display'ini pasif yapmalıyız. O yüzden PORTA, 0 ı 0V seviyesine çekiyoruz. 5- PORTB ye display'de 5 sayısını göstermek için gerekli data giriliyor (01101101). 6-10'lar basamağı aktif yapılıyor, diğerleri pasif (PORTA, 1 1 ). 7- Gecikme süresince bekleniyor (20ms). 8- Bekleme bittikten sonra 10'lar basamağı da pasif yapılıyor (PORTA, 1 0 ). 9- PORTB ye display'de 9 sayısını göstermek için gerekli data giriliyor (01101111). 10-100'ler basamağı aktif yapılıyor, diğerleri pasif (PORTA, 2 1 ). 11- Gecikme süresince bekleniyor (20 milisaniye). 12- Bekleme bittikten sonra 100'ler basamağı da pasif yapılıyor (PORTA, 2 0 ). Daha sonra 1. basamaktan itibaren işlemler sürekli tekrarlanırsa ekranda sıra ile 3, 5 ve 9 sayıları yazmasına rağmen biz onu 359 sayısı olarak göreceğiz. Bu yöntemi kullanarak PIC'i daha verimli kullanmış olduk. Unutmayalım ki aynı işi daha basit araçları kullanarak veya daha az malzeme kullanarak yapabilenler her zaman öndedir.
Şimdi sıra geldi bizim yaptığımız devreye ve programa. Bizim devremizde display'ler arası gecikme sadece 815 mikrosaniye. Bizim devre şemamızda kabloyu kesmek için switch'ler kullanılmıştır. Eğer assembly programını incelerken yandaki açıklamalara da dikkat ederseniz, bunun yanında aşağıdaki devre şemasını da incelerseniz, bu proje hakkında kafanıza takılmış bir soru kalmayacağını düşündüğüm için daha fazla açıklamıyorum İyi eğlenceler.. Şekil 1 list p=16f84a ; İşlemciyi tanımlamak için gerekli satır #include <p16f84a.inc> ; İşlemciye özel değişkenler tanımlı olan ; dosyayı programa dahil etmek için kullanılan ; satır. CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC ; İşlemci calışırken kullanacağı özelliklerin belirlendiği satır ; CP: code protect ; WDT: watch dog timer ; ON = ACIK, OFF = KAPALI ; OSC = kullanılacak osilatör tipi, XT=kristal, LP=low power (iç ; osilatör), RC=direnc kondansatör ikilisi ; Bit tanımaları #define komutu kullanılarak yapılıyor #DEFINE KABLO PORTA,4 ; Tuzak kablosu
#DEFINE BOMB PORTA,3 ; Bizim LED bağladığımız ekşın çıkışı #DEFINE BUTON PORTB,7 ; Sayıcıya başla sinyali veren buton #DEFINE DIS1 PORTA,0 ; 1'ler basamağı display'ini aktif etmek ; için kullanılacak #DEFINE DIS10 PORTA,1 ; 10'lar basamağı display'ini aktif etmek ; için kullanılacak #DEFINE DIS100 PORTA,2 ; 100'ler basamağı display'ini aktif etmek ; için kullanılacak ; Byte tanımlamaları EQU komutu kullanılarak yapılıyor SAY1 EQU 0X0F ; Gecikme ve sayma işlemlerinde kullanılacak SAY2 EQU 0X10 ; Gecikme ve sayma işlemlerinde kullanılacak SAY3 EQU 0X11 ; Gecikme ve sayma işlemlerinde kullanılacak SAY4 EQU 0X12 ; Gecikme ve sayma işlemlerinde kullanılacak DIG1 EQU 0X13 ; 1'ler basamağı display'inin göstereceği sayının değerini ; saklayan register DIG10 EQU 0X14 ; 10'lar basamağı display'inin göstereceği sayının ; değerini saklayan register DIG100 EQU 0X15 ; 100'ler basamağı display'inin göstereceği sayının ; değerini saklayan register ORG 0x000 ; Program memory'nin 0. adresini belirtir (reset ; adresi) GOTO BASLA ; BASLA isimli satıra git ORG 0X004 ; Program memory nin 4. adresini belirtir (kesme adresi) RETFIE ; Kesmeden dönmek için kullanılan komut (ama biz kesme ; kullanmıyoruz) GECIK ; 10ms'lik gecikme programı aynı zamanda display'i cağıran bir ; programdan oluşuyor. ; Eğer gecikme yaparken display programı çağırılmasaydı o zaman ; 10ms'lik gecikme ekranda bozulmalara neden olacaktı MOVLW D'4' MOVWF SAY3 CALL EKRANGOSTER ; Display'leri süren program 4 kere çağırılıyor DECFSZ SAY3 GOTO $-2 RETURN DISGEC nop ; İşlem yapma (1 komut çevrimi boyunca) nop MOVLW D'203' ; W register'ına 203 yükle MOVWF SAY1 ; W'yu SAY1 register'ına kopyala (SAY1 <== "203") NOP DECFSZ SAY1 ; SAY1'i 1 azalt sonuç 0 mı?
GOTO $-2 ; Hyr: O zaman 2 satır yukarıya dön RETURN ; Ewt: İyi alt programdan çık o zaman DONUSUM ADDWF PCL,F RETLW B'00111111' RETLW B'00111111' RETLW B'00000110' RETLW B'01011011' RETLW B'01001111' RETLW B'01000110' RETLW B'01101101' RETLW B'01111101' RETLW B'00000111' RETLW B'01111111' RETLW B'01101111' RETLW B'00111111' ; PCL (program adreslerini hafızasında tutan register) ; ile W'yu toplayıp yine PCL'ye attık ki W'nun içinde ; hangi değer varsa program o kadar satır+1 satır ; sonraya dallansın. 0 varsa 1 alttaki satıra ; dallanacak, 1 varsa 2 alttaki ; Display'e 0 yazdırmak için gerekli olan data ; Display'e 1 yazdırmak için gerekli olan data RETURN EKRANGOSTER MOVFW DIG1 ; Dönüşüm tablosunu kullanmak için 1'ler basamağı ; register'ındaki sayıyı W'ya yükledik CALL DONUSUM ; Dönüşüm tablosu çağırıldı BCF DIS10 ; 10'lar ve 100'ler basamağı display'leri pasif ; yapıldı BCF DIS100 MOVWF PORTB ; 1'ler basamağının sayı data'sı port b'ye gönderildi ; (yani bütün display'lerde aynı anda mevcut ama ; sadece aktif display'de görüntüleniyor) BSF DIS1 ; 1'ler basamağı display'i aktif yapıldı. CALL DISGEC ; display'de görüntülenen sayıdan sonra bir süre ; gecikme yapıldı ; Alttaki 2 program bloğu da üstteki gibi MOVFW DIG10 CALL DONUSUM BCF DIS1 BCF DIS100 MOVWF PORTB BSF DIS10 CALL DISGEC
MOVFW DIG100 CALL DONUSUM BCF DIS1 BCF DIS10 MOVWF PORTB BSF DIS100 CALL DISGEC RETURN BASLA BSF STATUS,RP0 ; Ram içindeki BANK1 seçildi ki TRISA ve TRISB ; register'larına ulaşılabilsin MOVLW B'00010000' MOVWF TRISA MOVLW B'10000000' MOVWF TRISB ; Bu 4 satırda PORTA'nın 4., PORTB nin 8. bit'i giriş, ; diğer bütün port bit'leri çıkış yapıldı. BCF STATUS,RP0 ; Tekrar BANK0 seçildi MOVLW D'10' ; Önce bütün digit'lerin registerlar'ı 10 ile ; yuklendi, ilerleyen satırlarda niye 9 değilde 10 ; olduğunu anlıcaksınız acele etmeyin :) MOVWF DIG100 MOVWF DIG10 MOVWF DIG1 BSF BOMB ; Önce bomba cıkışı (LED bağlı) aktif edildi (eğer ; "0" olursa (LED sonerse) patlıyor) CALL EKRANGOSTER BTFSS KABLO ; Butona basılmadan once tuzak kablosu kesilmiş mi ; kontrol ediyor. GOTO PATLADI ; Tuzak kablo kesildiyse (PORTA,4 "0V" seviyesine ; çekildiyse) PATLADI isimli satıra gidiyor. BTFSC BUTON ; Butona basılınca geri sayım başlayacak GOTO $-4 ; Butona basılmamışsa tekrar kabloyu kontrol etmeye ; ve ekranda "999" yazmaya devam edecek SAY BTFSS KABLO ; Geri saymayı sürdürürken bir yandan da kablonun ; kesilip kesilmediğini kontrol edecek GOTO PATLADI ; Kablo kesilirse "PATLADI" isimli satırdan programa ; devam edecek. CALL GECIK ; 10 milisaniyede sayıcının değerini 1 azaltacak o ; yuzden 10ms'lik gecikme altprogramını çağırıyor DECF DIG1 ; 1'ler basamağı register'ını 1 azaltarak başlıyoruz ; geri saymaya. Önceden değeri 10 olduğu için 1 ; azaltınca 9 kalıyor ve devam ediyor
BTFSS STATUS,Z ; 1'ler basamağı 0 landı mı? GOTO SAY ; Hyr: O zaman azaltmaya devam et MOVLW D'10' ; Evt: O zaman 1 komşuya git 10'lar basamağından ; 1 adet 10 ödünç al :) 1'ler basamağı register'ına ; yükle MOVWF DIG1 ; 1'ler basamağı register'ına yükle DECF DIG10 ; 10'lar basamağından 1 adet 10 ödünç alınca haliyle 1 ; adet azalacak. BTFSS STATUS,Z ; iyi peki azaldın da 0 mı oldun? GOTO SAY ; Hyr: o zaman azaltmaya devam et MOVLW D'10' ; Evt: hadiiii! napcaz.. neyse 100'ler basamağına ; soralım onda vardır belki diyip 100'lerden 1 adet ; 100 alıcaz MOVWF DIG10 ; 10'lar basamagına yüklicez DECF DIG100 ; E nolcak o zaman, 100'ler basamağı 1 azalacak BTFSS STATUS,Z ; Peki 100'ler basamağı azalınca 0 mı kalıcak? GOTO SAY ; Hyr: O zaman daha vakit var geri saymaya devam et ; Evt: Aha şimcik hapı yuttun, bombaya yan bastın.. PATLADI CLRF DIG1 ; Bütün digit'leri 0 yap çünkü geri sayım bitti CLRF DIG10 CLRF DIG100 BCF BOMB ; Bombayı patlat MOVLW D'5' ; LED'i yakıp söndürücez o yüzden de gecikme sağlamak ; için gerekli register'ı hazırla MOVWF SAY4 CALL GECIK ; Saydırırken kullandığımız gecikmeyi 5 ile çarpıp ; burada da kullandık DECFSZ SAY4 GOTO $-2 BSF BOMB ; Şimdi LED'i yak ve yine belirli süre bekle MOVLW D'10' ; Yukarıda 5 ile çarptık burada 10 ile çünkü o ; şekildeki bi yanıp sönme efekti daha etkileyici MOVWF SAY4 CALL GECIK DECFSZ SAY4 GOTO $-2 GOTO PATLADI END
Bağlantılar http://robot.ee.hacettepe.edu.tr/ Geri sayım cihazının ISIS ve.hex dosyası: http://robot.ee.hacettepe.edu.tr/dosyalar/geri_sayim_cihazi.zip Diyot ve transistörler hakkında daha detaylı bilgi için bakınız: http://baranelektronik.tripod.com/transistorler.htm http://www.elektrotekno.com/about31.html http://www.biltek.tubitak.gov.tr/merak_ettikleriniz/index.php?kategori_id=20&soru_id=2337 http://www.biltek.tubitak.gov.tr/merak_ettikleriniz/index.php?kategori_id=20&soru_id=4824 http://tr.wikipedia.org/wiki/transistor http://tr.wikipedia.org/wiki/diyot Yaptığımız cihaza benzer başka bir örnek için (Cihazın daha gelişmiş özellikleri var ama kullanılan programlama teknikleri çok gelişmiş değil, yeni başlayanlar anlayabilir rahatlıkla.): http://www.turbokeu.com/myprojects/countdown3.htm Common anode ve cathode display iç bağlantısı için örnek: http://www.forge-europa.co.uk/pdfs/fn4-040xx0cgw.pdf http://www.maxim-ic.com/appnotes.cfm/an_pk/874