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:
- Firing angle control circuit for thyristors
- For protection used with frequency-sensitive devices.
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:
- How to Use “MikroC PRO for PIC” to Program PIC Microcontrollers
- Pic microcontroller programming in c using Mikroc Pro for PIC
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:
- Temperature Sensor using PIC16F877A Microcontroller
- AC Voltage measurement using PIC16F877A microcontroller
- 8×8 LED Matrix Interfacing with MAX7219 and Pic Microcontroller
- DHT22 Temperature and Humidity Sensor Interfacing with Pic Microcontroller
- MAX7219 Interfacing with 8-digit 7 Segment Display and PIC16F877A
- LM35 Temperature Sensor with 7-Segment Display using Pic Microcontroller
need compelet porj.
good
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
Hi , can you send me the full project please. Thank you!
thank you
i need coplete siulation and code of these project
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
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.
please give the full code
can you explian your code
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.
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.
i need complete simulation and code of this project
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
code please
You could spend me your code and simulation?
could you send me full code and simulation please?
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 🙂
i need complete simulation and code of this project. Could you fwd it?
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.
hyy please mail me this program code with hex file
Can a frequency meter be made with an 8051 or similar microcontroller?
nice one. please mail me this program code with hex file
when will u post for sine wave,sir?
http://microcontrollerslab.com/sine-wave-frequency-measurement-using-pic/
is the code full, sir ???
Is the code full,sir??
Is the code full, sir?
Hi bilal sir. Really nice project. Sir I want to build its dual channel version. What is changes in coding for it?
Sir why you divided into this…what is this value…5007999
hey can u send me its header file and where are you calling that interrupt function?
i want complete code for reading the frequency of the square wave
SIR i got error on this line lcd_out(1,1,”frequency:”);
Invalid expression
hola seria posible el programa completo mi correo electronico es
victormanueldiaztorres22@gmail.com
gracias
how did you find 5007999
good
Hi thx for job.. i Want this code plz
rafikamineidrissi@gmail.com .
Can you give me please this programme with mplab xc8.
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
Complete code with detail explanation and also circuit explanation
could you please send me this code ?
jordantagne1@yahoo.coù
code is given in article
Hello!
What if I have more than one source of frequency generator and I need to measure their frequencies simultaneously?
Please help.
Thank you
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
Respected Mr Malik,
Your project is appreciable. Kindly elaborate the frequency calculation formula to enable novice like me to understand.Thanks a lot sir.
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.
hi, i need this project can you send me in mail
Thank you
This is complete by the way
Please can you give me the full project of this with full coding and complete simulation ,thank you
Hey there, I would appreciate so much if you send me the project . Thank you so much. You are great
Send the complete project
The Code is complete and 100% working
i have two questions which are still unclear to me
1. How we get 5007999?
2. why the LCD display 5.99k instead of 6K. (not cleared from your video)
What is the figure 5007999 in the code. I know that frequency is the inverse of time, and time period is stored in the value variable , then what is the need for this figure.
May I have the codes and simulation? Which simulation app did u use?.
Thank youu