I'm having a bit of an odd problem here. I'm programming a self-built quadcopter using an Arduino Uno for control. One of the sensor's that I'm using is Adafruit's GPS breakout. The motors are controlled with electronic speed controllers (ESCs) that controlled identically to normal servo motors. Everything is connected together with a custom Arduino shield. The GPS is using SoftwareSerial on pins 3 and 4, and the ESCs are connected on pins 5-8. Most of the GPS code is directly copied from Adafruit's documentation.
What I've found is that even when the throttle is held steady (at any power level), the motors experience quick bursts of power far beyond normal whenever there is communication between the GPS module and the Arduino. For example, the GPS updates on 1Hz intervals and so the motors get a burst of speed about every second. Has anyone else experienced something like this or could someone at least point me in the right direction?
Here's an abbreviated version of the code that I'm currently using:
#include <Servo.h>
#include <Wire.h>
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
Servo ESC1;
Servo ESC2;
Servo ESC3;
Servo ESC4;
const int maxThrottle = 2000;
const int minThrottle = 1000;
SoftwareSerial softwareSerial(4, 3);
Adafruit_GPS GPS(&softwareSerial);
// 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 false
bool usingInterrupt = false;
uint32_t timer = millis();
void setup() {
ESC1.attach(5);
ESC2.attach(8);
ESC3.attach(6);
ESC4.attach(7);
setThrottleAll(minThrottle);
GPS.begin(9600);
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
GPS.sendCommand(PGCMD_ANTENNA);
useInterrupt(true);
}
int throttleCommand = 20;
void loop() {
// Map throttle command percentage to raw throttle values that are sent to the ESCs
int throttle = map(throttleCommand, 0, 100, minThrottle, maxThrottle);
setThrottle(1, throttle);
setThrottle(2, throttle);
setThrottle(3, throttle);
setThrottle(4, throttle);
}
// GPS interrupt
SIGNAL(TIMER0_COMPA_vect) {
char c = GPS.read();
// if you want to debug, this is a good time to do it!
#ifdef UDR0
if (GPSECHO)
if (c) UDR0 = c;
// writing direct to UDR0 is much much faster than Serial.print
// but only one character can be written at a time.
#endif
}
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;
}
}
void setThrottleAll(int throttle) {
setThrottle(1, throttle);
setThrottle(2, throttle);
setThrottle(3, throttle);
setThrottle(4, throttle);
}
void setThrottle(int index, int throttle) {
if (index == 1)
ESC1.writeMicroseconds(throttle);
if (index == 2)
ESC2.writeMicroseconds(throttle);
if (index == 3)
ESC3.writeMicroseconds(throttle);
if (index == 4)
ESC4.writeMicroseconds(throttle);
}