From your request I am trying to explain frequency measurement using two timer. A timer can be used in various modes but here we need only two mode to use.
- Making a time duration
- Use as a counter
Since you are working with pulses then make Timer0 as a counter. Use Timer1 to measure a duration of 1 second . Suppose Timer0 starts counting the pulses, in the meantime Timer1 measures the time duration. When It measures 1 second, collect the value of counter. If the value of counter is 100 then frequency is 100Hz. Both Timer uses interrupt so your main code is free to assign any other tasks.
// LCD module connections
sbit LCD_RS at RB0_bit;
sbit LCD_EN at RB1_bit;
sbit LCD_D4 at RB2_bit;
sbit LCD_D5 at RB3_bit;
sbit LCD_D6 at RB4_bit;
sbit LCD_D7 at RB5_bit;
sbit LCD_RS_Direction at TRISB0_bit;
sbit LCD_EN_Direction at TRISB1_bit;
sbit LCD_D4_Direction at TRISB2_bit;
sbit LCD_D5_Direction at TRISB3_bit;
sbit LCD_D6_Direction at TRISB4_bit;
sbit LCD_D7_Direction at TRISB5_bit;
// End LCD module connections
int frequency,counter,cnt;
char txt[7];
void InitTimer1(){
T1CON = 0x31;
TMR1IF_bit = 0;
TMR1H = 0x0B;
TMR1L = 0xDC;
TMR1IE_bit = 1;
INTCON = 0xC0;
}
void Interrupt(){
//Timer1 code to measure 1s duration
if (TMR1IF_bit){
cnt++;
TMR1IF_bit = 0;
TMR1H = 0x0B;
TMR1L = 0xDC;
//Enter your code here
if (cnt >= 10) { // 1s; after 10 interrupts LEDs will be toggled
frequency=TMR0+(256*counter);
TMR0=0;
counter=0;
cnt = 0; // Reset cnt
}
}
// Timer0 code to count incomming pulses
if (TMR0IF_bit){
TMR0IF_bit = 0;
counter++;
}
}
void main() {
frequency=0;
T0CS_bit=1;
T0SE_bit=0;
TMR0IE_bit=1;
InitTimer1();
Lcd_Init();
Lcd_Cmd(_LCD_CURSOR_OFF);
Lcd_Out(1,1,"Frequency In Hz:");
do {
IntToStr(frequency,txt);
Lcd_Out(2,4,txt);
} while(1);
}
This code is written in MikroC. You can convert it as your compiler requirements.
You can see this tutorial for further details.
I saw some tutorial where a delay of 1 second is made to measure frequency. But a 1s delay just set the processor idle for 1 second which is wastage of resources. The key idea is to make this delay by interrupt method then I can place another tasks for the controller such as voltage or current measurement. I think this will be helpful for all.
There are different ways to trigger your scope.
- Use your scope in single-shot operation. Trigger once then work on the captured waveform.
- Use the math functionality (page 6-21) with a low-pass filter to filter the PWM signal. With the proper cutoff-frequency you should be able to see the sinewave. You could display the PWM on another channel and overlay the PWM with the filtered signal. You should be able to trigger on the math channel. Update: Triggering on the math channel is not possible with this scope.
- Use an external trigger. The scope has a trigger input that you can use. You could program your microcontroller to generate the trigger signal on another pin that you can feed to your scope (see chapter 5).
- Filter the PWM using a two-stage RC-filter and trigger on the sinewave. Use two channels the see the PWM and the filtered signal.
Actually you should try all of these since this a nice exercise that will help you to get to know your scope better.
Best Answer
This is the key element of the frequency measurement code:
The author is using the TMR0 timer/counter to count the zero-crossing events of the input signal. (The article uses a transformer to step down 220VACrms 50Hz mains line frequency to 9VACrms, then uses a full bridge rectifier and a resistive divider to generate the zero-crossing event signal. I'm not sure how they intended to test this circuit.)
After running the counter for 1 second, the value in the counter is equal to double the frequency, because each full-wave rectified cycle has two pulses.
The rest of the code in
Display_Freq(f)
is just user interface code, to convert the numerical frequency into characters to display on the LCD.