Arduino Basit Frekansmetre yapımı.

Bu yazımda sizlere Arduino kullanarak basit olarak nasıl frekans ölçebileceğinizi anlatacağım. Biraz daha gelişmeye ihtiyacı var. Fakat temel kısmı burası olduktan sonra sizlerin katkı yaparak geliştirebileceğinizi umuyorum.
Burada sadece arduino  komut yada fonksiyonlarını değil, yüksek frekansları da ölçebileceğiniz metotlar üzerinde durulacak.

Frekansmetre sadece frekansı göstermez periyodunu ve pals’in nasıl bir pals olduğunu da bize gösterebilecektir.
Dikkat edeceğimiz nokta Arduino 5V tan büyük sinyal genliğinde problem yaşayabilecektir. Bundan dolayı gerektiğinde sinyalin gerilim seviyesini düşürmeyi de eklemeniz gerekir. Genlik bizim için sorun teşkil etmesin diyorsak 5V luk zener diyot ile fazlalık gerilimleri kırpabiliriz. Kırpma işleminde frekans etkilenmez. 

Frekansmetre 2 şekilde yapılabilir.

1-) Pals’in periyodunu ölçüp f=1T kuralından hesaplama yapabilirsiniz. Burada periyot ölçtüğünüz için dalga şekli hakkında da fikir sahibi olabilirsiniz. ( PULSIN kullanımı)
2-) Belirli bir süre içerisinde gelen palsleri sayabilirsiniz. (Millis Kullanımı)

PIC işlemci kullananlar hazır yapılmış bir örneği bu sayfadan bulabilirler.
Mantık benzerdir. 

1- Pals periyodu ölçerek ( PULSIN )

kare dalga Bu kare dalganın gördüğünüz gibi high ve low kısımları birbirine eşit. Zaman zaman bu kısımlar birbirine eşit olmayabilir. Frekans
(T) periyot değeri kadar gösterilecektir. Arduino hem High seviyesini hem de Low seviyesini ayrı ayrı ölçtüğünden sinyalin nasıl bir sinyal olduğunu da fark edebilirsiniz.
Hatta geliştirip grafik ekranda resmi çizdirebilirsiniz.
Arduino ölçme yaparken dijital bir giriş bekler. bundan dolayı sinüs dalga geldiğinde bunu kare dalgaya çevirmemiz gerekir. Bunu yapabilmek için hızlı çalışan (Schmitt-Trigger) 7414 entegresi ile kare dalgaya çevrilir. Aşağıdaki şekil ideal olandır fakat gerçekte kullanacağınız entegrenin sınırlarına göre High ve Low kısımlarında küçük değişiklikler olabilmektedir.
sinuskareBu şekilde sinüs dalga kare dalgaya çevrilecektir.
Entegrenin Datasheet’ine buradan ulaşabilirsiniz.
Ayrıca entegrenin iç yapısına bakarsanız bir parçasını kullandığınızda çıkış sinyali giriş sinyalinin tersi olduğunu görürsünüz. Bunu entegrenin 2 parçasını kullanarak tersinin, tersi= kendisidir kuralı olarak düzenledim. Düzenlemeye ihtiyaç varmıydı? Normalde tek parçası da iş görür fakat siz sinyalin High seviyesi uzun derken aslında High seviyesi kısa bir sinyalle uğraşıyor olabilirsiniz. Bundan dolayı orijinal sinyali yakalamak için 2 parçasını seri olarak kullandım. 

Videoda DUTYcycle anlatılmaya çalışıldı. Dutycycle nedir. Genelde PWM sistemlerde kullanılan bu terim. Sinyalin periyodunu anlatmak için kullanılır. Bir periyot içerisinde High ve Low kısımlarının birbiriyle farkını gösterir. 1 periyot = %100 olarak ifade edilir. %50 dutycycle denildiğinde High=%50 Low=%50 kısmıdır. Bu frekans ölçümü için idealdir. İsterseniz %10 duty cycle sinyalide kullanabilirsiniz fakat burada Low seviyesi uzun olduğunda arduinonun sayma limiti dışına çıkabileceğinden tam periyodu hesaplamak zor olacaktır. Bundan dolayı mümkün olduğu kadar %50 civarı dutycycle bulunması avantajdır. biz bunu nerede kullandık, Bölücü entegrelerde her bacaktan Frekans/10 sinyali alabilirsiniz fakat ideal olanı %50 %50 olanıdır bundan dolayı şemadaki bağlantı şekli kullanılmıştır.
Aşağıdaki tablodan Bu işlemi daha net görebilirsiniz. 
dutycycle

