12f675 ile analog girişe bağlanan 10k lık bir potansiyometre

Başlatan . Kağan, 23 Kasım 2013, 18:17:32

. Kağan

675'e bağlayacağım bir led'i, 12f675'in analog girişe bağlanan 10k lık bir potansiyometre ile ayarlanabilen aralıklarla (5-180 sn) yakıp söndürmek istiyorum. Yani pic'e enerji verdikten sonra yanıp sönmeye başlamalı, aralıkları ben pot ile ayarlamalıyım. Potansiyometreyi okutmak için nasıl bir kod kullanmam gerekir. TEŞEKKÜRLER

ete

Basla:
Adcin 0, ham
Adc kanalını okuma komutudur. Burada sıfır an0 kanalını okumak için yazılmıştır. An1 için Adcin 1, ham yazılması gerekir. 10 bitlik bir okuma yapıldığını var sayarsak,
Kanaldan sıfır değerini okursak yani minimum değer yanma süresi 5 sn , kanaldan 1023 okunduğu zaman ise 180 sn yanma süresi olacaktır.  Ohalde formülü şöyle oluşturabiliriz.
Min değer 5 sn olacağına göre bunu 180 den çıkarmak gerekir. Sabit çarpan, 175/(1023+1)=0,171
Bunu 256 ile çarparak */ çarpımı kullanabiliriz. 0,171*256=43,75  bunu virgülden kurtarmak için 100 ile çarparız 4375 buluruz. Böylece formül. Sure=((ham+1)*/4375)/100+5
Bu formül okunan adc değerine bağlımolarak bize 5-180 arasında bir değer hesaplar.
Geriye bunu program gecikmesine bağlamak kalır.  Bulunan sayı saniye cinsindendir. Bunu ms ye olarak hesaplarsak 180.000 ms eder. Bir döngü ile 10 ms lik dilimler kullanırsak 18.000 lik bir döngü işimizi görecektir.  O halde hesaplanan gecikmeyi sağlamak için şöyle bir döngü kullanabiliriz.
Önce formülümüzde ufak bir tadilat yapalım. Formülü,
Sure=((ham+1)*4375+500 şeklinde kullanırsak maksimum değerimiz 18000 olarak hesaplanacaktır.
Hemen deneyelim. Okunan değer 1023 olacaktır. Sure=(1023+1)*4375/256+500=18.000 olarak bulunur. Pic matematiğinde */ 4375 işleminin normal matematik karşılığı sayı * 4375/256 şeklindedir   
Şimdi döngümüzü kuralım,
For I=0 to sure
   Pause 10
Next
Bize hesaplanan süre kadar saniye bekleme süresi sağlar. Aslında süre biraz fazla tutabilir bu nedenle pause 10 yerine pause 8-9 gibi bir değer kullanmak daha hassas bir süre sağlayabilir.

Tabiiki döngüden evvel led=1 komutu ile led yakılmalı
Sonra gosub gecikme deyip program döngüye yönlendirilmeli ve ardından led=0 komutu ile led söndürülmeli ve ardından yine program gosub gecikme ile döngüye yeniden yönlendirilmelidir.
Sonunda goto basla denilerek aynı işlemler en baştan tekrarlanmalıdır.
İşin nasıl olacağını detayları ile verdim sana düşen bunu program haline getirmek.

Ete


. Kağan


. Kağan

#3
AŞAĞIDAKİ KODU YAZDIM

                                       
@ device pic12F675 & WDT_OFF & PWRT_ON & PROTECT_OFF & MCLR_OFF & INTRC_OSC_NOCLKOUT 

DEFINE OSCCAL_1K 1 
DEFINE OSC 4
DEFINE ADC_BITS    10                 'A/D  çevirim sonucu kaç bit olacak
DEFINE ADC_CLOC   3                   'Clock  kaynağı (3=rc)
DEFINE ADC_SAMPLEUS  100 

CMCON = 7
ANSEL = %00010001
ADCON0=%10000000
GPIO=0
TRISIO=%00001001
WPU=0

ham var byte
sure var byte
                     
adcin 0, ham

GPIO.0=0
GPIO.1=1    'LED YAK

BASLA:
     For I=0 to sure
     Pause 10
Next
     GOSUB yak    'yak etiketine git ve RETURN komutu ile geri gel
     GPIO.1=0     'LED SÖNDÜR
     GOTO BASLA   'baslangic etiketine git

yak:
     Sure=((ham+1)*4375+500   'SÜREYİ HESAPLA
     RETURN                   'GOSUB komutu ile  geldiği yere git

END


FAKAT "sure, NEXT ve sure hesapla satırlarında hata veriyor.
Nerede mantık hatası var acaba?

MS_59

I değişkeni tanımlı değil    I VAR WORD
diğer değişkenlerde word olacak
SURE satırında parantezi kapatmamışsın birde adc okuma kısmı ana programda olacak

eksikler şimdilik bu kadar
mehmet

ete

Algoritma sıralamasına pek dikkat etmemişsin.
Bir defa her şey Basla satırından sonra başlamalı. Öncesinde koyduğun komutlar bir kereliğine çalışır.
Basla satırından evvel pause 200 gibi birde gecikme vermelisin.
Adc okuma ve formül uygulama için alt programa gerek yok ama toplam 3 satırdan oluşan gecikme için alt programa yazma bendce daha gerekli.
Sistem şöyle olmalı,
Basla:
Adc oku
Sure formülü ile süre hesaplanmalı
Led yakılmalı
Gosub zaman deyip gecikme döngüsüne gidilmeli
Led söndürülmeli
Gosub zaman deyip yeniden gecikme verilmeli
Goto basla deyip aynı işlemler tekrarlanmalıdır.
Proteus un verdiği eksiklikleride tamamla ve programı dediğim sırada yeniden yaz bakalım. Unutma bütün değişkenlerin WORD tipinde olmalı. Byte değişkenleri 0-255 arası değerler alabilir. Ama word 0-65535 arası değer alır.
Ete

. Kağan

KODU AŞAĞIDAKİ ŞEKİLDE DEĞİŞTİRDİM.
                                        
@ device pic12F675 & WDT_OFF & PWRT_ON & PROTECT_OFF & MCLR_OFF & INTRC_OSC_NOCLKOUT 

DEFINE OSCCAL_1K 1 
DEFINE OSC 4
DEFINE ADC_BITS    10           'A/D  çevirim sonucu kaç bit olacak
DEFINE ADC_CLOC   3             'Clock  kaynağı (3=rc)
DEFINE ADC_SAMPLEUS  100 

CMCON = 7
ANSEL = %00010001
ADCON0=%10000000
GPIO=0
TRISIO=%00001001
WPU=0

ham var WORD
sure var WORD
I VAR WORD       

GPIO.0=0
GPIO.1=1
PAUSE 200

BASLA:
adcin 0, ham              'ADC KANALINI OKU
Sure=((ham+1)*4375+500)   'SÜREYİ HESAPLA
     GPIO.1=1             ' LEDİ YAK
     For I=0 to sure      ' "0" DAN SUREYE KADAR SAY
     Pause 8              ' 8 ms BEKLE
Next                      ' TEKRARLA

     GOSUB ZAMAN    'ZAMAN etiketine git ve RETURN komutu ile geri gel
     GPIO.1=0       'LED SÖNDÜR
     GOTO BASLA     'baslangic etiketine git

ZAMAN:
     PAUSE 100
     RETURN          'GOSUB komutu ile  geldiği yere git

END


Mikro Code Studio ile derlediğimde
hatası alıyorum.

ete

Mcs de view menüsünü aç compile and program options seçeneğini seç ve ortada yer alan assembler butonuna tıkla. Açılan pencerede sağda yer alan use mpasm kutusundaki işareti kaldır öyle dene.
Makinan 64 bitlik bir makina ise mpasm seçili kalsın ama sigorta ayarlarının formatını mpasm ye göre ver. Format için  ,
http://etepic.com/index.php/topic,300.0.html
Konusunu dikkatlice oku.

Yine programda anlamsız işler yapmışsın. Ben döngüyü alt programa al demiştim sen pause komutunu oraya almışsın. Onuda alma direk gosub zaman yerine psuse 100 yaz olsun bitsin.
Alt program önermemin sebebi döngünün iki defa çalışacağını düşünmemdi. Sen bir defa çalıştırmışsın. O hslde alt programa gerek yok.
Ete

onurinci

DEFINE ADC_BITS    10           'A/D  çevirim sonucu kaç bit olacak
DEFINE ADC_CLOC   3             'Clock  kaynağı (3=rc)

bu iki satırda ayırma işaretlerinin yanlış olduğunu gözlemledim.
shift F2 ile basacaksın.

. Kağan

#9
Alıntı YapAlt program önermemin sebebi döngünün iki defa çalışacağını düşünmemdi. Sen bir defa çalıştırmışsın. O hslde alt programa gerek yok.
demişsiniz. Döngünün iki defa yada bir defa çalışması ne demek? Anlamadım. Çalıştırıldığında sürekli başa dönmeli ve 10K pot. çevrildiğinde sönme aralığı belirlenmeli. Yani 25 sn sonra yanıp sönmeli yada 46 sn sonra yanıp sönmeli. Bu durumda program süreli başa dönerek çalışıyor olmuyor mu?


                                       
@ __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_ON & _CP_OFF

DEFINE OSCCAL_1K 1 
DEFINE OSC 4
DEFINE ADC_BITS    10           
DEFINE ADC_CLOC   3           
DEFINE ADC_SAMPLEUS  100 

CMCON = 7
ANSEL = %00010001
ADCON0=%10000000
GPIO=0
TRISIO=%00001001
WPU=0

ham var WORD
sure var WORD
I VAR WORD       

GPIO.0=0
GPIO.1=1
PAUSE 200

BASLA:
adcin 0, ham              'ADC KANALINI OKU
Sure=((ham+1)*4375+500)   'SÜREYİ HESAPLA
     GPIO.1=1             ' LEDİ YAK
     For I=0 to sure      ' "0" DAN SUREYE KADAR SAY
     Pause 8              ' 8 ms BEKLE
Next                      ' TEKRARLA

     PAUSE 100
     GPIO.1=0       'LED SÖNDÜR
     GOTO BASLA     'baslangic etiketine git

END


Şeklinde olduğunda LED nasıl tepki verir?

NOT: Verdiğiniz linktekileri yaptım, artık derleyici hata vermiyor.

ete

Pot bir süre ayarı yapıyor. Bu süre led in yanma süresi olduğu kadar sönük kalma süresidirde. Peki sen ne yapmışsın?  Ledi yakıp ayarlanan süre kadar beklemiş sonra ledi söndürdükten sonra yalnızca 100 ms bekleyip sonra yeniden ledi yakmışsın. Bu durumda ledin sönük kaldığını göremiyorsun yada anlık sönüp yeniden yanıyordur öyle değilmi?
İki defa gecikme yada bekleme çalışacaktan kastım birinde led yandıktan sonra ikincide ise led söndükren sonra aynı süre beklemesi gerekmezmi?
Ete

. Kağan

#11
SORU 1: BEKLEME SÜRESİ

PAUSE 100   yerine
PAUSE 2000 yazsam bu durumda LED 2 sn yanık kalmaz mı? Ledin sönük kalma süresini 10K POT. ile ayarlamak istiyorum.

SORU 2: A/D giriş çıkış ayarlaması nasıl yapılır?
CMCON = 7    'Bu komutla TÜM PORTLAR DİGİTALE Mİ çevrilir yoksa Comperator işlemimi iptal edilir. İkisi aynı şey mi? Bu durum bu kurguya uyar mı?

BİR PORTUN 10K İÇİN ANALOG OLMASI gerekmez mi? Yani ADCON=7 yazamayız doğru mu?

Ayrıca ADCON0 = %10000000  ne anlatır?  'CMCON ile aynı işe mi yarar?

ete

Pause 2000 ,2 sn  lik bir bekleme yapar.  Ledin sönük kalma süresini pot ile ayarlamak istiyorsan sure döngüsünü yeniden çalıştırman gerekir. Yukarıdaki mesajlarımda bunu anlatmaya çalışıyorum. Daha nasıl anlatayım bilmemki? Bu yüzden sure dongüsünü alt program olarak hazırla ve pot kadar gecikme lazım olunca oraya gosub ile programı gönder.

Adc ayarlaması işlemcilere göre farklı olabilir. Data sheetler bu bilgileri okumanız için haxırlanıyor.
Kullandığın işlemcide bunu yapmak için.
-adc pini giriş olarak ayarlanır. TrisIo registerinden ayarlanmaktadır.  Giriş pini hangisi ise ona karşılık gelen bit "1" yapılır.
- Ansel (analog seçim) registerinin ilgili biti "1" yapılır.
- define komutları ile kaç bit analog okuma yapılacağı belirlenecek.
- adc için clock kaynağı yine define komutları ile belirlenecek.
- 10 bit okuma yağıldığında sonucun sola yaslı veya sağa yaslımı olacağını Adcon0 registeri 7 nolu biti ile ayarlanır. Bu bit 1 olursa sonuç sağa yaslı ( maksimum 1023) değeri okunur. Bit 0 olursa sonuç  sola yaslı alınır ve okunan maksimum değer 65472 olur.
Cmcon registeri yalnızca komparatör ayarlama registeridir. Adc ile alakası yoktur.
Bir işlemcide  bazı pinler hem komparatör hemde adc işini yapabilir. Kompsratör özelliğini iptal ederseniz (cmcon=7) o pinler ya analog yada digital kullanıma hazır olur. Analog özelliğini de iptal ederseniz pin digital olur.
Adcon1=7 komutu 16f877 veya 16f876 ve bazı diğer işlemcilerde analog özelliğini iptal etmek için kullanılır. Senin işlemcide bu işi Ansel=0 komutu yapar.
Adcon0.7 biti sağa yaslı veya sola yaslı adc okuma sonucu almak için kullanılır yuksrıda amlatmıştım.
Ete

. Kağan

Alıntı YapPause 2000 ,2 sn  lik bir bekleme yapar.  Ledin sönük kalma süresini pot ile ayarlamak istiyorsan sure döngüsünü yeniden çalıştırman gerekir. Yukarıdaki mesajlarımda bunu anlatmaya çalışıyorum. Daha nasıl anlatayım bilmemki? Bu yüzden sure dongüsünü alt program olarak hazırla ve pot kadar gecikme lazım olunca oraya gosub ile programı gönder.

Sevgili ETE.
Elektronik bilgim önceden olsa da, Pic programlamayı yeni yeni öğreniyorum. Senin derslerin 7. sini bitirdim. Lazım oldukça ayrıca ileri geri gidip geliyorum. Asıl mesleğim Vet. hekimlik. Bu nedenle bazı konuları sen ne kadar iyi anlatırsan anlat kafamda kurmakta zorlanıyorum. Bu nedenle bana örnek yazarak anlatırsan daha kolay anlayabilirim.

Yukarıda bahsettiğin süre döngüsünü ZAMAN: diye bir alt program yazarak tekrar çalıştırmamı anlatmaya çalışıyorsun sanırım.
Doğru yaptımmı bilmiyorum ama, Ben yinede yaptığım değişikliği aşağıya ekliyorum.

@ __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_ON & _CP_OFF

DEFINE OSCCAL_1K 1 
DEFINE OSC 4
DEFINE ADC_BITS    10           
DEFINE ADC_CLOC   3           
DEFINE ADC_SAMPLEUS  100 

CMCON = 7             'TÜM PORTLAR DİGİTALE ÇEVRİLİR. BU YANLIŞ DEĞİLMİ? BİR PORT 10K İÇİN ANALOG OLMASI GEREKMEZ Mİ?
ANSEL = %00010001
ADCON0 = %10000000    'CMCON İLE AYNI MI?
GPIO = 0
TRISIO = %00000001
WPU = 0

ham var WORD
sure var WORD
I VAR WORD       

GPIO.0=0

PAUSE 200

BASLA:
     adcin 0, ham              'ADC KANALINI OKU
     Sure=((ham+1)*/4375+500)   'SÜREYİ HESAPLA
     GPIO.1=1             ' LEDİ YAK
     Gosub zaman
     GPIO.1=0       'LED SÖNDÜR
     GOSub ZAMAN
     Goto basla

ZAMAN:
For I=0 to sure      ' "0" DAN SUREYE KADAR SAY
     Pause 8              ' 8 ms bekle
Next
Return
END

ete

Yine olmadı. Yazdıklarını düzelttim incele istersen
Ete

Powered by EzPortal