Page 1 of 1
zx-24a inputcapture routine
Posted: 17 February 2010, 9:12 AM
by mte
hello,
I am measuring pulse widths from an incremental encoder for a fairly easy application. Since the revolution on the shaft varies over a long range, I want to be able to read for as long as possible without losing accuracy. Right now, I have set the register.timerspeed1 @ 1/256th pre-scaled value and am content with accuracy. I do not want to lower that. SO, Does the 'inputcapture' routine allow me to keep track of the timer overflows, (BTW, tried using the timeout parameter as a count unsuccessfully) thereby allowing me to get longer lengths or does it restart itself once it reaches 65535 and is rendered meaningless. If not, is there any way where I can measure pulse widths while keeping count of the overflows, so i can add them to my widths, in the case of very low frequency inputs..
Please advise.
Thanks
--kemt
Re: zx-24a inputcapture routine
Posted: 17 February 2010, 9:45 AM
by dkinzer
mte wrote:Does the 'inputcapture' routine allow me to keep track of the timer overflows
Once the first edge has been seen, the lengths of the high and low times will be stored in successive elements of the data array. If the timer overflows twice with no intervening edge, a special value of &HFFFF is stored to indicate that an overflow occurred. If three timer overflows occur without an intervening, you'll get a second &HFFFF value, etc. When the next edge finally occurs, the data stored for it is meaningless (due to the sequence of overflows preceding it) but the next edge will cause useful data to be stored assuming that no more than one overflow occurs between those edges.
The key to understanding why it works this way is to realize that the timer runs continuously. An input edge causes the then-current timer value to be stored in a special register, and an interrupt is generated, but the timer continues to run. When the timer wraps from &HFFFF to 0, an overflow interrupt is generated. The input capture code uses these two interrupts together with the captured timer value to compute the values to store in the data array. When the array has filled (or the timeout threshold is reached, in the case of InputCaptureEx) the calling task is resumed.
With all that said, my opinion is that InputCapture() is not particularly well suited to the task of handling an encoder. A better solution is to use external interrupts and there is an application note on that topic. See
AN-221.
Posted: 18 February 2010, 12:43 PM
by mte
Thanks for your response.
I had one more question. On page 132 of the ref. maual, on the description of "inputcaptreEX' , it says,
InputCaptureEx(pin, data, count, flags)
data is "The array in which pulse width information will be stored" & "The stored data reflects the width of the successive high and low portions of the pulse train."
Does this mean that it stores the high and low portion separately as (2) successive elements in the array , i.e, does it read the rising edge and falling edge successively, or does it store the total period as one element and move on to the next. (I'm starting my reading from a rising edge). I want to store the high and low portions of the pulse as separate widths. Can I define data as a 1x2 array? would this affect my count?
Also, if you have the source code for this routine, that would make things much clearer.
Please advise.
Regards,
Kjmt
Posted: 18 February 2010, 13:47 PM
by dkinzer
mte wrote:Does this mean that it stores the high and low portion separately as (2) successive elements in the array?
Precisely. Each full cycle of the input waveform is represented by two data elements; one for the "high" segment and one for the "low" segment. Since you specify, via the fourth parameter, which edge begins the storage process you thereby control the order of the waveform segment data in the array.
It may be helpful to note that InputCapture() is in a sense the inverse function of OutputCapture(). The latter generates an output waveform using segment length data and the former collects the same type of data from an input waveform.
Posted: 19 February 2010, 10:35 AM
by mte
The only problem that I seem to be having is that when I output my pulse readings (as shown below), it seems to be reading only the high(or low) the portion of the pulse. Am I missing something?
Thanks,
kemt
Code: Select all
Public Sub pulsecount() ' to get pulse from channel A
count = 1 ' capture both high AND low pulse duration times
i = 0
register.timerspeed1 = 5 'timer set to 14.4 KHZ
Do
Call inputcapture(data,count,1)
If (data = 65535) then
width = 0.0
Else
width =csng(data)*(1.0/14400.0) ' timer correction going from counts to secs
i=i+1
timenow = timer()
frequency = 1.0/width
End If
debug.print " ";cstr(i);" ";Fmt(csng(timenow), 2);"(s) ";Fmt(width,6);" ";Fmt(frequency,2);" ";cstr(data)
Loop
End sub
Posted: 19 February 2010, 11:10 AM
by dkinzer
mte wrote:Am I missing something?
The second parameter to InputCapture() tells it how many segments you want to capture. Your code sets the
count variable to 1 so that's all the data you get.
Perhaps this example will clarify a bit. Consider a 250Hz signal with a 25% duty cycle. That signal will have a high time of 1mS and a low time of 3mS. Now consider this code excerpt:
Code: Select all
Dim data(1 to 5) as UnsignedInteger
Call InputCapture(data, UBound(data), 1)
After the InputCapture() call returns, the data array will contain the following (approximate) values assuming that Register.TimerSpeed1 is 1:
- 14746 ~1mS
- 44237 ~3mS
- 14746 ~1mS
- 44237 ~3mS
- 14746 ~1mS