# Digital Frequency Meter using Pic Microcontroller

A digital frequency meter with an LCD display can be used to measure the frequency of a square wave. With a little modification in this embedded systems project, you can also measure the frequency of a sine wave. In this digital frequency meter, the PIC16F877A microcontroller is used to measure the frequency with the help of an external interrupt. Additionally, a 16 * 2 LCD is used to display the frequency digitally.

## Digital Frequency Meter Applications

Many applications use digital frequency meters. Many sensors do not output in voltage form, so it is necessary to perform signal conditioning to interface these sensors with a digital system. For instance, in capacitive sensors, an additional circuit is used to convert changes in capacitance to another physical parameter that a digital system can easily read. Capacitive sensors typically convert the change in frequency with respect to the input into a proportional frequency square wave using additional circuitry. An example of such a sensor is a humidity sensor.

There are many other examples of a digital frequency meter, such as:

## Components

Complete list of components you need to make a digital frequency meter:

```Resistors,"R1",4k,
Capacitors,"C1",22pF,
Capacitors,"C2",22pF,
Integrated Circuits,"U1",PIC16F877A,
LCD,"LCD1",LM016L,
CRYSTAL,"X1",CRYSTAL 20Mhz,```

## How to Measure Frequency with Pic Microcontroller

Frequency and time period are inversely proportional to each other.

``Frequency = 1 / time period``

If one knows the time period of a wave, the frequency can also be easily calculated using the above relation. We can’t measure the frequency directly with this method. In this project, the time period of a square wave is measured first, which is then converted into frequency using the above relationship between frequency and time period.

## Circuit Diagram

The PIC16F8877A microcontroller uses external interrupts at rising edges and timers to measure the time period of a square wave. It develops an algorithm to convert the time period into frequency and displays the measured frequency digitally using a 16×2 LCD.

In the above circuit diagram, a pulse generator is used to generate a square wave of any frequency. This is for simulation purposes only. You can connect any device to this pin to measure its frequency. We have connected a 6 kHz square wave with the interrupt pin to measure its frequency. However, the LCD is showing 5.99 kHz. To remove this error, read the frequency 5-10 times and display the average on the LCD.

## Pic Microcontroller Code

The code for this project is written in the MIKROC compiler. If you do not know how to use MikroC for Pic, you can refer to these tutorials:

The provided code is for a digital frequency meter using a microcontroller, specifically for a PIC16F877A. The purpose of this code is to measure the frequency of an input signal using an interrupt-driven approach and display the calculated frequency on an LCD screen.

``````// Digital Frequency Meter using Interrupts

sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;

sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;

int on = 0;         // Unused variable, likely for future functionality
int value, freq;    // Variables to store Timer1 value and calculated frequency
char text[7];       // Character array to hold the frequency as a string

// Interrupt Service Routine for external interrupt
void interrupt(void)
{
// Check if Timer1 is not running
if (T1CON.TMR1ON == 0)
{
T1CON.TMR1ON = 1;   // Start Timer1
INTCON.INTF = 0;    // Clear the external interrupt flag
}
else if (T1CON.TMR1ON == 1)
{
T1CON.TMR1ON = 0;   // Stop Timer1
value = (TMR1H << 8) | (TMR1L); // Combine Timer1 high and low bytes
INTCON.INTE = 0;    // Disable external interrupt

freq = 5007999 / value; // Calculate frequency

IntToStr(freq, text);   // Convert frequency to a string

Lcd_Init();             // Initialize LCD
lcd_out(1, 1, "frequency:"); // Display label on LCD
lcd_out(2, 1, text);    // Display frequency on LCD
delay_ms(1000);         // Delay for one second

TMR1H = 0;              // Reset Timer1 high byte
TMR1L = 0;              // Reset Timer1 low byte

INTCON.INTE = 1;        // Re-enable external interrupt
INTCON.INTF = 0;        // Clear the interrupt flag
}
}

