adc den butona kaç defa basıldıgını sayan program

Başlatan dedim, 05 Temmuz 2015, 16:02:58

dedim

ekte devre seması ve yazılım mevcuttur.istedigim  gibi calısıyor.butona 3 defa basıp cekınce led yanıp sönüyor.bir dahada yanıp sönmuyor say=0 komutunu nereye koymam gerekıyor butun yolları denedım ama olmadı.butona 3 defa basınca ledın sürekli olarak yanıp sönmesını istemıstım.1 defa yanıp sönuyor baskada olmadı.3 defa butona basınca led sürekli olarak yansın sönsun seklinde olurmu
Device = 16F88
Xtal 4


Declare Adin_Res 10
Declare Adin_Tad FRC     
Declare Adin_Stime 50

ANSEL=%00000001   'ra0 anolog giriş         
ADCON1.7=1
ADCON0=%01000000
CMCON=7
TRISA=%00000001
TRISB=%11101111
       
Symbol LED=PORTB.4         

Output LED

Dim  HAM  As  Word 
Dim say As Byte
PORTA=0                                                   
PORTB=0                                                 
DelayMS 250
say=0
;-------------------------------------------------------------------------------
BASLA:
While HAM <835: ADCIN 0, HAM: Wend     
say=say+1
If say=3 Then
High LED
DelayMS 1000
Low LED
DelayMS 1000
say=0
EndIf
While HAM >950: ADCIN 0, HAM: Wend     
DelayMS 50
 
GoTo BASLA
End 


ektede devre seması vardır.ardımcı  olacak arkadaslara tesekkur ederım.

ete

Bu programda sorulması gereken sorular var.
Sorulara geçmeden önce neden ledlerin bir kere yandığını belirteyim.
Birinci while:wend döngüsü butona basılmamış ise programı oraya bloke etmektedir.
Bu durumda birinci sorumuzu soralım. Şayet SAY=3 olsa idi ve programda burada bloke edilmiş olsa idi ne olurdu ?
Elbette ledler flash yapmayacak idi. Peki bu blokal esnasında da şayet SAY=3 ise ledler flash yapmaya devam etmelimi?
Bence etmeli o halde çözümü buna göre değerlendireceğiz.
Tabiiki çözüm flash işlemini bir alt programda yaptırıp programı buraya yönlendirmekten geçiyor. Bunu hemen yazalım o halde,
While HAM <835
ADCIN 0, HAM
gosub flash
Wend

Buraya FLASH alt programıda eklemek gerekiyor. Zira orada SAY=3 ise flash işlemini yaptırıyoruz değilse geri dönüyoruz.
FLASH:
IF SAY=3 THEN
  High LED
  DelayMS 1000
  Low LED
  DelayMS 1000
ENDIF
RETURN
 

Tuşa basar basmaz program bu döngüden çıkacaktır. SAY=SAY+1 yapacak ve flash kısmını oradan çıkartırsak hemen tuşun bırakılmış olmasını kontrol eden döngüye gelecektir. Bu döngüyede bir GOSUB FLASH eklersek her konumda flash işlemi SAY=3 olduğu müddetçe devam edecektir. Taaki SAY=4 oluncaya kadar. O halde bu konum yakalandığında ancak SAY=0 demeliyiz ki flash işlemi SAY=3 olduğu müddetçe devam edebilsin. Bu komutu SAY=SA+1 in altına eklemek gerekirdi oraya eklendi.

   say=say+1:IF SAY=4 THEN SAY=0
While HAM >950: ADCIN 0, HAM
GOSUB FLASH
Wend
Delayms 50
GOTO BASLA

Bu satırlardan sonra biraz gecikme ekleyip programı başa yönlendirirsen istediklerini yaptırmış olacaksın.

Ete

dedim

usta valla anlamadım verdigin kod parcacıklarını bir arayada getirdim ama genede olmadı.baska bir sekilde yazsaydım keske ama işin içinden cıkamıyorum.düşünmem gerek

ete

Aslında basit toparlamak ama nasıl toparladığınıda belirtmediğin için yanlışmı yaptın doğrumu yaptın anlayamadım.
Ben yinede toparlanmış halini vereyim bari;
Device = 16F88
Xtal 4


Declare Adin_Res 10
Declare Adin_Tad FRC     
Declare Adin_Stime 50

