ds1302 saatin hızlı ilerlemesi sorunu

Başlatan AYKIRI, 10 Eylül 2013, 12:29:41

AYKIRI

merhaba arkadaşlar

ds1302 ve ds18b20 ile LCD üzerinde alarmlı saat yapmaya çalışıyorum. iki problemle karşılaştım yardımlarınızı rica ediyorum

1. Saat çalışırken 7 saat sonra kontrol ettiğimde yaklaşık 2 dakika hızlı ilerlediğini gördüm osilatör 32768 kararlı olmayabilir diyerek 2 farklı osilatör denedim sonuç değişmedi bununla ilgili ne yapabilirim (sorun çıkarmayacağı kesin olan başka bir rtc varsa onuda kullanabilirim)

2. ds18b20 okuma yaparken sistemi çok yavaşlatıyor kesmede kullandığım işlemler zamanından erken yada geç işlem yapıyor bu normalmidir ?

saygılar

LukeSkywalker

Kod ve devreyi görmeden yorum yapmak zor. Osilatör DS1302'ye nasıl bağlandı? Breadboard üzerinde mi yoksa baskı devreye bağladınız mı?. Bunlar önemli.

ete

Saatin hızlı ilerlemesindeki sorun RTC de değil OSC sistemindedir. Data sheet de kristral bağlantısının nasıl yapılacağı gösterilmiş. Gösterilen şekilde kristal bacakları bir GND çerçevesi içine alınmaktadır. İlave tedbir olarak kristal yan yatırılıp gövdesi bir tel ile GND 'ye  birleştirilmelidir. Bu onun ısıl kararlılığını artıracak ve doğru gitmesini sağlayacaktır. Elbette her şey kristalin hassaslığına ve kalitesine bağlı. Çok uyduruk bir şey kullanmadığınız müddetçe saatin doğruya çok yakın gitmesi gerekir.

DS18B20 sıcaklıks ensörü okuma süresi yaklaşık 750 ms dir. Programın diğer işlerininde en azından bir 250 ms zaman alacağını düşünürseniz 1 sn lik süreyi doldurmuş oluyorsunuz. Bu durumda yapmanız gereken bir iki alternatif tedbir var. Birincisi çözünürlüğü 12 bit den 11 bite düşürürseniz çevrim süresi 375 ms olacaktır. 10 bit yaparsanız 188 ms, 9 bit yaparsanız 94 ms ye düşecek böylece size yeterince zaman kalacaktır. Çözünürlüğün değiştirilmesi data sheet de açıklanmış olup Configürasyon registerinin 5-6 nolu bitlerine değer vererek çözünürlük seçilmektedir. Default değer 12 bit dir.
Diğer bir alternatif ise benim kullandığım alternatif olup sensöre $44 emrini vererek konvert işlemini başlatıp sensörün başından ayrılmak ve yapılacak işleri yaptıktan sonra en son gidip çevrilmiş sıcaklığı okumaktan ibarettir.
Normalde sensöre $44 ile konvert emri verildikten sonra  sensörün meşgul olup olmadığı test edilir ve meşgul olduğu sürece beklenir. Sonunda sensör işlemi tamamlar ve muşgulden kurtulur. Ama program hep orada bekler. Daha sonra $BE ile skratchpad hafızasının okuma emri verilerek çevrilmiş sıcaklık oradan okunur. Bunun yerine Konvert emri verilip  oradan ayrılmalı işinizi yapmalısınız. İŞiniz tamamlandıktan sonra geri dönüp Scratchpad hafızanın okuma emrini vererek çevrilmiş sıcaklığı okyup oradan ayrılmalısınız. Hepsi bu. Epeyce işe yarıyor bu yöntem.

Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

AYKIRI

#3
Alıntı yapılan: LukeSkywalker - 10 Eylül 2013, 12:43:07
Kod ve devreyi görmeden yorum yapmak zor. Osilatör DS1302'ye nasıl bağlandı? Breadboard üzerinde mi yoksa baskı devreye bağladınız mı?. Bunlar önemli.

delikli plaket üzerinde yaptım osilatör 2 ve 3 nolu pinlere bağlı
kodun tamamı aşağıdadır

