1

So, This is your code slightly altered. I am using it to read the readings of the roll and pitch of a quadcopter. I have tried using this code for a mega 2560 but it does not work in ports A0 and A1. I think it might in A5 and A6 but I am unsure how to alter this code. THank you, Rohan Paleja

/*  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[2]; // times of prev. rising edges
volatile unsigned long rcTimes[2]; // recent pulse lengths
volatile unsigned int  rcChange=0; // Change-counter
int Roll, Pitch;
// 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

  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(9600);
  Serial.println("Starting RC Timing Test");
  setup_rcTiming();
}

void loop() {
  unsigned long rcT[2]; // 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
    Roll = rcTimes[0];
    Pitch = rcTimes[1];


    sei();          // reenable interrupts

    Serial <<  " " << Roll << " " << Pitch
       << " "  << rcN << endl;

  }
  sei();            // reenable interrupts
  delay(1000);
}
Edgar Bonet
  • 45,094
  • 4
  • 42
  • 81

1 Answers1

1

You are trying to do an Pin Change Interrupt on Port F (A0-A7). On the arduino Uno, this port does support PCINT but not on the Arduino Mega.

An option is to use the Port K for the PCINT. Instead of A0 and A1 you then use A8 and A9. A few little changes in the code should do the job:

void setup_rcTiming() {
rcOld = 0;
pinMode(A8, INPUT);  // pin 14, A0, PC0, for pin-change interrupt
pinMode(A9, INPUT);  // pin 15, A1, PC1, for pin-change interrupt

PCMSK2 |= 0x0F;       // Four-bit mask for four channels
PCIFR  |= 0x04;       // clear pin-change interrupts if any
PCICR  |= 0x04;       // enable pin-change interrupts
}

and

ISR(PCINT2_vect) {
byte rcNew = PINK & 15;
...
}
Janw
  • 294
  • 1
  • 9