26 Nisan 2014 Cumartesi

PIC16F877A MCU İle Sıcaklığa Bağlı Çalışan Kontrol Kartı

Hydro Marmara Club adına tasarımını gerçekleştirdiğim kontrol kartını siz elektronik meraklılarıyla paylaşmak istiyorum. Tasarım hidrojen enerjisi ile çalışan araçlarda, elektrik enerjisi üreterek aküyü besleyen yakıt hücresinin aşırı ısınmasının önüne geçerek devreyi kesmektedir. Ortam sıcaklığının 60 derece dolaylarında seyretmesi halinde öncelikle sürücüye buzzer aracılığıyla uyarı verilmektedir. Sıcaklığın 70-75 dereceye çıkması halinde ise ana kontrol rölesinin enerjisi kesilerek devre kapatılmakta ve yakıt hücresinin aşırı ısınmasından kaynaklanabilecek deformasyon ve patlama riski minimize edilmektedir. Tasarımın ana kontrol ünitesi PIC16F877A MCU ile gerçekleştirilmiştir. Buzzer ve durum ledlerinin kontrolü için PIC16F84A MCU kullanılmıştır. PIC16F877A ile PIC16F84A mikrodenetleyicileri arasındaki haberleşme tek hat üzerinden dijital olarak yapılmıştır. İki farkı durum söz konusu olduğundan haberleşme protokolü kullanımına gerek duyulmamıştır. 

Şekil 1.1
Blok Şema
Şekil 1.2
Kontrol Kartı Eagle Şematik Çizimi
Şekil 1.3
Kontrol Kartı PCB

Şekil 1.4
Kontrol Kartı PCB
Şekil 1.4
Kontrol Kartı
Şekil 1.5
Kontrol Kartı Takmalı Sürücüler (Sürücüler İptal Edildi)
Şekil 1.6
Kontrol Kartı Üsten Görünüşü
Şekil 1.7
Tüm Kontrol Kartları


Şekil 1.8
Proteus/Ares PCB Çizimi

Kontrol Kartı Test Süreci