#include <16F877A.h>
#device adc=16
#FUSES NOWDT, xt, PUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT     
#use delay(clock=4000000)

#define RTC_SCLK PIN_a2           
#define RTC_IO   PIN_a1
#define RTC_RST  PIN_a0 
                  
#define use_portb_lcd TRUE
#include "flexy_lcd.c"                            //lcd c dosyası
#include "ds18b20.c"                              //termometre entegresi c dosyası
#include "ds1302.C"                               //saat entegresi c dosyasi
#use fast_io(d)
#use fast_io(c)

int8 sicak,saniye,dakika,saat,gun,ay,hafta,yil,ayar=0,v1,v2,d1,d2;
int i;
byte r1;

#int_timer0 //timer0 kesmesi

void timer0_kesme()
{
 set_timer0(60); //timer0 degeri belirleniyor
 i++;
 if(i==100){ output_high(pin_c2);}
 if(i==200){ output_low(pin_c2);i==0;}
 }

void lcd()
{
   
   lcd_gotoxy(1,1);
   printf(lcd_putc,"%02d/%02d/20%02d",gun,ay,yil);  
   lcd_gotoxy(1,2);
   printf(lcd_putc,"%02d:%02d:%02d",saat,dakika,saniye);
   lcd_gotoxy(12,1);
   switch(hafta)  
      {                     
         case 1: printf(lcd_putc,"PZTSi"); break; 
         case 2: printf(lcd_putc,"SALI"); break; 
         case 3: printf(lcd_putc,"CARSM"); break; 
         case 4: printf(lcd_putc,"PERSM"); break;
         case 5: printf(lcd_putc,"CUMA"); break; 
         case 6: printf(lcd_putc,"CMRTS"); break; 
         case 7: printf(lcd_putc,"PAZAR"); break; 
  }
}


void alarm0()

{
 
  v1 = read_EEPROM (0);
  v2 = read_EEPROM (1); 
  d1=v1;  
  d2=v2;
     printf(lcd_putc,"\f  ALARM SAATi");lcd_gotoxy(7,2);printf(lcd_putc,"%02d:%02d",d1,d2);
     delay_ms(1000);
     while(1){
  if(d1==-1){d1=0;}
  if(d2==-1){d2=0;}
  if(input(pin_d3)==1){d1++;delay_ms(100);if(d1==24){d1=0;}write_eeprom(0,d1);while(input(pin_d3)==1);}
  if(input(pin_d4)==1){d2++;delay_ms(100);if(d1==60){d1=0;}write_eeprom(1,d2);while(input(pin_d4)==1);}
  printf(lcd_putc,"\f  ALARM SAATi");lcd_gotoxy(7,2);printf(lcd_putc,"%02d:%02d",d1,d2);
  delay_ms(100);
  if(input(pin_d5)==1){lcd_putc("\f");lcd_gotoxy(16,2);printf(lcd_putc,"%c",r1);break;}
  }
   }

void sicaklik()
{
 delay_ms(1000);
   sicak=ds1820_read();        
   lcd_gotoxy(11,2);printf(lcd_putc,"%02d%cC",sicak,223);
   }
