5 saniyede hangi butona fazla basıldığını nasıl bulabilirim

Başlatan dnaci, 22 Ekim 2020, 09:54:35

dnaci

Merhaba, proton basic için bir algoritmaya ihtiyacım var. PortB'ye bağlı dört butonum var ve 1 saniyede herhangi bir butona basılıyor. Aynı anda birden fazla butona basılmıyor. 2 buton arası eşitlik olma durumu hiçbir zaman gerçekleşmiyor. Aşağıya çalışmaya başladığım kodu ekledim ve 5 saniyede bir defa en fazla basılan butonu tespit etmek istiyorum. Buton değişkenlerine portb'yi yüklüyorum. Bu nedenle 5 saniyelik bir sayaç oluşturdum ve süre sonunda sayacı sıfırlıyorum.  Ana döngü butona basılan saniyede 1 defa hesap etiketine yönlendiriliyor. Proton manuelde de array örneklerinde böyle bir kod yok. Google araması ile bir sonuca ulaşamadım bazı c# örnekleri buldum ama işe yaramıyor. Konuyla ilgili bilgisi olan var mı?

Dim buton[5] As Byte

ana: 'saniyede 1 defa portb'deki herhangi bir butona basılıyor.
If PORTB = 1 Then GoSub hesap 'bit0
If PORTB = 2 Then GoSub hesap 'bit1
If PORTB = 4 Then GoSub hesap 'bit2
If PORTB = 8 Then GoSub hesap 'bit3
GoTo ana

hesap: 'portb buton değişkenine aktarılıyor.
sayi = sayi + 1 ' 1-5 sayaç
If sayi = 1 Then buton[0] = PORTB
If sayi = 2 Then buton[1] = PORTB
If sayi = 3 Then buton[2] = PORTB
If sayi = 4 Then buton[3] = PORTB
If sayi = 5 Then buton[4] = PORTB
If sayi = 5 Then sayi = 0
GoTo ana

elektro77

Alıntı yapılan: dnaci - 22 Ekim 2020, 09:54:35Merhaba, proton basic için bir algoritmaya ihtiyacım var. PortB'ye bağlı dört butonum var ve 1 saniyede herhangi bir butona basılıyor. Aynı anda birden fazla butona basılmıyor. 2 buton arası eşitlik olma durumu hiçbir zaman gerçekleşmiyor. Aşağıya çalışmaya başladığım kodu ekledim ve 5 saniyede bir defa en fazla basılan butonu tespit etmek istiyorum. Buton değişkenlerine portb'yi yüklüyorum. Bu nedenle 5 saniyelik bir sayaç oluşturdum ve süre sonunda sayacı sıfırlıyorum.  Ana döngü butona basılan saniyede 1 defa hesap etiketine yönlendiriliyor. Proton manuelde de array örneklerinde böyle bir kod yok. Google araması ile bir sonuca ulaşamadım bazı c# örnekleri buldum ama işe yaramıyor. Konuyla ilgili bilgisi olan var mı?

Dim buton[5] As Byte

ana: 'saniyede 1 defa portb'deki herhangi bir butona basılıyor.
If PORTB = 1 Then GoSub hesap 'bit0
If PORTB = 2 Then GoSub hesap 'bit1
If PORTB = 4 Then GoSub hesap 'bit2
If PORTB = 8 Then GoSub hesap 'bit3
GoTo ana

hesap: 'portb buton değişkenine aktarılıyor.
sayi = sayi + 1 ' 1-5 sayaç
If sayi = 1 Then buton[0] = PORTB
If sayi = 2 Then buton[1] = PORTB
If sayi = 3 Then buton[2] = PORTB
If sayi = 4 Then buton[3] = PORTB
If sayi = 5 Then buton[4] = PORTB
If sayi = 5 Then sayi = 0
GoTo ana
Her buton için ayrı bir sayac değişkeni belirleyip 5sn lik süre sonunda değeri en yüksek olanı sayacı secebilirsin. Yine 5snlik süre sonunda tüm sayacları sıfırlarsın
Örneğin:
if buton1=1 then sayac1=sayac1+1
if buton2=1 then sayac2=sayac2+1
if buton3=1 then sayac3=sayac3+1
if buton4=1 then sayac4=sayac4+1
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

dnaci

