PIC BASIC PRO Öğreniyoruz soru cevapları

Başlatan aster, 19 Mayıs 2005, 17:33:33

pea

Yine ben  :-\
Alttaki kodu , RGB hesap bölümü kesme içinde , ana döngü içinde , if then döngüsüyle olacak şekilde de denedim.Hepsinde de 12ms gibi olması gereken periyot 250ms'lere çıktı.
Hesaplama bölümünde bir hata var sanırım ama ne olduğunu bulamadım.
Program fark edildiği üzere PWM ile RGB Led kontrolü.Analog girişten okunan değer değişkene yazılıyor , bu değişkene düşen aralıktaki hesaba göre de renk üretiliyor.

@ __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF

DEFINE OSCCAL_1K 1  'bu komut mutlaka olacak OSCCAL değerini yeniden pice yazdırıyor

TRISIO = %000001    'GP0/AN0 input , gerisi output 
CMCON = 7           
ADCON0=%10000001  'Vdd referans , AN0 analog kanalı , A/DC bitik , modül çalışıyor 
ANSEL= %00110001  'RC osilatör clock , AN0 analog giriş
INTCON=%10100000   'interrupt etkin , timer kesmesi etkin
OPTION_REG =%00000000             ' timer osilatörü dahili

define ADC_SAMPLEUS 20
DEFINE   ADC_BITS   10
DEFINE   ADC_CLOCK   3

deger var word
R var byte
red var byte
G var byte
green var byte
B var byte
blue var byte
led0 var gpio.1       'led0=GP1
led1 var gpio.2       'led1=GP2
led2 VAR gpio.4

GPIO = 0
R=0 : G=0 : B=0
red=0 : green=0 : blue=0
Pause 50

on interrupt goto kesme

dongu:

adcin 0 , deger        'deger değişkenine AN0'dan gelen değeri ata
goto dongu

disable
kesme:

select case deger 
case is >767                                   'mor-beyaz
    R=32
    deger=deger/2
    G=deger-256 : G=G/8
    B=32 
case is >639        'pembiş mor
    R=deger-513 : R=R/8
    G=deger-640  : G=G/8
    B=deger-513   : B=B/8
case is >511         'mavi pembişimsi 128
    R=deger-512 : R=R/8
    G=0
    B=767-deger : B=B/8
case is >383     'yesil-mavi aralığı 128
    R=0
    G=511-deger : G=G/8
    B=deger-384 : B=B/4
case is >255           'sarı-yesil aralığı 128
    R=383-deger  : R=R/4 
    G=511-deger  : G=G/8 
    B=0   
case is > 0     'kırmızı-sarı aralığı 256
    R = 32
    G = deger/8
    B = 0
end select

red=red+1
if (led0=1 and red=R) or (led0=0 and red=32-R) then
led0=1-led0
red=0
endif

green=green+1           
if (led1=1 and green=G) or (led1=0 and green=32-G) then
led1=1-led1
green=0
endif 

blue=blue+1
if (led2=1 and blue=B) or (led2=0 and blue=32-B) then
led2=1-led2
blue=0
endif

TMR0=255
intcon.2=0
resume
enable
end

ete

Her bir komutun icra edilmesi için bir zaman gerektiğini hesaba katmıyorsun.
Kesme kısmına çok fazla kod yüklemişsin. Kesme zamanında oluşsa bile kesmede program çok zaman kaybediyor. Sebebi odur.

Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

pea

Kesme'ye neden hepsini koydum ben de bilmiyorum.Oysa ki düzgün bir sinyal çıkarmayacağını biliyorum da.Son çare olarak denemişim dalgınlıkla  :-\
Kodun normal halinde ADC ve ADC'ye bağlı değişen duty süreleri ana döngü içerisindeydi.
Kesme içinde ise sadece şu kısım var :
red=red+1
if (led0=1 and red=R) or (led0=0 and red=32-R) then
led0=1-led0
red=0
endif

green=green+1           
if (led1=1 and green=G) or (led1=0 and green=32-G) then
led1=1-led1
green=0
endif 

blue=blue+1
if (led2=1 and blue=B) or (led2=0 and blue=32-B) then
led2=1-led2
blue=0
endif

TMR0=150
intcon.2=0
resume
enable
end


Bu haliyle de ya yine bir hesapta hata var ya da Case Select döngüsünün ortasında kesme oluştuğu için sorun çıkıyor.
Ancak şöyle bir durum var ki ; Proteus'ta gözüken Duty değerleri benim istediklerimle pek alakalı değil.4Hz'lik sinyal almam da büyük olasılıkla bir hesap hatasını belirtiyor diye düşünüyorum

