AVR Zero-Cross Detector ile Frekans Okuyucu Uygulaması

İleri seviye AVR uygulamalarının sonuncusunda yine güzel bir analog uygulama yapacağız. Burada öncelikle zero-cross detector yapıp sonrasında bundan faydalanarak bir frekans okuyucu yapacağız.

Zero-cross detectoru özetlemek gerekirse değişken bir sinyaldeki sıfır noktalarını tespit etmeye yaramaktadır. Normalde bunu opamplar ile yapsak da burada sadece dijital ayağı kullanarak yapacağız. Üstelik frekans okuyucuyu da normalde zamanlayıcıları sayaç olarak kullanıp saat sinyalini hariçten alarak yapsak da bu sefer sadece zamanlayıcı olarak kullanarak yapacağız. Yapacağımız uygulamanın bir önceki ADC uygulaması gibi ilginç olacağını buradan anlayabilirsiniz.

Öncelikle zero-cross detector ile başlayalım. Bu fikri yine Atmel’in uygulama notlarında görüp elde ettim.
http://ww1.microchip.com/downloads/en/AppNotes/Atmel-2508-Zero-Cross-Detector_ApplicationNote_AVR182.pdf

Çalışma mantığını anlamanız için bu uygulama notuna kısaca göz atmanız yeterlidir. Burada prensip dijital devrelerin belli bir gerilim noktasında HIGH belli bir gerilim noktasında ise LOW konumuna geçmesine dayanmakta. Bu HIGH ve LOW eşiği ise sıfır noktası olmakta. Bu durumda değişken bir sinyal uyguladığımızda belli eşikleri geçince HIGH ve LOW sinyali elde ederiz. Bu elde etme anı da zero-cross olarak yorumlanabilir. Analog yönüyle gelişmiş mikrodenetleyicilerde ayrı bir birim olarak zero-cross detector olduğunu görebilirsiniz. Burada ise buna ucuz bir çözüm getirilmiştir. Uygulamada ise sadece zero-cross durumları algılanmayıp bu durumlara göre sinyalin frekansı hesaplanmıştır. O yüzden öncelikle bir sinyal üretici ile D2 ayağına sinyal uygulanması gereklidir. 0–5V kare dalga uygulayabilirsiniz. Bunun için daha önce “AVR ile Mikrodenetleyici Uygulamaları” kitabında anlattığımız kodu kullanabilirsiniz.

Frekans üretici kartın D9 ayağını kartımızın D2 ayağına doğrudan bağlamamız yeterlidir. Şimdi konu inceleyerek devam edelim.

Öncelikle bunu gerçekleştirmemiz için harici kesmeleri kullanmamız gerekli. Mikrodenetleyici hiç meşgul olmadan kesmeye gidecek ve zero-cross durumunu anında tespit edecek. Bunun için harici kesmeleri şu şekilde etkinleştirdik.

EICRA |= (1<<ISC01);
EIMSK |= (1<<INT0);

Burada düşen kenar kesmeyi tetikleyecek. Sonrasında ise zamanlayıcıyı her 1 saniyede bir kesmeye götürür şeklinde ayarlamaktayız. Bunun için OCR1A yazmacında OCR değerini belirleyerek yapmaktayız. Bunun formülünü datasheetten elde edeceğiniz gibi hesaplayıcı programlar vasıtasıyla da elde edebilirsiniz. Bundan sonra ise bütün işi kesmeler yapmaktadır. Şimdi bu kesme fonksiyonlarını inceleyerek devam edelim.

ISR(INT0_vect)
{
char temp;
for (temp= 0;temp< 10;)
{
if(!(PIND & (1<<PD2)))
temp++;
else
temp
= 0;
}
if(temp != 0)
{
zero_cross++;
}
}

Burada öncelikle parazitleri filtrelemek için belli bir miktar gecikme yapmaktayız. Sonrasında ise bunun zero-cross olduğunu anladıktan sonra zero_cross adında tanımladığımız sayaç değişkenini bir artırmaktayız. Her zero-cross durumunda bu değişken bir artacaktır.

ISR(TIMER1_COMPA_vect)
{
okuma = zero_cross;
zero_cross = 0;
sprintf(buf,"Zero-Cross/s : %ld \n", okuma );
uart_puts(buf);
}

Zamanlayıcı kesmesinde ise sayaç değişkenini sıfırlayıp elde ettiğimiz değeri ekrana yazdırıyoruz. Bu kesme bir saniyede bir yürütüldüğü ve zero-cross düşen kenarda saptandığı için çok kafa yormadan frekans değerini kolayca elde ediyoruz. Ben 1kHz sinyal uygularken şöyle bir çıktı elde ettim.

Burada biraz değer değişmesi biraz da offset hatası olduğunu görebiliriz. Bunu düzeltmek için kodda çeşitli değişiklikler yapma imkanımız vardır. Bu haliyle bile bazı uygulamalar için yeterli sonuç verdiğini söyleyebilirim.

Bu noktadan itibaren ileri seviye AVR uygulamalarını bitirmiş olduk. Yazılara dahil etmediğim birkaç uygulamayı Github deposundan bulabilirsiniz. Bu noktadan itibaren AVR hakkında yeterli eğitim kaynağını meydana getirdiğime inanıyorum.

Uygulamaların Github deposuna aşağıdan erişebilirsiniz.
https://github.com/GDokmetas/Ileri-AVR-Uygulamalari

--

--