Devremize gelince, Devre proteus üzerinde çizildi ve UNO ile çalışması sağlanacak şekilde dizayn edildi. NANO ile de çalıştırabilirsiniz.

şemaŞemada göreceğiniz gibi dip switchler mevcut. Bu 4 lü switch sinyallerin arduino tarafına geçişte ayırıcı olarak kullanılmasını sağlıyor. Neden buna ihtiyaç var derseniz Arduinonun ölçebileceği frekansların daha yükseğini ölçebilmesini sağlamak amaçlıdır. Gördüğünüz 4017 entegreler Frekans bölücü olarak çalışır. 1000000 Hz frekansı ölçmek sorun oluyorsa frekansı bölerek 1000000Hz / 10 = 100000Hz olarak ölçeriz ayrıca bu da sorun oluyorsa bunu da 10’a bölerek 100000Hz/10=10000Hz olarak ölçebiliriz. hatta daha da bölebiliriz. 4017 entegreleri ardarda bağlayabiliriz.
4017 entegresi yerine 7490 binary sayıcı entegresini de kullanabiliriz. Ya da 10 lu sayıcı bölücü entegreleri kullanabiliriz. Hatta sadece 10lu olması gerekmez çeşitli frekansları bölen özel bölücüler bulunmaktadır bunları da frekans bölücü olarak kullanabiliriz.
4017 entegre datasheet
7490 entegre datasheet
4521 özel bölücü entegre  datasheet. bu entegre belirlenen değerlerde bölme işlemi yapar.
Bölme tablosu aşağıdaki gibidir.

deviderBu tablodan da göreceğiniz gibi 10, 100 gibi bir standart yok. bu tip frekans bölücüler devrede bulunanlar gibi değil içinden sayarlar ve bağlantılı olan çıkıştan bölünerek bir pals çıkışı verir. Bu değere göre arduino yu ayarlayabilirsiniz. Bu Entegre çalışma voltajına göre  6-35Mhz arası çalışabilmektedir.
4017 entegresi 5Mhz civarına kadar çalışabilmektedir. 7490 entegresi ise 42Mhz frekansına kadar çalışabilmektedir. Bu değer ne kadar büyükse o entegreyi kullanıp frekansı bölmek bizim için daha iyi olacaktır. Çünkü yüksek frekansları ölçebilmek için böldüğümüz entegrenin de o frekansta stabil bir şekilde çalışması gerekir.

Programa bir bakalım bütün bunları nasıl yapıyoruz. PULSIN ayrıntılı bilgi
Burada pulsein komutunu kullanıyoruz. gelen sinyalin High seviyesinin kaç mikrosaniye olduğunu 37. satırda pulsin komutuyla buluyoruz.
Komut kullanımı: Htime=pulseIn(8,HIGH); bu satırda 8 arduino’nun input pimi. sinyali algılar. HIGH ifadesi ise High seviyesinde pals varsa say demektir. burada High seviyesinin kaç mikro saniye olduğunu bulup LOW seviyesine düştüğünde de 33 satırdaki gibi kullanıyoruz.
Bu iki sayıyı topladığımızda ise bize periyotu verir. Periyot ne işimize yarar. Aşağıdaki formül ile frekansı bulabiliriz.
Frekans= 1 / T (periyot zamanı saniye olarak yazılacaktır. )
Videoda LCD nin gösterdiği H ve L sinyal zamanlarını toplayıp bu formülden frekansı bulabilirsiniz.
40. satır ve 43. satırda bir açıklama vardır. Pulsin komutunun bir parametresi (Timeout) vasıtasıyla sinyal gelmediğinde hızlı bir şekilde öğrenmemizi sağlayacaktır.  Şayet bu parametre kullanılmazsa maksimum timeout süresi olacağından bu süreye kadar program beklemek zorunda kalacaktır. Videoda bu parametre kullanılmamıştır. Bu parametreyi kullanırsanız sonuç daima sıfır çıkar. Timeout dediğimiz mantık bu süre içerisinde değişim olmazsa mantığıdır. Mesela büyük frekanslarda timeout aşılmazken küçük frekanslarda timeout süresine denk gelir. bunu ayarlayamazsınız. Ne yapabiliriz? Burada yapabileceğimiz bir sinyal geldiğinde sadece High seviyesini kontrol etmek için timeout kullanan pulsin komutunu hesaplamadan önce ekleriz. ve if komutuyla geldiyse hesapla gelmediyse sinyal yok yaz diyebiliriz.

//#include 
//LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
int freq;
int val;
int val1;
int bol;
float Htime;              //integer for storing high time
float Ltime;                //integer for storing low time