ete

Programında hala hatalar görüyorum. Özellikle değişken değerlerinde,
R-G-B değerlerine iyice bir bak. Bu değerler Byte cinsinde olup 255 değerini aşamaz.
Ama sen ne yapmışsın? Değer-513 gibi hesaplar yazmışsın. Deger madem Pot 'dan okunacak alacağı değer 0-1023 arasında değişir.
Bu hesap sonucu 255 dan genelde büyük çıkar. Ayrıca Deger<513 olunca hesap sonucu eksi çıkar ve sistem sapıtır.
Bunların tedbirlerinin alınması gerek. Bana kalırsa PWM da % ile çalışmaya bak. R?100 olunca maksimum kırmızı rengi, %50 oluncada yarı kırmızı rengi olsun. Faydasını görürsün. SOnra diğer renkelerede aynı şekilde orantılı olarak 0-100 sınırı içinde renk değerlerini verirsin. Bu şekilde hem matematik daha hızlı yapılır hemde aşma taşma olma ihtimali sıfıra düşer.

Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

pea

R-G-B değişkenlerim 255'i aşmıyor ki.
Deger-513 yaptığım yerde deger değişkeninin 639'dan büyük olması ön koşulu var.Yani R=640-513=127 olacak.

Yoksa mikroişlemcinin çalışma mantığı şu şekilde mi ; R önce 640'a eşitleniyor , sonra 513 çıkarılıyor.Böyleyse taşma olur haklısınız.

Diğer bir olasılıkla da Select Case'in düşündüğüm mantıkta çalışmaması.Uygun aralık bulunduğunda diğer karşılaştırmaların yapılmadığını biliyorum.Yani ADC'den okunan 900 diyelim , ilk karşılaştırmadaki(>767) işlemleri yapıp Select Case'ten çıkması gerekiyor.Yoksa bu da mı böyle değil?

Önerileriniz için teşekkür ederim ama çözünürlüğü 100 yerine 32 yapmamın nedeni dahili osilatör kullanmak istemem.100 yapınca 14Hz'lik sinyal alıyorum ve göz algılıyor.

ete

Select Case komutu istediğin gibi çalışır. Ancak yinede mantık hataları olduğunu düşünüyorum. Beraberce inceleyelim;
select case deger 
case is >767                                   'mor-beyaz
    R=32
    deger=deger/2
    G=deger-256 : G=G/8
    B=32 
case is >639        'pembiş mor
    R=deger-513 : R=R/8
    G=deger-640  : G=G/8
    B=deger-513   : B=B/8
case is >511         'mavi pembişimsi 128
    R=deger-512 : R=R/8
    G=0
    B=767-deger : B=B/8
case is >383     'yesil-mavi aralığı 128
    R=0
    G=511-deger : G=G/8
    B=deger-384 : B=B/4
case is >255           'sarı-yesil aralığı 128
    R=383-deger  : R=R/4 
    G=511-deger  : G=G/8 
    B=0   
case is > 0     'kırmızı-sarı aralığı 256
    R = 32
    G = deger/8
    B = 0
end select

Öncelikle hemen belirteyim Case is... şeklinde bir kullanım görmedim ve açıklamalarda da böyle bir kullanım şekli yok.
Şayet çalışıyorsa diyecek lafım yok ama doğru kullanım şekli;
Case Deger>767 şeklindedir. Her neyse gelelim mantık hatalarına;
İlk Case seçeneğin Deger değişkeninin 767 den büyük olma durumu Yani Deger>767 ise; R-G-B ye değerler atamışsın.
Program bu satırları icra eder ve hemen alt satıra geçer. Orada;
Case Deger>639  şartı yer alıyor. Diyelimki Senin Deger değişkeninin aldığı değer 830 olsun.
Bu değeri ilk Case karşılaştırmasına uyuyor ve buna bağlı olarak RGB değikenleri değer alır. Program Alt satıra geldiğinde ise 830>639 olduğundan bu sefer ikinci şarta da uyar ve RGB değerleri burada değişir ve yeni değerler alırlar.
Anlayacağın aşağı indikçe deger değişkeni şartları karşıladığı için sürekli değeri değişecek ve en son uyan kimse ona uygun olarak değer alacaktır.
Buradaki hata Case sorgulamasının yerlerinin yanlış olmasıdır.
Yada sorgulama mantığının yanlış olmasıdır.
Şayet Deger değişkeninin aldığı değere bağlı olarka bir iş yapmak istiyorsan aralık vermek zorundasın. Örnek vermek gerekir ise
Case deger>512 and Deger<639  gibi bir şey verirsen yalnızca bu aralıktaki değer için RGB değişkenleri set edilir. Aksi halde karmakarışık bir durum ortaya çıkmaktadır.
Yada şöyle yapman gerekir.
Case deger<255
......
GOTO CIK
Case deger<512
...
Goto CIK
şeklinde devam eder. CIK etiketi ise END SELEC komutunun olduğu satır olacaktır. Böylece yalnızca ilgili satırlar çalışacak program diğerlerine bulaşmayacaktır.