PIC16F877A  MCU Kaynak Kod
#if defined(__PCM__) 
// __PCM__ önişlemcisi, 14-bit opcode ile çalışan MCU’ların derlenmesi
// için kullanılır.
#include <16f877a.h>
// PIC16F877A MCU header dosyası kaynak koda import ediliyor.
#device ADC=10
// ADC (Analog Digital Conventer) donanımı 10-bit çözünürlükte çalışacak.
#fuses HS, NOWDT, NOPUT, NOPROTECT, NOBROWNOUT, NOCPD, NOWRT, NODEBUG
// High Speed kristal osilatör kullanılacak. (HS)
// Watch Dog Timer kapalı. (WDT)
// Power-up Timer kapalı. (PUT)
// Kod Koruma kapalı. (PROTECT)
// Brown Out Reset kapalı. (BROWNOUT)
// Data EEPROM Kod Koruma kapalı. (CPD)
// Flash Program Belleği pasif. (WRT)
// Hata ayıklama kapalı. (DEBUG)
#use delay(clock = 20M)
// CCS C Complier'a 20MHz'lik osilatör kullanılacağı bildiriliyor.
// Zaman fonksiyonlarının kalibre edilmesi için derleyici tarafından kullanılır.
#define role_kontrol PIN_D0 // Röle kontrol pini, PORTD’nin 0. pinine bağlı.
#define mavi_led PIN_D1 // Mavi led, PORTD’nin 1. pinine bağlı.
#define yesil_led PIN_D2 // Yeşil led, PORTD’nin 2. pinine bağlı.
#define sari_led PIN_D3 // Sarı led, PORTD’nin 3. pinine bağlı.
#define kirmizi_led PIN_D4 // Kırmızı led, PORTD’nin 4. pinine bağlı.
#define start_led PIN_D6 // Start ledi, PORTD’nin 6. pinine bağlı.
#define stop_led PIN_D5 // Stop ledi, PORTD’nin 5. pinine bağlı.
#define buzzer_port PIN_D7 // Buzzer kontrol sinyali, haberleşme hattı.
#define gecikme 250
#use fast_io(d) // PORTD programcı tarafından yapılandırılacak.
#use fast_io(c) // PORTC programcı tarafından yapılandırılacak.
#endif
void sistem_test(void);
// Fonksiyon prototipi derleyiciye bildiriliyor.
void main(void)
// Ana program bloğu
{
   const float a=5000.0/1024.0;
   // Analog çözünürlük için kontrol değişkeni tanımlanıyor.
   // Çözünürlük 4,88 mV dolaylarındadır.
   float mV,derece;
   unsigned int sicaklik;
  
   set_tris_d(0x00);
   // PORTD dijital çıkış olarak kullanılacak.
   output_d(0x00);
   // PORTD’nin içeriğini temizle.
  
   set_tris_c(0x00);
   // PORTC dijital çıkış olarak kullanılacak.
   output_c(0x00);
   // PORTC’nin içeriğini temizle.
   sistem_test();
   // Sistem test fonksiyonunu çağır.
   setup_adc(ADC_CLOCK_INTERNAL);
   // +5V – 0V referans değerleri dikkate alınarak ADC donanımı kullanılacak.
   setup_adc_ports(ALL_ANALOG);
   // PIN_A0 analog giriş olarak kullanılacak.
   set_adc_channel(1);
   // AN1 girişinden analog sinyal okunacak.
   delay_us(50);
   // 50 mikro saniye zaman gecikmesi.
   // ADC donanımının tepkiye cevap verme süresi dikkate alınarak yapılandırılır.
   output_low(role_kontrol);
   // Rölenin normalde kapalı kontakları üzerinden ana kontrol rölesi
   // çalıştırılmaktadır.
   output_low(buzzer_port);
   while(1)
   // Sonsuz Döngü
   {
      sicaklik = read_adc();
      // AN1 kanalından analog sinyal okunuyor.
      // Okunan analog değer sicaklik değişkenine yazılıyor.
      delay_us(50);
      // 50 mikro saniye gecikme.
      mV = sicaklik * a;
      // Okunan analog gerilim değeri tespit ediliyor.
      derece = mV / 10.0;
      // Analog gerilim değerinden ortam sıcaklığı bulunuyor.
      if(derece < 25.0)
       // Okunan sıcaklık değeri 25 dereceden düşükse;
      {
         output_low(yesil_led);
          // Yeşil ledi söndür.
         output_low(sari_led);
         // Sarı ledi söndür.
         output_low(kirmizi_led);
         // Kırmızı ledi söndür.
         output_high(mavi_led);
         // Mavi ledi yak.
         output_low(buzzer_port);
         // Buzzer pasif kalsın.
         output_low(role_kontrol);
         // Röle pasif kalsın.
      }
      if( (derece >= 25.0) && (derece < 45.0))
       // Okunan sıcaklık değeri 25 dereceden yüksek
       // 45 dereceden düşükse
      {
         output_high(yesil_led);
         // Yeşil led yansın.
         output_low(sari_led);
         output_low(kirmizi_led);
         output_low(mavi_led);
         output_low(buzzer_port);
         output_low(role_kontrol);
      }
      if( (derece >= 45.0) && (derece < 55.0))
       // Okunan sıcaklık değeri 45 dereceden yüksek
      // 55 dereceden düşükse
      {
         output_low(yesil_led);
         output_high(sari_led);
         // Sarı led yansın.
         output_low(kirmizi_led);
         output_low(mavi_led);
         output_low(buzzer_port);
         output_low(role_kontrol);
      }
      if( (derece >= 55.0) && (derece < 60.0))
       // Okunan sıcaklık değeri 55 dereceden  yüksek
      // 60 dereceden düşükse
      {
         output_low(yesil_led);
         output_low(sari_led);
         output_high(kirmizi_led);
         // Kırmızı led yansın.
         output_low(mavi_led);
         output_low(buzzer_port);
         output_low(role_kontrol);
      }
      if( (derece >= 60.0) && (derece < 65.0))
       // Okunan sıcaklık değeri 60 dereceden yüksek
       // 65 dereceden düşükse
      {
         output_high(mavi_led);
         // Mavi led yansın.
         output_high(yesil_led);
         // Yeşil led yansın.
         output_high(sari_led);
         // Sarı led yansın.
         output_low(kirmizi_led);
         output_high(buzzer_port);
         // Buzzer aktif.
         output_low(role_kontrol);
         delay_ms(1500);
         // 1.5 saniye zaman gecikmesi.
      }
      if( (derece >= 65.0) && (derece < 70.0))
       // Okunan sıcaklık değeri 65 dereceden yüksek
       // 70 dereceden düşükse
      {
         output_high(mavi_led);
         // Mavi led yansın.
         output_high(yesil_led);
         // Yeşil led yansın.
         output_high(sari_led);
         // Sarı led yansın.
         output_high(kirmizi_led);
         // Kırmızı led yansın.
         output_high(buzzer_port);
         // Buzzer aktif.
         output_low(role_kontrol);
         delay_ms(1500);
         // 1.5 saniye zaman gecikmesi
      }
      if(derece > 70.0)
       // Okunan sıcaklık değeri 70 dereceden yüksekse
      {
         output_high(role_kontrol);
         // Yakıt hücresi devre dışı kalsın.
         delay_ms(5000);
         // 5 saniye zaman gecikmesi
      }
   }
}  
void sistem_test(void)
{
   int8 sayac = 0;
   int8 kontrol = 0b00000010;
   output_high(stop_led);
   // Kontrol devresi çalışmıyor.
      while(1)
      // Grup ledleri test et. 
      {
        output_d(kontrol);
        // kontrol değişkeninin içeriğini PORTD’ye yaz.
        delay_ms(gecikme);
        // gecikme sabiti kadar zaman gecikmesi.
        kontrol = kontrol < 1;
        // kontrol değişkeni içeriğini 1 bit sola kaydır.
        sayac++;
        // sayac değişkeninin 1 arttır.
        if(kontrol == 0b00010000)
         // kontrol değişkeninin içeriği 0b00010000 olduysa eğer;
        {
            while(1)
             // Sonsuz döngü
            {
                output_d(kontrol);
                delay_ms(gecikme);
                kontrol = kontrol > 1;
                sayac ++;
                if(kontrol == 0b00000010);
                    break;
            }
            if(kontrol == 0b00000010);
                break;
        }
        tekrar:
         if(sayac == 25)
         // sayac 25 değerine eriştiğinde test programını sonlandır.
            break;
      }
         output_d(0x00);
             // PORTD’yi sıfırla.
         output_low(stop_led);
             // STOP ledi pasif.
         output_high(start_led);
             // START ledi aktif.
      return;
             // Ana programa dön.
}