float Ttime;            // integer for storing total time of a cycle
float frequency;        //storing frequency
String stringOne =  String(freq);
String stringtwo =  String(bol);
String strHtime =  String(Htime);
//String strLtime =  String(Ltime);
void setup()
{
    Serial.begin(9600);
    pinMode(8,INPUT);
    pinMode(2,INPUT);
    pinMode(3,INPUT);
    Serial.print("LCDDD");
    delay(100);
    Serial.print("LCDWR 1,1-FREKANSMETRE Hz.");
    
   
    //  lcd.begin(16, 2);
    bol=1;
}


void loop()
{
  //  lcd.clear();
  //  lcd.setCursor(0,0);
  //  lcd.print("Frequency of signal");
    Htime=pulseIn(8,HIGH);      //High süresini  mikroSaniye olarak ölçüyor.
    Ltime=pulseIn(8,LOW);        //Low süresini mikroSaniye olarak ölçüyor.

// timeout süresini pals geldimi diye üst satırda kontrol edip pals gelmediyse gerçek pulsin komutuna girmemesini sağlayabilirsiniz
 //  bu şekilde gerçek te kullanıldığında timeout kadar bekler ve 1 seviyesi değişmediyse döngüden olumsuz cevapla çıktığından frekans devamlı 0 olacaktır. 
 // timeout ayarı neden önemli timeout yazılmazsa pals gelmediğinde maksimum timeouta kadar bekler ki bu en uzun süredir. ve sonuç almak uzun sürer. 
 //  bundan dolayı timeout parametresiyle bir üst satırda palsin gelip gelmediğini kontrol etmek işinizi güzelleştirecektir. 
    
    
    val = digitalRead(2);       // x10  butonu devrede mi
    val1 = digitalRead(3);      // x100 butonu devrede mi
    if (val==0){
      bol=10;
    }
    else if(val1==0){
      bol=100;
    }
    else {
      bol=1;
      
      
    }
    
   // Ttime = Htime; //  standart pals ölçümü
    Ttime = Htime+Ltime; //  periyod süresi
  
    frequency=(1000000/Ttime);    //frekans hesaplaması
    freq=round(frequency);        // yaklaşık değere yuvarlama
  //  lcd.setCursor(0,1);
 //   lcd.print(frequency);
 //   lcd.print(" Hz");
  stringOne=freq;stringtwo=bol;strHtime=Htime;
 
 Serial.print("LCDWR 2,1-   "+stringOne+" Hz  X"+stringtwo)+"        ";  // EASYLCD de yazdırmak için. bol= X10 veya X100 gibi skala 
 delay(50);
  Serial.print("LCDWR 3,1-   "+strHtime);
  delay(50);
 Serial.print("LCDWR 4,1-   ");Serial.print(Ltime);
  //Serial.println(Htime);
  //Serial.println(Ltime);
 
    delay(200);
    
}

Program çıktısı:  Proteus compim komponenti ile birlikte  Seri haberleşmeli EASYLCD modülünü kullanan LCD göstergedir. Program da Kütüphane kullanan LCD satırları kapatılmıştır. Silinebilirdi. Fakat aradaki farkı görebilmeniz için kapatıldı. Bu haliyle LCD kütüphanesinin de kullanılmasına gerek yoktu hafızadan tasarruf edildi.
Kütüphaneye gerek bırakmayan örnek komutlar, aşağıdaki anlamları taşıyor.
Serial.print(“LCDDD”);  LCD yi temizle Komutu  (Display Delete – DD)
Serial.print(“LCDWR 1,1-FREKANSMETRE Hz.”);  LCD nin 1. satır birinci sütunundan başla ve yazıyı yaz. Komut: LCDWR 1,1- (WR=WRITE 1. satır , 1. sütun.)

 stringOne=freq;stringtwo=bol;strHtime=Htime;  İNT yada FLOAT gibi ifadeleri kolaylıkla yazmak için STRING şekline dönüştürüldü. 
Serial.print(“LCDWR 2,1-   “+stringOne+” Hz  X”+stringtwo)+”        “; Burada yazdırdık.
Başka şekilde de yazdırabilirdik.
Serial.print(“LCDWR 4,1-   “);Serial.print(Ltime); birinci serial komutuyla LCD komutunu,  ikinci serial komutuyla float sayıyı direkt olarak yazdırdık. Bu şekilde hex sayıları da yazdırabilirsiniz. 

