avatar_ete

ADC çevrimi ile ilgili bir tecrübe

Başlatan ete, 25 Mayıs 2013, 11:01:56

ete

Bazı projelerde ADC çevrimi kullanıyorum. Ancak nedednini henüz bulamadığım bir sebepten dolayı bazı projelerde isis sürekli şöyle bir ikaz veriyor, "adc çevrimi min acquisition süresi dolmadan yeniden başladı " benzeri bir ikaz bu. Her bir ADC çevriminin bir süre aldığını biliyoruz. Sonuçta içeride bulunan bir kondansatörün ya şarj yada deşarj süresi ölçülerek ADC digital değeri hesaplanmaktadır. Dolayısıyla kondansatörün şarj edilmesi için yeterli sürenin verilmesi gerekiyor.
Bunu aslında Basic otomatik yapması gerekirken bazı işlemcilerde bu iş aksıyor her nedense. Bu sorunu genellikle 16F88 işlemcisi ile çalışırken görüyorum. Diğerlerinde pek olmuyor diyebilirim.

Bu gün bir işle uğraşırken bu sorunla yeniden karşılaştım. Ne yaptım ise sorunu gideremedim. İki okuma arasına 100 ms sürede koysan isis yine malum ikazı veriyor idi. Sonunda data sheete dikkatlic bakmaya karar verdim.
Genelde bir ADC çevriminin (assmbly ile) nasıl yapılacağına dair bilgiler veriliyor. 116 cı sayfada bir çevrim işlemini adımlar halinde açıklamış.
Bu adımlara tek tek bakarsak;
1. ADC modülünü konfigüre et demiş. Nedir bu iş derseniz, Sırası ile,
• Configure analog/digital I/O (ANSEL)   'Ansel yani analog select registerinde  giriş pinlerini işaretle
• Configure voltage reference (ADCON1) 'referans voltajları seç genellikle besleme voltajı ref voltajı olarak seçilir.
• Select A/D input channel (ADCON0)   'hangi kanalı ölçeceki isen onu seç, ADCON0 registeri 5-3 bitleri seçiyor
• Select A/D conversion clock (ADCON0)  'ADC çevriminin hangi CLK ile çalışacağını belirle. Basicde bu Define ile seçiliyor.
• Turn on A/D module (ADCON0)   'ADC modülünü aktive et  ADCON0 registeri 0 biti bunu yapıyor.
2. Gerekiyor ise ADC kesmesini aç
3. Wait the required acquisition time.  çevrim süresi kadar bekle. İşte işin püf noktası burada imiş.!!!!!!!!!!!!!!!
4. Start conversion:
• Set GO/DONE bit (ADCON0)
5. Wait for A/D conversion to complete, by either:
• Polling for the GO/DONE bit to be cleared
(with interrupts disabled); OR
• Waiting for the A/D interrupt
6.  A/D Sonuç register çiftini oku bunlar ,(ADRESH:ADRESL registerleridir), ADIF (ADC çevrim kesme bayrağı) gerekirse sıfırla.
7. Bir sonraki çevrim işlemi için adım 1 yada 2 ye git.
Her bir ADC sonucunda elde edilen sayının her bir biti için geçen zamana TAD deniliyor.  İkinci çevrime başlamadan evvel en azından 2 TAD kadar beklemek gerekiyormuş.

Şimdi gelelim işin püf noktasına yukarıda işin püf noktası burası imiş demiştim.  Bir ADC işlemini başlattığınız zaman kanal seçer seçmez kondansatör şarj olmaya başlıyor. İşte bu aşamada en azından kondansatörün dolmasına yetecek kadar zaman beklemek gerekiyor. Beklemez iseniz kondansatör yeterince şarj olamayacağı için elde edeceğiniz ADC sonucunun hatalı olma ihtimali yüksek olmaktadır. Bu gibi durumlarda isis sizi ikaz ediyor. İşte sorun burada.
Olayı daha iyi anlamak için bir ADC çevrim işleminin safhalarına bakmak lazım.
Siz kanal seçer seçmez hemen içeride yer alan kondansatör şarj olmaya başlıyor. Sistem min şarj süresi kadar bekliyor yada beklemek zorunda. Şarj işlemi tamamlandıktan sonra çevirim işlemi başlatılıyor. Sanırım bu aşamada da deşarj başlatılıyor ve kondansatörün tamamen boşaldığı anda işlem tamamlanmış oluyor.
Bana göre bütün bunları Basic in otomatik yapması lazım. Sonuçta size bir komut vermişler  (ADCIN Kanal, Değişken)
Bu komutta şurada bekle şurada yürü diyebileceğiniz bir bölüm yok maalesef. Bu durumda elinizdeki alternatif komutu kullanmadan ADC ölçümü yaptırmak olmalı. Bende öyle yaptım. Nasılmı,? yukarıdaki safhaları takip ederek.
1. ADCON1 registerine değer vererek kaç bit okuyacağıma karar verdim  ADCON1 = %11000000 '10 Bit okuma
2. Okunacak kanalı seçtim ve ADC modülünü aktive ettim ,  ADCON0 = %01000001 ', bit sıfır modülü aktive ediyor.
3. Gerekli Şarj süresi kadar bekledim  ,        PAUSEUS 20
4. ADC çevrimini başlattım ,   ADCON0.2 = 1
5. Çevrimin bitip bitmediğini  test ettim ,     WHILE ADCON0.2 = 1 : WEND
6. Bu test aşıldığında işlem bitmiştir deyip sonucu okudum.     HAM0.LOWBYTE=ADRESL:HAM0.HIGHBYTE=ADRESH
7. Sonra formülümü kullanıp sonucu değerlendirdim. ,         SUREA= (ham0+1)*/30