Alıntı yapılan: elektro77 - 22 Ekim 2020, 10:06:31Her buton için ayrı bir sayac değişkeni belirleyip 5sn lik süre sonunda değeri en yüksek olanı sayacı secebilirsin. Yine 5snlik süre sonunda tüm sayacları sıfırlarsın
Örneğin:
If buton1=1 then sayac1=sayac1+1
ıf buton2=1 then sayac2=sayac2+1
ıf buton3=1 then sayac3=sayac3+1
ıf buton4=1 then sayac4=sayac4+1

@elektro77 teşekkür ederim. En yüksek sayacı tespit etmek kaldı onuda yaparım. Kodu paylaşırım buradan.

elektro77

Alıntı yapılan: dnaci - 22 Ekim 2020, 10:27:53@elektro77 teşekkür ederim. En yüksek sayacı tespit etmek kaldı onuda yaparım. Kodu paylaşırım buradan.
En yüksek sayacı tespit etmek için MAX komutunu inceleyin.
pbp de MAX ve MIN komutları iki sayının büyük veya küçük olanını bulmamıza olanak sağlar.Bu komutlar genellikle bir sayıyı sınırlamak için kullanılır.
Fakat proton basic te max ın karşılığı nedir araştırmak gerek.

A= SAYAC1 MAX SAYAC2 ' SAYAC1 ile SAYAC2 den hangisi büyük ise A nın içerisine yazar

"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

dnaci

#4
Proton manualde max komutu yok, belki başka komut kullanılıyordur. Ben şöyle bir çözüm buldum:

TRISB = %00001111

Dim kontrol As Byte
Dim sonuc As Byte
Dim sayi As Byte
Dim sayac1 As Byte
Dim sayac2 As Byte
Dim sayac3 As Byte
Dim sayac4 As Byte

ana:
If PORTB = 1 Then GoSub hesap 'bit0
If PORTB = 2 Then GoSub hesap 'bit1
If PORTB = 4 Then GoSub hesap 'bit2
If PORTB = 8 Then GoSub hesap 'bit3
GoTo ana

hesap:
sayi = sayi + 1 '5 saniye sayılıyor.
If PORTB = 1 Then sayac1 = sayac1 + 1 '4 adet giriş sayılıyor.
If PORTB = 2 Then sayac2 = sayac2 + 1 
If PORTB = 4 Then sayac3 = sayac3 + 1 
If PORTB = 8 Then sayac4 = sayac4 + 1 

kontrol = 0 'en büyük sayaç sonuc değişkeninden tespit ediliyor.
kontrol = sayac1
If sayac2 > kontrol Then kontrol = sayac2
If sayac3 > kontrol Then kontrol = sayac3
If sayac4 > kontrol Then kontrol = sayac4
If sayac1 = kontrol Then sonuc = 1 
If sayac2 = kontrol Then sonuc = 2 
If sayac3 = kontrol Then sonuc = 4 
If sayac4 = kontrol Then sonuc = 8
If sayi = 5 Then sayac1=0
If sayi = 5 Then sayac2=0
If sayi = 5 Then sayac3=0
If sayi = 5 Then sayac4=0
If sayi = 5 Then sayi=0
return

ete

Bu işin bir çok çözümü olabilir.
Benzer durumlarda sıklıkla kullandığım bir metod şöyle.
SAYAC VAR BYTE[8]  'basılacak tuş sayısı kadar dizi değişkeni tanımlıyoruz. Ben bütün PORTB pinleri için tanımladım.
KONTROL:
 FOR X=0 TO 7
   IF PORTB.0[X]=1 THEN
      SAYAC[X]=SAYAC[X]+1
   ENDIF
NEXT

5 sn boyunca bu komut dizisi çalışıp basılan tuşların sayaclarını bir artırır.
5 sn sonunda ise bir sıraya dizme kodu yazıp en büyük olanı buluruz.
F
OR X=0 TO 6
  FOR Y=(X+1) TO 7
    IF SAYAC[X]>SAYAC[Y] THEN
       TEMP=SAYAC[X]
       SAYAC[X]=SAYAC[Y]
       SAYAC[Y]=TEMP
     ENDIF
  NEXT
NEXT     
Sonuçta en büyük olan sayac SAYAC[7]dir.
Ete


elektro77

