|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||
public interface PulseInput
An interface for pulse width and frequency measurements of digital signals.
PulseInput (commonly known as "input capture") is a versatile module which enables extraction of various timing information from a digital signal. There are two main use cases: pulse duration measurement and frequency measurement. In pulse width measurement we measure the duration of a positive ("high") or negative ("low") pulse, i.e. the elapsed time between a rise and a fall or vice versa. This mode is useful, for example, for decoding a PWM signal or measuring the delay of a sonar return signal. In frequency measurement we measure the duration between a rising edge to the following rising edge. This gives us a momentary reading of a signal's frequency or period. This is commonly used, for example, in conjunction with an optical or magnetic sensor for measuring a turning shaft's speed.
PulseInput instances are obtained by calling
IOIO.openPulseInput(ioio.lib.api.DigitalInput.Spec, ioio.lib.api.PulseInput.ClockRate, ioio.lib.api.PulseInput.PulseMode, boolean)
. Once created, the client would typically use getDuration() for getting the most recent
duration reading (either pulse width or period), or getFrequency() for getting the most
recent frequency reading (available only in frequency mode).
When creating the instance, some important configuration decisions have to be made: the precision
(single or double), the clock rate and the mode of operation. Modes are straightforward:
PulseInput.PulseMode.POSITIVE is used for measuring a positive pulse, PulseInput.PulseMode.NEGATIVE a
negative pulse, and PulseInput.PulseMode.FREQ / PulseInput.PulseMode.FREQ_SCALE_4 /
PulseInput.PulseMode.FREQ_SCALE_16 are used for measuring frequency. The difference between the
three scaling modes is that without scaling, the frequency is determined by measurement of a
single (rising-edge-to-rising-edge) period. In x4 scaling, 4 consecutive periods are measured and
the time is divided by 4, providing some smoothing as well as better resolution. Similarly for
x16 scaling. Note that scaling affects the range of signals to be measured, as discussed below.
The choice of single vs. double-precision is important to understand: IOIO internally uses either 16-bit counters or 32-bit counters for the timing. 16- counters force us to either limit the maximum duration (and the minimum frequency) or compromise accuracy as compared to 32-bit counters. However, if you need many concurrent pulse measurements in your application, you may have no choice but to use single-precision.
The clock rate selection is important (and even critical when working in single-precision) and requires the user to make some assumptions about the nature of the measured signal. The higher the clock rate, the more precise the measurement, but the longest pulse that can be measured decreases (or lowest frequency that can be measured increases). Using the scaling option when operating in frequency mode also affects these sizes. combinations. It is always recommended to choose the most precise mode, which exceeds the maximum expected pulse width (or inverse frequency). If a pulse is received whom duration exceeds the longest allowed pulse, it will be "folded" into the valid range and product garbage readings.
The following table (sorted by longest pulse) summarizes all possible clock / mode combinations. The table applies for single-precision operation. For double-precision, simply multiply the longest pulse by 65536 and divide the lowest frequency by the same amount. Interestingly, the number written in [ms] units in the longest pulse column, roughly corresponds to the same number in minutes when working with double precsion, since 1[min] = 60000[ms].
| Clock | Scaling | Resolution | Longest pulse | Lowest frequency |
|---|---|---|---|---|
| 62.5KHz | 1 | 16us | 1.048s | 0.95Hz |
| 250KHz | 1 | 4us | 262.1ms | 3.81Hz |
| 62.5KHz | 4 | 4us | 262.1ms | 3.81Hz |
| 250KHz | 4 | 1us | 65.54ms | 15.26Hz |
| 62.5KHz | 16 | 1us | 65.54ms | 15.26Hz |
| 2MHz | 1 | 500ns | 32.77ms | 30.52Hz |
| 250KHz | 16 | 250us | 16.38ms | 61.0Hz |
| 2MHz | 4 | 125ns | 8.192ms | 122.1Hz |
| 16MHz | 1 | 62.5ns | 4.096ms | 244.1Hz |
| 2MHz | 16 | 31.25ns | 2.048ms | 488.3Hz |
| 16MHz | 4 | 15.6ns | 1.024ms | 976.6Hz |
| 16MHz | 16 | 3.9ns | 256us | 3.906KHz |
In some applications it is desirable to measure every incoming pulse rather than repetitively
query the result of the last measurement. For that purpose the getDurationBuffered()
method exists: every incoming pulse width is pushed into a small internal queue from which it can
be read. The client waits for data to be available, then reads it and data that comes in in the
meanwhile is stored. The queue has limited size, so it is important to read quickly if no pulses
are to be lost. Note that once a pulse is detected, the next one must have its leading edge at
least 5ms after the leading edge of the current one, or else it will be skipped. This throttling
has been introduced on purpose, in order to prevent saturation the communication channel when the
input signal is very high frequency. Effectively, this means that the maximum sample rate is
200Hz. This rate has been chosen as it enables measuring R/C servo signals without missing
pulses.
In other circumstances, the client may want to guarantee that a certain sample has been observed
strictly after certain other data has been received from the IOIO. For that purpose the
getDurationSync() and getFrequencySync() variants exist. They are can be used
to impose strict ordering between samples captured by different inputs, or relative to setting of
outputs, using IOIO.sync().
Typical usage (servo signal pulse width measurement):
// Open pulse input at 16MHz, double-precision
PulseInput in = ioio.openPulseInput(3, PulseMode.POSITIVE);
...
float widthSec = in.getDuration();
OR:
float widthSec = in.getDurationBuffered();
...
in.close(); // pin 3 can now be used for something else.
Typical usage (frequency measurement):
// Signal is known to be slightly over 150Hz. Single precision can be used.
PulseInput in = ioio.openPulseInput(3,
ClockRate.RATE_2MHz,
PulseMode.FREQ_SCALE_4,
false);
...
float freqHz = in.getFrequency();
...
in.close(); // pin 3 can now be used for something else.
| Nested Class Summary | |
|---|---|
static class |
PulseInput.ClockRate
Supported clock rate enum. |
static class |
PulseInput.PulseMode
An enumeration for describing the module's operating mode. |
| Method Summary | |
|---|---|
float |
getDuration()
Gets the pulse duration in case of pulse measurement mode, or the period in case of frequency mode. |
float |
getDurationBuffered()
Reads a single measurement from the queue. |
float |
getDurationSync()
This is very similar to getDuration(), but will wait for a new sample to arrive
before returning. |
float |
getFrequency()
Gets the momentary frequency of the measured signal. |
float |
getFrequencySync()
This is very similar to getFrequency(), but will wait for a new sample to arrive
before returning. |
float |
waitPulseGetDuration()
Deprecated. Please use getDurationBuffered() instead. |
| Methods inherited from interface ioio.lib.api.Closeable |
|---|
close |
| Method Detail |
|---|
float getDuration()
throws java.lang.InterruptedException,
ConnectionLostException
The first call to this method may block shortly until the first data update arrives. The client may interrupt the calling thread.
java.lang.InterruptedException - The calling thread has been interrupted.
ConnectionLostException - The connection with the IOIO has been lost.
float getDurationSync()
throws java.lang.InterruptedException,
ConnectionLostException
getDuration(), but will wait for a new sample to arrive
before returning. This is useful in conjunction with IOIO.sync(), in cases when we
want to guarantee the we are looking at a sample that has been captured strictly after
certain other commands have been executed.
java.lang.InterruptedException - The calling thread has been interrupted.
ConnectionLostException - The connection with the IOIO is lost.getDuration()
float getDurationBuffered()
throws java.lang.InterruptedException,
ConnectionLostException
This method may not be used if the interface has was opened in frequency mode.
java.lang.InterruptedException - The calling thread has been interrupted.
ConnectionLostException - The connection with the IOIO has been lost.
float waitPulseGetDuration()
throws java.lang.InterruptedException,
ConnectionLostException
getDurationBuffered() instead.
java.lang.InterruptedException
ConnectionLostException
float getFrequency()
throws java.lang.InterruptedException,
ConnectionLostException
The first call to this method may block shortly until the first data update arrives. The client may interrupt the calling thread. - *
This method may only be used if the interface has been opened in frequency mode.
java.lang.InterruptedException - The calling thread has been interrupted.
ConnectionLostException - The connection with the IOIO has been lost.
float getFrequencySync()
throws java.lang.InterruptedException,
ConnectionLostException
getFrequency(), but will wait for a new sample to arrive
before returning. This is useful in conjunction with IOIO.sync(), in cases when we
want to guarantee the we are looking at a sample that has been captured strictly after
certain other commands have been executed.
java.lang.InterruptedException - The calling thread has been interrupted.
ConnectionLostException - The connection with the IOIO is lost.getFrequency()
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||