7 segde sıcaklık gostermede kucuk bır sorun

Başlatan baranekrem9, 25 Mart 2014, 19:26:12

baranekrem9

Merhaba daha onceden de konu acmısım sağ olsun ete hocam fıkır verdi yaptım fakat kucuk bır sıkıntı var.Ben ds18b20 kullanarak 2 adet 7 seg de sıcaklıgı gostermeye calısıyorum paralel baglı ve orta ucları 2 adet transıstor ıle suruyorum onlar hanesınde bır problem yok gayet ıyı calısıyor fakat bırler hanesınde gıdıp gelme sorunu var koddan kaynaklandıgını kesın anladım oda soyle oluyor 1 sanıye gıbı bır aralıklarla bırler hanesı gozukuyor oda cok az bır ısık ıle ama derece falan dogru bu bırler hanesının yerını degıstırdım onlar hanesi ile bu sefer onlar hanesıne aynısı oldu nerede hata yaptıgımı bulamadım sorunu cozmeme yada baska bır yontem ıle yapmama yardımcı olur musunuz bu tarama ıslemını ıle yapılıyormus bunu bır turlu anlayamadım kolay gelsın ıyı calısmalar

#include <16F877A.h>
#device adc=16
#fuses NOWDT,XT,NOBROWNOUT,NOLVP,NOPUT,NOCPD,NOWRT,NOPROTECT,NODEBUG
#use delay(clock=4M)
#include "ds18b20.c"

#define digit_birler pin_d7
#define digit_onlar pin_d6

int temp,birler = 0,onlar = 0;
const int digit[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7C,0x07,0x7F,0x6F};

void main()
{
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_CCP1(CCP_OFF);
   setup_CCP2(CCP_OFF);
   
   set_tris_b(0x00);
   set_tris_d(0x00);
   output_b(0x00);
   output_d(0x00);

   while(TRUE)
   {
      temp = ds1820_read();
     
      output_low(digit_onlar);
      birler = temp % 10;
      output_b(digit[birler]);
      output_high(digit_birler);
      delay_ms(1);
     
      output_low(digit_birler);
      onlar = temp / 10;   
      output_b(digit[onlar]);
      output_high(digit_onlar);
      delay_ms(1);
   }
}

Mucit23

Hatan şudur. Ds18B20'den sıcaklık okuması yaklaşık 750ms sürer. Programa bakınca sen main döngüsü içerisinde hem sıcaklığı okuyup hemde display taramasını yapıyorsun. Display tarama şeklinde problem yok fakat yanlış yerde taramayı yapıyorsun. Şimdi programa adım adım bakalım neler oluyor.

   while(TRUE)
   {
      temp = ds1820_read();
     
      output_low(digit_onlar);
      birler = temp % 10;
      output_b(digit[birler]);
      output_high(digit_birler);
      delay_ms(1);
     
      output_low(digit_birler);
      onlar = temp / 10;   
      output_b(digit[onlar]);
      output_high(digit_onlar);
      delay_ms(1);
   }


İlk Başta Sıcaklığı okumuşsun. Sıcaklığın okunması yaklaşık 750ms sürdüğünü bildiğimize göre program ds18b20_read() fonksiyonuna gidip gelmesi yaklaşık 750 ms sürecektir. Yani program burada 750ms beklemiş oldu.

Sonra okuduğun sıcaklık değerinin birler hanesini Displaylere yollayıp 1. dijiti aktif ediyorsun. Birler hanesi yanmış oluyor. Sonra 1ms bekleyip Onlar hanesini display'e gönderip tekrar 1ms bekliyorsun. Bu sırada birler hanesi söndü ve onlar hanesi yanmaya başladı. Sonra main döngüsü başa dönüyor ve tekrar sıcaklık okuması yapılıyor. İşte işler buradan sonra kopuyor. Tekrar sıcaklık okuması yapıldığı zaman program tekrar 750ms bekliyor. En son sen onlar hanesini yanık bıraktığın için onlar hanesi 750ms boyunca yanar. Sıcaklık okuduktan sonra onlar hanesini kapatıp birler hanesini açıyorsun fakat birler hanesi sadece 1ms açık kaldığı için çok az bir yanma görüyorsun. Ardından tekrar onlar hanesi yanıyor sıcaklık okunuyor vs vs..

Sorun dediğim gibi sıcaklık okuma işleminden kaynaklanan gecikmedir.

Yapman gereken şudur.
Timer0 sayacını 1-2ms aralığında kesme üretecek şekilde kuracaksın. Ardından kesme alt programında sürekli olarak displayleri tarayacaksın. Sıcaklık okuması kesme oluşmasına engel olmadığı için displaylerin taraması kesintisiz bir şekilde yapılacaktır.

Sen ise main programında istediğin gibi sıcaklığı okursun artık. Çünkü display tarama gibi bir derdin yok. O iş otomatikmen halloluyor.
Sıcaklığı okuyup birler hanesini ve onlar hanesini ayrı değişkenlere atarsın. Kesme içerisindede bu değişkenlere aktardığın değerler displaylere gönderilir.

İşin özü budur.

Kolay gelsin.

