Haberler:

Foruma Resim Yükleme ve Boyut Sınırlaması ( ! )  https://bit.ly/2GMFb8H

Ana Menü

Lm35 ve ADC0831

Başlatan vitruvius, 04 Şubat 2012, 19:00:36

vitruvius

Merhaba, daha önce Lm35 ve 16F877 ile yaptığım projeyi şimdi 16F628A ve ADC0831 kullanarak yapmak istedim. Ezbere yapmak istemedim. Datasheeti okuyarak denemeye çalıştım ama sıcaklığı 2 yada 0 olarak görüyorum. #byte ve #bit komutlarını da ilk defa deniyorum port tanımlamalarında da hata yapmış olabilirim.

Adc0831 Datasheetinden:



Burada benim anladığım CS 1'den 0'a düştüğünde adc hazır oluyor. 2 adet clk darbesinden sonra data en yüksek biti çıkış veriyor. Her clk darbesiyle bir sonraki biti veriyor. En son CS tekrar 1 yapılarak iletişim bitiriliyor. Yazdığım kodda bu mantığı kurmaya çalıştım.

CCS C:
#include <16f628A.h>
#fuses XT, NOWDT, NOPROTECT, NOBROWNOUT, NOLVP, NOPUT, NOCPD
#use delay (clock=4000000)
#use fast_io(a)
#use fast_io(b)
#define use_portb_lcd TRUE
#include <lcd.c>

#byte porta=0x05
#byte trisa=0x85

#bit cs=porta.0 //ADC'nin Cs pini pinA0'da
#bit clk=porta.2 //ADC'nin CLK pini pinA2'de
#bit data=porta.1 //ADC'nin Data pini pinA1'de

void clk_sinyali () // Bir kez clk sinyali üreten fonksiyon
{
clk=1;
delay_ms(5);
clk=0;
delay_ms(5);
return;
}

int sicaklik=0;
int vdata=0;
int x=0;
int cnt=0;
void main ( )
{
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_CCP1(CCP_OFF);

set_tris_b(0x00);
trisa=0b00000010;
porta=0;

cs=1; // Adc'nin CS'si 1 yapıldı

lcd_init();

while(1)
{
cs=0; // Cs 1'den 0 olduğunda ADC hazır
delay_ms(5);

clk_sinyali ();
clk_sinyali (); // İki kere clk darbesi yolladım ADC iletişime hazır

   for (cnt=0; cnt<8; cnt++)
   {
      vdata=data;  // ADC'nin data çıkışından gelen bit
      sicaklik=x | vdata; // Datayı kullanmak için x ile toplayıp sıcaklığa atadım
      sicaklik = sicaklik << 1; // Bir bit kaydırıp sıradaki biti aldım
      clk_sinyali();
   }
   
cs=1; // İletişim bitti

printf(lcd_putc, "\f Sicaklik:%d", sicaklik);
delay_ms(1000);

}
}


Devre şemam:




Teşekkür ederim.

JKramer

vdata=data;  // ADC'nin data çıkışından gelen bit
sicaklik=x | vdata; // Datayı kullanmak için x ile toplayıp sıcaklığa atadım
sicaklik = sicaklik << 1; // Bir bit kaydırıp sıradaki biti aldım

x'in değeri hep sıfır, neden vdata ile topluyorsunuz?

Son satırda sıcaklığı bir bit sola kaydırıyorsunuz ama ikinci satırda tüm sıcaklık değerini x | vdata işlemi sonucuyla kaybediyorsunuz. Sonuç olarak işlem sonunda sıcaklık, son gelen data'nın bir bit sola kaydırılımış hali oluyor. Yani son gelen bit 1 ise sıcaklık 2, 0 ise 0 oluyor -ki siz de bunu elde etmişsiniz-.

Kendiniz yapmak istediğinizden cevabı yazmayıp sadece hatanızı göstermek istedim, çözemezseniz yarın bakarız.

vitruvius

Evet teşekkür ederim hazır çözüm yada proje istemiyorum =) Sıfır ile toplamam gereksiz olmuş farkettim. Sıcaklık konusunda yardımınız için teşekkürler. Söyledikleriniz ışığında tekrar düzenliyorum kodları.

vitruvius

Hocam dediklerinizden yola çıkarak şu şekilde düşündüm. Adc'nin data bitinden ya 0 gelecek yada 1. Ben bunu bir değerle toplayayım. Bu topladığım değer ilk başta sıfır olsun. Sonra sonucu bir bit sola kaydırayım. Ardından sola kaydırdığım değeri bir sonraki döngüde tekrar datadan gelen bit ile toplayayım. Bunu 8 kere yapıp en son elde ettiğim değeri lcd'ye yazdırayım.

Bu şekilde yapınca sonuç 2 derece fazla çıkıyor. Bir de tek değerleri alamıyorum. Yani lm35'i 20 veya 21 dereceye kurduğumda lcd'de 22, 22 veya 23 dereceye kurduğumda 24 derece görüyorum. Ek olarak da 40 dereceden sonra bir şey dikkatimi çekti. Mesela lm35'i 20 veya 21 dereceye kurduğumda 22 görüyorum ancak 40'a kurduğumda 42, 41'e kurduğumda 44 olarak görüyorum.

Buralardaki sorun nerden kaynaklanıyor olabilir? Teşekkürler.

For döngüsünün yeni hali:

for (cnt=0; cnt<8; cnt++)
   {
      vdata=data;  // ADC'nin data çıkışından gelen bit
      y = x + vdata; // x ilk durumda 0, sadece data ile toplanıyor.
      x = y<<1;      // Üst satırda elde ettigimiz değer bir bit sola kaydırılıp tekrar data ile toplanmaya hazırlanıyor.
      clk_sinyali();
      sicaklik = x; // En son x'i elde ettik bu yüzden sıcaklığa eşitledik.
   }


Bu arada int x,y=0

JKramer

Döngü dışına x=0; eklemelisiniz. Bunun dışında kataloğa kabaca baktım, çözünürlük zaten 8 bit'miş; yani her bir adım 19.6 mV olacak. LM35'de bir derecelik değişim 10 mV'a karşılık geliyor. Bir de buna +- hatayı eklerseniz birkaç derece yanlışlık normal gibi.

elektronikhobi

Bir de tam emin değilim ama bana sanki ikinci saat sinyali fazla gibi geldi. Ben de bu konulara yabancıyım aslında  :-[



Ama ADC0831'in dökümanına baktım. Bir de PIC C ile Sıcaklık Projeleri kitabını okuyorum.  Benim anladığım kadarıyla CS(yonga seç) ucu 0 yapıldıktan sonra 1 saat pulsu gönderiliyor. Sonra verileri okurken de 8 puls gönderiliyor. Her pulstan sonra D0 bacağından gelen veri okunuyor ve sola kaydırılıp mini denetçide saklanıyor. Sonra yonga seçim biti 1 yapılarak çevrim bitiriliyor.

Gene arkadaşımızın da bahsettiği gibi  programda kayar noktalı sayı kullanılmadıysa (örneğin PIC'nin belleği sınırlı olabilir) PIC16F877 gibi denetçilere göre daha az hassas netice elde edilmesi normal diye düşünüyorum.