PIC16F84A MCU Kaynak Kod
#include <16f84a.h>
// PIC16F84A mikrodenetleyicisine ait header dosyasını projeye ekle. 
#fuses XT, NOWDT, NOPUT, NOPROTECT
// XT 4 MHz kristal osilatör kullanılacak.
// WDT konfigürasyon sigortası kapalı.
// Power-up Timer konfigürasyon sigortası kapalı.
// Kod koruma özelliği kapalı. 
#use delay(clock = 4M)
// Zaman fonksiyonları 4MHz'lik kristal osilatör kullanılacağı
// belirtilerek yapılandırılsın.
#use fast_io(b)
// PORTB programcı tarafından yapılandırılacak.
#use fast_io(a)
// PORTA programcı tarafından yapılandırılacak. 
#define kirmizi_led PIN_B1
// Kırmızı led PORTB'nin 1. pinine bağlanacak.
#define yesil_led PIN_B2
// Yeşil led PORTB'nin 2. pinine bağlanacak.
#define buzzer PIN_B0
// Buzzer sürücü kontrol pini PORTB'nin 0. pinine bağlı. 

void main(void)
// Ana program
{
   int1 bit_test, sayac = 0;
   // 1 bitlik değişkenler tanımlanıyor. 0 veya 1 değerini alabilirler. 
  
   set_tris_b(0x00);
   // PORTB dijital çıkış olarak kullanılacak. 
   output_b(0x00);
   // PORTB pinlerinin temizle.
   set_tris_a(0xff);
   // PORTA dijital çıkış olarak kullanılacak. 
  
   while(1)
   // Sonsuz Döngü
   {
      bit_test = input(PIN_A0);
      // RA0 pinini oku ve bit_test değişkenine yaz.     
      if(bit_test == 1)
      // RA0 pininde +5V analog sinyal değeri varsa;
      {
         output_high(kirmizi_led);
         // Kırmızı ledi yak.
         output_low(yesil_led);
         // Yeşil ledi söndür. 
         output_high(PIN_B0);
         // Buzzer'ı sür.
         delay_ms(100);
         // 100 ms bekle.
         sayac = 1;
         // sayac değişkenine 1 değeri yaz. 
      }
      else
      // RA0 pinindeki analog değer +5V değilse;
      {
         output_low(kirmizi_led);
         // Kırmızı ledi söndür. 
         output_high(yesil_led);
         // Yeşil ledi yak.
         output_low(PIN_B0);
         // Buzzer pasif.
      }
     
      if(sayac == 1)
      // Eğer RA0 pininden okunan değer dijital 1 ise;
      {
         delay_ms(2500);
         // 2.5 saniye bekle.
         sayac = 0;
         // sayac değişkenini sil. 
      }
   }
}


Hiç yorum yok:

Yorum Gönder