void ayaryap(){
   if(((input(pin_d3)==1)&& (input(pin_d4)==1))&& (input(pin_d5)==0)){ayar++;delay_ms(20);printf(lcd_putc,"\f AYAR MODU");delay_ms(450);printf(lcd_putc,"\f");}
   while(ayar==1){
   lcd();lcd_gotoxy(1,1);lcd_send_byte(0x01,0x0d);lcd_gotoxy(2,1);lcd_send_byte(0x02,0x0d);   
   if(input(pin_d3)==1){gun++;delay_ms(20);if(gun==32){gun=1;}while(input(pin_d3)==1);}
   if(input(pin_d4)==1){gun--;delay_ms(20);if(gun==0){gun=31;}while(input(pin_d4)==1);}
   if(input(pin_d5)==1){ayar++;delay_ms(200);while(input(pin_d5)==1);}}
   
   while(ayar==2){
   lcd();lcd_gotoxy(4,1);lcd_send_byte(0x04,0x0d);lcd_gotoxy(5,1);lcd_send_byte(0x05,0x0d);
   if(input(pin_d3)==1){ay++;delay_ms(20);if(ay==13){ay=1;}while(input(pin_d3)==1);}
   if(input(pin_d4)==1){ay--;delay_ms(20);if(ay==0){ay=12;}while(input(pin_d4)==1);}
   if(input(pin_d5)==1){ayar++;delay_ms(200);while(input(pin_d5)==1);}}
   
   while(ayar==3){
   lcd();lcd_gotoxy(7,1);lcd_send_byte(0x07,0x0d);lcd_gotoxy(8,1);lcd_send_byte(0x08,0x0d);
   if(input(pin_d3)==1){yil++;delay_ms(20);while(input(pin_d3)==1);}
   if(input(pin_d4)==1){yil--;delay_ms(20);if(yil==-1)yil=99;while(input(pin_d4)==1);}
   if(input(pin_d5)==1){ayar++;delay_ms(200);while(input(pin_d5)==1);}}
   
   while(ayar==4){
   lcd_gotoxy(11,1);lcd_send_byte(0x11,0x0d);lcd();delay_us(5);
   if(input(pin_d3)==1){hafta++;delay_ms(20);if(hafta==8){hafta=1;}while(input(pin_d3)==1);}
   if(input(pin_d4)==1){hafta--;delay_ms(20);if(hafta==0){hafta=7;}while(input(pin_d4)==1);}
   if(input(pin_d5)==1){ayar++;delay_ms(200);while(input(pin_d5)==1);}}
   
   while(ayar==5){
   lcd_gotoxy(1,2);lcd_send_byte(0x40,0x0d);lcd_gotoxy(2,2);lcd_send_byte(0x41,0x0d);lcd();
   if(input(pin_d3)==1){saat++;delay_ms(20);if(saat==24){saat=0;}while(input(pin_d3)==1);}
   if(input(pin_d4)==1){saat--;delay_ms(20);if(saat==-1){saat=23;}while(input(pin_d4)==1);}
   if(input(pin_d5)==1){ayar++;delay_ms(200);while(input(pin_d5)==1);}}
   
   while(ayar==6){
   lcd_gotoxy(4,2);lcd_send_byte(0x43,0x0d);lcd_gotoxy(5,2);lcd_send_byte(0x44,0x0d);lcd();
   if(input(pin_d3)==1){dakika++;delay_ms(20);if(dakika==60){dakika=0;}while(input(pin_d3)==1);}
   if(input(pin_d4)==1){dakika--;delay_ms(20);if(dakika==-1){dakika=59;}while(input(pin_d4)==1);}
   if(input(pin_d5)==1){ayar++;delay_ms(200);while(input(pin_d5)==1);}}
      
   while(ayar==7){rtc_set_datetime(gun,ay,yil,hafta,saat,dakika);   
   delay_ms(20);
   printf(lcd_putc,"\f    AYARLAR\n   YUKLENIYOR");
   delay_ms(1000);printf(lcd_putc,"\f");
  ayar=0;}
}   
void main()
{  

 setup_psp(PSP_DISABLED);
 setup_spi(SPI_SS_DISABLED);
 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_CCP1(CCP_OFF);
   
   set_tris_d(0b00111110);
   output_d(0x00);
   set_tris_c(0b00000000);
   output_c(0x00);   
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_64); 
   set_timer0(60); 
   enable_interrupts(INT_timer0);
   enable_interrupts(GLOBAL);   
   lcd_init();       //lcd yi hazırla
   rtc_init();       //saat entegresini hazırla
   printf(lcd_putc,"\f");
   delay_ms(5);    
   
while(1)
{
      if(ayar==0){rtc_get_time(saat,dakika,saniye);rtc_get_date(gun,ay,yil,hafta);}
      sicaklik();
      lcd();
      ayaryap();
      v1 = read_EEPROM (0);
      v2 = read_EEPROM (1);
      byte b1 = lcd_getc(16,2);
      r1=b1;
      if(((saat==v1)&&(dakika==v2))&&(b1==0x41)){output_high(pin_c2);}else{output_low(pin_c2);}
       
if(input(pin_d5)==1) {alarm0();delay_ms(200);while(input(pin_d5)==1);}
if((input(pin_d4)==1) && (b1!=0x41)) {lcd_gotoxy(16,2);printf(lcd_putc,"A");while(input(pin_d4)==1);}
if((input(pin_d4)==1) && (b1==0x41)) {lcd_gotoxy(16,2);printf(lcd_putc,"-");while(input(pin_d4)==1);}

enable_interrupts(GLOBAL);

}
}




