Pin Change Interrupt problem vect conflict

Hi all, I am quite new to Arduino and code in general, have been teaching myself for a little while now. I have written a code that enables me to send data using the Xbee module attached to my computer, to the Xbee on my Arduino. The data received then turns one of four motors to a desired position using pulses counted from attached encoders. I got this working quite eaisily using the interrupt command for pin 2 on the arduino however, I have four motors therefore require four interrupt pins, as the arduino only has two this is a slight problem especially as because I am using the adafruit motorshield, pin 3 is already in use so I only have pin 2 available. I therfore looked into Pin Change interrupts and found the code to implement interrupts on the analog pins, I am not sure if I have done it correctly but I cant test it as I am finding an issue when compiling. Part of my code can be seen below, (i.e for just one motor) the full code runs 4:

#include <NewSoftSerial.h>                            // Wireless Library
#include <AFMotor.h>                                  // Motor Library
#define encoderPin  A5                                 // Encoder Pulse Pin 2 on Arduino
AF_DCMotor motor(1);                                  // Motor + & - M1
volatile unsigned int encoderPos;                     // Initial Encoder Position  
NewSoftSerial mySerial =  NewSoftSerial(10, 13);      // Xbee Pins 10 & 13
char inData[10];                                      // Declare Array
int n = 74;                                           // Define Integer n as 74 i.e. 74 Pulses = 1 Click on Damper  
int index;                                            // Define Index Integer
boolean chose = false;                                // Motor Choice Boolean Initial Set up
boolean started = false;                              // Input Code Begin Boolean Initial Set up
boolean ended = false;                                // Input Code Complete Boolean Initial Set up
boolean forwards = true;                              // Directional Boolean Initial Set up
boolean mot1 = false;                                 // Motor1 Boolean Initial Set up 

void setup() {                                        // Setup Procedure 

  PCICR |= (1<<PCIE1);
  PCMSK1 |= (1<<PCINT13);
  MCUCR = (1<<ISC01) | (1<<ISC01);
  pinMode(encoderPin, INPUT);                         // Encoder Pulse Pin Set as Input on Arduino  
  digitalWrite(encoderPin, HIGH);                     // Turn on Pullup Resistor
  mySerial.begin(19200);                              // Xbee Laptop Module Serial Set up Baud Rating 19200bps
  Serial.begin (19200);                               // Arduino Serial Set up Baud Rating 19200bps
  mySerial.println("start");                          // Label Start

  motor.setSpeed(200);                                // Set Motor Speed
 
} 

void loop(){                                          // Main Loop

  while (mySerial.available() >0) {                   // Check if There is a Character in the Serial Buffer
    char aChar = mySerial.read();                     // Read Input Character 
    if(aChar == '<') {                                // If a "<" is Input Signal Begining of Input
      chose = true;                                   // Boolean "Started" True 
      index = 0;                                      // Index Equals 0  
      inData[index] = '\0';                           // Add a Null to Position in Array    
      }
    else if(aChar == '>') {                           // If a ">" is Input Signal End of Input                            
      ended = true;                                   // Boolean "Ended" True 
      }
    else if(chose) {                                  // If Chose is True
      if(aChar == 'a') {                              // If 'a' has Been Input
         mot1 = true;                                 // Set Motor1 Boolean as True 
         }
    
      chose = false;                                  // Make Chose False again
      started = true;                                 // Set Started as True
    }  
    else if(started) {                                // If Started is True
      inData[index] = aChar;                          // Characters Entered Between < & >   
      index++;                                        // Increment Index
      inData[index] = '\0';                           // Add a Null to Position in Array to Signal End of String
      }
    }
  if(started && ended && mot1) {                      // If Started and Ended and Motor1 are True
    int x = atoi(inData);                             // Convert Character to Integer  
    Serial.println(x);                                // Print Integer Value in Serial

    for(encoderPos; (x * n) > encoderPos;) {          // For Encoder Position Greater Than Last Encoder Position  
      forwards = true;                                // Directional Boolean is True
      motor.run(FORWARD);                             // Drive Motor1 Forward
      }
    motor.run(RELEASE);                               // Stop Motor1 
  
    for(encoderPos; (x * n) < encoderPos;) {          // For Encoder Position Greater Than Last Encoder Position  
      forwards = false;                               // Directional Boolean is False
      motor.run(BACKWARD);                            // Drive Motor1 Backwards
      }
    motor.run(RELEASE);                               // Stop Motor1 

  mySerial.print ("Number of Pulses Read:");          // Print Number of Pulses
  mySerial.println (encoderPos, DEC);                 // Print Actual Value of Pulses Read 
  
  if (encoderPos = (x*n)) {                           // If Encoder Position Equals Required Encoder Position 
     mySerial.println ("CORRECT");                    // Print 'Correct'  
     }
  else if (encoderPos != (x*n)) {                     // if Encoder Position Does Not Equal Required Encoder Position 
     mySerial.println ("FAILED");                     // Print 'Failed'
     mySerial.println ("Input Position Again:");      // Print 'Input Position Again'
     }
     
  started = false;                                    // Reset Started Boolean
  ended = false;                                      // Reset Ended Boolean 
  mot1 = false;                                       // Reset Motor1 Boolean 
  index = 0;                                          // Reset Index Integer
  inData[index] = '\0';                               // Add a Null to Position in Array  
  }
}