Ete

Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

pea

#321
Select Case düşündüğüm gibi çalışmıyormuş , bunu öğrenmiş olduk :)
MicroCode Studio'nun help bölümünde IS kullanıldığı yazıyor , o yüzden böyle yaptım.
The variable used in all of the comparisons is specified in the SELECT CASE statement. Each CASE is followed by the statements to be executed if the CASE is true. IS may be used to specify a comparison other than equal to. If none of the CASEs are true, the statements under the optional CASE ELSE statement are executed. An END SELECT closes the SELECT CASE.


PBP'da "Elseif" komutu var mı acaba?Bazı yerlerde var , bazı yerlerde yok deniyor.Select Case yerine if-elseif döngüsü yapmıştım , Microcode Studio hata vermemişti.

Ekleme : Select Case'i düzeltip denedim.Yine hala aynı sorun var.Kesme'deki hesaplar yanlış ama neden?

ete

Derlerken hata vermiyor ama doğru derlediğinide sanmıyorum. Sen yinede dediğim şekilde kullanmaya bak.
MCS de komut üzerine gelip F1 tuşuna basarsan komut açıklaması ekrana gelir. EN hızlı bu şekilde formatları öğrenebilirsin.

Basic de IF THEN ELSE var ancak ELSEIF komutu yok. Yok derken kullanım formatı farklı Şöyle kullanabilirsin.
IF DEGER>239 THEN
   R=23
ELSE
  IF B=47 THEN R=75
ENDIF
Burada Deger 239 dan büyük değil ise ELSE satırından sonrakiler değerlendirilir.

Case kısmını düzelttim hala hata var diyorsun. Kodu göreyim.!!

Hatanı kolayca görebilmen için değişken değerlerini takip etmende yarar var. Muhtemelen isis de çalışıyorsun.
Değişkenlere değişken adresi olareak 56 dan başlayarak byte lar için tek adres word leri için çift adres ver.
Mesela,
Deger var word 56
R        var byte  58
G        var byte 59
sonra bu adresleri İsis de kullanarak değişkenlerin programın çalışması esnasında aldığı değerleri izleyebilirsin.
Muhtemelen hesap hatasınıda bu yolla bulabilirsin. İsis de yapman gereken şey;
Pause tuşuna basarak programı çalıştır. Yukarıda yer alan Debug menüsüne tıkla ve açılan pencerede aşağıda yer alan Watch Window seçeneğini seç. Ekrana bir bilgi penceresi açılacaktır. Üzerine sağ tıkla ve açılan pencerede "Add Items by Address " seçeneğini seç.
Açılan pencerede Name kısmına değişken adını gir altındaki address kısmınada verdiğin adresi yaz. Birden fazla değişken adını aynı şekilde ilave et. Programı çalıştırdığında bu değişkenlerin aldıkları değerleri artık izleyebilirsin. Değeri çok hızlı değişen değişkenleri isis yetiştiremediği için yazmayabilir.
Kolay Gelsin
Ete

Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

pea

#323
Isis'teki debug'ın nasıl olduğunu merak ediyordum , çok iyi oldu teşekkürler.
Kodda pek değişiklik olmadığı için forum dolmasın diye koymamıştım :) Kodun son hali şöyle :
@ __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF

DEFINE OSCCAL_1K 1  'bu komut mutlaka olacak OSCCAL değerini yeniden pice yazdırıyor

TRISIO = %000001    'GP0/AN0 input , gerisi output 
CMCON = 7           
ADCON0=%10000001  'Vdd referans , AN0 analog kanalı , A/DC bitik , modül çalışıyor 
ANSEL= %00110001  'RC osilatör clock , AN0 analog giriş
INTCON=%10100000   'interrupt etkin , timer kesmesi etkin
OPTION_REG =%00000000             ' timer osilatörü dahili

define ADC_SAMPLEUS 20
DEFINE   ADC_BITS   10
DEFINE   ADC_CLOCK   3

deger var word 56
R var byte    58
red var byte    59
G var byte        60
green var byte      61
B var byte            62
blue var byte           63
led0 var gpio.1       'led0=GP1
led1 var gpio.2       'led1=GP2
led2 VAR gpio.4