ANSEL=%00000001   'ra0 anolog giriş         
ADCON1.7=1
ADCON0=%01000000
CMCON=7
TRISA=%00000001
TRISB=%11101111
       
Symbol LED=PORTB.4         

Output LED

Dim  HAM  As  Word 
Dim say As Byte
PORTA=0                                                   
PORTB=0                                                 
DelayMS 250
say=0
;-------------------------------------------------------------------------------
BASLA:
While HAM <835
ADCIN 0, HAM
gosub flash
Wend   
   say=say+1:IF SAY=4 THEN SAY=0
While HAM >950: ADCIN 0, HAM
GOSUB FLASH
Wend
Delayms 50
GOTO BASLA
FLASH:
IF SAY=3 THEN
  High LED
  DelayMS 1000
  Low LED
  DelayMS 1000
ENDIF
RETURN
End 

Bu program yinede göze hoş gelecek şekilde çalışmayacaktır. Zira bir flash yaptıma işlemi 2 sn sürmektedir.
Sistem flash yapıyor ise ADC okuma işlemine başlayabilmesi için 2 sn geçecektir. Bence Flash kısmındaki gecikme değerleri 1000 ms değilde 100 ms yapılsa daha uygun olurdu.

Ete

ete

Bu sistemi kusursuz çalıştırabilmenin yolu ledi flash yaptırırken aynı zamanda adc kontrolünüde yapabilmekten geçer.
Daha açık bir ifade ile benbir yandan ADC girişini kontrol etmeliyim ama SAY değerim 3 olmuş ise led her 500ms de bir konum değiştirmeli ama ben orada 500 ms beklememeliyim. Bu anlattığım sistemi yapmanın yolu TMR kullanmaktan geçiyor.
Geri planda çalışan timer senin adc okumalarını bekleme olmadan yapabilmeni sağlar.

İlişikte bu sisteme ait örneği veriyorum. Ben senin programını PBP ya çevirdim devamınıda o şekilde yaptım.
Önce istersen verdiğim hex dosyasını kullanarak sistemi bir çalıştır sonra programı anlamaya çalış.
Ben programın kritik yerini açıklamalı olarak burada vereyim.
BASLA:
    T1CON=%00110001:TMR1H=$0B:TMR1L=$DC:PIR1.0=0  'TMR1 sayacı 500 ms de bir kesme yaratacak şekilde kuruldu
   
     while PIR1.0=0  'kesme bayrağı sıfır ise wend komutuna kadar olanları tekrarla
BIR:   
       ADCIN 0, HAM              'ADC den değer oku (buton basılı ise HAM>835 , basılı değil ise HM<835 olacaktır
       IF ham>835 THEN        'butona basılmış ise
         IF BIRAK=0 THEN      'tusa ilk defa basılıyor ise
           SAY=SAY+1:BIRAK=1  'say değerini artır bırak bayrağını set et.
           IF SAY=4 THEN      'say=4 olmuş ise
             SAY=0:LED=0      'say=0 yap ve led yenıyorsa söndür.
           ENDIF   
         endIF 
         GOTO BIR             'tuş basılı durumda olduğu için BIR etiketine git
       ENDIF                  'tus basılı olduğu müddetçe bırak=1 olacak ve say değeri bir kere artacaktır.
       BIRAK=0                'tus brakılınca program bu noktaya gelecek ve BIRAK=0 yaparak birdaha ki basılışta say değeri artacak
    WEND
'program 500 ms çalışarak yukarıdaki işleri yapacak. 500 ms sonra PIR1.0=1 olacak ve otomatikman alttaki satıra ulaşacaktır.
   IF say=3 THEN toggle led  'say=3 ise led, her 500 ms de bir yanacak bir sönecek
   
   GOTO BASLA
End


Ete

dedim

usta adc kanalından ldr yı okuyorum.buna görede işlemler yapılıyor.ben adc kanalındakı ldr yede buton u paralel baglayıp acma kapama ve diger işlemlerimi yaptırıyorum.adc kanalında ldr baglı aynı zamanda butonda baglı.butonu okumak ıcın kesme kullanmak dahamı dogru oluyor.bu kesme olayı timer saydırma gibi işlemleri derslerınden ögrenmelıyım.kodlar yabancı geldıgınden dolayı asına olamadım.ama en son verdıgın yazılım calısıyor.tesekkur ederım.

dedim

usta burdakı tımer için yazılan degerler ne anlama gelıyor