sayın ete yardımınız için teşekkür ederim ccs ile ilgili örnek varmı bahsettiğiniz sıcaklık sensörü ile ilgili olan kısmı denemek istiyorum

ete

CCS C için örnek bende yok maalesef.
Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

AYKIRI

#5
Alıntı yapılan: ete - 10 Eylül 2013, 14:24:49
CCS C için örnek bende yok maalesef.
Ete
ds1302 için eski bir bilgisayar anakartından osilatörü söktüm gövdesini gnd ye bağladım şimdilik test ediyorum bir kaç saat sonra belli olur
verdiğiniz bilgiler için teşekkürler

son test ettiğim sonuçlara göre 3 saatte 2 saniye önden gidiyor bu durum için önerileriniz varmı ?

AYKIRI

arkadaşlar ds18b20 zırt pırt sorgulama yapıyor ben bunu dakikada bir defa yaptırmak istiyorum delay koyduğumda malumunuz lcd bekliyor böyle bir şey nasıl yapabilirim. timer düşündüm ama ustalar bu konuda ne önerirse onu yapayım

saygılar

mistek

Alıntı yapılan: AYKIRI - 10 Eylül 2013, 18:48:46
arkadaşlar ds18b20 zırt pırt sorgulama yapıyor ben bunu dakikada bir defa yaptırmak istiyorum delay koyduğumda malumunuz lcd bekliyor böyle bir şey nasıl yapabilirim. timer düşündüm ama ustalar bu konuda ne önerirse onu yapayım

saygılar

En basit ve vasat işlem
while(1)
{
    degisken++;
    ....diğer kodlar

    if(degisken >= istediğim kadar){
        ds18b20_oku();
    }

}


vasat olmasın iyi olsun dersen timer kullanman gerekir.
boş işlerin adamı ---- OHM Kanunu: I = V/R ---- Güç Formülü: P = V*I = I^2*R = V^2/R

Kabil ATICI

Zaten bir saatin var. Saatin dakika hanesi değiştiğini kontrol et. Değiştiği zaman okuma yaptır.!
Olay bir tane ek hafızaya bakar.
ambar7

AYKIRI

aynen dediğiniz gibi yaptım arkadaşlar teşekkür ederim
şu ileri sayma sorununuda çözersem gayet güzel olacak

yusuf3101

#10
Merhaba Hocam..

ds1302 ile bende çalıştım ve yaptığım saate 3 ay sonra baktım yine aynı ve doğruydu. bence sen yeni bir ds1302 daha al öyle dene.
Ayrıca programda sleep(); modunu uygularsan ve bunuda wdt(bekçi köpeği) resetlemesiyle sleep(); modundan uyandırırsan devreyi 3 adet kalem pil ile 6 ay çalıştırabilirsin tabi bu normal pil ile bu kadar çalışıyor sen gidip 3000mAH pil alırsan 1 yıl yine gider. ayrıca sıcaklık sensörü fazla akım çekiyor onu devreden çıkartman gerek yada ds16b20 kullan.

Bu resimdeki saati ilk yaptığım zamanlardaki ve sıcaklık sensörü ile saat ayarında problem yaşadığım zamanlar ayrıca bunda fişe takmalıydı normal pili 2 günde bitiriyordu taaki sleep(); (uyku) modunu yapana kadar bu modu yapmayı başardıktan sonra masa saati olmayı haketti :)


kodların belirli kısımları

