This section will show you how to build this f-meter :
The C language source code is freely provided !
This is the source code for building a very simple, but efficient frequency-meter, you can test it directly with an EasyPic board with no extra component.
The program counts the pulses on the RB0 pin during 1 second, and send the result to a software emulated serial communication line on RB1 and RB2.
Each level transition from 0V to +5V on the RB0 pin triggers a software interrupt, which increments the cntr counter.
We only have to wait 1 second to know how much times the counter has been increased, this will give us directly the signal frequency.
A simple delay loop with Delay_ms(1000) will not be accurate enough. When interrupts are enabled, like in our case, the delay function lasts longer than expected, that's why we will have to find another way to wait 1 second :
A timer is started at the beginning of each mesure, its overflow will produce another software interrupt, which will increment the ovrflw counter.
When the counter rises to the number corresponding to one second delay, the interrupts are disabled and the cntr counter is converted to string and written to the serial communication line. A new reading cycle is then started.
This simple frequency meter will give a 1 Hz accuracy in the range from 1 Hz to 67 KHz approximately with a 16 MHz crystal.
The maximum frequency depends on the speed of the microcontroller : with a 20 Mhz clocked pic, the maximum frequency range should be around 83 KHz.
You can also make it run with a high-speed PIC : 40 MHz or 48 MHz, which should allow more than 160 KHz.
The limitation comes from the interrupt routine : have a look on the asm file produced by the MikroC compiler, you will see that around 60 clock cycles are needed to complete the call. If the transitions on the RB0 pin are too fast, they will overlap, and the cntr counter will not be incremented at each edge.
If you need higher frequency range, just add a cheap decade counter like the 4017 : it will multiply by 10 the maximum frequency range, but you will lost the last significiant digit.
Add another divider if you want to multiply it by 100, or a programmable divider : you have enough free I/O pins on the pic to control it.
Here is the ultra simple code for MikroC compiler :
Set your RS232 terminal configuration to 38400 bauds, 8 bits, no parity, 1 stop, no flow control.
Power up the board : the frequency meter starts counting !
The code is less than 900 bytes, it will fit within the MikroC demo limit.
- PIC16F84 microcontroller
- RS232 text output
- one output per second
- basic frequency range from 0 to 83 KHz with 20 Mhz crystal
- 1 Hz accuracy
- no extra component !
- can be build without MikroC compiler licence !
The C language source code is freely provided !
This is the source code for building a very simple, but efficient frequency-meter, you can test it directly with an EasyPic board with no extra component.
The program counts the pulses on the RB0 pin during 1 second, and send the result to a software emulated serial communication line on RB1 and RB2.
Each level transition from 0V to +5V on the RB0 pin triggers a software interrupt, which increments the cntr counter.
We only have to wait 1 second to know how much times the counter has been increased, this will give us directly the signal frequency.
A simple delay loop with Delay_ms(1000) will not be accurate enough. When interrupts are enabled, like in our case, the delay function lasts longer than expected, that's why we will have to find another way to wait 1 second :
A timer is started at the beginning of each mesure, its overflow will produce another software interrupt, which will increment the ovrflw counter.
When the counter rises to the number corresponding to one second delay, the interrupts are disabled and the cntr counter is converted to string and written to the serial communication line. A new reading cycle is then started.
This simple frequency meter will give a 1 Hz accuracy in the range from 1 Hz to 67 KHz approximately with a 16 MHz crystal.
The maximum frequency depends on the speed of the microcontroller : with a 20 Mhz clocked pic, the maximum frequency range should be around 83 KHz.
You can also make it run with a high-speed PIC : 40 MHz or 48 MHz, which should allow more than 160 KHz.
The limitation comes from the interrupt routine : have a look on the asm file produced by the MikroC compiler, you will see that around 60 clock cycles are needed to complete the call. If the transitions on the RB0 pin are too fast, they will overlap, and the cntr counter will not be incremented at each edge.
If you need higher frequency range, just add a cheap decade counter like the 4017 : it will multiply by 10 the maximum frequency range, but you will lost the last significiant digit.
Add another divider if you want to multiply it by 100, or a programmable divider : you have enough free I/O pins on the pic to control it.
Here is the ultra simple code for MikroC compiler :
/* * SIMPLE SERIAL FREQUENCY METER * * this program writes one time per second to the RS232 communication line, * the frequency of the input signal on the RB0 pin * * PIC16F84A * 16 Mhz crystal, HS clock * * PORTB.0, in : counter input * PORTB.1, out : RS232 tx * PORTB.2, in : RS232 rx * */ /* * RAM variables */ unsigned long cntr ; // number of RB0 transition unsigned int ovrflw ; // number of timer0 overflows unsigned char str[10] ; // display result string /* * constant strings */ const unsigned char welcome[] = "\r\r RS232 Frequency Meter Ready\r\r" ; const unsigned char unit[] = " Hz\r" ; /* * write the s ram string to RS232 */ void Comm_Write(unsigned char *s) { while(*s) { Soft_Uart_Write(*s) ; s++ ; } } /* * write the s constant string to RS232 */ void Comm_WriteConst(const unsigned char *s) { while(*s) { Soft_Uart_Write(*s) ; s++ ; } } /* * convert the cnrt long value to string */ void Long2str(void) { unsigned char i, j ; if(cntr == 0) { str[0] = '0' ; str[1] = 0 ; } else { str[0] = 0 ; i = 0 ; while(cntr > 0) { for(j = i + 1 ; j > 0 ; j--) { str[j] = str[j - 1] ; } str[0] = cntr % 10 ; str[0] += '0' ; i++ ; cntr /= 10 ; } } } /* * interrupt routine called 4000000/256 times by seconds : * the timer TMR0 is increased each 4 clock cycles (quartz frequency is 16 Mhz), * and overflows when reseting from 255 to 0, * calling the interrupt procedure with bit T0IF set * * also called on each RBO transition, with bit INTF set */ void interrupt(void) { if(INTCON.INTF) { /* * RB0 interrupt */ cntr++ ; // inc. transition counter INTCON.INTF = 0 ; // clear interrupt flag to enable next call } else if(INTCON.T0IF) { /* * TIMER 0 overflow */ ovrflw++ ; // inc. overflow counter INTCON.T0IF = 0 ; // clear interrupt flag to enable next call on overflow } } /* * entry point */ main() { Soft_Uart_Init(PORTB, 1, 2, 38400, 0) ; // RS232 on PORTB, bits 1 & 2, 38400 bauds Comm_WriteConst(welcome) ; // write welcome message TRISB.F0 = 1 ; // RB0 interrupt pin as input OPTION_REG = 0b11011000 ; // no prescaler /* * main loop */ for(;;) { cntr = 0 ; // clear counters ovrflw = 0 ; INTCON = 0b10110000 ; // T0IF, INTF and GIE enabled while(ovrflw < 15626) ; // wait 1 second : 15626 = 16 000 000 / 4 / 256, rounded up INTCON.GIE = 0 ; // stop all interrupts Long2Str() ; // convert counter to string Comm_Write(str) ; // write string Comm_WriteConst(unit) ; // write unit } } //Don't forget to plug the RS232 jumpers to RB1 and RB2 on your Easypic board !
Set your RS232 terminal configuration to 38400 bauds, 8 bits, no parity, 1 stop, no flow control.
Power up the board : the frequency meter starts counting !
The code is less than 900 bytes, it will fit within the MikroC demo limit.
1 comments:
Does your blog have a contact page? I'm having trouble locating it but, I'd like to shoot
you an e-mail. I've got some creative ideas for your blog you might be interested in hearing. Either way, great website and I look forward to seeing it expand over time.
my web blog; investment property financing guidelines
Post a Comment