I finally made some progress on both the code and the quad. It does not fly yet, but hopefully that is just because I don't have enough propellers (one was destroyed). I was able to change the code around until it would stabilize reasonably well on one axis, so my hope is when I get the new propellers I will only have to do minor tweaks.
For those interested, here is the code (I haven't commented it, so if you have questions about what a certain part is for, just ask):
#include <Wire.h>
#include <Servo.h>
#define GYRO (0x69)
#define ACC (0x53)
int currMicros, pastMicros, count = 0;
int xAcc, yAcc;
int xAccFix = 0, yAccFix = 0;
float xAccAngle, yAccAngle;
int xGyro, yGyro;
int xGyroFix, yGyroFix;
float MDPS = 0.0000875;
float xGyroAngle, yGyroAngle;
float dt = 0.01;
Servo myservo, myservo1, myservo2, myservo3;
float xFix = 0, yFix = 0;
float xAngle = 0.0, yAngle = 0.0;
int signalAngleX = 0, signalAngleY = 0;
int throttle = 0;
float xVal_1, xVal_2, yVal_1, yVal_2;
int shutdownCount;
void setup()
{
Serial3.begin(9600);
Wire.begin();
rotorStartup();
AccSetup();
GyroSetup();
AccFix();
GyroFix();
}
void loop()
{
pastMicros = currMicros;
currMicros = micros();
dt = (float) (currMicros - pastMicros) / 1000000;
getSignal();
getAngles();
if (xAngle < (signalAngleX - 1.5) )
{
if (xFix < 0)
{
xFix = 0;
}
else if (xAngle < (signalAngleX - 5) )
{
if (xAngle < (signalAngleX - 10) )
{
if (xAngle < (signalAngleX - 15) )
{
xFix = 5;
}
else xFix = xFix + 1.25;
}
else xFix = xFix + 0.25;
}
else xFix = xFix + 0.0625;
}
else if (xAngle > (signalAngleX + 1.5) )
{
if (xFix > 0)
{
xFix = 0;
}
else if (xAngle > (signalAngleX + 5) )
{
if (xAngle > (signalAngleX + 10) )
{
if (xAngle > (signalAngleX + 15) )
{
xFix = -5;
}
else xFix = xFix - 1.25;
}
else xFix = xFix - 0.25;
}
else xFix = xFix - 0.0625;
}
else xFix = 0;
if (yAngle < (signalAngleY - 1.5) )
{
if (yFix < 0)
{
yFix = 0;
}
else if (yAngle < (signalAngleY - 5) )
{
if (yAngle < (signalAngleY - 10) )
{
if (yAngle < (signalAngleY - 15) )
{
yFix = 5;
}
else yFix = yFix + 1.25;
}
else yFix = yFix + 0.25;
}
else yFix = yFix + 0.0625;
}
else if (yAngle > (signalAngleY + 1.5) )
{
if (yFix > 0)
{
yFix = 0;
}
else if (yAngle > (signalAngleY + 5) )
{
if (yAngle > (signalAngleY + 10) )
{
if (yAngle > (signalAngleY + 15) )
{
yFix = -5;
}
else yFix = yFix - 1.25;
}
else yFix = yFix - 0.25;
}
else yFix = yFix - 0.0625;
}
else yFix = 0;
count = count + 1;
if (count >= 25)
{
yFix = 0;
xFix = 0;
count = 0;
}
if ((yFix > 5) or (yFix < -5))
{
yFix = 0;
}
if ((xFix > 5) or (xFix < -5))
{
xFix = 0;
}
xVal_1 = throttle + xFix;
xVal_2 = throttle - xFix;
yVal_1 = throttle + yFix;
yVal_2 = throttle - yFix;
myservo.write(xVal_1);
myservo1.write(xVal_2);
myservo2.write(yVal_1);
myservo3.write(yVal_2);
}
void getSignal()
{
int x, y;
if (Serial3.available())
{
throttle = Serial3.read();
x = constrain(Serial3.read(), 0, 30);
signalAngleX = map(x, 0, 30, -15, 15);
y = constrain(Serial3.read(), 0, 30);
signalAngleY = map(y, 0, 30, -15, 15);
}
else if (throttle > 50)
{
shutdownCount = shutdownCount + 1;
if (shutdownCount > 25)
{
throttle = throttle - 1;
shutdownCount = 0;
}
}
}
void getAngles()
{
AccGetVals();
xAcc = xAcc - xAccFix;
yAcc = yAcc - yAccFix;
xAccAngle = map(xAcc, -256, 256, -90, 90);
yAccAngle = map(yAcc, -256, 256, -90, 90);
GyroGetVals();
xGyroAngle = (xAngle + (xGyro - xGyroFix) * dt);
yGyroAngle = (yAngle + (yGyro - yGyroFix) * dt);
xAngle = (0.9) * xGyroAngle + (0.1) * xAccAngle;
yAngle = (0.9) * yGyroAngle + (0.1) * yAccAngle;
}
void AccSetup()
{
i2cWrite(ACC, 0x2D, 0);
i2cWrite(ACC, 0x2D, 16);
i2cWrite(ACC, 0x2D, 8);
}
void GyroSetup()
{
i2cWrite(GYRO, 0x20, 0b00001111);
i2cWrite(GYRO, 0x21, 0b00000000);
i2cWrite(GYRO, 0x22, 0b00001000);
i2cWrite(GYRO, 0x23, 0b00000000);
}
void AccFix()
{
int i = 1;
while (i <= 3)
{
AccGetVals();
xAccFix = xAccFix + xAcc;
yAccFix = yAccFix + yAcc;
i++;
}
xAccFix = xAccFix / 3;
yAccFix = yAccFix / 3;
}
void GyroFix()
{
xGyroFix = 0;
yGyroFix = 0;
int i = 1;
while (i <= 3)
{
GyroGetVals();
xGyroFix = xGyroFix + xGyro;
yGyroFix = yGyroFix + yGyro;
i++;
}
xGyroFix = xGyroFix / 3;
yGyroFix = yGyroFix / 3;
}
void AccGetVals()
{
byte MSB = i2cread(ACC, 0x33);
byte LSB = i2cread(ACC, 0x32);
xAcc = ((MSB << 8) | LSB);
MSB = i2cread(ACC, 0x35);
LSB = i2cread(ACC, 0x34);
yAcc = ((MSB << 8) | LSB);
}
void GyroGetVals()
{
byte MSB = i2cread(GYRO, 0x29);
byte LSB = i2cread(GYRO, 0x28);
xGyro = ((MSB << 8) | LSB) * MDPS;
MSB = i2cread(GYRO, 0x2B);
LSB = i2cread(GYRO, 0x2A);
yGyro = ((MSB << 8) | LSB) * MDPS;
}
void i2cWrite(int device, byte address, byte value)
{
Wire.beginTransmission(device);
Wire.write(address);
Wire.write(value);
Wire.endTransmission();
}
int i2cread (int device, byte address)
{
Wire.beginTransmission(device);
Wire.write(address);
Wire.endTransmission();
Wire.beginTransmission(device);
Wire.requestFrom(device, 1);
int value = Wire.read();
return value;
Wire.endTransmission();
}
void rotorStartup()
{
myservo.attach(35);
myservo1.attach(37);
myservo2.attach(23);
myservo3.attach(25);
int val = 10;
myservo.write(val);
myservo1.write(val);
myservo2.write(val);
myservo3.write(val);
delay(1000);
val = 10;
while (val < 65)
{
myservo.write(val);
myservo1.write(val);
myservo2.write(val);
myservo3.write(val);
val++;
delay(50);
}
}