Mega RC Receiver Hook-up

Hi there,

Please excuse my ignorance.

I understand the the best way to approach this problem is by using interrupts, and I understand that the overall idea is that the loop is interrupted when a pulse is detected, and I also understand how to measure then length of the pulse.

What I do not understand is why the results are quite so random, and I don’t understand how to change the raw data so that I can get a result which is more like that returned by pulseIn().

Most of the code that I’ve looked at has something like this to measure the length of the pulse;

thanks to vinceherman for this code

void Chan1_begin()           // enter Chan1_begin when interrupt pin goes HIGH.
          Chan1_startPulse = micros();     // record microseconds() value as Chan1_startPulse
          detachInterrupt(Chan1Interrupt);  // after recording the value, detach the interrupt from Chan1_begin
          attachInterrupt(Chan1Interrupt, Chan1_end, FALLING); // re-attach the interrupt as Chan1_end, so we can record the value when it goes low

void Chan1_end() 
         Chan1_val = micros() - Chan1_startPulse;  // when interrupt pin goes LOW, record the total pulse length by subtracting previous start value from current micros() vlaue. 
         detachInterrupt(Chan1Interrupt);  // detach and get ready to go HIGH again
         attachInterrupt(Chan1Interrupt, Chan1_begin, RISING);
         if (Chan1_val < 1000 || Chan1_val > 2000) { Chan1_val = Chan1_val_last;}
         else {Chan1_val_last = Chan1_val;}

full code @,39900.0.html

but then the results are taken directly to servo outputs, I would really like to be able to understand the bit in the middle.

Thanks in advance… :slight_smile:

thanks to vinceherman for this code

I doubt that vince supplied that crap.

DO NOT USE THE STUPID COPY FOR FORUM OPTION. If you must, do NOT then use code tags.

[moderator edit to remove code tags for better display]

Sorry about the issue with the tags.

I got the code from,39900.0.html

and I can't see any credits on the code, so I assumed that must be by vinceherman.

I'd be grateful if you could let me know whats wrong with it.


there is also;

Copyright 2011 Lex Talionis (Lex.V.Talionis at gmail)
This program is free software: you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any
later version.
This code uses pin change interrupts and timer 1 to mesure the
time between the rise and fall of 3 channels of PPM
(Though often called PWM, see
on a typical RC car reciver.  It could be extended to as
many channels as you like.  It uses the PinChangeInt library
to notice when the signal pin goes high and low, and the
Timer1 library to record the time between.
#include <PinChangeInt.h>    //
#include <PinChangeIntConfig.h>
#include <TimerOne.h>        //
#define NO_PORTB_PINCHANGES //PinChangeInt setup
#define NO_PORTC_PINCHANGES    //only port D pinchanges (see:
#define PIN_COUNT 3    //number of channels attached to the reciver
#define RC_TURN 3    //arduino pins attached to the reciver
#define RC_FWD 2
#define RC_FIRE 4
byte pin[] = {RC_FWD, RC_TURN, RC_FIRE};    //for maximum efficency thise pins should be attached
unsigned int time[] = {0,0,0};                // to the reciver's channels in the order listed here
byte state=0;
byte burp=0;    // a counter to see how many times the int has executed
byte cmd=0;     // a place to put our serial data
byte i=0;       // global counter for tracking what pin we are on
void setup() {
    Serial.print("PinChangeInt ReciverReading test");
    Serial.println();            //warm up the serial port
    Timer1.initialize(2200);    //longest pulse in PPM is usally 2.1 milliseconds,
                                //pick a period that gives you a little headroom.
    Timer1.stop();                //stop the counter
    Timer1.restart();            //set the clock to zero
    for (byte i=0; i<3; i++)
        pinMode(pin[i], INPUT);     //set the pin to input
        digitalWrite(pin[i], HIGH); //use the internal pullup resistor
    PCintPort::attachInterrupt(pin[i], rise,RISING); // attach a PinChange Interrupt to our first pin
void loop() {;        //while you got some time gimme a systems report
    if (cmd=='p')
        for (byte i=0; i<PIN_COUNT;i++)
        Serial.print(burp, DEC);
/*      Serial.print("\t");
        Serial.print(clockCyclesToMicroseconds(Timer1.pwmPeriod), DEC);
        Serial.print(Timer1.clockSelectBits, BIN);
        Serial.println(ICR1, DEC);*/
    switch (state)
        case RISING: //we have just seen a rising edge
            PCintPort::attachInterrupt(pin[i], fall, FALLING); //attach the falling end
        case FALLING: //we just saw a falling edge
            i++;                //move to the next pin
            i = i % PIN_COUNT;  //i ranges from 0 to PIN_COUNT
            PCintPort::attachInterrupt(pin[i], rise,RISING);
            //do nothing
void rise()        //on the rising edge of the currently intresting pin
    Timer1.restart();        //set our stopwatch to 0
    Timer1.start();            //and start it up
//  Serial.print('r');
void fall()        //on the falling edge of the signal
    time[i]=readTimer1();    // read the time since timer1 was restarted
//  time[i];    // The function below has been ported into the
                            // the latest TimerOne class, if you have the
                            // new Timer1 lib you can use this line instead
//  Serial.print('f');
unsigned long readTimer1()        //returns the value of the timer in microseconds
{                                    //rember! phase and freq correct mode counts
                                    //up to ICR1 then down again
    unsigned int tmp=TCNT1;
    char scale=0;
    switch (Timer1.clockSelectBits)
    case 1:// no prescalse
    case 2:// x8 prescale
    case 3:// x64
    case 4:// x256
    case 5:// x1024
    while (TCNT1==tmp) //if the timer has not ticked yet
        //do nothing -- max delay here is ~1023 cycles
    tmp = (  (TCNT1>tmp) ? (tmp) : (ICR1-TCNT1)+ICR1  );//if we are counting down add the top value
                                                        //to how far we have counted down
    return ((tmp*1000L)/(F_CPU /1000L))<<scale;

but the code seems to jam with the Timer1 at the first call to Timer1.restart(); on line 47

is there something in the TimerOne library that I have to change to use it on the mega?