GPIO = %010110
R=0 : G=0 : B=0
red=0 : green=0 : blue=0
Pause 50

on interrupt goto kesme

dongu:

adcin 0 , deger        'deger değişkenine AN0'dan gelen değeri ata

select case deger 
case deger >767                                   'mor-beyaz
    R=32
    G=deger/16 : G=G-32
    B=32 
case deger >639 and deger <768       'pembiş mor
    R=deger-513 : R=R/8
    G=deger-640  : G=G/8
    B=deger-513   : B=B/8
case deger >511 and deger <640         'mavi pembişimsi 128
    R=deger-512 : R=R/8
    G=0
    B=767-deger : B=B/8
case deger >383 and deger <512    'yesil-mavi aralığı 128
    R=0
    G=511-deger : G=G/8
    B=deger-384 : B=B/4
case deger >255 and deger <384           'sarı-yesil aralığı 128
    R=383-deger  : R=R/4 
    G=511-deger  : G=G/8 
    B=0   
case deger < 256     'kırmızı-sarı aralığı 256
    R = 32
    G = deger/8
    B = 0
end select

goto dongu

disable
kesme:

red=red+1
if (led0=1 and red=R) or (led0=0 and red=32-R) then
led0=1-led0
red=0
endif

green=green+1           
if (led1=1 and green=G) or (led1=0 and green=32-G) then
led1=1-led1
green=0
endif 

blue=blue+1
if (led2=1 and blue=B) or (led2=0 and blue=32-B) then
led2=1-led2
blue=0
endif

TMR0=150
intcon.2=0
resume
enable
end


Isis'teki debug sonucunda R ve B değişkenlerinin 32'de sabit kaldığını , G değişkeninin yazılan işleme girdiğini ancak X ve X-32 gibi değerler aldığını gördüm.Yani Select Case döngüsünün ilk adımı olan >767 durumunda takılma var , daha ileri gitmiyor.
Bir de kesme içerisindeki red , green , blue değişkenleri negatif değerler de dahil olmak üzere sürekli değişiyor.Negatife gitmesinin mantığını ve nasıl engelleneceğini çözemedim.

Ekleme : kesme içerisindeki değişkenler,  if ifadesine girerken 0'a eşit olamayacağı için taşmaya neden oluyor.Düzgün bir yöntem düşünmeye çalışıyorum , daha bulamadım.
Ekleme2: Duty değerlerine 1 ekleyerek kısmen çözüm bulmuş oldum.Tabi bu şekilde asla %0 Duty'ye ulaşamayacağım ama hiç çalışmamasından iyidir ::)
Select Case'te ise sürekli ilk duruma giriş devam ediyor.

ete

Kod da bu sefer bir hata göremedim. Her şey mantıklı gözüküyor. Tabiiki program mantığına henüz %100 hakim değilim.
Aslında bana dosyalarıda yollasan simulasyonda bende baksam. Belki bir şey yakalarım diye düşünüyorum.
Bu arada PBP da eksi sayı yoktur. Sayılar işaretsizdirler. Eksi çıkacak bir işlemde sonuç şöyle hesaplanır.
A=12-45 diye bir hesap işleminde 12 sayısında 45 çıkartılırken 12 den geriye 45 basamak gidilir. 13. basamakta sayı sıfırlanır. ve sonuçta A=223 olur. (45-12=33 A=256-33=223)
Bu nedenle aritmetikişlemlerine dikkat etmek gerekiyor.Şayet büyükten küçük sayıyı çıkartırsanız sorun yok ama küçük sayıdan büyük sayı çıkartırsanız sonuç beklediğiniz gibi çıkmaz.

Ete

Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

pea

Select case gerektiği gibi çalışmadığı için küçükten büyüğü çıkartma sorunu oluyor.
Birkaç gündür bu program takıntım oldu.Okuldan verilen ödevleri yapmaz oldum sırf bu yüzden ::)
Dosyaları hemen yolluyorum , ilginiz için çok teşekkür ederim.

pea

Sanırım Select Case ifadesinin ortasında timer'dan kesme geldiği için sorun çıkıyordu ve değişkenler ait olduğu aralıklardaki değerleri almıyordu.
Ben de Select Case'den önce bir if sorgusu koydum , okunan değerde değişim yoksa boşuna select case'e girmiyor.Böylece Isis simülasyonu doğru çalışmaya başladı.
Ancak devreye yerleştirince analog giriş sadece 0V ya da 5V olunca doğru çalışıyor.Bunların dışındaki değerlerde led'ler 'titriyor' , örneğin mor renk almam gerekirken pembe-mor-beyaz arası gidip geliyor.
Bu da sanırım potansın az da olsa oynaması durumunda ölçüm değiştiği için tekrar o select case sorununun başlamasına neden oluyor.

