duminică, 22 septembrie 2013

Frecventmetru cu.. Arduino

    Un aparat de masura foarte util celor care au pasiunea echipamentelor de telecomuncatii radio este frecventmetrul, adica aparatul care masoara frecventa.
    Pe site-ul lablll (interface.khm.de) am gasit articolul Arduino Frequency Counter Library scris de Martin Nawrath, care prezinta un frecvenmetru care face masuratori pana la 8MHz folosind o librarie proprie (pe care o puteti se descarca de la http://interface.khm.de/wp-content/uploads/2009/01/FreqCounter_1_12.zip).
   Atentie: intrarea semnalului se face doar pe pinul digital 5 al placii Arduino...
   Schema de conectare este foarte simpla constand dintr-un un preamplificator sau un inversor pentru a avea la intrare semnal logic compatibil cu microcontrolerul ATmega depe placa Arduino:

   Sketch-ul propus in acel articol e unul foarte simplu, afisarea frecventei facandu-se pe ecranul calculatorului (monitorizare seriala):
 #include <FreqCounter.h>  
   
 void setup() {  
  Serial.begin(57600);          // connect to the serial port  
  Serial.println("Frequency Counter");  
 }  
   
 long int frq;  
 Void loop() {  
   
  FreqCounter::f_comp= 8;       // Set compensation to 12  
  FreqCounter::start(1000);      // Start counting with gatetime of 1000ms  
  while (FreqCounter::f_ready == 0)     // wait until counter ready  
    
  frq=FreqCounter::f_freq;      // read result  
  Serial.println(frq);        // print result  
  delay(20);  
 }  

   Aceeasi librarie este folosita si in articolul Arduino Frequency Counter, de data asta afisarea facandu-se pe un ecran LCD cu 16 coloane si 2 randuri (cel care foloseste driver-ul DS44780 si notat, uneori, 1602):
   Schema de conectare este urmatoarea:
iar sketch-ul este:
 #include <FreqCounter.h>  
 #include <LiquidCrystal.h>  
   
 LiquidCrystal lcd(2, 3, 4, 6, 7, 8, 9); //Delcares LCD display pins  
 unsigned long frq; //Declares an extended size variable for the measured frequency  
 int cnt;  
   
 void setup() {  
    
  lcd.begin(16, 2); //LCD display columns and rows  
    
  lcd.print("FrequencyCounter"); //Prints a splash screen for 2 seconds  
  lcd.setCursor(0, 1);  
  lcd.print(" Version 2.1 ");  
  delay(2000);  
    
  lcd.clear();  
  lcd.setCursor(0, 0);  
  lcd.print("Frequency /Hz :"); //Prints "Frequency /Hz :"  
    
 }  
   
 void loop() {  
   
  FreqCounter::f_comp=10;  
  FreqCounter::start(1000);  
   
  while (FreqCounter::f_ready == 0)   
   
  frq=FreqCounter::f_freq; //Sets the 'frq' variable as the measured frequency  
    lcd.setCursor(0, 1);  
    lcd.print(frq); //Prints this measured frequency  
    lcd.print("    ");  
 }  

 
   Un alt articol, care foloseste aceasta librarie, facand si comparati intre masuratori cu acest frecventmetru si unul profesional, se numeste http://www.toddfun.com/2013/02/07/arduino-frequency-display-for-kenwood-ts-520s-hf-ham-radio-part-1/

   Ulterior am gasit un site frantuzesc, http://f5mna.free.fr/, care are publicat articolul Fréquencemètre VHF UHF Arduino Exploitation de la librairie "FreqCount"
   Acest frecventmetru masoara pana la 600MHz cu o rezolutie de 100Hz folosindu-se de un divizor dedicat, MB506 (datasheet-ul s epoate descarca de la http://www.qsl.net/n9zia/900/mb506.pdf, pus la intrarea placii Arduino sa divizeze cu 64.
   Partea de conectare si programele aferente se gasesc la adresa http://f5mna.free.fr/arduino/Freq_Arduino.zip, schema dedivizare fiind:
   Partea de afisare se poate adapta pentru domenii de Hz, kHz, MHz, inclusiv o autoscalare, prin conectarea divizorului si selectarea domeniului de divizare 64 sau 256, dar asta intr-un articol viitor...
   Pana una alta, prezint sketch-ul din articolul frantuzesc, cu explicatii ale liniilor din program:
 /*   
  //////////////// Fréquencemètre///////////////////  
    
  * Utilise le prédiviseur MB506 FUJITSU   
  * Les limites de la fréquence d'entrée Arduino et le division par 64  
  * autorisent un comptage jusqu'à environ 600 Mhz pour cette version.  
  * Pour mesurer une fréquence supérieure, le facteur de division sera  
  * de 128 ou 256 (Cf Datasheet).  
  * la ligne " unsigned long count = FreqCount.read() * 0.64001422;"  
  * sera modifiée en conséquence: 1.28 ou 2.56  
  * La valeur 001422 ci-dessus est une valeur d'ajustement.  
  *  
  * Mon site : http://f5mna.free.fr  
  *  
  *   
  * Entrée comptage PIN 5 dig.  
  */  
  // comentarii in romaneste de Nicu FLORICA aka niq_ro  
    
 #include <FreqCount.h> // foloseste libraria dedicata pentru a masura frecventa  
 #include <LiquidCrystal.h> // foloseste libraria dedicata pentru afisaj LCD gen 1602  
 LiquidCrystal lcd(8, 9, 4, 3, 6, 7); // indica modul de conectare al pinior afisajului la placa Arduino  
// LiquidCrystal lcd(RS, E, D4, D5, D6, D7); //se definesc pinii utilizati la afisajul LCD
   
 unsigned long count0, count1, count2, count3, count4, count5; // se definesc variabile de lungime mare de la 0 la 4.294.967.295 (2^32-1)  
   
 void setup() {  
  lcd.begin(16, 2); // definire LCD ca 16x2  
  lcd.setCursor(0, 0); // pozitionare cursor in colt stanga sus  
  lcd.print (" FREQUENCEMETRE "); // scrie textul  
  lcd.setCursor(0, 1); // muta cursorul in colj stanga jos  
  lcd.print ("F5MNA Version 1"); // scrie alt text  
  delay(2000); // asteapta 2 secunde (2000ms)  
  lcd.clear (); // sterge ecranul  
  lcd.setCursor(3, 0); // muta cursorul pe colaone 3 de pe randul 0 (randul de sus)  
  lcd.print("Frequence"); // scrie frecventa  
  FreqCount.begin(1000); // citeste frecventa timp de 1 secunda (1000ms)  
    
 }  
   
 void loop() { // aici incepe progrsmul care ruleaza in blucla infinita  
   if (FreqCount.available()) // daca la intrare este semnal  
   {   
   unsigned long count = FreqCount.read() * 0.64007324; // valoare citita la pinul 5 este inmultita cu 0,64. deoarece a fost divizata anterior cu 64   
     
   // ATENTIE: face asta deoarece nu-i ajung numarul de cifre.. deci "count" e valoarea frecventei impartita la 100  
     
    //unsigned long count = FreqCount.read() * 1.28; // GHz // daca divizarea ar fi cu 128  
 // era asa:  if (count < 10000) { (count = 0);} // signaux parasites ! / daca valaorea citita e mai mica de 10000x100=1MHz, insemna ca e zgomot si considera frecventa zero  
 // eu zic, deoare nu ar masura sub 1MHz  
   if (count < 100) { (count = 0);} // signaux parasites ! / daca valaorea citita e mai mica de 100x100=10000Hz=10kHz, insemna ca e zgomot si considera frecventa zero  
      
   /* Calcul du facteur de division.(1.0000222 ci-dessus)  
    Le quartz de 16 Mhz pilotant Arduino n'est pas précis ni identique pour toutes les platines.  
    Une correction peut être nécessaire au niveau logiciel. Pour ce faire,   
    mesurer la fréquence avec un fréquencemetre étalonné.  
    Puis faire le rapport entre féquence étalon mesurée et fréquence mesurée avec   
    ce fréquencemetre. Exemple 145000200/145000000 = 1.0000014   
    Multiplier le facteur de division (exemple 64) par cette valeur  
    vous obtenez 64.000088. Le facteur de correction devient 0.64000088   
    donc (count = count * 0.64000088)  
   */  
     
  /*     
  // Affichage GHz si nécessaire  
  /////////////////////////////  
    
  // e asa ca nu e bine gandit..  
    
   if (count > 999999999) {   
   count1= (count/100000);   
   count2 = (count - (count1*100000));  
   count3 = (count2/10);  
   count4 = ((count2) - count3*10 );  
   }   
  */  
    
  //  Mhz   
  ///////////////////   
 // original: if ((count > 999999) and (count < 1000000000)) (count1 = (count /10000));  
 // eu zic ca:  
   if ((count > 9999) and (count < 10000000)) (count1 = (count /10000));  
    {   
   count1 = (count /10000); // afla partea intreaga a milioanelor, care reprezinta si numarul milioanelor din numar  
   count2 = (count - (count1*10000)); // afla valoarea numarului de la mii in jos  
   count3 = (count2/10); // afla cifrele de mii  
   count4 = ((count2) - count3*10 ); // afla valoarea ultimei cifre din variabila "count", care reprezinta cifra sutelor din frecventa masurata  
   }  
    
  //  < 1 MHz  
  ////////////////////  
 // nu prea trebuie asta ca e acelasi lucru ca mai sus... deoarece count1=0  
 // original: if (count < 1000000)   
 // eu zic asa:  
   if (count < 10000) // faca frecventa citita e mai mica decat 1MHz (deci valoarea lui "count" < 10000  
   {  
   count2 = (count - (count1*1000)); // valoarea numarului de la mii in jos  
   count3 = (count2/10); // afla cifrele de la mii  
   count4 = ((count2) - count3*10 ); // afla valoarea ultimei cifre din variabila "count"  
   }  
   
   lcd.setCursor(3, 1); // pune cursorul pe randul 1, de jos, si a 3-a coloana  
   lcd.print (count1); // afiseaza cifrele din milioane  
   lcd.print ("."); // pune punct  
   if ((count3 < 100)and (count3 > 9)) (lcd.print ("0")); // daca cifrele din mii sunt de 2 cifre scrie un zero   
   if (count3 < 10) (lcd.print ("00")); // daca e doar o cifra la mii pune 2 de zero  
   lcd.print (count3); // afiseaza cifrele din mii  
   lcd.print ("."); // pune un punct  
   lcd.print (count4); // afiseaza cifra sutelor din frecventa  
   lcd.print ("00"); // rotunjeste cu 2 zerouri  
   lcd.print ("Hz  "); // pusa de niq_ro si unitatea de masura  
   delay (100); // asteapta 0,1secunde si incepe iar masurarea si calculele  
  }  
  }  
   

PS: divizorul cu MB506 modificat pentru 256 in loc de 64 arata asa:

23.09.2013
   Pe ecran sunt afisate urmatoare variante:


   Eu m-am gandit sa afisez frecventa, dar am doua variante:
- in Hz cu puncte intre multiplii
- in GHz cu virgula dupa cifra GHz-ilor, respectiv puncte intre ceilalti multiplii
   Trebuie sa am si un aranjament al afisarii, asa ca m-am gandit la urmatoarele situatii:
- frecventa sub 1kHz
- frecventa peste 1kHz si sub 1MHz
- frecventa peste 1MHz si sub 1GHz
- frecventa peste 1GHz

24.09.2013
   Situatiile ar fi:


31.12.2014
   Am realizat un montaj de testare pentru un generator de semnal cu AD9850 dupa indicatiile din articolul de la http://www.ad7c.com/projects/ad9850-dds-vfo/ obtinand:
   Apoi am incarcat intr-o alta placa Arduino primul sketch, pentru a vedea cum se comporta frecventmetrul (legare directa fara preamplificator, deoarece am semnal cu nivel suficient):
   Rezultatul este foarte bun, eroare de 0,165%:


3 comentarii:

  1. Exista frecventmetre de la Agilent care masoara pana la 350 de MHz

    RăspundețiȘtergere
  2. Pana la ce frecventa pot masura cu ajutorul placutei Arduino.ma refer la primul proiect.Multumesc frumos

    RăspundețiȘtergere
  3. Hi everyone,

    I have an idea about this sketch,
    how about to make a menu for manual corrections for prescaler value?

    begin from this code line:

    unsigned long count = FreqCount.read() * 0.64000088

    in reality to get correct reading on 145.000.000 Hz compared with my standard frequency source, i need to change the value if the prescaler 0.64000088 to 0.64007234.

    If anyone can help:, how to make a changeable values between 0.64000000 to 0.64010000,

    that mean 0.00000001 to 0.00009999 as a value setting that accessible from set menu using a rotary encoder?

    Simple words,
    There is a one button to access prescaler:
    SET Prescaler code : 0.6400000000, 1.28, and 2.56

    SET correction 0.00000001 to 0.00009999 (save it in EEPROM after exit this set menu)

    a apreciate to anyone who understand my idea and help me to resolve this.

    RăspundețiȘtergere