Alıntı yapılan: ete - 22 Ekim 2020, 17:57:21Bu işin bir çok çözümü olabilir.
Benzer durumlarda sıklıkla kullandığım bir metod şöyle.
SAYAC VAR BYTE[8]  'basılacak tuş sayısı kadar dizi değişkeni tanımlıyoruz. Ben bütün PORTB pinleri için tanımladım.
KONTROL:
 FOR X=0 TO 7
   IF PORTB.0[X]=1 THEN
      SAYAC[X]=SAYAC[X]+1
   ENDIF
NEXT

5 sn boyunca bu komut dizisi çalışıp basılan tuşların sayaclarını bir artırır.
5 sn sonunda ise bir sıraya dizme kodu yazıp en büyük olanı buluruz.
F
OR X=0 TO 6
  FOR Y=(X+1) TO 7
    IF SAYAC[X]>SAYAC[Y] THEN
       TEMP=SAYAC[X]
       SAYAC[X]=SAYAC[Y]
       SAYAC[Y]=TEMP
     ENDIF
  NEXT
NEXT     
Sonuçta en büyük olan sayac SAYAC[7]dir.
Ete


Evet hocam bunu yapmanın bir çok yolu olabilir ama zirvesi bu olurdu heralde. Dün akşamdan beri çözmeye çalışıyorum algoritmanızı. Formül gibi olmuş resmen. Hayranım beyninizin çalışma şekline.
Kodları daha sonra faydası olması adına biraz açıklarsanız sevinirim. Birde böyle bir mantığın hangi işi yapan bir devrede kullanılabileceğini çok merak ettim doğrusu.
Saygılar
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

ete

Açıklamaya PORTB de bağlı butonlar üzerinden başlayalım. Butonların sıralı pinlere bağlı olması bir avantaj. Bu sayede Index değişkeni kullanarak (Index değişkeni bitlerin tespitinde kolaylık sağlıyor) hangisine basıldığını kolaylıkla anlayabiliriz.
PORTB.0 - PORTB.1 - PORTB.2 ve PORTB.3 de bağlı butonlarımız olsun.
Hangisine basıldığını aşağıdaki kodla kolaylıkla anlayabiliriz. (Basıldığında pin HIGH olacak ama terside olabilir)
FOR X=0 to 3
  IF PORTB.0[X]=1 THEN ....
Next
Şimdi sıradan döngüyü çalıştıralım.
X=0 iken PORTB.0[0]=1 ise demek ilk bite bağlı butona basılmış ise demek olacak.
X=1 iken PORTB.0[1]=1 ise
X=2 iken PORTB.0[2]=1 ise
X=3 iken PORTB.0[3]=1 ise demek 3 nolu bit bağlı butona basılmış ise demek anlamına geliyor.
Temel amaç hangisine basıldı ise ona ait sayacı bir artırmak olacağına göre Buton sayısı kadar bir dizi değişkeni tanımlayıp onuda index değişkeni ile kullanılır hale getiriyoruz.
IF PORTB.0[X]=1 THEN SAYAC[X]=SAYAC[X]+1
şeklindeki komut ise hangi butona basılmış ise onun sayac değerini bir artıracaktır.
İşte index değişkeni (X) kullanmanın avantajıda buradan geliyor.
Son kısımda ise dizi değişkeni içindeki sayıları Bubble Sort denilen sıraya dizme işlemine tabi tutup küçükten büyüğe doğru sıralıyoruz. Tabiiki en büyük olanıda en sondaki değişken oluyor.
Hepsi bu.

Ete

muyat

Ete hocam yukardaki örnegi rica etsem index değişkeni değilde
tus1
tus2
tus3
tus4
şeklinde sigorta ayarlarından sonra girişlere bu şekilde isim verdigimiz tanımlamalar üzerinden yapabilir misiniz
Çünkü girişlerin hepsi portb de olmayabilir.Ben index değişkeni kullanmıyorum çünkü...Girişlere hep farklı isimler veririm genelde.

ete

Yukarıda istediğin şeyi yapmışlar zaten. Oradan faydalanamıyormusun?
Ete

İlyas KAYA

Ayni mantıkla yola çıkarak bir lookup tablosu oluşturun ve ayni for döngusune sokarak farklı pinleri de kontrol edebilirsiniz.
Göz odur ki dağ ardını görsün,
Akıl odur ki başa geleceği bilsin.!

elektro77

