Geri Sayırdırma

Başlatan aberk, 26 Nisan 2016, 22:33:41

aberk

Arkadaşlar herkese kolay gelsin   PİC'te geri sayım yaptıktan sonra eksiye nasıl döneriz. örneğin iki buton var biri ile  10 a kadar artırdım sonra diğer buton ile eksiye  doğru saydırmak istiyorum fakat sıfıra gelince bu kez -1  -2  -3  diye geri ye saymasını istersek nasıl  yol izlemem lazım?

karacan451


ıf sayı=0 sayı=sayı-1

aberk

Ustad böyle yapınca benim işimi görmüyor neden dersen bu  kod ile eksiye basmaya devam edersek 0 dan sonra  en yüksek rakamı  ekrana getiryor ben ise 0 dan sonra  -1,-2,-3 ....... diye devam etsin istiyorum

karacan451

#3
ıf sayı=0 sayı=(sayı-1)*-1
böyle yaparsan olur mu

kartal_0689

#4
Merhaba,

Tanımladığın değişken sanırım byte ya da word.
Bu değişken tipleri 0-255 ve 0-65535 arasında değer alır.
Negatif işaretli değişkenler için derleyicilerin belirlediği tipler olur. Örneğin MikroPascal için
bit,byte,short,word,dWord,integer,longinteger,real gibi.
Siz hangi derleyiciyi kullanıyorsunuz bilmiyorum ama help kısmını inceleyin ve negatif
işaretli bir değişken tanımlayın. Örneğin;


var SAYICI : LongInt; // -32767 ile +32767 arası

SAYICI := SAYICI - 1;
Delay_ms(100);
if (SAYICI < -100) then
    SAYICI := 100;


yukarıdaki örnekte program otomatik olarak 0' dan sonra -1, -2 olarak aşağı saymaya devam eder
ve -100 den sonra +100 değerini alır.
TURKEY/ANK

sonmoikan

Diyelimki değişkenimiz byte tipinde ise yani 0-255 arası sayı demek oluyor, bu alan içerisinde - değer yok.
Yani Pic Basic de - değerli bir değişken tanımı yapılamaz. 0-1 dediğinizde sayı 255 olarak döner.
ABDULLAH

ete

Bu işi yaptırabilmek için bir de işaret biti kullanmanız gerekir. Sayac daima pozitif sayar ama işaret biti pozitifden negatife geçer. BU örnekte işaret biti (SIGN) byte cinsinden bir değişken. Aynı işi Bit bazlı değişken ilede yapmak mümkün.
SIGN=0 ise sayı pozitif , SIGN=1 ise Sayı negatif kabul edilebilir.
Bütün mesele sayı eksiltirken sıfır aştığınızı tespit edebilmek. Aştıktan sonra işaret negatife dönecek ve eksiltme butonuna basılmasına rağmen sayı artırılacak. Aynı şekilde sayı negatif iken artırma seçildiğinde Sayı eksiltilecek ve sıfıra yaklaşılacak sıfırdan sonra artışa geçilecek.

Örnek kod aşağıdadır.
IF ARTIR=0 THEN
   IF SIGN="+" THEN
     SAYI=SAY+1
   ELSE
     SAYI=SAYI-1
     IF SAYI=0 then SIGN="+"
   ENDIF
   WHILE ARTIR=0:WEND
   PAUSE 50
ENDIF

IF AZALT=0 THEN
   IF SIGN="+" THEN
     SAYI=SAYI-1
     IF SAYI=255 THEN SIGN="-"
   ELSE
     SAYI=SAYI+1
     IF SAYI=0 THEN SIGN="-"
   ENDIF
   WHILE AZALT=0:WEND
   PAUSE 50
ENDIF     

LCDOUT $fe,$c0,"SAYI=",SIGN,DEC3 SAYI

GOTO BASLA


BU kodu denemedim ama aynı mantığı defalarca kullandım projelerimde.

Ete

aberk

#7
Arkadaşlar   programlama olayında acemiyim ara ara kafam duruyor  yazdığım  kodlamadan bunu anlamş olmalısınız:)
Arkadaşlar bu yaptığım sistemde  RB2  ile RB3 portlarına bağlı butonlar limiti artırıp düşürüyor. RB0 ile RB1 ise Encoder Mantığı ile çalışıyor ben Temsili olarak buton bağladım ama gercek sistemde iki adet sessör bağlanacak gelelim sorunuma ben bu sistemde  geriye doğru sayım yaptığımda -1  .-2   . -3  diye saymasını istiyorum  ama bunu bi türlü yapamadım yardımcı  olursanız sevinirim.

