I'm still working on my frequency counter, and noticed some strange issues with the TCPWM counter. It seems I cannot start / stop it properly via signals coming from the UDB cells (I'm using DFFs there). I also had problems gating the count signal via an AND gate.
See the attached project - it is basically self-contained, but needs a a Nokia 5110 connected (but it could be replaced by sending the results via a serial port).
This implements a reciprocal frequency counter. It uses two similar counters (with 24 bit period). They are started with the first falling edge of the input signal, and the the counter waits until the reference counter overflows for the first time. When this happens, the next falling edge of the input signal stops both counters. Then one can use the count values of the reference and the input counter to calculate the input frequency.
To start a measurement cycly, a control register is used which resets the DFFs and reloads the counters (by a '1' pulse).
Since the TCPWMs of PSoC6 do not have an enable signal (as there was in the PSoC4), I'm using the start and stop inputs. A rising flank on the enable signal (which comes from the 3-input AND) starts the counters, and the falling edge stops the counters. Also, the falling edge captures the current counter values.
What I observe is:
- even though the counters are stopped, they seem to count further - reading the current counter value, and comparing them with the captured value show differences (which should not be since the counters are stopped)
- I tried to counter that by gating the path from inclk to count of the input counter with an AND gate (using the enable signal). When doing so, the counter does not count at all.
- at certain low input frequencies, the input counter does not reload, but keeps its current value (which can be seen because the display shows the actual counter values, and input value just
- at other low input frequencies, the input counter overflows as soon as its started (which the code displays as 'frequency too high')
The last one is probably caused by the third one - but issues one to three are very puzzling. Especially number 2 - this is so simple that I think one cannot do anything wrong, yet it does not work.
I observer this behaviour regardless of the core the code is running. I have one version of that running on the M0, one with the M4 and one where the code is split. The latter one seems to be the worst, from what I have found out during debugging this seems to be because the delay between finishing one measurement and starting the next is the shortest here.
I also tried to reset the counters by using the _SetCounter() function, but this seems to completely break them.
Any idea what I'm doing wrong here?
I did a quick look at your project. First thing that stands out to me is that the start, stop and capture inputs are all connected together. Looking at the TRM it indicates that if a start and a stop occur at the same time the stop has higher priority so the start is ignored. A reload does reload and start the counter, so maybe you don't need to start input connected, just the reload. Were you wanting to use the start for something? Or just not wanting any unconnected nodes on your schematic.
As for you comment about the enable signal I'm not sure I understand. The TCPWM counters in PSoC 4 don't have an enable maybe you are referring the UDB counters. Regardless you can think of the count input as the enable. The way the count input works is that when ever the count input is high the counter will count on a rising edge of the clock input. To say it another way the counter counts each rising edge of the clock input when the count input is high.
CE220692 provides a method for measuring the frequency using a TCPWM have you looked at that. I would recommend something similar to what is shown in that example. Just replace the PWM for generating different frequencies with your input.
CE220692 does measurement by the gate-counting method. Using the means accuracy gets lower with lower frequencies - thats why I wanted to use reciprocal counting.
Yes, start and stop are connected together, but start triggers on a rising edge and stop on a falling edge. So they will never be triggered at the same time. Both inputs are connected to a signal (which should be labelled 'enable') which determines when the counters need to run. I could look into splitting this up since its actually calculated from a start and several stop events.
Regarding the enable signal: you are right, this does not exist in the PSoC4 TCPWM. I confused that with the UDB-based counter of the PSoC5 (which was my original project).
But your observation that the reload event also starts the counter might actually be the culprit. It would explain at least some of my observations. I will try to to use reload instead of start this evening and see what happens.
I'm a little bit confused now how how the counter actually works. From what you wrote it seems it counts pulses from the clock input when count is '1'. What I actually want is to just count pulses (or rising edges) on the count input. The TRM just says
The counter functionality is performed on an “active count” prescaled clock, which is gated by a “count event” signal. For example, a counter increments or decrements by ‘1’ every counter clock cycle in which a count event is detected.
which leaves the question what a 'count event' is. I have configured the count to 'rising edge' because I thought that's what I need. CE220692 also works that way (it would not work correctly when 'count' would act as an enable signal for 'clock' - in fact then the input frequency should no influence the captured value at all, assuming a 50% duty cycle).
An additional note: one cannot connect an external signal to the TCPWM 'clock' input. I found out that the clock input can be configured to 'level', which makes it act like an enable signal (I used 'rising edge' before). But the clock signal must actually come from the clock block. Its not even possible to use a clock derived from an external digital signal (at least I had no success in doing so).
Using 'reload' as a start signal did not work out. What works is to disable the 'reload' input, and do the reload in software (with SetCounter()). But still the InputCounter does not seem to capture properly, nor does it stop properly (the RefCounter behaves fine, and both are configured identically).