Ete Hocam
benim konum değil ama merakımdan dolayı verdiğiniz index kullanımı örneğini anlamaya çalışıyorum ama hala çözemedim.
İsiste bir devre üzerinde uygulayıp incelemeye çalıştım ama kodları doğru şekilde çalıştıramadım.
Bu kodları nasıl 5 saniye veya daha uzun süre çalıştırabilirim ve tüm değişkenleri  ekranda nasıl görebilirim. Yardımcı olurmusunuz?
isis dosyaları ektedir.
Birde index kullanımı ile ilgili bir ders verebilir misiniz lütfen?
BASLA:   
GOSUB EKRAN

FOR X=0 tO 7
   IF PORTB.0[X]=1 THEN
      SAYAC[X]=SAYAC[X]+1
      ENDIF
NEXT


fOR X=0 TO 6
  FOR Y=(X+1) TO 7
    IF SAYAC[X]>SAYAC[Y] THEN
       TEMP=SAYAC[X]
       SAYAC[X]=SAYAC[Y]
       SAYAC[Y]=TEMP
     ENDIF
  NEXT
NEXT 
'--------------------------------
GOTO BASLA

EKRAN:
lcdout $FE,$80,"X    :",DEC3 X
lcdout $FE,$C0,"Y    :",DEC3 Y
lcdout $FE,$94,"TEMP :",DEC3 TEMP
lcdout $FE,$d4,"SAYAC:",DEC3 SAYAC
RETURN
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

ete

Yazdıklarına eklemeler yaparak sistemi anlaşılır hale getirdim.
Aşağıdakini dene bakalım ekranda ne göreceksin.
Süreyi 10 sn yaptım ki kolayca tuşlara basacak zamanın olsun.
Ayrıca 10 dolmadan bütün tuşlara rastgele bas ve bekle. 10 sn dolduktan sonra program basılan tuş adetlerini sıraya dizecek ve ekrana dizilmişleri verecektir.
Bu aşamadan sonra tekrar bir tuşa basarsan her şey silinecek ve aynı işlem tekrarlanacaktır.

Ete
@ __config _XT_OSC & _WDT_ON & _LVP_OFF & _CP_OFF
define OSC 4
ADCON1=7  
CMCON=7  
 '-------------------------------------------------------------------------------

DEFINE LCD_DREG        PORTC    'LCD data bacakları hangi porta bağlı?
DEFINE LCD_DBIT        4        'LCD data bacakları hangi bitten başlıyor?
DEFINE LCD_EREG        PORTC    'LCD Enable Bacağı Hangi Porta bağlı?
DEFINE LCD_EBIT        3        'LCD Enable Bacağı Hangi bite bağlı ?
DEFINE LCD_RSREG       PORTC    'LCD RS Bacağı Hangi Porta bağlı ?
DEFINE LCD_RSBIT       2        'LCD RS bacağı Hangi Bite bağlı  ?
DEFINE LCD_BITS        4        'LCD 4 bit mi yoksa 8 bit olarak bağlı?
DEFINE LCD_LINES       4        'LCD Kaç sıra yazabiliyor
'-------------------------------------------------------------------------------
 TRISA=%00000000
 TRISB=%11111111
 TRISC=%00000000
 PORTA=0: PORTB=0: PORTC=0
 '------------------------------------------------------------------
                                                  
 '-------------------------------------------------------------------------------
x var byte
y var byte
SAYAC VAR BYTE[4]60'İNDEX DEĞİŞKENİ
temp var byte
KES  VAR BYTE
'---------------------------------------------------------------------------
pause 200

BASLA:   
GOSUB EKRAN
 WHILE PORTB=0:WEND 
FOR X=0 TO 3
    SAYAC[X]=0
NEXT
 LCDOUT $FE,1:GOSUB EKRAN  

BASLA_BIR:
           T1CON=%00110001:KES=40 
'her bir kesme 250 ms ve 4 kesme 1 sn olacağı için 10 sn için 40 kesme kullanacağız.
BASLA_IKI:
          TMR1H=$85:TMR1L=$EE:PIR1.0=0
          WHILE PIR1.0=0           
FOR X=0 tO 3
   IF PORTB.0[X]=1 THEN
      SAYAC[X]=SAYAC[X]+1
      WHILE PORTB.0[X]=1:WEND
      GOSUB EKRAN
   ENDIF
NEXT
         WEND
         KES=KES-1:IF KES>0 THEN BASLA_IKI

fOR X=0 TO 2
  FOR Y=(X+1) TO 3
    IF SAYAC[X]>SAYAC[Y] THEN
       TEMP=SAYAC[X]
       SAYAC[X]=SAYAC[Y]
       SAYAC[Y]=TEMP
     ENDIF
  NEXT
