user15153: I am designing my own quadcopter control algorithm, whereby I currently read 4 RC receiver channels using PulseIn on each loop in the following manner:
ch1_raw = pulseIn(rcPin1, HIGH, 25000);

In other words, ch1_raw contains the length of a HIGH pulse in microseconds.
I now want to avoid PulseIn in the interest of speed and instead achieve the same using interrupt. 
I have looked at http://playground.arduino.cc/Main/PinChangeIntExample and I am aware that other similar questions have been asked (e.g. How to read RC receiver channels without using pulsein() command with arduino and Is PulseIn fast enough for Quadcopter?), but I don't understand how to implement interrupt to give me the correct ch1_raw value on each loop.
Can somebody help me? (I'm new to Arduino, so go easy on me please!) Thanks!

Edit:
So far I have tried to implement the following:
#include <PinChangeInt.h>

unsigned long pulsestart, pulsewidth;

int rcPin1 = A0;

void setup(){

  pinMode(rcPin1, INPUT);

  Serial.begin(9600);

  PCintPort::attachInterrupt(rcPin1, counttime,RISING); 
  PCintPort::attachInterrupt(rcPin1, subtracttime,FALLING);

}


void loop(){

  Serial.print("  pulsewidth: ");
  Serial.println(pulsewidth);

}


void counttime()
{
  pulsestart = micros();
}

void subtracttime()
{
  pulsewidth = micros()- pulsestart;
}

Edit 2: 
(Somewhat) successful implementation so far, using EnableInterrupt.h instead. It seems that FALLING is being detected, but not RISING.
#include <EnableInterrupt.h>

#define rcPin1 10

volatile uint16_t pulsestart=0; 
volatile uint16_t pulsewidth=0;
//volatile unsigned long pulsestart=0; 
//volatile unsigned long pulsewidth=0;
volatile uint16_t risingcount=0;
volatile uint16_t fallingcount=0;

void counttime()
{
  pulsestart = micros();
  risingcount++;
}
void subtracttime()
{
  pulsewidth = micros()- pulsestart;
  fallingcount++;
}

void setup() {
  Serial.begin(9600);
  pinMode(rcPin1, INPUT_PULLUP);  
  enableInterrupt(rcPin1, counttime, RISING);
  enableInterrupt(rcPin1, subtracttime, FALLING);
}

void loop() {
  //delay(1000);
  Serial.print("risingcount: ");
  Serial.print(risingcount);  
  Serial.print(" fallingcount: ");
  Serial.println(fallingcount); 
  //Serial.print("pulsewidth: ");
  //Serial.println(pulsewidth);
}


user4143: Interrupts don't obey, or even understand the concept of, the "loop" paradigm.
An interrupt fires when it needs to fire, and if you're reading a PWM signal then that means it's firing hundreds of times a second.
As long as your interrupt is updating a variable that can be read from within the loop, and you ensure that the variable doesn't get updated during your reading of it (Google: Critical Sections) then you will always have the most up to date value at your fingertips whenever you need it.
As for the interrupt itself, that's very straight forward - you just need to recognise if it's a rising or falling edge:

If rising edge: record the timestamp (micros()).
If falling edge: Subtract the recorded timestamp from the current micros() and store in the global variable.


user3917: Regarding the question, “Does PinChangeInt only work on digital pins?”, note that PCI's work on all the digital pins of an ATmega328, and on the first six analog pins.  (32-pin '328s have eight analog pins, A0-A7; 28-pin '328s only six, A0-A5.)
Regarding the problem symptom that “pulsewidth just seems to increase continuously”, that could happen if for some reason rising edges aren't processed.  To debug, add a couple more volative byte variables, say nrises and nfalls; increment each of them in the appropriate interrupt handler; and report their values from time to time.
Regarding your #include <PinChangeInt.h> statement, note that PinChangeInt.h is deprecated (as of 3 April 2015).  Consider using EnableInterrupt.h instead.
It's possible you'll resolve your problem while changing libraries.  If so, fine.  If not, or if that library's performance isn't adequate, consider changing over to handling the  pin change interrupts more directly.  The ISR in the following sketch shown below runs several times faster than code that uses PinChangeInt or EnableInterrupt library calls.
[Edit: This edit encloses the ISR in a sketch that compiles.  The code previously shown was missing two array length specifications.  This code was tested with a rotary encoder attached to A2, A3, with A0 and A1 grounded; an output sample (using an Arduino Nano) follows the code.]
/*  rcTiming.ino -- JW, 30 November 2015 -- 
 * Uses pin-change interrupts on A0-A4 to time RC pulses
 *
 * Ref: http://arduino.stackexchange.com/questions/18183/read-rc-receiver-channels-using-interrupt-instead-of-pulsein
 *
 */
#include <Streaming.h>
static   byte rcOld;        // Prev. states of inputs
volatile unsigned long rcRises[4]; // times of prev. rising edges
volatile unsigned long rcTimes[4]; // recent pulse lengths
volatile unsigned int  rcChange=0; // Change-counter

// Be sure to call setup_rcTiming() from setup()
void setup_rcTiming() {
  rcOld = 0;
  pinMode(A0, INPUT);  // pin 14, A0, PC0, for pin-change interrupt
  pinMode(A1, INPUT);  // pin 15, A1, PC1, for pin-change interrupt
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);
  PCMSK1 |= 0x0F;       // Four-bit mask for four channels
  PCIFR  |= 0x02;       // clear pin-change interrupts if any
  PCICR  |= 0x02;       // enable pin-change interrupts
}
// Define the service routine for PCI vector 1
ISR(PCINT1_vect) {
  byte rcNew = PINC & 15;   // Get low 4 bits, A0-A3
  byte changes = rcNew^rcOld;   // Notice changed bits
  byte channel = 0;
  unsigned long now = micros(); // micros() is ok in int routine
  while (changes) {
    if ((changes & 1)) {  // Did current channel change?
      if ((rcNew & (1<<channel))) { // Check rising edge
        rcRises[channel] = now;     // Is rising edge
      } else {              // Is falling edge
        rcTimes[channel] = now-rcRises[channel];
      }
    }
    changes >>= 1;      // shift out the done bit
    ++channel;
    ++rcChange;
  }
  rcOld = rcNew;        // Save new state
}

