我有一个Arduino Mega,我正在使用Ultimate GPS Logger shield(由Adafruit提供)和9-axis motion shield(由Arduino提供)

我目前需要4个中断来充当轮速传感器(转速计) . 但是,目前软件序列似乎耗尽了所有这些,而我只留下了目前正在工作的引脚2(INT.0)的中断 . 有没有办法可以修改软件序列以允许我在电路板上使用更多的中断?

目前,Mega正在使用这样的跨接电缆以实现兼容性(这是因为GPS屏蔽不能完全与Arduino Mega配合使用) .

//GPS 8  RX --> MEGA 18 TX1
//GPS 7  TX --> MEGA 29 0RX1
//GPS 13 CLK--> MEGA 52 SCK
//GPS 12 DI --> MEGA 51 MOSI
//GPS 11 DO --> MEGA 50 MISO

9轴运动传感器和GPS提供使用中断但我不想使用它们,除非它们是严格必要的 . 我最初尝试使用pinchangeint库,但这不适用于SoftwareSerial库!

我的代码如下:

#include <SPI.h>
#include <Adafruit_GPS.h>
#include <SD.h>
#include <avr/sleep.h>
#include "NAxisMotion.h"
//Contains the bridge code between the API and the Arduino Environment (Accelerometer)
#include <Wire.h>
#include <math.h>
#include <SoftwareSerial.h>

//APPS definitions
#define APPSpin A0
double APPSvalue;

// Wheel speed definitions
#define FLpin  2 //WORKING
#define FRpin  21 //INT.1 (3) Does not work

volatile byte FLtooth;
volatile byte FRtooth;
double FLrpm;
double FRrpm;
unsigned long FLtime;
unsigned long FRtime;

// Accelerometer definitions
NAxisMotion mySensor; //Object that for the sensor
uint8_t range = 3; // 0 = 2G, 1 = 4G, 2 = 8G, 3 = 16G
uint8_t bandwidth = 3; // 0 - 7 = 7.81Hz x 2^bandwidth
uint8_t powerMode = 0; // 0 - 5 = Norm, Suspend, Low Power 1, Standby, Low Power 2, Deep Suspend
bool updateSensorData = true;
//Flag to update the sensor data. Default is true to perform the first read before the first stream

// Connect to the GPS on the hardware port     
#define GPSSerial Serial1
Adafruit_GPS GPS(&GPSSerial);

// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences
#define GPSECHO true

// This keeps track of whether we're using the interrupt off by default!
boolean usingInterrupt = false;
void useInterrupt(boolean);

// Set Adafruit SD Card pin
#define chipSelect 10

File logfile;
uint32_t timer = millis();

