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:
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.
- 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.
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);
}
}
}
}