NOT Arkadaşlar kodların karışındaki Hatırlatıcı yorumlara takılmayn  onlar daha önce yazğım programlardanda kalmış oluyor  bende kopyala yatır yapınca  acıklama bu programa göre uygun olmayabilir Lütfen açıklamalar sizi yanıltmasın.

@ __config _XT_OSC & _WDT_ON & _LVP_OFF & _CP_OFF   

DEFINE OSC 8     'Osilatör olarak
CMCON=7           'Komparatör pinleri iptal edip dijitale cevirildi.
ADCON1 = 7        'Analog pinleri dijital pinlere çevrildi.
TRISA=%00000000   'Port A ÇIKIŞ olarak ayarlandı.
TRISB=%11111111   'Port B GİRİŞ olarak ayarlandı.
TRISC=%00000000   'Port C çıkış olarak ayarlandı.
TRISD=%00000000   'Port D çıkış olarak ayarlandı.
TRISE=%00000000   'Port E çıkış olarak ayarlandı.

PORTA=0           'Port A  Sıfırlandı.
PORTB=0           'Port B  Sıfırlandı.
PORTC=0           'Port C  Sıfırlandı.
PORTD=0           'Port D  Sıfırlandı.
PORTE=0           'Port E  Sıfırlandı.

OPTION_REG.7=0    'Dahili  pull-up lar AKTİF yapıldı ayrıca pull-up direncine gerek yok


'********************  LCD TANIMLAMA*******************

DEFINE LCD_DREG PORTD 'LCD data bacakları hangi porta bağlı?
DEFINE LCD_DBIT 4 'LCD data bacakları hangi bitten başlıyor?
DEFINE LCD_EREG PORTD 'LCD Enable Bacağı Hangi Porta bağlı?
DEFINE LCD_EBIT 2 'LCD Enable Bacağı Hangi bite bağlı ?
'define LCD RWREG PORTD 'LCD R/W Bacağı Hangi Porta bağlı? // NOT  bu bacak şaye direkt bağlı olduğu için iptal edildi.
'define LCD_RWBIT 1 'LCD R/W Bacağı Hangi bite bağlı ?     // NOT  bu bacak şaye direkt bağlı olduğu için iptal edildi.
DEFINE LCD_RSREG PORTD 'LCD RS Bacağı Hangi Porta bağlı ?
DEFINE LCD_RSBIT 0 'LCD RS bacağı Hangi Bite bağlı ?
DEFINE LCD_BITS 4 'LCD 4 bit mi yoksa 8 bit olarak bağlı?
DEFINE LCD_LINES 2 'LCD Kaç sıra yazabiliyor

'*********************  DEĞİŞKENLER  *****************************


DUR CON 200
symbol ARTIR=PORTB.2
symbol EKSILT=PORTB.3
SIPIR VAR WORD
SAYAC   VAR WORD    '  xxx adında bir değişken tanımlandı.
YON   VAR WORD      '  xxx adında bir değişken tanımlandı.                     
ESKI VAR BYTE
YENI VAR BYTE
ZAMAN  VAR BYTE
SEC VAR WORD
SS VAR WORD
LMT  VAR WORD
'******************************   REKLAM **************************
                                   
LCDOUT $FE,1                         'LCD ekranı sil                       
pause  50                          'LCD nin açılmasını bekle

lcdout  "CiHAZ ACiLiYOR..."          'iki tırnak arasındakini ekrana yaz
pause 150

lcdout $FE,$C0, "LUTFEN BEKLEYiN..."     'iki tırnak arasındakini ekrana yaz
pause 150

LCDOUT $FE,1
pause 50
lcdout  "  PROJE SAHiBi"
lcdout $FE,$C0, "**AYHAN BiCER**"        'iki tırnak arasındakini ekrana yaz
PAUSE 150
LCDOUT $FE,1                              'LCD ekranı sil
PAUSE 50
 

'*************************  ANA PROGRAM  **********************
BASLA:

      IF ARTIR=0 THEN
         SEC=SEC+1
         WHILE ARTIR=0:WEND
         PAUSE 50
      ENDIF
     
      IF EKSILT=0 THEN
         SEC=SEC-1
         WHILE EKSILT=0:WEND
         PAUSE 50
      ENDIF
     

       IF SIPIR=SEC THEN          ' EĞER SİPİR İLE SEC  DEĞİŞKENİ BİRBİRİNE EŞİT İSE
              PORTC.0=1            'PORTC'NİN 0. BACAĞINI ÇIKIŞ YAP
         ELSE                       'DEĞİLSE
              PORTC.0=0            'PORTC NİN 0. BACAĞINI SIFIR  YAP (YANİ KAPAT)
       ENDIF
             
     
