PIC16F628A ile Tek Buton Kontrollü 4 Aşamalı Akıllı Röle Devresi

guclusat

Tanınmış Üye
Süper Moderatör
Daha önceki projelerimizde geliştirdiğimiz eksi tetik (GND active) mantığını bir adım öteye taşıyarak, tek bir buton üzerinden sırayla farklı çıkış senaryolarını yönetebileceğimiz 4 aşamalı (State Machine) akıllı röle kontrol devresini tamamladık. PIC16F628A mikrodenetleyici tabanlı bu projede, buton basış sayılarına göre çıkışların dinamik olarak nasıl kontrol edildiğini inceleyeceğiz.

Devre Çalışma Mantığı ve AşamalarSistem, kullanıcı butona bastığında debounce (kararlılık) filtresinden geçerek aşağıdaki 4 adımlı döngüyü sırasıyla gerçekleştirir:

  • 1. Basış: Sadece 1. Çıkış (PORTB.F0) aktif hale gelir.
  • 2. Basış: 1. çıkış aktif kalmaya devam ederken, 2. Çıkış (PORTB.F1) de sisteme dahil olur (Her iki çıkış aynı anda çalışır).
  • 3. Basış: 2. çıkış devre dışı bırakılır, sistem yalnızca 1. çıkışın açık olduğu konuma geri döner.
  • 4. Basış: 1. çıkış da kapatılır ve sistem tamamen başlangıç (her şey kapalı) konumuna döner. Kullanıcı tekrar butona basana kadar bu kapalı konum korunur.
Yazılım ve Donanım Detayları

  • Mikrodenetleyici: Microchip PIC16F628A (Dahili osilatör / INTOSC kullanılmıştır).
  • Tetikleme Tipi: Eksi Tetik (GND / 0V mantığı).
  • Yazılım Dili ve Derleyici: MikroC PRO for PIC.
  • Kararlılık: Parazitleri ve çift tetiklenmeleri önlemek için 250ms debounce ve 150ms bekleme süreleri eklenmiştir.
MikroC Kaynak Kodu
Kod:
void main() {
    unsigned char adim = 0; // Adım sayacımız (0, 1, 2, 3)

    // Tüm analog birimleri kapat, PORTA ve PORTB tamamen dijital olsun
    CMCON = 0x07;
    VRCON = 0x00;

    // Pin yönleri: RA0 giriş (tetik), PORTB.0 ve PORTB.1 çıkış
    TRISA = 0b00000001;
    TRISB = 0b00000000;

    // Başlangıçta tüm çıkışlar kapalı (0)
    PORTB.F0 = 0;
    PORTB.F1 = 0;

    while(1) {
        // RA0 pinine EKSİ (GND / 0V) sinyal geldi mi?
        if (PORTA.F0 == 0) {
            Delay_ms(250); // Kararlılık (debounce) gecikmesi

            // Kısa bir süre sonra hâlâ basılı/eksi seviyede mi diye kontrol et
            if (PORTA.F0 == 0) {
                
                // Her basışta adımı bir artır (0 -> 1 -> 2 -> 3 -> 0...)
                adim++;
                if (adim > 3) {
                    adim = 0;
                }

                // Adımlara göre röle/çıkış durumlarını belirle
                switch(adim) {
                    case 0: // Başlangıç / 4. Basış Sonrası: Her şey kapalı
                        PORTB.F0 = 0;
                        PORTB.F1 = 0;
                        break;

                    case 1: // 1. Basış: Sadece 1. Çıkış Açık
                        PORTB.F0 = 1;
                        PORTB.F1 = 0;
                        break;

                    case 2: // 2. Basış: 1. ve 2. Çıkışlar Birlikte Açık
                        PORTB.F0 = 1;
                        PORTB.F1 = 1;
                        break;

                    case 3: // 3. Basış: 2. Çıkış kapanır, sadece 1. Çıkış kalır
                        PORTB.F0 = 1;
                        PORTB.F1 = 0;
                        break;
                }

                // Tetiğin (butonun) kaldırılmasını/bırakılmasını bekle
                while (PORTA.F0 == 0) {
                    Delay_ms(10);
                }

                // Çift tetiklenmeyi önlemek için kısa bekleme
                Delay_ms(150);
            }
        }
    }
}
 
