User Manual

8. Orangutan Pulse/PWM Inputs
This section of the library makes it easy to measure pulse inputs such as hobby servo RC pulses, PWM frequency
and duty cycle, discharge time of a capacitor (measured digitally), etc. For example, with these functions, it
becomes simple to program your Orangutan to respond to multiple channels from an RC receiver or to read data
from the multitude of sensors that use pulse outputs. The pulses can be connected to any digital input, and there
is no limit to the number of pulse inputs you can have (beyond the obvious I/O line and RAM limitations; each
pulse channel requires 17 bytes of RAM). These functions are not available within the Arduino environment,
which has its own pulse-reading functions.
The pulse-measuring occurs in the background and is entirely interrupt driven, requiring no further action
from you once you have initiated it by calling pulse_in_start(). Required memory is allocated using malloc()
when pulse-measuring is initiated, which conserves RAM. The pulse_in_stop() function frees this dynamically
allocated memory. Once measuring is started, you can use these functions to get information about the most
recently received high and low pulse, as well as the current pulse in progress. The system tick counter from
OrangutanTime is used to time the pulses, which means pulse width measurements have a resolution of 0.4 µs,
and the upper limit on pulse width is approximately 28 minutes.
This section of the library uses the AVR’s pin-change interrupts: PCINT0, PCINT1, and PCINT2 (and PCINT3
on the Orangutan SVP and X2). It will conflict with any other code that uses pin-change interrupts (e.g.
OrangutanWheelEncoders).
Pulse Information Variables
The OrangutanPulseIn code uses an array of 17-byte PulseInputStruct structs to keek track of the pulse data; each
element of the array represents one pulse input channel. Struct data is automatically updated by the pin-change
interrupt service routine (ISR) as pulses are received.
#define LOW_PULSE 1
#define HIGH_PULSE 2
#define ANY_PULSE 3
struct PulseInputStruct
{
volatile unsigned char* pinRegister;
unsigned char bitmask;
volatile unsigned long lastPCTime;
volatile unsigned char inputState;
volatile unsigned long lastHighPulse;
volatile unsigned long lastLowPulse;
volatile unsigned char newPulse;
};
The bottom five struct variables are declared “volatile” because their values are changed by the pin-changed
interrupt service routine (ISR), so we require the compiler to load them from RAM every time they are
referenced. If a variable is not declared “volatile”, the compiler will eliminate what it decides are superfluous
reads of a variable from RAM and instead work with that variable in local registers, which saves time and code
space, but this can cause situations where you fail to detect when an ISR has changed that variable’s value.
pinRegister & bitmask : Used by the pin-change ISR to determine the input state of the channel. You
should not use these two struct variables in your programs because they might be removed in future versions
of the library.
lastPCTime : The system tick counter value when the last state change happened on this channel. You
can use (get_ticks()-lastPCTime) to figure out how long ago (in units of 0.4 µs) the last pulse ended.
inputState : This byte has a value of 1 (HIGH) if the channel is high, else it has a value of 0 (LOW).
Pololu AVR Library Command Reference © 2001–2015 Pololu Corporation
8. Orangutan Pulse/PWM Inputs Page 30 of 65