'////////////////////   LCD  ÇIKTISI  /////////////////////////////////// 
     
     IF YON=1 THEN                                       
         LCDOUT $FE,1,   "TUR(iLERi)=",#SIPIR
     ELSE
         LCDOUT $FE,1
         LCDOUT $FE,1,   "TUR( GERi)=",#SIPIR
     ENDIF
         LCDOUT $FE,$C0, "LiMiT SEC =",#SEC
           
SAYAC= 0
REPEAT            ' TEKRARLANACAK  KOMUT DİZİNİNİN BASLANGICI
      IF PORTB and (%00000011)=3 then basla
      IF SIPIR=(SEC-5) THEN PORTC.0=1
         
'/////////////////ENCODER DÖNGÜSÜ////////////////////////////////
 
ESKI=PORTB & %00000011
ZAMAN=0
DEVAM:
      YENI=PORTB & %00000011 'burada aynı okumayı yeniden yapıyoruz ve ESKI den farklı bir durum elde etmeye çalışıyoruz.
      IF YENI=ESKI THEN
        ZAMAN=ZAMAN+1
        IF ZAMAN<200 THEN DEVAM
        IF SAYAC=8 THEN CIKIS
      ENDIF 
     
      YON=Eski.1 ^ Yeni.0  'eski nin sıfır nolu biti ile yeninin 1 nolu bitini XOR yapıyoruz.
      IF YON=1 then  'sonuç sıfır ise
        SAYAC=SAYAC+1           
      ELSE  'sonuç 1 ise
        SAYAC=SAYAC-1   
      ENDIF
'/////////////////ENCODER DÖNGÜSÜNÜN BİTİŞİ////////////////////////////////

UNTIL SAYAC= 14     '  SAYAC 14 VEYA 8 OLURSA BİR ALT SATIRA İN 
CIKIS:
      IF SAYAC= 14 THEN SIPIR=SIPIR+1
      IF SAYAC= 8 THEN SIPIR=SIPIR-1
     
'//////////////////////////////////   

GOTO BASLA

  END
 
'******************** PROGRAM SONU *********************************


Edit(ete) : Programın düzeltilmiş hali buraya yüklendi

ete

Programda bir sürü kusur var. Ayrıca bu kadar kısır bir açıklama ile istediğini elde etmen kesinlikle mümkün değil.
Programda hem ileri saydırma hemde geri saydırma düzeneği mevcut.
Üstelik hem butonlar bu işi yapıyor hemde encoder düzeneği bu işi yapacak gözüküyor.
Peki sayac değişkeni pozitif iken geri saydırmada neden -1 ,-2 -3 diye gitsin öyle bir kural yok.
Sayı önce sıfıra kadar geri gider ve geri gitmeye devam ediyor ise -1 -2 -3 diye geri sayar. Ama senin açıklamanda geri sayıyor ise eksi değer büyüyerek saysın şeklinde anlaşılıyor.

     IF SIPIR=SEC THEN          ' EĞER SİPİR İLE SEC  DEĞİŞKENİ BİRBİRİNE EŞİT İSE
              PORTC.0=1            'PORTC'NİN 0. BACAĞINI ÇIKIŞ YAP
         ELSE                       'DEĞİLSE
              PORTC.0=0            'PORTC NİN 0. BACAĞINI SIFIR  YAP (YANİ KAPAT)
       ENDIF
       komut satırlarında SPIR sayısı SEC değerine eşit ise PORTC.0=1 oluyor eşit değil ise sıfır oluyor.
Bu dururmda aşağıdaki komutun hiç bir işlevselliği kalmıyor.
       IF SIPIR=0000 THEN PORTC.0=0
Bir defa sıfır tek bir sıfırdır. Hiç bir zaman 4 sıfır yan yana olamaz SPIR=0 ise PORTC.0=0 şeklinde doğru yazılmış olur.
Hex formatında yazarken $0000 şeklinde yazabilirsin. Ama desimal formatta sıfır tek hanedir.
Dediğim gibi o komutu oradan silmen daha doğru çünki zaten SAYAC=SPIR değil ise PORTC.0=0 olacak.