Bir ulusu yok etmenin En iyi yolu o ulusun dilini yok etmektir.

www.arectron.com/

baranekrem9

yanıtınız ıcın tesekkur ederım anladıgım kadarıyla taram bolumunu timer0 kesemeine atacagım, 1-2 ms kurarak bu kadar mı ?

Mucit23

Dediklerimi bir yapın başka bir eksiklik var ise zaten göreceksiniz.
Bir ulusu yok etmenin En iyi yolu o ulusun dilini yok etmektir.

www.arectron.com/

baranekrem9

sabahtan berı arastırıyorum su timer0 kesmesini anlayamadım nasıl ayarlandığını en son soyle bır sey oldu cok sacma olabılır ama tımerı ılk kullanısım kusura bakmayın  :-[

#include <16F877A.h>
#device adc=16
#fuses NOWDT,XT,NOBROWNOUT,NOLVP,NOPUT,NOCPD,NOWRT,NOPROTECT,NODEBUG
#use delay(clock=4M)
#include "ds18b20.c"

#define digit_birler pin_d7
#define digit_onlar pin_d6

#int_timer0

int temp,birler = 0,onlar = 0;
const int digit[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7C,0x07,0x7F,0x6F};

void timer0_kesme ()
{
   set_timer0(60);
   
   output_low(digit_onlar);
   birler = temp % 10;
   output_b(digit[birler]);
   output_high(digit_birler);
   delay_ms(1);
   
   output_low(digit_birler);
   onlar = temp / 10;
   output_b(digit[onlar]);
   output_high(digit_onlar);
   delay_ms(1);
}

void main()
{
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_CCP1(CCP_OFF);
   setup_CCP2(CCP_OFF);
   set_timer0(60);

   enable_interrupts(INT_timer0);
   enable_interrupts(GLOBAL);
   
   set_tris_b(0x00);
   set_tris_d(0x00);
   output_b(0x00);
   output_d(0x00);

   while(TRUE)
   {
      temp = ds1820_read();
   }
}

Mucit23

Ufak tefek hatların var.

Timeri Kurarken RTCC ile ilgili parametreleri kullanma. Farkeden birşey yok gerçi ama zaten timer0 ın kendi parametreleri tanımlanmış

setup_timer_0(T0_INTERNAL | T0_DIV_256 );

Diğer bir hatan timer ön yükleme değeri ile ilgili. Timerin 2ms aralıklarla oluşmasını için timer bölücü ve preload değerleri ile oynamak gerekiyor. Timer bölücüsünü 256 yapıp ön yükleme değerinide 60 yaparsan timer yaklaşık 50ms aralıklarla oluşur. Çok yüksek bir değer.

2ms için 8 bit timer'de bölücüyü 1/16 yapıp, preload değerinide 131 olarak verirsen yaklaşık 2ms aralıklarla kesme oluşur. Bunun gibi birkaç alternatif var. Mesela Bölücüyü 1/64 yapıp, timer sayacınada 224 değerini yüklersen yine yaklaşık 2ms aralıklarla kesme oluşur.

Timer pwm usart ve bunun gibi hesaplamalar için PicMultiCalc Programını kullanabilirsin. Forumda var. 

Kesme fonksiyonun başına #int_timer0 tanımlamasını yapman lazım. Bu bi anlamda işlemciye kesme vektörünün adresini tanıtır. Araya başka bir kod eklememen lazım
Doğrusu aşağıdaki gibi olacak

#int_timer0
void timer0_kesme (){
...
..
.
}

Kesme fonksiyonunun içerisine gelirsek

Displayi taramak için Switch Case yapısını kullansan daha güzel olur. Kesme içerisinde bekleme yapmak iyi birşey değil. Bizim fonksiyonumuz zaten 2ms aralıklarla oluşuyor. Eğer Switch case yapısını kullanırsam işlemci her fonksiyona geldiğinde sıradaki displayi aktif eder.

programın başına sayac diye bir değişken tanımla

void timer0_kesme () 
{
   set_timer0(60);
 
   switch(sayac)
  {
     case 0:
       output_low(digit_onlar);
       birler = temp % 10;
       output_b(digit[birler]);
       output_high(digit_birler);
     break;
     case 1:
       output_low(digit_birler);
       onlar = temp / 10;
       output_b(digit[onlar]);
       output_high(digit_onlar);
     break;
   }
   sayac++;if(sayac>1)sayac=0;
}


Kesme fonksiyonunu bu şekilde düzenlersin. Preload ve bölücü değerlerini düzeltmeyi unutma.

İyi çalışmalar.
Bir ulusu yok etmenin En iyi yolu o ulusun dilini yok etmektir.

www.arectron.com/

baranekrem9

#6
Ve zafer anı teşekkür ederim yaptım oldu :) dediğini timer kurulumunu tam anlamamıştım 256 yı 1/16 nasıl yaparım dedım 877a.h dosyasını kurcalardım direk 16 yazmam yeterli oldu set_timer0(131); değerinide verdim 2,007 mili saniye kesme oluşturdum multicalc da cok işime yaradı tekrardan teşekkür eder iyi çalışmalar dilerim.

Powered by EzPortal