Tüm yazılar
Programlama İpucu

R_TRIG Sandım, F_TRIG Yazdım: Alarmı Yakalamak İçin Ters Kenarı Seçtim

Bir alarmı tetiklemek için yükselen kenar (R_TRIG) sandım, alçalan kenar (F_TRIG) yazdım. Kenar tetiklemenin '0'dan 1'e' mi '1'den 0'a' mı geçtiği anı yakaladığını, ve kenarı ters seçince alarmın neden asla tetiklenemediğini kendi vaka üzerinden anlatıyorum.

R_TRIG Sandım, F_TRIG Yazdım: Alarmı Yakalamak İçin Ters Kenarı Seçtim

Perşembe, gece. Bir “kapak açık” alarmını sayaç olarak sayıyordum — günde kaç kez kapak açılıyor, istatistik için. Sayaç hiç artmıyordu. Kapak günde onlarca kez açılıp kapanıyordu, sayaç 0 kaldı. Ben de “tetikleme bozuk mu?” dedim. Bozuk değildi; ben, “yükselen kenar” sandığım bir bloğu, “alçalan kenar” olarak yazmıştım. Ve aradaki fark, alarmın hiç yakalanmamasıydı.

R_TRIG ve F_TRIG, Farklı Anları Yakalar

Bir sinyali düşün: kapak kapalıyken 0, açıkken 1. Kapak açıldığında, sinyal 0’dan 1’e yükselir. Kapak kapandığında, 1’den 0’a alçalır.

R_TRIG (yükselen kenar tetikleyici), sinyalin 0’dan 1’e geçtiği tek scan’da çıkışı ON yapar. Yani kapak açıldığı an.

F_TRIG (alçalan kenar tetikleyici), sinyalin 1’den 0’a geçtiği tek scan’da çıkışı ON yapar. Yani kapak kapandığı an.

Ben “kapak açıldığında say” istiyordum. O, R_TRIGti. Ben ne yazmıştım? F_TRIG. Yani ben, kapak kapanırken sayıyordum. Peki neden sayaç hiç artmadı? Çünkü…

Neden Hiç Artmadı: Kenar, “Bir Scan” Sürer

Kenar tetikleyicinin çıkışı, yalnızca bir scan boyunca ON’dur. Sonra 0’a döner. Ben sayacı, o çıkışla artırıyordum:

#FTRIG_KAPAK(CLK := #kapak_acik);
if (#FTRIG_KAPAK.Q)  #kapak_sayaci := #kapak_sayaci + 1;

Bu, kapak kapandığında (1’den 0’a) bir kez artardı. Kapak gerçekten kapanıyordu, o yüzden sayaç artmalıydı. Ama artmadı, çünkü sayaç artırma satırı, F_TRIG’in çıkışının ON olduğu o tek scan’da çalışıyor, ve ben o scan’ı kaçırmıştım — çünkü #kapak_acik sinyali, PLC’nin okuma hızı yüzünden, kenar oluşmadan çoktan 0 olmuştu. Kapak mekanik olarak hızlı kapanıyordu; 0’dan 1’e geçen 1, bir scan penceresine sığmıyordu. Kenar, “görülmeyen” bir scan’da oluşup geçiyordu.

Çözüm: doğru kenarı seç, ve sinyali filtrele. İstatistik “kapak kaç kez açıldı” istiyorsa, R_TRIG kullan:

#RTRIG_KAPAK(CLK := #kapak_acik);
if (#RTRIG_KAPAK.Q)  #kapak_acik_sayaci := #kapak_acik_sayaci + 1;

Ve eğer sinyal çok hızlıysa, kenarı yakalamadan önce kısa bir yazma (debounce) koy — 20-50 ms. Kenar, “gürültüsüz” bir kenar olsun.

Kural: Kenarı, “Ne Zaman Tetiklenmeli?” Sorusuyla Seç

Artık kuralım şu: bir kenar tetikleyici kullanırken, “bu olayın başlangıcı mı, bitişini mi sayıyorum?” diye sor. Başlangıcı = R_TRIG, bitişini = F_TRIG. İkisi birbirinin tersi anıdır; tersini seçersen, ya asla tetiklenmez (kenar o sinyalde oluşmuyorsa), ya da tam tersi olayı sayarsın.

Bir de ek: kenar tetikleyicinin çıkışının bir scan sürdüğünü unutma. O bir scan’ı kaçırırsan, olay gitti. Önemli bir olayı sayıyorsan, kenarın gürültüsüz olacağından emin ol — ya debounce, ya da sinyali bir ara değişkene (latch) yazıp o ara değişkenin kenarını al.

O perşembe, o “artmayan sayaç,” bir R_TRIG ve 30 ms debounce ile gitti. Sayaç, o gece, kapak açıldıkça artmaya başladı. Ben de o an anladım ki, F_TRIG bana kapak kapanışını vermişti; ben de açılışı saymak istiyordum. Kenar, olayın hangi “yüzünü” saydığının tek anahtarıydı ve ben, anahtarı ters çevirmiştim.

Bir sonraki yazıda, “aynı tag’e üç farklı network’ten yazıyordum” diye anlatıyorum. Bir değişkenin, bir scan içinde birden fazla yere yazılmasının neden “son yazan kazanır” (last-writer-wins) kuralı olduğunu, ve bu kuralın neden bir adımı sessizce ezdiğini.