void setup() {
  Serial.begin(115200);
  Serial.println("Starting RC Timing Test");
  setup_rcTiming();
}

void loop() {
  unsigned long rcT[4]; // copy of recent pulse lengths
  unsigned int rcN;
  if (rcChange) {

    // Data is subject to races if interrupted, so off interrupts
    cli();          // Disable interrupts
    rcN = rcChange;
    rcChange = 0;       // Zero the change counter
    rcT[0] = rcTimes[0];
    rcT[1] = rcTimes[1];
    rcT[2] = rcTimes[2];
    rcT[3] = rcTimes[3];
    sei();          // reenable interrupts

    Serial << "t=" << millis() << " " << rcT[0] << " " << rcT[1]
       << " " << rcT[2] << " " << rcT[3] << " " << rcN << endl;
  }
  sei();            // reenable interrupts
}

The code shown above uses Streaming.h, a contributed library that adds some “syntactic sugar” to Arduino C.  That is, at compile time it converts C++-like << Serial stream operators to Serial.print statements, without increasing code size.  If you don't have Streaming.h installed, either install it via Streaming5.zip from arduiniana.org or manually translate the Serial << ... statement to Serial.print statements.
A sample of the sketch's output on serial monitor:
t=35773 0 0 14196 13456 4
t=35775 0 0 14196 13456 3
t=35778 0 0 14196 5748 4
t=35781 0 0 5244 5748 3
t=35783 0 0 5244 5748 4
t=35785 0 0 5244 5748 3
t=35786 0 0 5244 28 12
t=35788 0 0 3024 28 3
t=35789 0 0 3024 28 4
t=35792 0 0 3024 28 3
t=35796 0 0 3024 6396 4
t=35802 0 0 9316 6396 3
t=35809 0 0 9316 6396 4

