I have a question regarding the interruptport. My goal is to measure pulses on 4 interruptports simultaneously in a set period of time. e.g. count the pulses every 20ms. Pulses are coming in at max 500 per second. I generate the pulses with a second emx board via pwm. When i use only one interrupt i can measure up to about 1000 pulses per second. When i use a second interrupt my values are not reliable and the rate measured is dramatically lower. Below is a sample of the code used for catching the interrupt. I thought emx could easily handle this. Any ideas?
_interruptPort = new InterruptPort((Cpu.Pin)pinNumber, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeHigh);
_interruptPort.OnInterrupt += new NativeEventHandler(InterruptPort_OnInterrupt);
private void InterruptPort_OnInterrupt(uint pin, uint state, DateTime timestamp)
There is only one thread handling the interrupts. Try without the lock.
In the code you posted, what is not reliable?
The lock was added later as a way to try and fix the issue. The problem is the same with or without lock.
With unreliable I mean that the amount of pulses handled by eventhandler is inconsistent. So the amount of pulses is no longer the same with every second measured while the pwm outputs at the same frequency. I know this is probably due to the fact that the pulses are buffered and send to the handler later. But I thought the emx should be able to pull this off. Or am I mistaken?
What is the variance of the rate?
When we connect 4 pwm signals to 4 interrupts on another board at 500 p/s we see measurments between 50 and 150 pulses. Also when sending pulses at higher rates we get signals on interrupts which aren’t even connected to a pwm signal.
If I just ask it this way:
I want to measure pulses on 4 interruptports simultaneously in a set period of time. e.g. count the pulses every 20ms. Pulses are coming in at max 500 per second. Is this possible with EMX? If so, could you provide a code example?
Actually, asking your question this way doesn’t make any more sense.
What that seems to mean is every 20ms, find out how many pulses came in on four separate inputs. So what that sounds to me is just a counter on each input line, and periodically pulling out the count out to the rest of the code. You could use a dedicated counting circuit/chip to achieve that. You could also use a number of other ways to drive this too, PinCapture might be another option.
What is probably more important is what are you going to do with the data once you get it. In scenarios where you have a tight timing constraint then it often makes sense to offload the timing sensitive portions with the display/output portion of your system. The other thing you may come across is as soon as you use text-type output of strings (debug.print for example) you might well hit the GC harder than what your final app might; higher GC load means less deterministic timing around your main functionality.
So one thing you can help us with is actually by showing your code that you’re trying to use when you are collecting more than one input.
In the end the devices that will generate the pulses are a set of flowmeters that register the speed of a fluid passing through them. The amount of pulses are then used to calculate the actual amount of fluid passed through the flowmeter using a set of predetermined values. e.g. 10 pulses registered in 20ms == 1 liter. This way we calculate a total volume passed through a pipe.
you’re still avoiding the question - what do you need to do with the counts?
Actually isn’t the maths simpler and not dependent on your time - 10 pulses means 1 litre, and the volume over a time is what is important? I would expect a flowmeter to simply pulse when a specified volume went by; in that case, you can simply count every second and say 1209 pulses occurred, so 120.9 litres.
Capturing 500Hz on 4 simultanous lines asks for RLP interrupt handling AFAIK.
I would use RLP that installs the interrupt handler for the 4 IO lines and keeps 4 counters that increment each interrupt.
Managed code will then read those counters at a fixed interval (each second f.e.) and compare with previous value.
I agree this sounds like a counter problem - not a timer problem.
I’d approach it in one of two ways:
- Use the hardware counters on the chip.
LPC2388 datasheet says: “Four general purpose timers/counters with 8 capture inputs and 10 compare
outputs. Each timer block has an external count input.”
You can get to those counters from managed code using the Register classes.
- Record the current time
- Start a loop to sample all 4 inputs, say, 1000 times.
- Increment counter variables when you see low to high transitions.
- Record the end time
- Calculate the flow rate
You will miss some pulses using the second method - so it depends if you need to be absolutely accurate about the volume (count every pulse) or accurate about the flow rate (count for a defined period).
Personally, if this is a serious application, I’d use a dedicated counter chip with an SPI or I2C interface (or RLP :))
@ realiser: the first method will not work in this case, since I think at least 1 timer is used by the framework itself.
By the way… There’s a discussion going on next door that could help…
If you’re interested in flow rate (pulses per second) then the LM2917 chip can convert it to analog for you and you can use the analog ports to read the values. No interrups required.
There is another approach.
Each interrupt has a timestamp. If you measure the time between two pulses you can determine flow rate.
If the total number of interrupts per second is 500 you should be able to handle it in managed code. If it is 500 per sensor then 2000 is too much and RLP is the answer.
Thanks for all your great input on this matter. We actually got some encouraging results! ;D
We used the following test setup: 1 emx that mimics the flowmeters by outputting pulses via 4 pwm ports all set at 1000 pulses per second. A 2nd emx with 4 io’s connected to the pwm’s of the 1st emx board. All 4 io’s have an interrupt handler that increases a pulsecount variable everytime it is hit. We also have a pwm signal on the same board connected to a 5th interruptport. This pwm is set to generate a pulse every 20ms. (this seems more accurate than a software timer) In the interrupt handler of this io we use the amount of pulses counted by each interrupt connected to the pwm’s which mimic the flowmeters. We then use these values to calculate the actual flow.
At first we got some really unreliable and weird pulse counts which we thought were caused by the fact that we were somehow demanding too much from the boards. We finally got some advice from a someone with more knowledge of electrics. He said we had to connect the ground of both boards together. And voila!!! We now count exactly the amount of pulses generated by the pmw’s at an interval of 20ms. We maybe only miss 1 or 2 pulses every 20ms. For our needs this is acceptable.
Hopfully this will be usefull for others with similar issues. Thanks!!
How long have you let the collection EMX run?
The interrupts are queuing in memory and the EMX does not have enough power to process 4000+ interrupts per second in managed code. At some point you will run out of memory.
We let it run for about 5 minutes. We will do a more lengthy test and let you know how it goes!
We did some more testing and indeed when trying to process 4000+ interrupts it runs out of memory in about 3 minutes. What are the best alternatives? Could the ChipworkX handle these numbers? Or are external pulse counters like a pixaxe the best solution? We also tried doing the counting via the hardware timer/counter but unfortunately we can’t connect 4 pulse generators because at least one of the pins is used by the display connector.
As said before, I think you don’t even have 4 free timers. At least one is used for the NETMF framework as Gus told me in the past.
I would use RLP code that installs 4 interrupt handlers on 4 IO lines, if possible. Each interrupt handler increment it’s own 8 bit value.
Each second (or faster, with RLP timer interrupt) you can send a 32 bit value (made out of the four 8bit value) from RLP to managed code with RLPext->PostManagedEvent.
Managed code then calculates the delta with the previous received values and determines the flow.
Thanks for your reply. I have no experience RLP so i woudn’t know where to begin. But i will look into it. Maybe if you have some sample code or if you could point me in the right direction i would be very gratefull.
“ps: do you speak dutch? your name sounds dutch. I’m from the Netherlands”