T1CON=%00110001:TMR1H=$0B:TMR1L=$DC:PIR1.0=0


burdakı TMR1H=$0B VE TMR1L=$DC  esittirden sonrakı degerler neyı belırlemıs oldu 500 mılısanıye yimi?bu degerlerı degiştirmek istersem nasıl bir yol izlemem gerek

dedim

usta

bu degişkenlerde bulunan [56] ve [60] similasyonda debug menusunden watch wındow da takıp  ıcın kullanıldıgını ögrenmıstım ama protonda boyle bır yazıma musade etmıyor.proton derleyıcısınde degişkenlere verilen degerlerı takıp etmek ıcın baska bır yazım yolu varmı bılıyormusunuz.nette de konuyla ılgılı bilgilere ulasamadım.bilmiyorsanızda canınız sagolsun

dedim

USTA

arama yaparken buldum konuyla ilgili bilgileri

şimdi protonda şöyle oluyor.

1)ısıste işlemciye program fıle kısmında .bas dosyası yüklenir.
2)program çalıştırılır.
3)debug menusunden  watch wındow işaretlenir böylece ekranda penceresi açılır.
4)sonra programın çalışması pause ile durdurulur.
5)ekranda pıc cpu varıables penceresi açılır.
6)bu pencerede değişkenlerin name,address,valuekısımları vardır.bize eddress ve name lazım.
7)wındow watch penceresinin üzerinde sağ tıkla açıyoruz ve add ıtems (by address) tıklıyoruz.
8)sonra açılan pencerede name kısmına pıc cpu varıables penceresinden, görmek istediğimiz değişken ismi ne ise yazılır.
9)yine  pıc cpu varıables penceresinden address olarak değişken adresi address kısmına yazılır.adres yazarken 0x003A gibi çarpı işareti x(iks harfidir).
10)adres ve name den sonra aşağıda  data type ,değişkenimiz bıt mi,byte mı,wordmu ne ise işaretleriz.
11)yine aşağıda dısplayde değişkeni ne olarak görmek istiyoruz.bınary decımal hex vb. işaretlenir
12)add ile eklenerek başka bir değişken daha aynı şekilde girilebilir.ama tek ise done ile çıkılır.
13)simülasyon tekrar play yapılırsa değişkeni pencerede birebir göreceksin.

F.T nikli arkadas acıklama yapmıs zaten.kendisinede burdsan tesekkur ederım

ete