void main(void)
{
TRISB.f0 = 1;            // Set RB0 as input for external interrupt
T1CON = 0X00;            // Timer1 configuration
TMR1H = 0;               // Initialize Timer1 high byte
TMR1L = 0;               // Initialize Timer1 low byte
INTCON.GIE = 1;          // Enable Global Interrupt
INTCON.INTE = 1;         // Enable RB0/INT external Interrupt
OPTION_REG.INTEDG = 0;   // Interrupt on falling edge

do
{
// Wait here for interrupts
} while(1);
}
``````

### How Does the Code Work?

``````sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;``````

These lines of code define the LCD control pins (RS, EN) and data pins (D4-D7) using the `sbit` keyword with PORTB of PIC16F877A microcontroller.

``````sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;``````

Define the direction of pic microcontroller LCD control pins and data pins as output using the `sbit` keyword.

``````int on=0,value,freq;
char text[7];``````

These lines of code declare variables `on`, `value`, `freq`, and `text` as integer and character arrays respectively.

``````void interrupt(void)
{
if (T1CON.TMR1ON == 0)
{
// Positive Edge Trigger: Start Timer1 on the positive edge of input signal
T1CON.TMR1ON = 1;    // Start Timer1
INTCON.INTF = 0;     // Clear external interrupt flag
}
else if (T1CON.TMR1ON == 1)
{
// Negative Edge Trigger: Stop Timer1 on the negative edge of input signal
T1CON.TMR1ON = 0;    // Stop Timer1
value = (TMR1H << 8) | (TMR1L); // Combine Timer1 high and low bytes to form a 16-bit value
INTCON.INTE = 0;     // Disable external interrupt

// Calculate frequency using a predefined constant and Timer1 value
freq = (5007999 / value);

// Convert the frequency value to a string
IntToStr(freq, text);

// Initialize and set up an LCD display
Lcd_Init();

// Display "frequency:" on the first line of the LCD
lcd_out(1, 1, "frequency:");

// Display the calculated frequency on the second line of the LCD
lcd_out(2, 1, text);

// Wait for a short duration (1 second)
delay_ms(1000);

// Reset Timer1 values
TMR1H = 0;
TMR1L = 0;

// Enable external interrupt for the next cycle
INTCON.INTE = 1;

// Clear external interrupt flag
INTCON.INTF = 0;
}
}
``````

This interrupt function serves as an interrupt service routine (ISR) for an external interrupt triggered by a positive edge and a subsequent negative edge of an input signal. When the positive edge occurs, denoting the start of a cycle, the code checks if Timer1 is not already running. If it isn’t, Timer1 is initiated, and the external interrupt flag is cleared. This marks the beginning of measuring a time interval.

Upon encountering the negative edge, indicating the end of a cycle, the code halts Timer1, combines its high and low bytes to form a 16-bit value, and temporarily disables the external interrupt. This value is then used to calculate the frequency of the input signal by applying a predefined constant and a formula. The calculated frequency is converted into a textual representation and displayed on a two-line LCD screen, along with an introductory label. After a brief one-second delay, Timer1 is reset to zero, external interrupt functionality is re-enabled, and the interrupt flag is cleared to prepare for the next cycle. In essence, this code captures the time between consecutive positive and negative edges of an input signal, calculates its frequency, displays it on an LCD, and then readies the system for the next signal cycle.

``````void main(void)
{
TRISB.f0 = 1;            // Set RB0 as input for external interrupt
T1CON = 0X00;            // Timer1 configuration
TMR1H = 0;               // Initialize Timer1 high byte
TMR1L = 0;               // Initialize Timer1 low byte
INTCON.GIE = 1;          // Enable Global Interrupt
INTCON.INTE = 1;         // Enable RB0/INT external Interrupt
OPTION_REG.INTEDG = 0;   // Interrupt on falling edge

do
{
// Wait here for interrupts
} while(1);
}``````

This is the main function. It configures the RB0 pin of the PIC16F877A microcontroller as an input pin, initializes the timer and interrupt settings, and enters an infinite loop.

## Demonstration

Sure, here’s the corrected version:

By making a slight modification to the aforementioned circuit, you can also measure the frequency of a sine wave. All you need is a small external circuitry that can convert the sine wave into a square wave with the same frequency. This can be easily achieved using an operational amplifier. The operational amplifier can be used as a comparator for this purpose, and you can also utilize a zero-detection circuit. I will also provide an article on measuring the frequency of a sine wave and an example of a digital frequency meter using a humidity sensor.