UNTIL SAYAC= 14 OR SAYAC = 8
komut satırında 8 sayısı 14 den önce gelir ve hiç bir zaman program SAYAC değerinin 14 olmasını beklemez. 8 olur olmaz bir alt satıra geçer. Bu durumda sen hiç bir zaman ,
IF SAYAC= 14 THEN SIPIR=SIPIR+1    satırını çalıştıramazsın. Sayac değeri hiç bir zaman 14 olamaz çünki.
Bunlar mantık karşılaştırmalarıdır. Program yazarken bu gibi mantıksal konulara çok dikkat etmek lazım. Kafa çalıştırmak gerekiyor anlayacağın.

Encoder kısmı yukarıda açıkladığım sorundan dolayı çalışmaz. Hep eksiltme yapar. Artırma hiç yapamaz.
Ayrıca aynı yerde Artır tuşu LMT artırıyor azalt tuşu LMT eksiltiyor. Halbuki Artır ve Azalt tuşları SEC değerini artırıp eksiltiyor programın başında. Üstelik LMT değiştirilen yer bekleme yeride değil program anında başa giderek sen tua basarken bu sefer SEC değerlerini değiştirecektir. Bir tuş gurubu bazen bir değişkeni bazen diğer değişkeni artırmaz. Nereden emin olacaksın sen LMT yi artırdığına?. Ya üçüncü bir parametre ekleyeceksin oraya yada o işi başka türlü halledeceksin.

Repeat komutundan önce SAYAC=11 demişsin. Sabit değer vermişsin. Muhtemelen 8 değerini geçsin diye verdin bu değeri Yoksa hep eksiltme yapıyordu ve sen çare olarak bu değeri verdin gibi geliyor bana. Sabit değer vermek de hatalı. Nereden çıktı bu 11 mesela. Belirli bir amacımı var belli değil. Oraya yakışan değer SAYAC=0 olması. Zira encoder rutini içerisinde sayac değeri artırılıyor. Yeni bir artırma işlemine başlamadan önce sayac değerini sıfırlamak en doğrusu olur.

Encoder mantığını çalıştırırken programın oraya takılıp kalmasını istemeyiz. Zira encoder dönmediği zaman dönünceye kadar program orada bekler durur. Bu ise bazı sorunlar yaratır. O nedenle ESKI ile YENI bir birine eşit ise encoder dönmüyor demektir. İşte o noktada Zaman değişkeni artırılarak belirli bir değere ulaşması ulaştığı zaman encoder okuma ksımından çıkılıp geri dönülmesi gerekir. Sen Zaman değişkenini artırmışsın ama belirli bir değere ulaşıp ulaşmadığını kontrol etmemişsin. O belirli değere ulaşınca başa git de dememişsin. Kısaca burasını muhtemelen benim programlardan kopyaladın ama eksik yapmışsın. Mantığını anlattım şimdi ona uygun değişikliği yapman gerekiyor.

Bana kalırsa otur yeni bir senaryo yaz. Senaryo denilen şey programın adım adım çalıştırılma mantığıdır. Laf ile programı çalıştırmaktır. Oradan görürsün kusurlarını ve düzeltirsin mantığını. Sonra oturup onu programa tercüme edersin olur biter.

Ete


ete

#9
Biraz boş vakit bulunca bu projeninnasıl olması gerektiği üzerinde kafa yordum.
Mevcut yazılan programa bakınca encoderin her 14 palsinde bir spri sayısının bir artacağına ama tersine çevirişte yine geriye doğru her 14 encoder palsi sonunda spir sayısının bir azalması gerektiğine karar verdim.
Hiç bir sistemde ileri doğru (saat yönünde) 14 puls gelince spir 1 artsın geriye doğru (saatin tersi yönünde) döndüğünde ise 8 pus geldiğinde 1 eksiltsin şeklinde uygulama olmaz sanırım. Bu nedenle programı biraz değiştirip öncelikle 4x20 LCD ekranı kullanarak bütün verilerin ekranda görülmesini sağladım.
Söylediğim sistemi uygulayarak spir sayısının arttığını ve azalmasını izleyebildim. Üstelik puls adedini dönüşün ilerimi gerimi olduğunuda izlemek mümkün olmaktadır.
Projenin özelliği nedeni ile tuş kontrolü haricinde herhangi bir pause kullanılmamıştır. Kullanırsanız puls kaçırır sistem.

Dosyalar ilişiktedir. Hem versiyon -7 hemde 8 üzerinden şema hazırladım.isteyen istediği ile çalışır.
Yeni öğrenenler ve algoritma takip edenlerinde incelemesini isterim.
Bir encoder hangi mantıkla çalıştırılıyor anlamak açısından dikkate değer bir çalışma bu.
Encoderi motor encoder ve 2 buton kullanarak yaptım. Gerçek devrede tabiiki bu kısım yer almayacak.