Gördüğünüz gibi bir ADC okuma işlemi ADCIN komutu kullanılmadan da yapılabilmektedir.
Bu şekilde kullandığım komut sayesinde Isis ikazından kurtulmuş oldum.

Burada bir başka konuyada değinmek isterim. İşlemcilerde min ölçme süresi farklı olabiliyor. Ben ve benim gibi pek çok kişi ADC ile ilgili Define komutlarını ya bir başka programdan kopyalıyoruz yada MultiCalc isimli programdan yararlanıyoruz.
MultiCalc programı çok faydalı bir program ancak ADC parametrelerini işlemciden bağımsız veriyor. Bu nedenle genellikle sorunlar standart değerlere sahip olmayan işlemcilerde ortaya çıkıyor. Örnek verelim,
MultiCalc programında ADC seçeneğini seçip 4 Mhz de 10K lık bir kaynak empedansı olan sistem için basic tanıumlamalarını aldım. Bana şunları verdi;
DEFINE ADC_BITS 10     ' ADCIN resolution  (Bits)
DEFINE ADC_CLOCK 1     ' ADC clock source  (Fosc/8)
DEFINE ADC_SAMPLEUS 11 ' ADC sampling time (uSec)
Bu değerler 16F88 işlemci için doğru olmuyor maalesef. Zİra bu işlemcide min acquistation zaman 19,72us olarak verilmiş.
O halde ADC_SAMPLEUS değeri 11 değil 20 olarak verilmesi gerekiyor.
11 kullanırsanız simulasyon sürekli ikaz üretiyor. Ama 20 verirseniz her şey doğru çalışıyor.
Bu nedenle işlemci data sheet ine bakıp "min acquistation time" değerini bulup (genelde Analog to Digital Conversion Module kısmıda oluyor) oradaki değeri tam sayıya tamamlayıp adc_sampleus değeri olarak vermek gerekir.

Bir diğer konuda programınbaşında verilen tanımlamalara da dikkat etmek gerekir.
Yukarıda vermiş olduğum 3 satırlık komut dizisi aslında bazı ADC registerlerine değer verilerek yapılmaktadır.  Hem bunları verip hemde o registerlere de değer verirseniz ortaıl çorbaya döner. Bu nedenle şu nıoktalara dikkat edin.
- Mümkün olduğunca ADCON0 registerine değer vermemeye çalışın. Bu registerle ilgili işlemleri basic otomatik yapmaktadır. Bazı istisnalar olabilir. Sorun çıktığında data sheeti inceleyip kontrollü değer verebilirsiniz.
- Data sheet lerde o işlemcinin hangi frekanslarda hangi ADC clock değeri ile çalışacağı açıklanmıştır. Yukarıda verilen ADC_CLK parametresi bu iş içindir. Bana kalırsa işlemci data sheetine bakıp çalışılan frekansa göre bir CLK cinsi seçilmelidir.
Yine 16F88 den örnek verecek olursak, Datasheet sayfa 118 de bir tablo vermişler. Başlığında şunlar yazılı;
TAD vs. MAXIMUM DEVICE OPERATING FREQUENCIES – STANDARD DEVICES (C)
Altında frekanslara göre Tad değerleri ve bunu ayarlamak için ilgili registerin bitlerine verilecek değerler sıralanmıştır.
Diyelimki frekansımız 4 Mhz . Tabloda maksimum 2,5Mhz değeri var ve max. 5 Mhz değeri var. Tabiiki biz 5 seçeceğiz. Karşısında 8 Tosc değeri görülüyor. Yukarıdaki seçimimizde bunu göstermektedir. Ama frekansımız 20 Mhz ise 32 veya 64 Tosc değerlerinden birisini seçmemiz gerekecektir.
Bu işi yapan register ise ADCON0 ve ADCON1 registerleridir. Asıl ayarlamayı ADCON0 registeri yapıyor (16F88 için) bit7 ve bit 6 bu işi ayarlamaktadır. İşte burada şayet define komutları ile bunları ayarlamış iseniz ya ADCO0 registerinede aynı seçeneği sağlayacak değer vermeniz yada hiç dokunmamanız gerekir.

