analog dijital dönüşümü

Başlatan nuwanda, 26 Ağustos 2006, 14:48:26

nuwanda

cc5xte analog dijital dönüşümü nasıl yapılıyor ? assembly ile mi yazıyoruz yoksa o kısmı ? yani mesela bir pot ile bir led'in yanıp sönme hızını ayarlamak istesem ne gibi birşey yazmam gerekiyor.amatörlüğüm için kusura bakmayın , yardımcı olursanız sevinirim.  :roll:

freewalks

Merhabalar

tam emin değilim ama bu sekilde fazla cevap alamazsın çünkü sıkça sorulan birsey..

ilk önce arama filan yapsan ii olur,belki yapmısındır ama, önceden tartısılmıs bir konu olabilir..

kolay gelsin..

picusta

Kusura bakma cevap vermek için biraz (çok) geciktim. CC5X standart C'ye yakin oldugu için pot komutu oldugunu sanmiyorum. CCS(built-in olarak) veya Basic kullaninca tabii bu fonksyon var.

PIC16F877 ve kardesleri için ben fonksyonumu kendim yazdim, yaptigim tek sey datasheet'eki ASM kodu C'ye çevirmek oldu. Asagida verdigim kodda açiklamalari biraz abartmisim, verdigim sayfa numaralari 16F877 datasheet'inden.

//**********************************************************************
//potansyometrenin konumunu sayisala çevir :
//belirtilen portaki gerilimi ölçer ve sayisala çevirir.
//**********************************************************************

uns8 Potansyometre_voltaji(uns8 port){

	uns8 i;	
	
	// (ADCON0) Hangi pinden ölçüm yapilacagini seçer bkz. sayfa 127
	if (port==1) CHS0 = 0;	
	else CHS0 = 1;
	// A/D çevrimini yapmak için saati ayarlar.(ADCON0)
	ADCS0 = 1;	// 					0 0 : FOSC/2  ;  0  1  : FOSC/8
	ADCS1 = 1;	//  1 1 :Frc
	ADON = 1;	// A/D yi aç
	for (i=0;i<30;i++) nop(); // birkaç mikro saniye bekle (Tacq sayfa 130)
	GO = 1;		// A/D	BASLA!!!!!
	while(GO==1);   // A/D 'nin bitmesini bekle
	ADON = 0;	// A/D yi kapa
	return ADRESH;
}

nuwanda

Ben de cevap vermek için geciktim ama yaz ayları sonuçta olabiliyor böyle şeyler : )
       Öncelikle teşekkür ederim verdiğiniz cevap için ama birkaç ufak tefek sorum daha olacak...Ben pic programlamaya cc5x ile başladım sayılır yani Orhan Altınbaşak'ın "Mikrodenetleyiciler ve Pic programlama " kitabını okudum ama pek fazla uygulama yapmadım  , yani assembly bilgim de var biraz.Kısaca amatörüm o yüzden çok basit ve saçma sorular da sorabilirim kusura bakmayın : )

16f877 datasheet'inden ben de inceledim analog/dijital dönüşümünü ama pek fazla anlamadım..

nyse fazla uzatmayayım ;

uns8 Potansyometre_voltaji(uns8 port){
burda fonksiyonun parametre olarak aldığı "port" değişkeni main fonksiyonundaki neye karşılık gelmektedir ?"

return ADRESH;
bu return ettiğimiz değer şimdi dijitale çevrilmiş bir sayıyı mı ifade etmektedir bize ? zaten bu adresh - adresl olayını pek anlayamadım..şimdilik bu kadar sanırım sorularım..cevaplarınız için şimdiden teşekkürler , iyi çalışmalar ;)

picusta

Bence CC5X ile baslamakla iyi etmissin. Daha çok elektronikçimisin, programcimi? C'yi daha önce kullandinmi?
asm'in nasil çalistigini anladiktan sonra, bende PIC'i CC5X ile programlamaya basladim. Bende amatörüm, PIC ile hiç profesyonnel devrem olmadi (gerçi iki kere olacakti nerdeyse).

Burdaki "port" PARAMETRESI aslinda A/D çevrim yapilacak bacagi (pin) seçer.
Main'de fonksyonu çagrirken bu parametreye 8 bitlik bir sayi verebilirsin. fakat su anki versyonda sadece 1 ve 0'i kullanmani tavsiye ederim.
MAIN