In the output above, the two 0's are from A0, A1 being grounded and not changing.  The next two numbers are from the DT and CLK lines of a KY-040 rotary encoder, which toggle alternately to encode step-direction.  They should represent on-times in microseconds, and are always multiples of 4 because micros() reports multiples of 4.  
The last number is the number of times the ISR's change-checking loop ran since loop()'s previous print.  An A2 change will show a count of 3 or more, and an A3 change 4 or more.  Cases where times are the same may represent contact bounces shorter than the ISR's service time; ie, several falling edges in a row might be detected, or several rising edges.  A storage scope or logic analyzer probably is necessary for finding out exactly what happens.

15153: <p>I am designing my own quadcopter control algorithm, whereby I currently read 4 RC receiver channels using PulseIn on each loop in the following manner:</p>

<pre><code>ch1_raw = pulseIn(rcPin1, HIGH, 25000);
</code></pre>

<p>In other words, ch1_raw contains the length of a HIGH pulse in microseconds.</p>

<p>I now want to avoid PulseIn in the interest of speed and instead achieve the same using interrupt. </p>

<p>I have looked at <a href="http://playground.arduino.cc/Main/PinChangeIntExample" rel="nofollow noreferrer">http://playground.arduino.cc/Main/PinChangeIntExample</a> and I am aware that other similar questions have been asked (e.g. <a href="https://arduino.stackexchange.com/questions/16740/how-to-read-rc-receiver-channels-without-using-pulsein-command-with-arduino">How to read RC receiver channels without using pulsein() command with arduino</a> and <a href="https://arduino.stackexchange.com/questions/9465/is-pulsein-fast-enough-for-quadcopter?newreg=1d1811fae8244f409488e6c4dba0d915">Is PulseIn fast enough for Quadcopter?</a>), but I don't understand how to implement interrupt to give me the correct ch1_raw value on each loop.</p>

