LCD Saat ve Sıcaklık Sensörü

Mayıs 20, 2017

Bu uygulamayı da Mikroişlemciler ve Programlanması dersi için yapmıştım. Aşağıdaki içeriği dersin projesi için hazırladığım rapordan kopyaladım.

LCD saat ve sıcaklık sensörüLCD saat ve sıcaklık sensörüLCD saat ve sıcaklık sensörü

Devrenin amacı etrafındaki sıcaklığı, güncel tarihi ve zamanı canlı olarak kullanıcıya yansıtabilmektir. Devrenin sıcaklık tanıyabilmesi için 1-wire haberleşme metodu kullanan DS18B20, saat takibi ve devrede güç olmasa bile saymaya devam edebilmesi için 3-wire haberleşme metodu kullanan DS1302 kullanılmıştır. Devrede mikro işlemci olarak PIC16F877A kullanılmış olup, 20MHz osilatör frekansı ile işletilmiştir. Aşağıda işler hal, simülasyon, şema ve kod görüntüleri bulunmaktadır.

Devrenin simülasyonu aşağıdaki gibidir;

LCD ISIS

Devrenin PCB ve 3D versiyonları aşağıdaki gibidir;

LCD ARESLCD 3D
 

PIC’in türü, çalışma frekansı ve parametreleri ayarlandı. LCD için gerekli olan kütüphaneler eklendi ve lcd portu belirtildi. Saat entegresinin 3 iletişim bacağının hangi pinlere bağlı olduğu tanımlandı, entegrenin kütüphanesi eklendi. DS18B20 sıcaklık entegresinin mikroişlemciye bağlı olduğu data hattı mikroişlemciye one wire pini olarak tanıtıldı. Açılışa özel olacak olaylar ve saat entegresinden okunacak değerlerin aktarılması için gerekli değişkenler oluşturuldu.
 

#include <16f877.h>                
#use delay(CLOCK=20000000)
#fuses HS,NOWDT,NOPROTECT,NOLVP
#define use_portb_lcd TRUE
#include <lcd.c>
#define RTC_SCLK PIN_D4
#define RTC_IO PIN_D3
#define RTC_RST PIN_D2
#include <DS1302.c>
#define ONE_WIRE_PIN PIN_C0

float temp; 
short acilis=1;
byte saniye,dakika,saat,gun,ay,yil,hgun;

Burada PIC’te kullanmak için onewire iletişim protokolünü uygulayan hazır kod kullanıldı.

void onewire_reset()

{
output_low(ONE_WIRE_PIN);
delay_us( 500 ); 
output_float(ONE_WIRE_PIN); 
delay_us( 500 ;
output_float(ONE_WIRE_PIN);
} 

void onewire_write(int data)
{
int count;
for (count=0; count<8; ++count)
{
output_low(ONE_WIRE_PIN);
delay_us( 2 ); 
output_bit(ONE_WIRE_PIN, shift_right(&data,1,0)); 
delay_us( 60 ); 
output_float(ONE_WIRE_PIN); 
delay_us( 2 ); 
}
} 

int onewire_read()
{
int count, data;
for (count=0; count<8; ++count)
{
output_low(ONE_WIRE_PIN);
delay_us( 2 ); 
output_float(ONE_WIRE_PIN); 
delay_us( 8 ); 
shift_right(&data,1,input(ONE_WIRE_PIN)); 
delay_us( 120 ); 
}
return( data );
} 

float ds1820_read()
{
int8 busy=0, temp1, temp2;
signed int16 temp3;
float result;
onewire_reset();
onewire_write(0xCC);
onewire_write(0x44);
while (busy == 0)
busy = onewire_read();
onewire_reset();
onewire_write(0xCC);
onewire_write(0xBE);
temp1 = onewire_read();
temp2 = onewire_read();
temp3 = make16(temp2, temp1);
result = (float) temp3 / 16.0;
return(result);
}

Öncelikle Timer 1 iç frekanstan 8 prescale değeri ile tanımlandı, saniyede 10 kere kesme yaratması istenen Timer1 gerekli değer olan 3036’ya eşitlendi. Timer 1 interruptları devreye sokuldu, LCD ve saat entegresi başlatıldı, entegreden tarih bilgileri çekildi. Interruptlar işlenmezken 350ms gibi makul aralıklarla sıcaklık bilgisi sensör üzerinden güncellendi. Sıcaklık güncellemesinin saat ile aynı yerde bulunmamasının, saatin interrupta taşınmasının sebebi sıcaklık sensöründen okuma esnasında 200 ms civarı bir gecikme oluşmasıdır.

void main(void)
{

setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
set_timer1(3036);
enable_interrupts(int_timer1);
enable_interrupts(global);
lcd_init(); 
rtc_init();
rtc_get_date(gun,ay,yil,hgun);
   
   while(1)
   {
   
   temp = ds1820_read();
   delay_ms(350);

   }
   
}

Timer 1 interruptu her kesmede 3036 değerine geri döndürülerek 10Hz’lik kesme oranı korunuyor. Saat bilgisi her kesmede güncellenerek anlık bilgi akışı sağlanıyor. Eğer devre yeni açıldıysa önce isimler ve numaralar gösteriliyor, sonradan bunun olmasını sağlayan değişkenin değeri ters çevriliyor ve mesajın gizlenmesi sağlanıyor. Her kesmede LCD’deki bilgi güncelleniyor, LCD’de yüksek oranda yenilemeyle gelen göz kırpma sorunu gotoxy komutu yardımıyla giderilmiş oluyor.

#int_timer1
void zamanli() 
{

 set_timer1(3036);
 rtc_get_time(saat,dakika,saniye);
   if(acilis==1)
      {
      printf(lcd_putc,"\f ISIM SOYISIM \n NUMARA");
            delay_ms(1000);
      printf(lcd_putc,"\f ISIM2 SOYISIM2 \n NUMARA2");
            delay_ms(1000);      
      acilis=0;
      }

         lcd_gotoxy(1,1);
         printf(lcd_putc,"%3.1f%cC  %02d/%02d/%02d ",temp,223,gun,ay,yil); 
         lcd_gotoxy(1,2);
         printf(lcd_putc,"    %02d:%02d:%02d    ",saat,dakika,saniye); 


}

Kodu bir PIC programlayıcı kart ile PIC’e atıp devreyi kurduktan sonra sistem sorunsuz çalışıyor. Devreye butonlar eklenerek, menü, saat ayarı, alarm vb. gibi fonksiyonlar eklenebilir.