PIC16F628A Akıllı Röle Kontrolü: Kısa ve Uzun Basış (Dual-Action) Özelliğinin Eklendiği 2. Aşama

Gelişmiş Buton Algılama (Kısa / Uzun Basma Mantığı)


Projemizin ilk aşamasında tek butonla 4 adımlı (State Machine) bir geçiş döngüsü kurmuştuk. Sisteme kullanım kolaylığı ve esneklik kazandırmak adına buton tetiğine iki farklı işlev ekleyerek algılama mantığını geliştirdik:
  1. Kısa Basış (Tıklama): Butona kısa süreli basıp bırakıldığında sistem standart 4 aşamalı sırasını izlemeye devam eder:
    • 1. Tıklama: Sadece 1. Çıkış (PORTB.F0) aktif.
    • 2. Tıklama: 1. ve 2. Çıkış (PORTB.F1) birlikte aktif.
    • 3. Tıklama: 2. Çıkış kapanır, sadece 1. Çıkış açık kalır.
    • 4. Tıklama: Tüm çıkışlar kapatılır ve sistem sıfırlanır.
  2. Uzun Basış (Basılı Tutma - 1 Saniye): Butona adımları tek tek gezmeden direkt müdahale etmek istediğimizde, butona yaklaşık 1 saniye boyunca basılı tutmamız yeterlidir. Sistem uzun basışı algıladığı anda sırayı atlayarak doğrudan 1. ve 2. Çıkışları aynı anda devreye sokar.

Güncellenmiş MikroC Kaynak Kodu:​

Kod:
void main() {
    unsigned char adim = 0;        // Adım sayacımız (0, 1, 2, 3)
    unsigned int basma_suresi = 0; // Uzun basma için zaman sayacı

    // Tüm analog birimleri kapat, PORTA ve PORTB tamamen dijital olsun
    CMCON = 0x07;
    VRCON = 0x00;

    // Pin yönleri: RA0 giriş (Eksi Tetik), PORTB.0 ve PORTB.1 çıkış
    TRISA = 0b00000001;
    TRISB = 0b00000000;

    // Başlangıçta tüm çıkışlar kapalı (0)
    PORTB.F0 = 0;
    PORTB.F1 = 0;

    while(1) {
        // RA0 pinine EKSİ (GND / 0V) sinyal geldi mi?
        if (PORTA.F0 == 0) {
            Delay_ms(50); // Kararlılık (debounce)

            if (PORTA.F0 == 0) {
                basma_suresi = 0;
                
                // Kullanıcı buton basılı tuttuğu sürece basma süresini hesapla
                while (PORTA.F0 == 0) {
                    Delay_ms(20);
                    basma_suresi++; // Her 20ms'de bir sayacı artır
                    
                    // Yaklaşık 1 saniye (50 x 20ms = 1000ms) basılı tutulduysa döngüden çık
                    if (basma_suresi > 50) {
                        break;
                    }
                }

                // --- UZUN BASMA KONTROLÜ ---
                if (basma_suresi > 50) {
                    // Doğrudan 1. ve 2. çıkış aynı anda aktif
                    PORTB.F0 = 1;
                    PORTB.F1 = 1;
                    adim = 2; // Adım durumunu senkronize et
                }
                // --- KISA BASMA KONTROLÜ ---
                else {
                    adim++;
                    if (adim > 3) {
                        adim = 0;
                    }

                    switch(adim) {
                        case 0: // Her şey kapalı
                            PORTB.F0 = 0;
                            PORTB.F1 = 0;
                            break;
                        case 1: // Sadece 1. Çıkış açık
                            PORTB.F0 = 1;
                            PORTB.F1 = 0;
                            break;
                        case 2: // 1. ve 2. Çıkış açık
                            PORTB.F0 = 1;
                            PORTB.F1 = 1;
                            break;
                        case 3: // 2. Çıkış kapalı, 1. Çıkış kalır
                            PORTB.F0 = 1;
                            PORTB.F1 = 0;
                            break;
                    }
                }

                // Butonun tamamen bırakılmasını bekle
                while (PORTA.F0 == 0) {
                    Delay_ms(10);
                }

                // Çift tetiklenmeyi önlemek için bekleme
                Delay_ms(150);
            }
        }
    }
}
 
Geri
Yukarı