<p>Can somebody help me? (I'm new to Arduino, so go easy on me please!) Thanks!</p>

<hr>

<p>Edit:
So far I have tried to implement the following:</p>

<pre><code>#include &lt;PinChangeInt.h&gt;

unsigned long pulsestart, pulsewidth;

int rcPin1 = A0;

void setup(){

  pinMode(rcPin1, INPUT);

  Serial.begin(9600);

  PCintPort::attachInterrupt(rcPin1, counttime,RISING); 
  PCintPort::attachInterrupt(rcPin1, subtracttime,FALLING);

}


void loop(){

  Serial.print("  pulsewidth: ");
  Serial.println(pulsewidth);

}


void counttime()
{
  pulsestart = micros();
}

void subtracttime()
{
  pulsewidth = micros()- pulsestart;
}
</code></pre>

<p>Edit 2: 
(Somewhat) successful implementation so far, using EnableInterrupt.h instead. It seems that FALLING is being detected, but not RISING.</p>

<pre><code>#include &lt;EnableInterrupt.h&gt;

#define rcPin1 10

volatile uint16_t pulsestart=0; 
volatile uint16_t pulsewidth=0;
//volatile unsigned long pulsestart=0; 
//volatile unsigned long pulsewidth=0;
volatile uint16_t risingcount=0;
volatile uint16_t fallingcount=0;

void counttime()
{
  pulsestart = micros();
  risingcount++;
}
void subtracttime()
{
  pulsewidth = micros()- pulsestart;
  fallingcount++;
}

void setup() {
  Serial.begin(9600);
  pinMode(rcPin1, INPUT_PULLUP);  
  enableInterrupt(rcPin1, counttime, RISING);
  enableInterrupt(rcPin1, subtracttime, FALLING);
}

void loop() {
  //delay(1000);
  Serial.print("risingcount: ");
  Serial.print(risingcount);  
  Serial.print(" fallingcount: ");
  Serial.println(fallingcount); 
  //Serial.print("pulsewidth: ");
  //Serial.println(pulsewidth);
}
</code></pre>
 4143: <p>Interrupts don't obey, or even understand the concept of, the "loop" paradigm.</p>

<p>An interrupt fires when it needs to fire, and if you're reading a PWM signal then that means it's firing hundreds of times a second.</p>

<p>As long as your interrupt is updating a variable that can be read from within the loop, and you ensure that the variable doesn't get updated during your reading of it (Google: <em>Critical Sections</em>) then you will always have the most up to date value at your fingertips whenever you need it.</p>

<p>As for the interrupt itself, that's very straight forward - you just need to recognise if it's a rising or falling edge:</p>

<ul>
<li>If rising edge: record the timestamp (micros()).</li>
<li>If falling edge: Subtract the recorded timestamp from the current micros() and store in the global variable.</li>
</ul>
 3917: <p>Regarding the question, “Does PinChangeInt only work on digital pins?”, note that PCI's work on all the digital pins of an ATmega328, and on the first six analog pins.  (32-pin '328s have eight analog pins, A0-A7; 28-pin '328s only six, A0-A5.)</p>

<p>Regarding the problem symptom that “<code>pulsewidth</code> just seems to increase continuously”, that could happen if for some reason rising edges aren't processed.  To debug, add a couple more volative byte variables, say <code>nrises</code> and <code>nfalls</code>; increment each of them in the appropriate interrupt handler; and report their values from time to time.</p>

<p>Regarding your <code>#include &lt;PinChangeInt.h&gt;</code> statement, note that <code>PinChangeInt.h</code> is <a href="https://github.com/GreyGnome/PinChangeInt/commit/ec745f854b2b807640341cf479f540bb8bb3fc2f" rel="noreferrer">deprecated</a> (as of 3 April 2015).  Consider using <a href="https://github.com/GreyGnome/EnableInterrupt" rel="noreferrer"><code>EnableInterrupt.h</code></a> instead.</p>

<p>It's possible you'll resolve your problem while changing libraries.  If so, fine.  If not, or if that library's performance isn't adequate, consider changing over to handling the  pin change interrupts more directly.  The ISR in the following sketch shown below runs several times faster than code that uses <code>PinChangeInt</code> or <code>EnableInterrupt</code> library calls.</p>

<p>[<em>Edit:</em> This edit encloses the ISR in a sketch that compiles.  The code previously shown was missing two array length specifications.  This code was tested with a rotary encoder attached to A2, A3, with A0 and A1 grounded; an output sample (using an Arduino Nano) follows the code.]</p>

<pre><code>/*  rcTiming.ino -- JW, 30 November 2015 -- 
 * Uses pin-change interrupts on A0-A4 to time RC pulses
 *
 * Ref: http://arduino.stackexchange.com/questions/18183/read-rc-receiver-channels-using-interrupt-instead-of-pulsein
 *
 */
#include &lt;Streaming.h&gt;
static   byte rcOld;        // Prev. states of inputs
volatile unsigned long rcRises[4]; // times of prev. rising edges
volatile unsigned long rcTimes[4]; // recent pulse lengths
volatile unsigned int  rcChange=0; // Change-counter

// Be sure to call setup_rcTiming() from setup()
void setup_rcTiming() {
  rcOld = 0;
  pinMode(A0, INPUT);  // pin 14, A0, PC0, for pin-change interrupt
  pinMode(A1, INPUT);  // pin 15, A1, PC1, for pin-change interrupt
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);
  PCMSK1 |= 0x0F;       // Four-bit mask for four channels
  PCIFR  |= 0x02;       // clear pin-change interrupts if any
  PCICR  |= 0x02;       // enable pin-change interrupts
}
// Define the service routine for PCI vector 1
ISR(PCINT1_vect) {
  byte rcNew = PINC &amp; 15;   // Get low 4 bits, A0-A3
  byte changes = rcNew^rcOld;   // Notice changed bits
  byte channel = 0;
  unsigned long now = micros(); // micros() is ok in int routine
  while (changes) {
    if ((changes &amp; 1)) {  // Did current channel change?
      if ((rcNew &amp; (1&lt;&lt;channel))) { // Check rising edge
        rcRises[channel] = now;     // Is rising edge
      } else {              // Is falling edge
        rcTimes[channel] = now-rcRises[channel];
      }
    }
    changes &gt;&gt;= 1;      // shift out the done bit
    ++channel;
    ++rcChange;
  }
  rcOld = rcNew;        // Save new state
}