uns8 okunandeger;

....

okunandeger = Potansyometre_voltaji(1); // AN0'dan okuma yapar


Dikkat ettiysen port parametresi ile CHS0'i degistiren bir kosul var.
ADCON0 yazmacinin içindeki bu bit "channel"'i (çevrim yapilacak bacagi) seçiyor, nasil mi seçiyor?
Kodda sayfa numarasini yazdigim için bulmam pek zor olmadi:
16F877A datasheet'i:
http://ww1.microchip.com/downloads/en/DeviceDoc/39582b.pdf

Sayfa 127, ADCON0 yazmaci:
Alıntı Yapbit 5-3 CHS2:CHS0: Analog Channel Select bits
000 = Channel 0 (AN0)
001 = Channel 1 (AN1)
010 = Channel 2 (AN2)
011 = Channel 3 (AN3)
100 = Channel 4 (AN4)
101 = Channel 5 (AN5)
110 = Channel 6 (AN6)
111 = Channel 7 (AN7)
Note: The PIC16F873A/876A devices only implement A/D channels 0 through 4; the
unimplemented selections are reserved. Do not select any unimplemented
channels with these devices.

Gördügün gibi channel'i seçmek için sadece CHS0 kullanilmiyor, CHS2, CHS1,CHS0 3 bit olusturuyor, ve böylece 0'dan7 olan channeller seçiliyor.
Fakat kodda ben ne yapmisim? sadece CHS0 degistirmisim.
  // (ADCON0) Hangi pinden ölçüm yapilacagini seçer bkz. sayfa 127
   if (port==1) CHS0 = 0;   
   else CHS0 = 1;

Yani port parametresi sadece AN0 ve AN1 bacagi seçebiliyor sadece. demekki kodu yazarken biraz hizli yazmissim, ve o sirada sadece 2 girise ihtiyacim varmis.
Eger anladiysan, senden istedigim sey bu koddu gelistir ve böylece sadece 2 bacaktan değil, 8 bacaktan okuma yapabilsin (port parametresinin degerine göre AN0 ... AN8 bacagindan).  

ADRESH ADRESL : AD isleminin sonunda, çevrebirimi (AD'yi yapan çipin içindeki devre) sonucu bu yazmaçlara yazar. PIC'te bulunan ADC 10 bit. Fakat her yazmaç 8 bit. Demekki 10 biti yazmak için 1 yazmaç yetmiyor 2 yazmaç kullanmak gerekir. Bazi konfigürasyon bitleri sayesinde (ADFM) ilk 8 bit ADRESH'a mi ADRESL'e mi yazilacak belirlenir. Bir resetten sonra sonucun ilk 8 biti ADRESH'a yazilir. Anlayacagin, burda AD bitiminde, fonksyonumuz AD sonuç yazmacinin ilk 8 bitini gönderir.
Kendini gelistirmek için bu fonksyonu gelistir, birde 10 bitlik (16 bitlik degiskende) sonuç göndereni yaz.

nuwanda

Bölümüm elektrik-elektronik ama yazılımla aram daha iyidir açıkçası.Zaten cc5x seçmemin nedeni C ve C++ ile aramın çok iyi olmasıydı.Benim de profesyonel devrem olmadı , okulumun robot topluluğuna üyeyim , oradakilere uyum sağlayabilmek için bir an önce pic'te ilerlemek istiyorum : ) herneyse...

okunandeger = Potansyometre_voltaji(1); // AN0'dan okuma yapar
tam olarak ihtiyacım olan satır buydu zaten , şimdi bu okunan değer analog bir gerilimin dijital olarak ifadesinin saklandığı değişken oluyor sanırım...

Channel seçme olayını da gerçekten güzel anlatmışsın , şu an şehir dışında olduğum için internet cafeden giriyorum ve burdaki ortam nedeniyle bazı şeyleri tam olarak anlayamadımsa da , çalışma odamda anlayacağımdan eminim : )

Haftaya evime döndüğümde dediğin gibi 8 bacaktan nasıl okuma yapabileceğimle ilgili bir kod örneği yazmayı deniyeceğim..