void setup() {
  //SD Setup
  Serial.begin(115200);
  pinMode(chipSelect, OUTPUT);
  SD.begin(chipSelect, 11, 12, 13);

  //GPS Setup
  GPSSerial.begin(9600);
  // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY); //RMC (recommended minimum)
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_10HZ); // Set 1 Hz update rate (1Hz is suggested max), NOTE: This is the speed of the echo!
  GPS.sendCommand(PMTK_API_SET_FIX_CTL_5HZ); //Position fix update rate command
  GPS.sendCommand(PGCMD_ANTENNA); // Request updates on antenna status
  useInterrupt(true); //timer0 interrupt go off every 1ms and read GPS data

  char filename[15];
  strcpy(filename, "1.5_LOG00.csv");
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = '0' + i/10;
    filename[7] = '0' + i%10;
    if (! SD.exists(filename)) {
      break;
    }
  }
  logfile = SD.open(filename, FILE_WRITE);

  //APPS Setup
  APPSvalue = 0.00;

  //Wheel Speed Setup
  attachInterrupt(digitalPinToInterrupt(FLpin), FLdetect, RISING);
  //Initialize the intterrupt pin
  attachInterrupt(digitalPinToInterrupt(FRpin), FRdetect, RISING);
  FLtooth = 0;
  FRtooth = 0;
  FLrpm = 0.00;
  FRrpm = 0.00;
  FLtime = 0;
  FRtime = 0; 

  //Accelerometer Setup
  I2C.begin();
  //Initialize I2C communication to the let the library communicate with the sensor. 
  mySensor.initSensor();
  //The I2C Address can be changed here inside this function in the library
  mySensor.setOperationMode(OPERATION_MODE_NDOF);
  //Can be configured to other operation modes as desired
  mySensor.setPowerMode(0); //Normal = 0, Low Power = 1, Suspend = 2
  mySensor.setUpdateMode(MANUAL);
  //The default is AUTO. Changing to manual requires calling the relevant update functions prior to calling the read functions, setting to MANUAL requires lesser reads to the sensor
  mySensor.updateAccelConfig();
  updateSensorData = true;

  // Setup settings
  logfile.print("Accelerometer Range");
  logfile.print(", ");
  logfile.print(mySensor.readAccelRange());
  logfile.print(", ");
  logfile.println("2^(1+range)");
  logfile.print("Accelerometer Bandwidth");
  logfile.print(", ");
  logfile.print(mySensor.readAccelBandwidth());
  logfile.print(", ");
  logfile.println("7.81Hz x 2^bandwidth");
  logfile.print("Accelerometer Power Mode");
  logfile.print(", ");
  logfile.print(mySensor.readAccelPowerMode());
  logfile.print(", ");
  logfile.println("0 - 5 = Norm - Suspend - Low Power 1 - Standby - Low Power 2 - Deep Suspend");
  logfile.println();

  // Setup headings
  logfile.print("GPS Fix");
  logfile.print(", ");
  logfile.print("Time (5Hz)");
  logfile.print(", ");
  logfile.print("Date");
  logfile.print(", ");
  logfile.print("Latitude (5Hz)");
  logfile.print(", ");
  logfile.print("Longitude (5Hz)");
  logfile.print(", ");
  logfile.print("Throttle / %");
  logfile.print(", ");
  logfile.print("FL RPM");
  logfile.print(", ");
  logfile.print("FR RPM");
  logfile.print(", ");
  logfile.print("Acc X / m/s2");
  logfile.print(", ");
  logfile.print("Acc Y / m/s2");
  logfile.print(", ");
  logfile.print("Acc Z / m/s2");
  logfile.print(", ");
  logfile.print("LinAcc X / m/s2");
  logfile.print(", ");
  logfile.print("LinAcc Y / m/s2");
  logfile.print(", ");
  logfile.print("LinAcc Z / m/s2");
  logfile.print(", ");
  logfile.print("GracAcc X / m/s2");
  logfile.print(", ");
  logfile.print("GracAcc Y / m/s2");
  logfile.print(", ");
  logfile.print("GracAcc Z / m/s2");
  logfile.print(", ");
  logfile.print("Heading / deg");
  logfile.print(", ");
  logfile.print("Roll / deg");
  logfile.print(", ");
  logfile.print("Pitch / deg");
  logfile.print(", ");
  logfile.print("Acc Calibration");
  logfile.print(", ");
  logfile.print("Gyroscope Calibration");
  logfile.print(", ");
  logfile.print("System Calibration");
  logfile.println();
  logfile.flush(); //Waits for the transmission of outgoing serial data to complete
}

// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();
}