while(kaydır==1) menüsünün olduğu yer saatimin çalıştığı yer eğer proğramda hatan var ise bunlar örnek olabilir belki ama sanırım proğramda sorun yok çünki ds1302'de istersen 2 saniye delay koy yinede o bildiği saniyeyi yazıyor yani pice gelen bilgi doğru ama bunu ne kadar süre aralıklarla görmek sana kalmış olandır. yüksek ihtimal ds1302 bozulmuş veya osilatörde problem var her iksinide değiştirip denersen düzelebilir fakat kaliteli malzeme satan bir yer bulabilirsen iyi çünkü malzeme kalitesizliği yüzünden biraz problem yaşamıştım bende

#include <16f876.h>
#fuses XT,WDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay(clock=4000000)
#include <yusuf_lcd.c>
#include <yusuf_DS1302.c>
int saniye,dakika,saat,gun,ay,yil,haftanin_gunu;
int kaydir=1,ayar=0,arttir,esitle=0,sat,dak,zil=1,m,y,i;
void yazi(void);
void butonlar (void);
main()
{
   setup_spi(SPI_SS_DISABLED);     // SPI birimi devre dışı
   setup_timer_1(T1_DISABLED);     // T1 zamanlayıcısı devre dışı
   setup_timer_2(T2_DISABLED,0,1); // T2 zamanlayıcısı devre dışı
   setup_adc_ports(NO_ANALOGS);    // ANALOG giriş yok
   setup_adc(ADC_OFF);             // ADC birimi devre dışı
   setup_CCP1(CCP_OFF);            // CCP1 birimi devre dışı
   setup_CCP2(CCP_OFF);            // CCP2 birimi devre dışı
   lcd_init();
   rtc_init();
   setup_wdt(wdt_985ms);
   
   while(1)
   {

   // ANA SAATİN ÇALIŞTIĞI YER //
   while(kaydir==1)     // saat aktif ve çalışıyor
   {  
      rtc_get_time(saat,dakika,saniye);
      rtc_get_date(gun,ay,yil,haftanin_gunu);
      yazi();
      printf(lcd_putc,"\f >> %02d:%02d:%02d <<",saat,dakika,saniye),
      printf(lcd_putc,"\n>> %02d/%02d/20%02d <<",gun,ay,yil);
      restart_wdt();
      butonlar();
      sleep();
   }


hadi kolay gelsin umarım problemi çözersin hocam

Saygılar..

AYKIRI

saatim şuan 12 saatte 8 saniye ileri gidiyor (7 saatte 2 dakikadan çok iyi) ama memnun değilim alarm fonksiyonu ve diğer fonksiyonların tamamı normal ama ileri gitmesi rahatsız edici o yüzden DCF77 modül ile almanyadan atom saat sinyaliyle sıfır hatalı bir saat yapmayı düşünüyorum dcf modülünü sipariş ettim gelmesi 10 gün sürer sanırım

sizin saatinizin düzgün çalışmasına sevindim. kısmet işte belkide ds1302 bozuk emin değilim. artık başka çözümler deneyeceğim
saygılar

Lütfi AYYILDIZ

Kristalin ayakları ile gnd arasına 15pf kondansatör koy sorunun çözülecektir.


rree

Kristaller bir markada 3 tipi vardı. Hassasiyetine görede fiyatlar farklı idi.

Ben farklı bir yöntem uyguladım.  32.768 Mhz dikdörgen biçiminde  kristal osilator buldum.
Bu kristal ile pic çalıştırdım. pwm katında bölerek elde edilen 32768 hz sinyali  ds sürdüm.
Saati kullananlar ileri geri kaldığını söylemediler.

yusuf3101

Alıntı yapılan: AYKIRI - 14 Eylül 2013, 23:13:40
saatim şuan 12 saatte 8 saniye ileri gidiyor (7 saatte 2 dakikadan çok iyi) ama memnun değilim alarm fonksiyonu ve diğer fonksiyonların tamamı normal ama ileri gitmesi rahatsız edici o yüzden DCF77 modül ile almanyadan atom saat sinyaliyle sıfır hatalı bir saat yapmayı düşünüyorum dcf modülünü sipariş ettim gelmesi 10 gün sürer sanırım

sizin saatinizin düzgün çalışmasına sevindim. kısmet işte belkide ds1302 bozuk emin değilim. artık başka çözümler deneyeceğim
saygılar

Anladım hocam kolay gelsin o halde umarın sorunu çözersin