NEXT 
'--------------------------------
GOTO BASLA

EKRAN:
lcdout $FE,$80,"SAYAC-0 :",DEC sayac[0]
lcdout $FE,$C0,"SAYAC-1 :",DEC sayac[1]
lcdout $FE,$94,"SAYAC-2 :",DEC sayac[2]
lcdout $FE,$d4,"SAYAC-3 :",DEC SAYAC[3]
RETURN

Şayet 7 butonun hepsini kullanayım derseniz aşağıdaki programda bu iş için. 7 butona fasılalı basmak maalesed 10 sn den fazla sürdüğü için süreyi 15 sn ye çıkardım. Yinede zorlanıyorsun.
Bu nedenle tuşa basıldıktan sonraki bırakma kontrolünü kaldırdım. Böyle basılı tuttuğun sürece sayac değeri artıyor. Bu devrede PORTB nin bütün pinlerine buton bağlanmalıdır.

Ete

@__config _XT_OSC & _WDT_ON & _LVP_OFF & _CP_OFF
define OSC 4
ADCON1=7  
CMCON=7  
 '-------------------------------------------------------------------------------

DEFINE LCD_DREG        PORTC    'LCD data bacakları hangi porta bağlı?
DEFINE LCD_DBIT        4        'LCD data bacakları hangi bitten başlıyor?
DEFINE LCD_EREG        PORTC    'LCD Enable Bacağı Hangi Porta bağlı?
DEFINE LCD_EBIT        3        'LCD Enable Bacağı Hangi bite bağlı ?
DEFINE LCD_RSREG       PORTC    'LCD RS Bacağı Hangi Porta bağlı ?
DEFINE LCD_RSBIT       2        'LCD RS bacağı Hangi Bite bağlı  ?
DEFINE LCD_BITS        4        'LCD 4 bit mi yoksa 8 bit olarak bağlı?
DEFINE LCD_LINES       4        'LCD Kaç sıra yazabiliyor
'-------------------------------------------------------------------------------
 TRISA=%00000000
 TRISB=%11111111
 TRISC=%00000000
 PORTA=0: PORTB=0: PORTC=0
 '------------------------------------------------------------------
                                                  
 '-------------------------------------------------------------------------------
x var byte
y var byte
SAYAC VAR BYTE[8]60'İNDEX DEĞİŞKENİ
temp var byte
KES  VAR BYTE
'---------------------------------------------------------------------------
pause 200

BASLA:   
GOSUB EKRAN
 WHILE PORTB=0:WEND 
FOR X=0 TO 7
    SAYAC[X]=0
NEXT
 LCDOUT $FE,1:GOSUB EKRAN  

BASLA_BIR:
           T1CON=%00110001:KES=60 
'her bir kesme 250 ms ve 4 kesme 1 sn olacağı için 10 sn için 40 kesme kullanacağız.
BASLA_IKI:
          TMR1H=$85:TMR1L=$EE:PIR1.0=0
          WHILE PIR1.0=0           
FOR X=0 tO 7
   IF PORTB.0[X]=1 THEN
      SAYAC[X]=SAYAC[X]+1
'      WHILE PORTB.0[X]=1:WEND
      GOSUB EKRAN
   ENDIF
NEXT
         WEND
         KES=KES-1:IF KES>0 THEN BASLA_IKI

fOR X=0 TO 6
  FOR Y=(X+1) TO 7
    IF SAYAC[X]>SAYAC[Y] THEN
       TEMP=SAYAC[X]
       SAYAC[X]=SAYAC[Y]
       SAYAC[Y]=TEMP
     ENDIF
  NEXT
NEXT 
'--------------------------------
GOTO BASLA

EKRAN:
lcdout $FE,$80,"SAYAC-0-1 :",DEC sayac[0],"---",dec sayac[1]
lcdout $FE,$C0,"SAYAC-2-3 :",DEC sayac[2],"---",dec sayac[3]
lcdout $FE,$94,"SAYAC-4-5 :",DEC sayac[4],"---",dec sayac[5]
lcdout $FE,$d4,"SAYAC-6-7 :",DEC SAYAC[6],"---",dec sayac[7]
RETURN

elektro77

Hocam herzaman ki gibi yine harika bir iş çıkarmışsınız. Sizi tebrik ediyorum. Saygılar
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

Powered by EzPortal