You may also like to read:

## 60 thoughts on “Digital Frequency Meter using Pic Microcontroller”

1. need compelet porj.

2. good

3. send to my email

• Everything is available in post code +schematic use this post to make schematic and write your code

• Want this code but frequency required to generate from ICL8035

4. Hi , can you send me the full project please. Thank you!

5. thank you
i need coplete siulation and code of these project

6. Hello Bilal,
I am a fresh-woman. I am interested to work Proteus. I tried but I couldn’t run. Is it possible, please send Proteus file for me?
Thank you.

• code and schematic is available in post

7. i thin, as the given measured frequency increases the measurement accuracy will decrease .whats the maximum frequency which can be measured say with 1 or 2 percent of error.also the micro controller be run at 4 – 16 Mhz what will be the range of measurement when mcu is run at its max speed.

8. please give the full code

9. can you explian your code

10. from where you bring this number 5007999

• It is used to convert time measured by timers into frequency

• how did u calculate this number?

• Do tell about how u calculated that.

11. Thank You very much Mr. Malik… I am a student in power electronics doing my project. Your posts are really worthy and you prove that knowledge grows by sharing.

12. i need complete simulation and code of this project

13. Hi Malik, appreciate your work. May I ask how do you get this number in your coding?
“freq=(5007999/value);”. That 5007999 number, it is obviously frequency=1/T but can you explain how you did the calculation to get that number?
Thank you so much

15. You could spend me your code and simulation?

16. could you send me full code and simulation please?

17. hi , your projects are so sucsessful , everything is easily understandable.

thank you so much , your information is grateful for me.

the other people who wants the”full code” are stupid because all they need is at your article 🙂

• thanks for compliments 🙂

18. i need complete simulation and code of this project. Could you fwd it?

19. hi!,I like your writing so much! share we communicate
more approximately your post on AOL? I require an expert in this
house to solve my problem. May be that is you!

Taking a look ahead to look you.

20. hyy please mail me this program code with hex file

21. Can a frequency meter be made with an 8051 or similar microcontroller?

22. nice one. please mail me this program code with hex file

23. when will u post for sine wave,sir?

• is the code full, sir ???

24. Is the code full,sir??

25. Is the code full, sir?

26. Hi bilal sir. Really nice project. Sir I want to build its dual channel version. What is changes in coding for it?

27. Sir why you divided into this…what is this value…5007999

28. hey can u send me its header file and where are you calling that interrupt function?

29. i want complete code for reading the frequency of the square wave

30. SIR i got error on this line lcd_out(1,1,”frequency:”);
Invalid expression

31. how did you find 5007999

32. Can you give me please this programme with mplab xc8.

33. Could you please send full code and simulation to me at kuhnsterry@hotmail.com? Also, how would you modify code to read 3 separate variable frequencies input to the chip, A, B and C and then add A and B and subtract result from C ie. (X = C – (A + B)) and display X on the LCD…,. Thanks…Terry

34. Complete code with detail explanation and also circuit explanation

• code is given in article

35. Hello!
What if I have more than one source of frequency generator and I need to measure their frequencies simultaneously?
Thank you

36. I am happy and serious when I watched this program
Can you help me with a program similar to this if I told you about the details
Thank you so much

37. Respected Mr Malik,
Your project is appreciable. Kindly elaborate the frequency calculation formula to enable novice like me to understand.Thanks a lot sir.

38. Respected Mr Malik,
Thanks a lot Sir for this beautiful article. I would like to know that you have used external interrupt in square wave frequency measurement but ISR in code is quite big, does PIC 16 F 877 MCU contains enough memory space in Interrupt vector table ? Kindly elaborate. It will be a great help for the novice like me.

39. hi, i need this project can you send me in mail
Thank you

• This is complete by the way

40. Please can you give me the full project of this with full coding and complete simulation ,thank you

41. Hey there, I would appreciate so much if you send me the project . Thank you so much. You are great

42. Send the complete project