# PIC16F870 frequency counter

Discussion in 'Microcontrollers, Programming and IoT' started by metiz, Apr 3, 2015.

1. ### metiz

31
0
Apr 7, 2014
Disclaimer: this is schoolwork, so I'm not sure if it's in the right segment.

I need to write a frequency counter for a PIC16F870 microcontroller that can read frequencies from 0 to 255hz (8 bit, at least they had some mercy there...). This is for a school project where we have to build a capacitive pick-up and then output the RPM of a DC motor on a LCD screen. We've had SOME training in assembly language, but pretty much everyone (lots of project groups) is having a realy hard time with this and as far as I know, no-one has figured it out yet. The capacitor setup is done and we have a square-wave output, 5v=1 and 0v=0

Can someone assist us with this, maybe points us to some examples, give us a few tips? The controller is 8 bit, runs on 4mhz and uses a RISC instruction set (basically the same you find on a wide range of PIC's).

Any help is greatly appreciated, this project is realy grinding us down...
Joost.

2. ### BobK

7,682
1,689
Jan 5, 2010
So you have these pulses coming in. How might you determine their frequency? You should be able to think of two ways to do this.

Bob

3. ### metiz

31
0
Apr 7, 2014
Well, the pic runs at 4mhz, that's 4 million operations a second. Maybe it could count the number of operations between each pulse, 2 milion for example, and then calculate that the frequency must be 4 milion/ 2 milion =2 milion = 2 pulses per second, or 120 rpm? That's realy the only one I can think of. But what happens when you get a devision with a non-integer result?

4. ### Gaupa95

6
2
Jul 1, 2013
Ah. I worked on something simelar a few years ago. as I was building a tachometer.

There is two ways of thinking of it, But let me tell you they both probably will require timers.

a little tip I can give is timers, interrupts, and the PIC's CCP (Capture, Compare, PWM) module. Have fun!

5. ### hevans1944Hop - AC8NS

4,690
2,196
Jun 21, 2012
We don't appreciate your cross-posting the identically same question on multiple forums at the same time, for example here.
There are two solutions to your problem: either measure the period between pulses, or count the number of pulses that occur in a fixed time interval. Here is a website to get you started.

Last edited: Apr 4, 2015
6. ### BobK

7,682
1,689
Jan 5, 2010
Hop,

I knew you could get that answer, I was hoping the OP would try.

And he did get counting cycles between pulses.

metiz:

So you have the answer. You can count pulses in a time interval or count time between pulses. The chip has timers. Read up about them in the datasheet and see if you can figure out how to use them to do both of these.

But actually think about what your instructor asked you to do. The rate is between 0 and 255 hertz. That is actually a clue. What would happen if you counted the number of pulses that occur in 1 second?

Can you think of the advantages and disadvantages of each of the 2 methods? Hint: consider accuracy and time between readings.

Bob

7. ### metiz

31
0
Apr 7, 2014
I'm afraid part of this answer will somehow need to involve the word "prescaler".

Ok so there are 4 timers on this pic as far as I can tell, 3 of which could be useful: the WDT, timer0 (8bit) and timer1 (16bit). I asume timer0 would be the right choise because it counts between 0 and 255 (does that mean that it counts to 255 in 1 second/ 4.000.000 cycles?)

As far as accuracy goes, maybe using the 8bit counter isn't the most acurate (keep in mind this is a school project though, so rounding of to the closest integer should be fine) because if I had, for example, 3 cycles per second, that would mean 256/3=85.33, so the counter would be slightly below 3rpm?

8. ### BobK

7,682
1,689
Jan 5, 2010
The problem with counting pulses for 1 second is that the accuracy will be very low at the low end of the range. What if you get 1 count? It could be anywhere from 2 RPM to nearly 0. So the error can be as high as 100% of the value you read. At 10 ticks it is still 10%. For these low speeds, counting time between pulses would give much more accuracy. You can count times down to 1 microsecond using this PIC. So now your accuracy is lowest at the high end of the range. and it is at worst 1 microsecond out of 3291 (1000000 / 255) or 0.03%.

Bob

9. ### metiz

31
0
Apr 7, 2014
Right, that makes sense. So it would be better to use (at least) use the 16 bit timer?

10. ### hevans1944Hop - AC8NS

4,690
2,196
Jun 21, 2012
Let's see... you want to measure the frequency of a square-wave signal that varies from a maximum of 255 Hz to a minimum of... zero? And you want to display the results as a number on an LCD display in the range of 0 to 255?

One accurate way to do this is to measure the period of one cycle. So how long could this period measurement be? Well, at 250 Hz the period would be 1/250 seconds... 0.004 seconds or 4 milliseconds. At 255 Hz the period is (approximately) 0.0039215686274509803921568627451 seconds, or 3.92 milliseconds (plus some change). At 254 Hz, the period is (approximately) 0.00393700787401574803149606299213 seconds or 3.94 milliseconds (and you give back a little change for overestimating the period). So clearly, measuring the period of your square wave pulses with a resolution of 0.02 milliseconds or 20 microseconds will allow you display frequency to three significant digits up to 255 Hz.

All you need is a clock that "ticks" every 20 μs. Start counting the "ticks" on the positive-going edge of your square-wave and stop counting the "ticks" on the next positive-going edge. Now take the reciprocal of the number of ticks and multiply by 50000 (the frequency of 20 μs clock "ticks"). Check this: for a 250 Hz square wave there are 0.004 milliseconds or 4000 microseconds between positive transitions. Divide this by 20 microseconds per "tick"and you get 200 ticks between positive transitions. The reciprocal of 200 multiplied by 50000 is... 250.

One way to implement this with the 16F870 PIC is to use the interrupt function to start and stop a counter that is incremented by a 50 kHz clock. The interrupt is set by the rising edge of the frequency you are trying to measure and enables the counter. The next rising edge stops the counter and performs the arithmetic and displays the results on the LCD display. The devil is in the details, and Microchip provides an app note describing a number of methods of various accuracies. You should read this.

A problem that must be solved is counter over-flow at low frequencies. For example, the period of a one Hertz signal is obviously one second or one milllon microseconds. A 20 microsecond clock will therefore accumulate 1,000,000 / 20 = 50000 counts in one second. This would require a 16-bit counter to avoid overflow, and we aren't even close to zero frequency yet! One solution to this problem is to simply declare overflow from a 16-bit counter as the definition of zero frequency. So even though a count of 65535 (maximum for 16 bit counter before next count causes overflow) would really mean a frequency of about 0.763 Hz, our program will declare that to be the minimum frequency we can measure. If the counter overflows, the program will return a value of zero for the frequency.

It is left as an exercise for the student (that's you!) to figure out how to generate and count 10 μs clock pulses in a 16-bit counter that is started and stopped by positive transitions of your optically-derived tachometer signal, while also detecting counter overflow as a special case. You also need a "watch dog" timer to rescue the program if a positive transition occurs to start the counter, but another positive transition to stop the counter never occurs. This could happen if the shaft is turning very slowly and then stops before another positive transition is produced. You don't want this to "lock up" the program while it waits for an interrupt that never happens. If the "watch dog" barks, you just re-start the program.

As a practical matter, I would measure the period of a half-cycle instead of a full cycle and use the other half of the cycle to do the math and update the LCD display. This will keep the PIC busy most of the time. And BTW, how are you doing on programming the PIC to display the "RPM" on the LCD display?

11. ### metiz

31
0
Apr 7, 2014
Thanks for your help guys. I'll get to work on this. Needs to be done pretty soon so if I succeed, I'll post the code for anyone interested.

12. ### jayanthd

43
10
Jul 4, 2015
If you have not yet written the working code then I can help you. I can use T0CKI pin (8 bit Counter) or RB0/INT0 pin to count the pulses per second. I will use one more timer to generate a 1 sec delay and the counter and 1 sec delay timer is started at the same time and then after 1 sec the counter and timer are both stopped. I can use prescalars for the counters. It is better to use 8 bit counter and increment a variable like overflow once when Timer0 (counter) overflows. This overflow value can be multiplied by 256 to get the number of pulses and to it the count in TMR0 should be added. It is better to use Timer0 an 8 bit timer as a counter (RA4 pin) because your frequency is low.

Using Timer0 as 8 bit Counter and Timer1 as 16 bit Timer for 1 sec delay.

frequency = (overflow * 256) + TMR0  