EASYLCD Hakkında daha fazla bilgiye buradan ulaşabilirsiniz.
2-) Pals sayarak Frekans bulma. (MILLIS)Bu şekilde de frekans hesaplayabilirsiniz. Örnek programa bakarsanız sade ve anlaşılır durumdadır. 1. programda bulunan X1,X10,X100 bölümleri programa girilmedi. 1. programdan buraya kopyalayabilirsiniz. Frekansmetrenin basit olarak nasıl yapılabileceğini anladığınıza göre geliştirebilirsiniz.
Yukarıda değindiğimiz bir konu vardı Yüksek frekansları bölerken bölücü entegrenin çalıştığı frekans önemlidir dedik. Aşağıdaki linkte görüleceği üzere bu entegre 16 ya bölen bir entegre ve 5ns hızında çalıştığından yüksek frekans 200Mhz e kadar sinyalleri bölüp çalıştırabilirsiniz. SN54LV161A, SN74LV161A Datasheet
Bu şekilde yüksek frekansları bölerek Arduinoya verirseniz bölme hesabınıza göre X? olacak şekilde kullanıcıya bilgi verebilirsiniz.

// PULSIN programından çevrildiği için bu kadar değişken var.
// değişkenlerin hepsi kullanılmıyor.


int freq;
int val;
int val1;
int bol;
unsigned long tut;
float sayH ;
float sayL ;
float Htime;              //integer for storing high time
float Ltime;                //integer for storing low time

float Ttime;            // integer for storing total time of a cycle
float frequency;        //storing frequency
String stringOne =  String(frequency);
void setup()
{
    Serial.begin(9600);
    pinMode(8,INPUT);
    pinMode(2,INPUT);  // bolüntü için switch girişi
    pinMode(3,INPUT); // bolüntü için switch girişi
    Serial.println("LCDWR 1,1-FREKANSMETRE Hz.");
    bol=1;
}

void loop(){
 sayH=0;
tut=millis();
while ( millis() - tut <=1000 ) // 1000 rakamı 1sn lik pals yakala anlamındadır isterseniz yüksek frekanslarda 10ms ve 100ms ölçüm yapıp hesaplama yapabilirsiniz.
{
  if (digitalRead(8)==1 && val==0){
    val=1;sayH ++ ;
  }
  if (digitalRead(8)==0 && val==1){
    val=0; 
  } 
}

 stringOne=sayH;
Serial.println("LCDWR 2,1-   "+stringOne+" Hz  X"+bol);  // EASYLCD de yazdırmak için. bol= X10 veya X100 gibi skala bunu pulsin programından alabilirsiniz.
   delay(100);
}

Yine LCD de göstermek için EASYLCD Modül kullanıldığı için Kütüphaneye gerek duymayan EASYLCD komutu kullanıldı (serial.print kısmında. )

Frekansmetre_ PULSIN  dosyalar linktedir.

Frekansmetre_MILLIS dosyalar linktedir.

Ayrıca frekans metre mantığına yakından bakmak isteyenler bu siteye bakabilir

