ioio.lib.api
Interface PulseInput

All Superinterfaces:
Closeable
All Known Implementing Classes:
IncapImpl

public interface PulseInput
extends Closeable

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, ClockRate, PulseMode, boolean) . When created, 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 waitPulseGetDuration() 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 measure R/C servo signals without missing pulses.

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.waitPulseGetDuration();
 ... 
 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
          Suported 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 getFrequency()
          Gets the momentary frequency of the measured signal.
 float waitPulseGetDuration()
          Reads a single measurement from the queue.
 
Methods inherited from interface ioio.lib.api.Closeable
close
 

Method Detail

getDuration

float getDuration()
                  throws java.lang.InterruptedException,
                         ConnectionLostException
Gets the pulse duration in case of pulse measurement mode, or the period in case of frequency mode. When scaling is used, this is compensated for here, so the duration of a single cycle will be returned.

The first call to this method may block shortly until the first data update arrives. The client may interrupt the calling thread.

Returns:
The duration, in seconds.
Throws:
java.lang.InterruptedException - The calling thread has been interrupted.
ConnectionLostException - The connection with the IOIO has been lost.

waitPulseGetDuration

float waitPulseGetDuration()
                           throws java.lang.InterruptedException,
                                  ConnectionLostException
Reads a single measurement from the queue. If the queue is empty, will block until more data arrives. The calling thread may be interrupted in order to abort the call. See interface documentation for further explanation regarding the read queue.

This method may not be used if the interface has was opened in frequency mode.

Returns:
The duration, in seconds.
Throws:
java.lang.InterruptedException - The calling thread has been interrupted.
ConnectionLostException - The connection with the IOIO has been lost.

getFrequency

float getFrequency()
                   throws java.lang.InterruptedException,
                          ConnectionLostException
Gets the momentary frequency of the measured signal. When scaling is used, this is compensated for here, so the true frequency of the signal will be returned.

The first call to this method may block shortly until the first data update arrives. The client may interrupt the calling thread.

Returns:
The frequency, in Hz.
Throws:
java.lang.InterruptedException - The calling thread has been interrupted.
ConnectionLostException - The connection with the IOIO has been lost.