void useInterrupt(boolean v) {
  if (v) {
    // Timer0 is already used for millis() - we'll just interrupt somewhere
    // in the middle and call the "Compare A" function above
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } else {
    // do not call the interrupt function COMPA anymore
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

double convertDegMinToDecDeg (float degMin) {
  // converts lat/long from Adafruit degree-minute (DDM) format to decimal-degrees (DD)
  double min = 0.0;
  double decDeg = 0.0;

  //get the minutes, fmod() requires double
  min = fmod((double)degMin, 100.0);

  //rebuild coordinates in decimal degrees
  degMin = (int) ( degMin / 100 );
  decDeg = degMin + ( min / 60 );
  return decDeg;
}

void FLdetect() {
  //This function is called whenever a magnet/interrupt is detected by the Arduino
   FLtooth++;
   Serial.print("teeth: ");
   Serial.println(FLtooth);
 }

void FRdetect() {
  //This function is called whenever a magnet/interrupt is detected by the Arduino
  FRtooth++;
  Serial.print("teeth: ");
  Serial.println(FLtooth);
}

void FL_RPM() {
  //Measure RPM
  if (FLtooth >= 5) {
    FLrpm = (10.0*1000/((millis() - FLtime)));
    FLtime = millis();
    FLtooth = 0;
    return FLrpm;
  }
}

void FR_RPM() {
  //Measure RPM
  if (FRtooth >= 5) {
    FRrpm = (10.0*1000/((millis() - FRtime)));
    FRtime = millis();
    FRtooth = 0;
    return FRrpm;
  }
}

void loop() {
  if (!usingInterrupt) {
    // read data from the GPS in the 'main loop'
    char c = GPS.read();
  }
  // if a sentence is received, we can check the checksum, parse it...
  if (GPS.newNMEAreceived()) {
    // a tricky thing here is if we print the NMEA sentence, or data
    // we end up not listening and catching other sentences!
    // so be very wary if using OUTPUT_ALLDATA and trytng to print out data
    Serial.println(GPS.lastNMEA());
    // this also sets the newNMEAreceived() flag to false
    if (!GPS.parse(GPS.lastNMEA()))
      // this also sets the newNMEAreceived() flag to false
      return;
      // we can fail to parse a sentence in which case we should just wait for another
  }

  if (updateSensorData) {
    //Keep the updating of data as a separate task
    mySensor.updateAccel(); //Update the Accelerometer data
    mySensor.updateLinearAccel(); //Update the Linear Acceleration data
    mySensor.updateGravAccel(); //Update the Gravity Acceleration data
    mySensor.updateEuler(); //Update the Euler data into the structure of the object
    mySensor.updateCalibStatus(); //Update the Calibration Status
    updateSensorData = false;
  }

  FL_RPM();
  FR_RPM();
  APPSvalue = map(analogRead(APPSpin), 552, 710, 0, 100) ;

  // if millis() or timer wraps around, we'll just reset it
  if (timer > millis()) timer = millis();

  // approximately every 2 seconds or so, print out the current stats
  if (millis() - timer > 100) {
    timer = millis(); // reset the timer
    logfile.print((int)GPS.fix);    
    logfile.print(", ");
    logfile.print(GPS.hour, DEC); logfile.print(':');
    logfile.print(GPS.minute, DEC); logfile.print(':');
    logfile.print(GPS.seconds, DEC); logfile.print('.');
    logfile.print(GPS.milliseconds);
    logfile.print(", ");
    logfile.print(GPS.day, DEC); logfile.print('/');
    logfile.print(GPS.month, DEC); logfile.print("/20");
    logfile.print(GPS.year, DEC);
    logfile.print(", ");      
    logfile.print(convertDegMinToDecDeg(GPS.latitude),6);
    logfile.print(", ");
    logfile.print(-convertDegMinToDecDeg(GPS.longitude),6);
    logfile.print(", ");      
    logfile.print(APPSvalue,2);
    logfile.print(", ");
    logfile.print(FLrpm,2);
    logfile.print(", ");
    logfile.print(FRrpm,2);
    logfile.print(", ");
    logfile.print(mySensor.readAccelX()); //Accelerometer X-Axis data
    logfile.print(", ");
    logfile.print(mySensor.readAccelY()); //Accelerometer Y-Axis data
    logfile.print(", ");
    logfile.print(mySensor.readAccelZ()); //Accelerometer Z-Axis data
    logfile.print(", ");
    logfile.print(mySensor.readLinearAccelX()); //Linear Acceleration X-Axis data  
    logfile.print(", ");
    logfile.print(mySensor.readLinearAccelY()); //Linear Acceleration Y-Axis data  
    logfile.print(", ");
    logfile.print(mySensor.readLinearAccelZ()); //Linear Acceleration Z-Axis data  
    logfile.print(", ");
    logfile.print(mySensor.readGravAccelX()); //Gravity Acceleration X-Axis data
    logfile.print(", ");
    logfile.print(mySensor.readGravAccelY()); //Gravity Acceleration Y-Axis data
    logfile.print(", ");
    logfile.print(mySensor.readGravAccelZ()); //Gravity Acceleration Z-Axis data
    logfile.print(", ");
    logfile.print(mySensor.readEulerHeading()); //Heading data
    logfile.print(", ");
    logfile.print(mySensor.readEulerRoll()); //Roll data
    logfile.print(", ");
    logfile.print(mySensor.readEulerPitch()); //Pitch data
    logfile.print(", ");
    logfile.print(mySensor.readAccelCalibStatus()); //Accelerometer Calibration Status (0 - 3)
    logfile.print(", ");
    logfile.print(mySensor.readGyroCalibStatus()); //Gyroscope Calibration Status (0 - 3)
    logfile.print(", ");
    logfile.print(mySensor.readSystemCalibStatus()); //System Calibration Status (0 - 3)
    logfile.println();
    logfile.flush();
    updateSensorData = true;
  }
}