Ete

aberk

#10
Hocam ilginiz için çok teşekkür ederim, Fazladan kod kullanıyorum anlaşılan sizin yaptığınız çalışmaya bakınca bunu açıkça görüyorum.
Ben tam olarak ne yapmak istediğimi açıkça anlatmak istiyorum şuana kadar tam olarak istediğimi aktaramadım bu benim hatamdı kusura bakmayın.Şimdi en baştan size proje hakkında detaylı bilgi vermek istiyorum.

Elimde bir tane bobin sarma cihazı var elle çevriliyor.  Bu cihazın tur sayısını gösteren mekanik bir sayaç var ben ise bu mekanik sayacı iptal edip yerine kendim elektronik sayaç koymak istiyorum hem ileri hem de geri sayaç olarak kullanacam.

Elle çevrilen kasnağa iki adet optik sensörü  bitişik vaziyette bağladım .Sensörler boşta iken 11.konumunda  ileri sayarken  10.00.01   geri sayarken ise  01.00.10  yani sensörlerin  0 bilgisini pic'e okutuyorum.   Kasnak her turda bir defa sensörlerin önünden gececek  vaziyette dizayn edildi.

Gelelim Benim sıkıntı yaşadığım yerlere Birincisi  Tur ileri sayarken sıkıntı yok ama geri sayarken  eksiye doğru  saymada sıkıntı var
Örneğin: 1.2.3.4.diye artırıyorum daha sonra geri doğru sayarken söyle olsun istiyorum 4.  3 . 2. 1. 0. -1. -2 .-3. -4........ diye gitsin.
Bi kaç tane  resim ekledim bu resimlerde konuya yardımcı olma acısından iyi olacaktır.

Encoderi neden kullandın derseniz araştırmamda  baktımki iki sensörleri yanyana koyunca aynı encoder  gibi sinyal üretiyor o yüzden encoder kullandım similasyonda .
similasyonu yavaş yavaş takip etmek için  encoder uclarını boşa cıkartıp iki adet buton kullandım bu butonları ise aynı encoder gibi sırası ile basıp bırakıyorum böylece takibi daha kolay oluyor.

ete

#11
Düzenlediğim sistem bu mantıkla çalışıyor zaten. Ancak encoderin saydığı puls lar ile tur sayısı yani spir arasındaki ilişki şu anda yanlış. Önceki programında bir 14 bir 8 puls değerleri var idi. Ben 14 ü kullandım. Yapman gereken şey bir turda encoderin kaç konum değiştirdiğini bulmak. Buna tur başına kaç puls üretiyor desek de olur. Bu parametreyi programda 14 kullandım. Sen doğrusu ile değiştirdinmi oldu bitti demektir.
Bu arada encoder pulslarını daha rahat incelemek istersen tur başına puls sayısını düşür. Encoder motor üzerine sol tıkla açılan pencerede tur başına puls sayısı şu anda 100 idi sanırım , onu 10 yap yada dahada düşür böylece pulsleri izleyebilirsin.
Ete

aberk

#12
Hocam sistem çalıştı fakat sesörlerin önünden cisim hızlı gecince sensör okumuyor yavaş geçirince sorunsuz çalışıyor nedeni ne olabilir?

Dahili  pull-up lar AKTİF yapıldı ayrıca pull-up direnci kullanmadım acaba aktif edip 47k lık direnç koysam farkedermi hocam yada Sensörün + ile - arasında kondansatör koysam fark  edermi?

ete

Cisim dediğin şey bu beyaz disk ise onun konumunun hassas ayarlanması gerekir diye düşünüyorum. Ayrıca beyaz malzemeden yaptığın bu disk de IR yi geçirebilir.  Aslında nasıl çalışıyor anlamadım. Orada 2 sensör var ise IR kaynağı nerede?

Ete

aberk

#14
Hocam beyaz alanda okuma islemi yaptırmıyorum çemberdeki boş alana geline sayma işlemini yapıyorum fakat dediğim gibi hızlı cevirince okumuyor yavaş çevirince sorunsuz okuyor. bit türlü işin içinden çıkamadım.

Resimlerin üzerinde Tekrar çizim yaptım hocam IR sinyal kaynağı ile algılayıcı kısmını Bu arada yazıcıların  içinde kullanılıyor bu sensörler bazı yerlerde  ise optocoupler olarakta kullanılabilir.

Powered by EzPortal