Buton okumada kesme kullanmanın avantajı sadece PORTB de mümkün. Sen ADC kanalından hem LDR okuyorsun hem buton kontrolü yapıyorsun. Bu nedenle kesme işini unut.
Bir yandan flash yapacak ledler olması bir yandan sürekli ADC okuma gerekliliği ve bir yandan da flash işleminin 3 basıştan sonra başlayacak olması senin işini zorlaştırıyor.
ADC okuma işlemi vakit almaz. Ama tuşa her basışta tuşun bırakıldığını kontrol etmez isem SAY değeri anında 255 e kadar sayıverir. Zira işlemci çok hızlı çalışıyor. Bu nedenle butonu bırakıncaya kadar ya programı orada bloke edeceğim (senin yaptığın şekilde) yada öyle bir şey kullanacağım ki program yapması gerekenleri yapmaya devam edecek ama SAY değerini bir kere artırdıktan sonra tuşu bırakıncaya kadar bir daha artırmayacak (benim yaptığım gibi)
Üstelik SAY=3 olmuş ise flash işlemi başlaması gerekiyor. Peki tuşu bırakmamış isem ve program orada bloke olmuş ise nasıl başlayacak flash işlemi başlayamayacaktır elbette (senin yaptığın gibi). Ama öyle bir şey yapayımki flash da başlayacak ise başlasın (benim yaptığım gibi.
Diğer yandan tuşun basılıp basılmadığının da kontrolü gerekiyor. Şayet tuş basılıncaya kadar bekle dersen senin yaptığın gibi program yapması gerekenleri yapamadan orada bekleyecektir taaki sen tuşa basıncaya kadar buda onun flash yapması gerekiyor ise yapmamasına sebep olacaktır.
O halde temel kriterlerimiz tuşa basıldığını algılayabilmeliyim tuşa basılı tuttuğumuda algılayabilmeliyim ve aynı şekilde tuşu bıraktığımıda algılayabilmeliyim. Bu algılamalar arasında yapmam gerekenleride yapmalıyım.
İşte bunu yolu Timer kullanmaktan geçiyor.
Flash için en uzun flash sürelerinden birisi 500 ms olacağı için ben 1000 ms yerine 500 ms kullandım.
Bir timer'ın 500ms=500.000 ms sayabilmesi normalde mümkün değildir. 16 bitlik bu sayac enfazla 65535 e kadar sayar sonra sıfıra döner. Ama bunu düşünen tasarımcılar bu timer'a birde bölücü kullanma özelliği eklemişler. işlemci pulslarını 8'e bölersem benim sayac her 8 işlemci palsinde 1 sayacağı için toplamda 8*65535 kadar saymış olacaktır. Buda 524.280us yada 524ms ye denk gelir. Ben net 500 ms olsun istediğim için Sayacı belirli bir sayıdan başlatmak zorunda kaldım. Kısaca Sayac sıfırdan saymaya başlarsa toplamda 524.280us sayar. Ama sayacı 524.280-500.000=24.280/8=3035 ki buna 1 eklemek gerekiyor 3036 dan başlarsam toplamda 500.000 saymış olurum. Başka bir hesaplada şöyle bulunur 500.000/8=62.500 bunu 65536 dan çıkartırsak 3036 sayısını elde etmiş oluruz ki bunu hex formatında yazarsak $BDC olduğunu anlarsın. O halde TMR1H=$0B ve TMR1L=$DC verilirse bu sayac 3036 dan 65535 e kadar sayacak demektir. Yani toplamda 62500 adet puls sayacaktır. 8 e böldüğümüz için bunu 8 ile çarparsak net 500.000 değerini bulmuş oluruz.
Sorduğun soruların cevaplarını almış oldun böylece.

Şimdi işin algoritma kısmına yeniden bakalım. TMR1 sayacı 3036 değerinden başlayıp 65535 e kadar sayacak ve bundan sonra 65536 ya geçerken PIR1.0 bayrağını 1 yapacaktır. İşte bizim ip ucumuz bu bayrak olacaktır.
O halde döngümüze başlamadan evvel;
- TMR1 sayacını 1/8 bölme oranı ile  aktif ediyoruz  (T1CON=%00110001):PIR1.0 Bayrağını sıfırlıyoruz.
500 ms de bir PIR1.0 bayrağı 1 e eşit olacaktır. Döngüyü ;
WHILE PIR1.0=0 ...... WEND şeklinde kurarsak PIR1.0=0 olduğu müddetçe WEND satırına kadar olan işlemleri program tekrarlar ve PIR1.0=1 olunca WEND satırını aşarak bir sonraki satıra gelir.
O halde ben bayrak set edilinceye kadar sürekli ADC okuması yaparsam ve burada tuşa basıldığını tespit edersem SAY değerini bir artırırım. Programı bloke etmemek için de tuşa basıldığı anda BIRAK=1 yaparım SAY değerini BIRAK=0 ise artırırım ve böylece BIRAK=1 olduğu için ikinci defa program oraya geldiğinde SAY değerini artırmayacaktır.
Tuş basılı olduğu müddetçe programı While komutunun alt satırına gönderirim yani alta geçmesini engellerim. Program alt kısma ancak tuşu bırakırsam gidecektir. Oraya gidincede Bırak=0 olacağı için sistem mükemmel şekilde çalışır.
500 ms dolduğunda ise wend satırından sonra şayet SAY=3 ise TOGGLE LED yaptırarak lede konum değiştiririm. Program aynı yere 500 ms sonra  geleceği için LED o konumda 500 ms kalmış olur ve bildiğin flash işlemini yapmış olur. SAY=3 değil ise zaten led konum değiştirmeyecek ve değişen bir şey olmayacaktır.

Anlatması uzun ama ama sistem aslında basit ama mükemmel şekilde kurgulanmış oluyor. Şimdi daha iyi anlayacağını umuyorum.

Ete

dedim

usta peki bu rakamları hex formatında yazmak ıcın program varmı yoksa hesap makınası kagıt ve kalemlemı yapılıyor.girmiş oldugun sayıları hex formatına nasıl dönusturuyorsun?

ete

Hesap makinası ile. Aslında desimal değerde verebilirsin. Bunun için sayımız yine 3036 olsun.
Tmr1H=(3036/256)
Tmr1L=3036 - (Tmr1H*256)
Şeklinde eşitlik kullanabilirsin.
Neden hex kullandığımızıda açıklayayım.  3036 desimal sayının hex karşılığına bakınca $0BDC olduğunu görürsün. Bunu sağdan başlayarak 2 şer hane ayırırsan 0B DC şeklinde ayrılır. En soldaki TMR1H değeri diğeride TMR1L değeri olur.

Ete

dedim

USTA

bu programı eproma kayıt etmek ıstedım ama basaramadım bir yol göstermen mumkunmu


Device = 16F88
Xtal 4

Declare Adin_Res 10
Declare Adin_Tad FRC     
Declare Adin_Stime 50

ANSEL=%00000001   'ra0 anolog giriş         
ADCON1.7=1
ADCON0=%01000000
CMCON=7
TRISA=%00000001
TRISB=%11101111
       
Symbol LED=PORTB.4         

Output LED
Dim BIRAK As Byte
Dim  HAM  As  Word 
Dim say As Byte
PORTA=0                                                   
PORTB=0                                                 
DelayMS 250
say=0
BIRAK =ERead 10
;-------------------------------------------------------------------------------
BASLA:
    T1CON=%00110001:TMR1H=$0B:TMR1L=$DC:PIR1.0=0  'TMR1 sayacı 500 ms de bir kesme yaratacak şekilde kuruldu
   
     While PIR1.0=0  'kesme bayrağı sıfır ise wend komutuna kadar olanları tekrarla
BIR:   
       ADCIN 0, HAM              'ADC den değer oku (buton basılı ise HAM>835 , basılı değil ise HM<835 olacaktır
       If HAM>835 Then        'butona basılmış ise
         If BIRAK=0 Then      'tusa ilk defa basılıyor ise
         
           say=SAY+1:BIRAK=1  'say değerini artır bırak bayrağını set et.
            EWrite 10,[BIRAK]:DelayMS 10
           If say=4 Then      'say=4 olmuş ise
         
             say=0:LED=0      'say=0 yap ve led yenıyorsa söndür.
           EndIf   
         EndIf 
         GoTo BIR             'tuş basılı durumda olduğu için BIR etiketine git
       EndIf                  'tus basılı olduğu müddetçe bırak=1 olacak ve say değeri bir kere artacaktır.
       BIRAK=0                'tus brakılınca program bu noktaya gelecek ve BIRAK=0 yaparak birdaha ki basılışta say değeri artacak
    Wend
'program 500 ms çalışarak yukarıdaki işleri yapacak. 500 ms sonra PIR1.0=1 olacak ve otomatikman alttaki satıra ulaşacaktır.
   If say=3 Then Toggle LED  'say=3 ise led, her 500 ms de bir yanacak bir sönecek
   
   
   GoTo BASLA
End 


debug yaptıgım zaman yazmadıgı ıcın okumada yapamadım

ete

Terimleri doğru kullanmak gerek. Program eproma kayıt edilemez. Parametre kayıt edilir. Programda yalnızca BIRAK değerini eproma kayıt ettiğini görüyorum. 10 nolu adrese kayıt ediliyor. 10 nolu adrestende okunabilir. Bırak aslında bir bit değişkeni ve sen onu byte gibi kayıt ediyorsun buda pek doğru değil. Kayıt yapılabilir ama her şeyden önce Bırak değerini kayıt edeceksinde ne olacak. Tuşun basılı olduğunu gösteriyor bırakınca Bırak=0 olacak zaten. Kayıt mantığını öğrenmk için yapıyorsan sözüm yok anuda zaten biliyorsun sanıyorum. O halde tam olarak ne yapmak istiyorsun açık anlatırsan yerdımcı olabilirim belki.

Tuşa basıp led flash yaptığı zaman Bırak değeride 10 nolu eprom adresine kayıt edilmiş demektir. İsis de simule ederken programı pause ile durdurup debug menüsünden eprom adreslerine bakarsan kayıdı orada görmen gerekir.

Ete

dedim

burda yapmak ıstedıgım şu idi.yanıp sönmeyi kayıt altına alıpta enerjıyı kesıp tekrar verınce ben tusa basmadan yanıp sönmesını yanı hafızaya almayı ıstemıstım.ne yapmam gerekkı kayıt edıldıkten sonra tusa basmasam bıle program oraya dallanarak ledı yakıp söndurebılıyım.

Powered by EzPortal