我有一个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;
}
}