ISR(PCINT1_vect) {                                    // Interrupt 
    
  if (digitalRead(encoderPin) == HIGH) {              // Interrupt when Pulse is Detected on Encoder Pin
      if (forwards) {                                 // If Boolean True 
      encoderPos++;                                   // Increment Value by 1 
      }
      if (!forwards) {                                // If Boolean False
      encoderPos--;                                   // Decrement Value by 1
      }
  }
}

I get an error that the vect has already been defined:

NewSoftSerial\NewSoftSerial.cpp.o: In function __vector_4': C:\Program Files\arduino-0022\arduino-0022\libraries\NewSoftSerial/NewSoftSerial.cpp:323: multiple definition of __vector_4'
sketch_may31b.cpp.o:C:\DOCUME~1\COMPAQ~1.DEA\LOCALS~1\Temp\build6271291997586514344.tmp/sketch_may31b.cpp:95: first defined here

Looking into the NewSoftSerial.cpp file I found where this was at line (306-341) I'm not sure how to get round this, therefore need someone's help. The SoftwareSerial library doesn't have this problem, but the mySerial.available() command doesn't work using that library, is there another bit of code I could use to get around that instead maybe? Also SoftwareSerial only works up to speeds of 9600 currently im running at 19200 so I would prefer to find a fix with newsoftserial

Thanks for your help

I'm not sure what this is doing:

  PCMSK1 |= (1<<PCINT13);

but it looks to me like you are trying to attach the pin change interrupt to pin 13, which you have defined as for use by NewSoftSerial. Which pin are you trying to attach the pin change interrupt to?

The xbee is wired to digital pins 10 and 13

PCMSK1 |= (1<<PCINT13);
This tells the pin change mask (PCMSK1) that it needs to watch for a change on pin (13) where pin 13 relates to analog pin 5

Reading around I found that arduino uses its own chip assignments, there is a map that needs to be used to find the arrays and pin assignments that the ATMEGA uses to control these pins. Analog pins A0-A5 are mapped as Pin PCIN 8-13, This was found using the information datasheet for the ATMEGA 328

I believe that the problem is actually simpler than this: The compiler only allows the ISR for the pin change interrupt vectors to be defined in one location. By defining the ISR in your main code as well, you encounter an error. Just comment out the ISR in NewSoftSerial, to solve the problem (but it will disable receive on the associated pins).

Hey thank you for replying, as i mentioned I am very new to this and only have a basic understanding, so sorry if i ask obvious things :~ How do I go about commenting out the ISR in NewSoftSerial? and what effect will disable receive on the associated pins have on my code?

thanks

You should comment out the part that has this in it:

ISR(PCINT1_vect) {
    // something
}

from NewSoftSerial.cpp.

Disabling this pin change interrupt for NewSoftSerial will mean that you will not receive any serial data on pins in PORTC, that is, the analog input pins.

By commenting out i guess you mean putting // in front of the code, I'm guessing this is so that i can edit back to the original if needs be.

Just tried it and it has worked!! :slight_smile: thank you, by doing this you say i will therefore be unable to receive serial data on the anolog pins, I'm guessing that is ok as I only want to use them for the encoder pulse readings? I will be writing more code to make it work for all four motors, so I might be back but at the moment that has solved my problem so thank you again

It should be fine as long as you aren't expecting to use serial communications on the analog pins. And yes, commenting means putting // in front (or surrounding it with /* and */).