Ufacık bir devrede amma sorunla karşılaştım yahu :/

Kodun son hali bu arada :
@ __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _PWRTE_ON & _MCLRE_OFF

DEFINE OSCCAL_1K 1  'bu komut mutlaka olacak OSCCAL değerini yeniden pice yazdırıyor

TRISIO = %000001    'GP0/AN0 input , gerisi output 
CMCON = 7           
ADCON0=%10000001  'Vdd referans , AN0 analog kanalı , A/DC bitik , modül çalışıyor 
ANSEL= %00110001  'RC osilatör clock , AN0 analog giriş
INTCON=%10100000   'interrupt etkin , timer kesmesi etkin
OPTION_REG =%00000000             ' timer osilatörü dahili

define ADC_SAMPLEUS 50
DEFINE   ADC_BITS   10
DEFINE   ADC_CLOCK   3

deger var word 56
degerkontrol var word
R var byte    58
red var byte    59
G var byte        60
green var byte      61
B var byte            62
blue var byte           63
led0 var gpio.1       'led0=GP1
led1 var gpio.2       'led1=GP2
led2 VAR gpio.4

GPIO = %010110
R=0 : G=0 : B=0
red=0 : green=0 : blue=0
Pause 50

on interrupt goto kesme

dongu:

adcin 0 , deger        'deger değişkenine AN0'dan gelen değeri ata
if deger=degerkontrol then 
goto cik
else
select case deger  
case is < 256     'kırmızı-sarı aralığı 256
    R = 33
    G = deger/8 : G=G+1
    B = 1 : goto cik
case is <384           'sarı-yesil aralığı 128
    R=383-deger  : R=R/4 : R=R+1
    G=511-deger  : G=G/8 : G=G+1
    B=1 : goto cik
case is <512    'yesil-mavi aralığı 128
    R=1
    G=511-deger : G=G/8 : G=G+1
    B=deger-384 : B=B/4  : B=B+1 : goto cik
case is <640         'mavi pembemsi 128
    R=deger-512 : R=R/8 : R=R+1
    G=1
    B=767-deger : B=B/8 : B=B+1 : goto cik
case is <768       'pembe mor
    R=deger-513 : R=R/8 : R=R+1
    G=deger-640  : G=G/8 : G=G+1
    B=deger-513   : B=B/8 : B=B+1 : goto cik
case is <1024                                   'mor-beyaz
    R=33
    G=deger/16 : G=G-31
    B=33 : Goto cik
Cik:
degerkontrol = deger
end select
endif

goto dongu

disable
kesme:

red=red+1
if red=R and led0=1 then
    led0=0
    else
        if red=34 and led0=0 then
        led0=1
        red=0
        endif
endif 

green=green+1           
if green=G and led1=1 then
    led1=0
    else
        if green=34 and led1=0 then
        led1=1
        green=0
        endif
endif 

blue = blue+1
if blue=B and led2=1 then
    led2=0
    else
        if blue=34 and led2=0 then
        led2=1
        blue=0
        endif
endif 

TMR0=100
intcon.2=0
resume
enable
end

ete

İf sorgusunu şöyle değiştir.
if deger=degerkontrol then 
goto Dongu
else
select case deger  
....

Ayrıca bütün register değerlerini 8 bit üzerinden ver. Yani  TRISIO = %000001  yerine TRISIO = %00000001 ,
GPIO = %010110  yerine GPIO = %00010110  şeklinde vermelisin.
Bunlar hata değil kusur. Aynı kapıya çıkıyor ama elin böyle alışsın .
Başka bir hata göremiyorum.

Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

pea

Port 6 giriş çıkışa sahip olduğu için 6bit olarak yapmıştım.Artık 8 bit olarak yaparım.Ama farkı olur mu diye merak etmiyor da değilim.
Dediğiniz if sorgusu daha doğru oldu , haklısınız.
Bir de derlerken şu uyarıyı veriyor , bu nedir acaba?Gereğinden yüksek değer verdiğim bir şey de göremiyorum.
"Warning[202] ~~.mac 109 : Arguement out of range.Least sigificant bits used."

ete

#329
Hata mesajını anlamadım. İlk defa görüyorum bu mesajı.
Çözersem bildiririm.

Ete

Edit: Şimdi derledim sorunsuz derlendi. Sen MPASM de derliyorsun sanırım. Makinan 64 herhalde.
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com