I used for that purpose UDB Timer-components and connected enable and capture, so that during the input high phase was counted my provided clock and at hi->low transition the value got captured.
In the interrupt handler I stopped the timer, removed the interrupt cause(!!!), red/calculated the pulse width and restarted the timer again. The 16 interrupts within 20ms do not put a hevy load on the ARM M3. Just avoid long loops.
Do not forget to declare all global variables that are modified in the interrupt handlers as "volatile"
You will needsomething like a 20 MHz clock and a 16-bit timer.
Two projects, one that does PW measurement, but both frequency measurement as well -
One uses interrupts, but they are low rate, at the pulse edge of the 20 mS in your case.
The demo projects are working well with a few signals, but not with 16. I have massive problems with jitter and chip resources.
Can you post your actual complete project, so that we all can have a look at all of your settings? To do so, use
Creator->File->Create Workspace Bundle (minimal)
and attach the resulting file.
PS: Grüß Gott, Herr Inschenör!
Since you have to mux the PW and Freq measurement operation you
have, in control theory, a lot of latency from measurement to action.
There are quite a few solutions, both linear and non linear, to resolve
a problem like this. Beyond the scope of simple post soultions.
Or do a fully HW solution. Possibly verilog. Or consider using DFB engine.
If you start with 10 uS resolution, then you would sample / count at 5 uS.
The max period is 20 mS so worst case, each channel, you have to wait
18 mS to initiate first edge of pW measurement. So latency for each channel
from measurement to action is 20 mS x 16 = 320 mS, a very long time from
measurement to measurement in a specific channel.
Go parallel in design, several measurement engines ? One possibility.
What are you trying to do with the measurement results ? How many PWM
periods can you allow in each channel before action from that channel
is required ?
Back from dinner I am thinking about whether it is needed to write to the counter-register of the timer between stop() and start() or if the Start() allone will reload the counter from the period-register. Someone should try that.
If the measured PW is from 1 - 2 mS then in Bobs solution only 8 bit
counters needed. 1 mS / .01 mS = 100 count.
To cut down on brute force solution consider a mux sampling each input
every 10 uS, driven by a 4 bit counter, and edge detection, say a LUT,
to detect rising and falling edge, and / or a 2 bit SR to detect sample to
sample edge. You could increase sample rate to 1 uS to minimize jitter.
Each channel when edge detected 10 uS counter value stored, if falling
edge then subtract rising edge count - falling edge count, and store in a
variable for that channel.
Just a thought in case the Bob solution eats up too many resources
for your design.
In verilog this should be a fairly straighforward solution I would think
(he who does not know verilog yet thinks....)
I tried a few things and I was not really successful :-(
Generating synchronized servo signal was surprisingly easy compared to other microcontrollers, but I have Problems measuring them correctly. I tried a few approaches and neither is working.
Are you trying to generate 16 PWM signals, or measure 16 PWM signals ?
I need to generate 16 servo signals (transmitter) and to measure them (receiver)
I'm abusing hobby equipment for my RV, but that's another story.
I don't know if this will work, but here goes.
create a 1mhz clock. That will give you a 1us resolution.
Put it into a count down timer. Trigger an interrupt every 10us, have the timer interrupt at TC, and reload at TC.
in the interrupt from the TC, scan all the input pins for current state (high/low)
increment a "high" counter for every pin that is high. Once the pin goes low, move the "high" count for that pin to a staging variable and reset the high counter for that pin.
In your main loop, check the staging variable for non-zero, take it, calculate with it.
Run your PSoC ARM processor as fast as possible. If you run at 80mhz, then you should be able execute 800 assembly instructions every 10us. A tight isr might work for a pin or four.
It may be you can handle 3, 4, 5, 10, reliably, but no more. In that case, buy another $10.00 cy8cKit-059 board and use it as your second, third, etc processor for the additional signals.
I could see using 3 boards ($30) and have two feed into one main one using SPI, so that you can then do whatever you wish to the data without having too many issues with lag.
Another way to do it is to bring the pin into an AND gate, and feed the AND gate from the 10us pulse from the countdown timer. Feed the AND gate output to a counter, it will count a "high" every 10us.
That provides your count. Once you see the Pin go low in your ISR, pull the counts from the up counter and store in the staging variables. That should be faster in code. Your mainloop code would then do differences to get the uptime, so it would need to store the last value read that it used.