Ete


kudretuzuner

Merhaba,
Değerli bilgiler için teşekkürler.

enginkanat

Hocam mümkünse 16F88 ile ilgili basit bir uygulama ekleyebilirmisiniz? Kendim için belirteyim örnek olmadan anlayamıyorum.
ayrıca burada;
http://etepic.com/index.php/topic,1687.msg17167.html#msg17167
sigorta ayarlarından bahsetmişsiniz sağolun ancak bazı programlarda

@ __config _CONFIG1, _INTRC_IO & _WDT_OFF & _MCLR_OFF & _LVP_OFF & _CPD_ON & _BODEN_OFF & _CP_ALL & _WRT_PROTECT_ALL & _CCP1_RB3
@ __config _CONFIG2, _IESO_OFF & _FCMEN_OFF


koyu yazılı kısımlar nedir?

ete

16F88 sıradan bir işlemci nasıl bir örnek vermemi isterdin? N ekonuda örnek vereyim. Aslında örneğe bence hiç gerek yok. İşin ayarlama safhası (Programın ön ayarlar ksımı) işlemciye göre değişir. Onu açıklayayım gerisi sıradan örneklerden farkı yok zaten.
Sigorta ayarlarından başlayalım;
_CP_ALL  bu ifadenin anlamı tüm kod korumayı (Flash Program Memory Code Protection) aktif etmesidir.

_WRT_PROTECT_ALL  bu ifadenin anlamı ise tüm flash program hafızasını (Flash Program Memory Write Enable) korumaya almasıdır.

_CCP1_RB3  bu ifade, işlemcide CCP1 çıkışı seçenekli olarak PORTB.3 ile PORTB.0 pinleri arasında değiştirilebilmektedir. Buraya RB3 yerine RB0 yazarsanız çıkış RB0 dan olacaktır.

_IESO_OFF  ifadesi , genelde çift hızlı osilatör seçeneği  seçilerek ilk çalışmadaki osc nin gerğ kalması gibi sorunların ortadan kaldırılacağı söylenmektedir. Bu seçeneği pek kullanmadım. Nerede gerekir onuda bilemiyorum.
_FCMEN_OFF   Fail-Safe Clock Monitor Enable bit olarak ifade edilen bu açıklamada bazı durumlarda sistem OSC sinin çokmesi durumunda FCMEN_ON yapılmış ise sistem otomatikman RC osilatör moduna dönerek pic in çalışmasını sürdürmesini sağlamaktadır.

Bu işlemcide dahili OSC  31,25 Khz den 8Mhz kadar seçenekli olarak kullanılabilmektedir. Sigorta ayarlarından dahili OSC kullanılacak diye seçtikten sonr ayrıca OSCCON registerinden de hangi hızda çalışacağı seçilmelidir.
Mesela OSCCON=%01100000 4Mhz dahili OSC seçeneği ,  OSCCON=%1110000 8Mhz dahili OSC seçeneğidir.
Bu işlemcide ADC pinlerine Analog özelliği ANSEL registeri tarafından verilir veya kaldırılır.
ANSEL=0 vermek pinleri digital giriş çıkış pini haline getirir. ANSEL registerininhangi biti "1" olurs ao bite karşılık gelen pin analog hale gelir.

Bu işlemcide yine Comparatör pinleri CMCON=7 verilerek digital hale getirilir.
Başkada spesifik özellik yok sanırım.

Ete

enginkanat


. Kağan

Merhaba Erol bey,

16F88 de aşağıdaki sigorta ayrlarını sizin bahsettiğiniz gibi yapmama rağmen yinede "adc conversion clock period is less than min Tad=1,6msn" hatası alıyorum. Acaba nerede hata yapıyorum.
;----[16F88 Hardware Configuration]---------------------------------------------
#CONFIG
cfg1 = _INTRC_IO              ; INTRC oscillator; port I/O function on both RA6/OSC2/CLKO pin and RA7/OSC1/CLKI pin
cfg1&= _WDT_ON                ; WDT enabled
cfg1&= _PWRTE_OFF             ; PWRT disabled
cfg1&= _MCLR_OFF              ; RA5/MCLR/VPP pin function is digital I/O, MCLR internally tied to VDD
cfg1&= _BODEN_OFF             ; BOR disabled
cfg1&= _LVP_OFF               ; RB3 is digital I/O, HV on MCLR must be used for programming
cfg1&= _CPD_OFF               ; Code protection off
cfg1&= _WRT_PROTECT_ALL       ; 0000h to 0FFFh write-protected
cfg1&= _DEBUG_OFF             ; In-Circuit Debugger disabled, RB6 and RB7 are general purpose I/O pins
cfg1&= _CCP1_RB0              ; CCP1 function on RB0
cfg1&= _CP_ALL                ; 0000h to 0FFFh code-protected (all protected)
  __CONFIG _CONFIG1, cfg1