9 Comments

  1. Merhaba Şafak Bey. Elinize sağlık, güzel bir çalışma olmuş. Birkaç ekleme yapmak istiyorum. 4017 çipi CMOS olup 3-18V arasında besleme gerilimi ile kullanılabilir. 5V ‘ta max. 2-3 MHz civarında saat darbesi uygulanabilir. 15 V’da belirttiğiniz gibi 5 MHz’e ulaşır bu frekans. Bunun yerine HCMOS serisi yani 74HC4017 kullanılacak olursa 5V ‘ta 20 MHz saat darbesi uygulamak mümkündür. Bu çipte sayma çıkışları reset girişi ile kombine olarak kullanılmadığı taktirde her çıkışta fclk/10 yani saat darbesi frekansının 1/10 ‘u belirir. Ancak uygun bağlantılarla 2-10 arası bölmek mümkündür. Binary sayıcılarda bölme oranı 2’nin kuvvetleri şeklindedir. Decade yani onluk sayıcılarda 3,5,6,7,9,10 gibi oranları elde etmek kolaydır. Giriş işareti bölündükçe sayma değeri hassasiyetini yitirir. Yani 10 ‘a bölünmüş bir sinyali 10 Hz. hassasiyet ile sayabilirsiniz. Bölme oranı arttıkça bu hassasiyet azalmaya devam eder. Bu nedenle işareti bölmek için kaskad bağlı bölücüler kullanmak yerine kaskad bağlı yüksek hızlı sayıcılar kullanmak ve bu sayıcıların çıkışını okumak daha iyi bir fikir olabilir. Örneğin 3 adet kaskad bağlı 8 bitlik sayıcı ile 24 bitlik bir değer yani 16-17 MHz civarındaki bir frekansı bölmeden, çok hassas olarak saymak mümkün olacaktır.

    1. kusura bakmayın yorumunuzu geç gördüm. siteden bildirim gelmemişti. 74 serisi olanda haklısınız 7490 kullanılması da bu fikirlerden biriydi. yaklaşık 45 mhz. fakat sayıcı kısmı için düşünüyorum harici 24 bitlik bir sayıcının çıkışını arduino ile okumak için araya paralel seri çevirici entegreler girmesi lazım gibi geldi. port sarfiyatından dolayı. Dediğiniz gibi yüksek hızlarda bölmek yerine birim zamanda gelen palsi saymak kolay olacağından belki ikili çalışma gerekebilir. birincisi bölücü kullanılarak frekans kabaca belli olur ve belli bir yükseklikten sonra sayma işlemine dönerek ki arduinoda 24 bit ( sanırım float 24 bit sayıyordu) sayac koyup saydırılabilir. bu da alternetif olacaktır yapmak isteyenlere. 1ms de bir yada 10ms de bir. bu konuyu da sona eklediğim millis komutunun kullanımında görebilirsiniz sanıyorum.

  2. Merhaba iyi akşamlar.Ben Cep telefonu Dedektörü devresi ile ilgili çalışmaktayım.Bu devreye arduino kullanarak bir frekansmetre eklemek istiyorum bu konuda yardımcı olabilirmisiniz.Şimdiden teşekkür ederim.

    1. cep telefonu detektör dediğinizde yüksek frekansa giriyor sanırım. bu şekilde olduğunda bu tip devrelerin bunu çözmesi zor olur fakat buradaki mantıkla çalışacağınız frekans konusunda beni bilgilendirirseniz, belki frekans bölücü entegre bulunabilir bu şekilde frekansı ölçülebilecek boyuta getirip buradaki devre mantığına göre ölçebilirsiniz.

  3. Merhaba, bu değerli çalışmadan ötürü teşekkür ederim. Çokta ihtiyacım olan bir konuydu. Sayenizde öğrenmiş oldum. Aslında tam olarak 0 – 100hz arasını saymaya ihtiyacım vardı. Yinede yanlışlık yapmamak adına sormak isterim; istediğim frekans aralığı için devrede yapmam gereken değişikliğe değinirmisiniz.
    Teşekkür ederim.

    1. yukarıda 2 yol var dedim. sizin frekansınız düşük olduğundan doğru ölçüm için 1. yolu denemeniz iyi olur. yani periyot süresini ölçmek. Şayet yüksek frekans olsaydı o zaman pals saydırın derdim. çümnkü 1 ve sıfır seviyelerinin süreleri çok kısa olduğundan hata yapabilirdiniz. Fakat düşük frekanslarda periyot uzundur. ölçüm daha stabil olur. Sadece 1 hz 1sn olduğu için yani periyot 0.5sn 1 0.5sn 0 seviyesinde olur bundan dolayı ölçüm uzun sürer. sadece tepki süresi diyelim 1 sn. civarında olacaktır. Düşük frekans olunca beklemek normal..

      1. Şafak Bey girişte ki frekans düşük olsada, oldukça düzensiz. genliği sürekli değişmekte olan bir analog sinyal. Bu durumda, kare dalgaya çevrildiğinde sorun olmayacak mı?

  4. kare dalga da genlik şöyle önemlidir. dijital devreler 2V un üstünü 1 seviyesi yani high seviyesi olarak görür. kare dalgaya çevirirken buna dikkat etmelisiniz. bu seviyenin altına düşerse 0 seviyesi olarak göreceğinden periyot devamlı değişir. bundan dolayı sinyali güçlendirip genliğinin 2V un altına rastlansal düşmeyeceği bir kare dalga elde etmeniz gerekir. bunu yapamazsanız aldığınız değerler yanlış olur.

  5. Merhaba Şafak bey

    Ardıono konusunda yeni sayılırım

    Arduıno ile doğal frekans ölçümü cihazı yapmak. (Darbe yolu ile herhangi bir cismin , örenk : bir taşın doğal frekansını gibi ) Bu iş için Adruino UNO R3 Klon + 16×2 Karakter LCD Ekran I2C ve ayrıca Piezo Vibration Sensor 1.1v Modüllü aldım Sensor linki: https://wiki.seeedstudio.com/Grove-Piezo_Vibration_Sensor/

    Acemi olsamda güç bela ekranı çalıştırabildim en azından “Hello world ” yazdırmayı başardım :)) ondan öteye malaefes gidemedim bu konuda yardımlarınız bekliyorum . Bu işin altından nasıl ne şekilde çıkabilirm

Şafak Ağustoslu için bir cevap yazın Cevabı iptal et

E-posta hesabınız yayımlanmayacak.