Bu arada şimdi 8bit'e kadar okuma yazdığımızda değer ADRESH'a yazılıyor , 8 bitten sonrası için ise ADRESL kullanılmaya başlanıyor..Bunu doğru anlamış mıyım ? O zaman hem ADRESH hem de ADRESL kullandığımızda fonksiyondan 2 değer geri göndermemiz gerekicek o yüzden de pointer kullanıcaz sanırım , fazla atıyor olabilirim ama sadece yazılı bir biçimde düşünüyorum : )

Şu an uygun bir çalışma ortamım olmadığı için söylediklerini deniyemiyorum ama haftaya deneyip sonuçlarını burada paylaşacağımdan emin olabilirsin.Cevaplar için teşekkür ederim tekrar tekrar : )

picusta

Alıntı YapBölümüm elektrik-elektronik ama yazılımla aram daha iyidir açıkçası.Zaten cc5x seçmemin nedeni C ve C++ ile aramın çok iyi olmasıydı.
Benim 2-3 yil önceki halimi hatirlatti.
Anladigin üzere fonksyonumuz 8 bitlik veri gönderiyor (0 ile 255 arasinda bi deger) Bu degerde ADC çevrimine denk geliyor. NAsil mi? Referans voltajina göre tabii, örn ref voltaj 5V ise, ADC ucunda 2V verirsek, okuyacagimiz deger : 255 * 2/5. 10 bitlik çevrimde ise, 1023 * 2/5.

Degeri istersen pointer olarak gönder. O zaman pointerin pespese 2 registere point edecek. Buna ne gerek var peki? Fonksyonumuz dogrudan 16 bitlik bir deger gönderse olmazmi? iki 8bitlik yazmaci birlestirip 16 bitlik bir degisken olusturmayi C otomatik yapar. ADRESH ve ADRESL'deki degerler  aslinda   LSB ve MSB karsiligidir.
sonuç = 8*MSB + LSB
AD yaparken son bir tavsiyem var, oda ölçüm gürültüsünden etkilenmemek için, pespese AD yap, topla sonra ortalama al. örnegin pesepese 4 deger al topla sonra 4'e böl (not: 2'nin kuvvetindeki bir sayi ile bölmek kolaydir)

nuwanda

Alıntı YapBenim 2-3 yil önceki halimi hatirlatti.
Umarım 2-3 yıl sonra sizlerin seviyesine yetişmiş olurum ;)

Şimdi o zaman ben şöyle bir program yazmış olsam , bir pot'tan gelen değerlere göre 8 tane ledi farklı şekillerde yakıcak bir program işte..şöyle birşey ;

#include <16F877.h>
uns8 pot_oku(uns8);
void main()
{
          ADCON1=0x01;               //AN3 Vref girişi,gerisi analog (sanırım :)
          TRISA=0xFF;
          TRISB=0;
          while(1)
                    PORTB=pot_oku(0);
}


"pot_oku" fonksiyonu da senin yazdığın fonksiyon olarak yazarsak sence bu program çalışır mı ? şu an kafadan yazdım yani deniyebileceğim veya simulasyon yapabileceğim bir ortam yok maalesef.Bu programda dediğin gibi peşpeşe 4 Ad yapıp ortalama almadım ama onu da yaparım daha sonra, sadece temel olarak böyle birşey mi ?

Ben sadece bu adc fonksiyonunu geliştirmeden önce , çalışma şeklini tam olarak kavramak istiyorum , o yüzden uygulamalı bir örneğe ihtiyacım var o yüzden yukardaki programı yazdım.Hatalarımı düzeltip çalışana en yakın hale getirirsen eğer çok sevinicem..Yardımların için çok teşekkürler, eminim bu sayfa benim gibi başka arkadaşlara da yardımcı olacaktır.

nuwanda

Tamamdır , tam olarak istediğim programı yazdım..Picusta'ya burdan sonsuz teşekkürler.Eve dönünce programı düzenleyip burda da yayınlarım.Ben bu kadar süründüm başkası sürünmesin : ) gerçi en iyi öğrenme yöntemi de bu ama...iyi günler , iyi çalışmalar ;)

Bu akşam da PWM'e başlamayı düşünüyorum , yarın sorularımla beraber tekrar burdayım : )