cfg2 = _FCMEN_ON              ; Fail-Safe Clock Monitor enabled
cfg2&= _IESO_ON               ; Internal External Switchover mode enabled
  __CONFIG _CONFIG2, cfg2

#ENDCONFIG


DEFINE OSC 4
DEFINE ADC_BITS 10      ' ADCIN resolution  (Bits)   
DEFINE ADC_CLOCK 1      ' ADC clock source  (Fosc/8)   
DEFINE ADC_SAMPLEUS 20  ' ADC sampling time (uSec)

ADCON1 = %10000000  ' 1024 (10 BİT) hesaplanacak, (VREF+ vref+) (VREF-AVSS)
ANSEL  = 0           ' TÜM PİNLER DIGITAL OLARAK AYARLANDI
CMCON  = 7           ' KOMPARATÖRLER KAPALI
OSCCON = %01100100   '4Mhz dahili OSC seçeneği
'OSCCON = %01101110   ' İNTERNAL OSİLATÖRÜ 4mhz' E AYARLA 
TRISA  = %00000100   ' RA2 GİRİŞ   
TRISB  = %00000000   ' HEPSİ ÇIKIŞ
PORTA  = 0           ' PORTA SIFIRA ÇEK   
PORTB  = 0           ' PORTB SIFIRA ÇEK

???

ete

#6
Bu hatanın sigorta ayarları ile alakası yok. Her bir ADC çevirim işlemi dahili kondansatörün şarj edilmesi ve deşarj süresine bakılması şeklinde belirli bir zaman alır. Özellikle deşarj süresinin (Sampling Time) ne kadar zaman alacağı işlemci data sheetlerinde belirtilir. İşlemciden işlemciyede bu fark eder.
Data sheet de bu bir hesap şeklinde verilir sonuçta us cinsinden bir belirtilir.
Bu değeri tam sayıya yuvarlayarak (hesap bazen 7,75us gibi değerler hesaplar siz bunu 8us olarak alırsınız)
kullanıyorsanız aşağıdaki komutlarda yer alan 11 rakamı yerine kullanırsınız.
16F88 data sheet de 117 ci sayfada "EQUATION 12-1" hesaplama tablosunda bu süre 19,72us olarak hesaplanmış değerin 20us olarak alınıp define komutunda kullanılması gerekir.

Böylece geri planda ADC işlemi esnasında işlemci dahili kondansatörü şarj ettikten sonra bu verilen süre kadar bekler sonra çevrim sonucunu alır. Süre rastgele verilmiş ise ve beklenenden kısa ise İsis söz konusu hatayı verir.


Programın başına yerleştirdiğimiz aşağıdaki komutlardan en alt sırada olanı bu süreyi belirlemektedir.;
DEFINE ADC_BITS 10     ' ADCIN resolution  (Bits)
DEFINE ADC_CLOCK 1     ' ADC clock source  (Fosc/8)
DEFINE ADC_SAMPLEUS 11 ' ADC sampling time (uSec)

Ete

. Kağan

Her iki şekilde de derleyip denedim aynı hatayı almaya devam ediyorum.
DEFINE ADC_BITS 10     ' ADCIN resolution  (Bits)
DEFINE ADC_CLOCK 1     ' ADC clock source  (Fosc/8)
DEFINE ADC_SAMPLEUS 11 ' ADC sampling time (uSec)

DEFINE ADC_BITS 10     ' ADCIN resolution  (Bits)
DEFINE ADC_CLOCK 1     ' ADC clock source  (Fosc/8)
DEFINE ADC_SAMPLEUS 20 ' ADC sampling time (uSec)

ete

#8
İsis in hatası da olabilir ADC ölçümü yapıyorsa fazla kafaya takmamak gerek.
Ete

Edit:
şimdi bir iki deneme yaptım ve bu sorunu yaratan sebepin, ADCON0 registerine değer verilmemesi olduğunu tespit ettim.
ADCON1 registerinden hemen önce ADCON0 registerine;
ADCON0=%01000000 değerini verip tekrar deneyin. Bu komutu eklemeden önce aynı hatayı veriyor idi. Ekleyince sorun ortadan kalktı.

Ete

Powered by EzPortal