void setup() {
  Serial.begin(115200);
  Serial.println("Starting RC Timing Test");
  setup_rcTiming();
}

void loop() {
  unsigned long rcT[4]; // copy of recent pulse lengths
  unsigned int rcN;
  if (rcChange) {

    // Data is subject to races if interrupted, so off interrupts
    cli();          // Disable interrupts
    rcN = rcChange;
    rcChange = 0;       // Zero the change counter
    rcT[0] = rcTimes[0];
    rcT[1] = rcTimes[1];
    rcT[2] = rcTimes[2];
    rcT[3] = rcTimes[3];
    sei();          // reenable interrupts

    Serial &lt;&lt; "t=" &lt;&lt; millis() &lt;&lt; " " &lt;&lt; rcT[0] &lt;&lt; " " &lt;&lt; rcT[1]
       &lt;&lt; " " &lt;&lt; rcT[2] &lt;&lt; " " &lt;&lt; rcT[3] &lt;&lt; " " &lt;&lt; rcN &lt;&lt; endl;
  }
  sei();            // reenable interrupts
}
</code></pre>

<p>The code shown above uses <code>Streaming.h</code>, a <a href="https://www.arduino.cc/en/Reference/Libraries" rel="noreferrer">contributed library</a> that adds some “syntactic sugar” to Arduino C.  That is, at compile time it converts C++-like <code>&lt;&lt;</code> Serial stream operators to <code>Serial.print</code> statements, without increasing code size.  If you don't have <code>Streaming.h</code> installed, either install it via <a href="http://arduiniana.org/Streaming/Streaming5.zip" rel="noreferrer"><code>Streaming5.zip</code></a> from <a href="http://arduiniana.org/libraries/streaming/" rel="noreferrer">arduiniana.org</a> or manually translate the <code>Serial &lt;&lt; ...</code> statement to <code>Serial.print</code> statements.</p>

<p>A sample of the sketch's output on serial monitor:</p>

<pre><code>t=35773 0 0 14196 13456 4
t=35775 0 0 14196 13456 3
t=35778 0 0 14196 5748 4
t=35781 0 0 5244 5748 3
t=35783 0 0 5244 5748 4
t=35785 0 0 5244 5748 3
t=35786 0 0 5244 28 12
t=35788 0 0 3024 28 3
t=35789 0 0 3024 28 4
t=35792 0 0 3024 28 3
t=35796 0 0 3024 6396 4
t=35802 0 0 9316 6396 3
t=35809 0 0 9316 6396 4
</code></pre>

<p>In the output above, the two 0's are from A0, A1 being grounded and not changing.  The next two numbers are from the DT and CLK lines of a KY-040 rotary encoder, which toggle alternately to encode step-direction.  They should represent on-times in microseconds, and are always multiples of 4 because <code>micros()</code> reports multiples of 4.  </p>

<p>The last number is the number of times the ISR's change-checking loop ran since <code>loop()</code>'s previous print.  An A2 change will show a count of 3 or more, and an A3 change 4 or more.  Cases where times are the same may represent contact bounces shorter than the ISR's service time; ie, several falling edges in a row might be detected, or several rising edges.  A storage scope or logic analyzer probably is necessary for finding out exactly what happens.</p>
