Hello,
I'm building a drone right now with an Arduino Mega and I'm using an MPU6050 accelerometer. I'm having an issue where when I turn up the throttle to the drone, instead of flying up, it wobbles and rotates. I haven't managed to get it off the ground. Here is the code that I'm running(I took inspiration from Carbon Aeronautics):
#include <Servo.h>
Servo motor1;
Servo motor2;
Servo motor3;
Servo motor4;
// MPU-6050 initialized below
#include <Wire.h>
float RatePitch, RateRoll, RateYaw, RateCalibrationPitch, RateCalibrationRoll, RateCalibrationYaw;
int RateCalibrationNumber;
// Reciever initialization below
#define throttlePin 9
#define rollPin 10
#define pitchPin 11
#define yawPin 12
float ReceiverValue[4]={};
uint32_t LoopTimer;
// All variables required for PID Control Loop initialized below
float DesiredRateRoll, DesiredRatePitch, DesiredRateYaw;
float ErrorRateRoll, ErrorRatePitch, ErrorRateYaw;
float InputRoll, InputThrottle, InputPitch, InputYaw;
float PrevErrorRateRoll, PrevErrorRatePitch, PrevErrorRateYaw;
float PrevItermRateRoll, PrevItermRatePitch, PrevItermRateYaw;
float PIDReturn[] = {0,0,0};
// PID constants defined below
float PRateRoll = 0.6; float PRatePitch = PRateRoll; float PRateYaw = 2;
float IRateRoll = 3.5; float IRatePitch = IRateRoll; float IRateYaw = 12;
float DRateRoll = 0.03; float DRatePitch = DRateRoll; float DRateYaw = 0;
float MotorInput1, MotorInput2, MotorInput3, MotorInput4;
void read_receiver(){
ReceiverValue[0] = pulseIn(yawPin, HIGH);
ReceiverValue[1] = pulseIn(pitchPin, HIGH);
ReceiverValue[2] = pulseIn(throttlePin, HIGH);
ReceiverValue[3] = pulseIn(rollPin, HIGH);
/*Serial.print("Yaw: ");
Serial.print(ReceiverValue[0]);
Serial.print(" | Pitch: ");
Serial.print(ReceiverValue[1]);
Serial.print(" | Roll: ");
Serial.print(ReceiverValue[2]);
Serial.print(" | Throttle: ");
Serial.println(ReceiverValue[3]);
*/
Serial.print("| MotorInput4 ");
Serial.print(MotorInput4);
Serial.print("| MotorInput3 ");
Serial.print(MotorInput3);
Serial.print("| MotorInput2 ");
Serial.print(MotorInput2);
Serial.print("| MotorInput1 ");
Serial.println(MotorInput1);
}
void gyro_signals() {
Wire.beginTransmission(0x68);
Wire.write(0x1A);
Wire.write(0x05);
Wire.endTransmission();
Wire.beginTransmission(0x68);
Wire.write(0x1B);
Wire.write(0x08);
Wire.endTransmission();
Wire.beginTransmission(0x68);
Wire.write(0x43);
Wire.endTransmission();
Wire.requestFrom(0x68,6);
int16_t GyroX = Wire.read() << 8 | Wire.read();
int16_t GyroY = Wire.read() << 8 | Wire.read();
int16_t GyroZ = Wire.read() << 8 | Wire.read();
RateRoll = (float) GyroX / 65.5;
RatePitch = (float) GyroY / 65.5;
RateYaw = (float) GyroZ / 65.6;
// Serial.println(GyroX);
}
void pid_equation(float Error, float P, float I, float D, float PrevError, float PrevIterm){
float Pterm = P*Error;
float Iterm = PrevIterm+I*(Error + PrevError)*0.004/2;
if (Iterm > 400){
Iterm = 400;
} else if (Iterm < -400){
Iterm = -400;
}
float Dterm = D*(Error-PrevError)/0.004;
float PIDOutput = Pterm+Iterm+Dterm;
if (PIDOutput > 400){
PIDOutput = 400;
} else if (PIDOutput < -400){
PIDOutput = -400;
}
PIDReturn[0] = PIDOutput;
PIDReturn[1] = Error;
PIDReturn[2] = Iterm;
}
void reset_pid(){
PrevErrorRateRoll = 0; PrevErrorRatePitch = 0; PrevErrorRateYaw = 0;
PrevItermRateRoll = 0; PrevItermRatePitch = 0; PrevItermRateYaw = 0;
}
void setup() {
motor1.attach(5);
motor2.attach(6);
motor3.attach(7);
motor4.attach(8);
Serial.begin(9600);
pinMode(throttlePin, INPUT);
pinMode(yawPin, INPUT);
pinMode(pitchPin, INPUT);
pinMode(rollPin, INPUT);
// initializing communication with the gyroscope below
Wire.setClock(400000);
Wire.begin();
delay(250);
Wire.beginTransmission(0x68);
Wire.write(0x6B);
Wire.write(0x00);
Wire.endTransmission();
// calibrating gyroscope
for (RateCalibrationNumber = 0; RateCalibrationNumber < 2000; RateCalibrationNumber++){
gyro_signals();
RateCalibrationRoll += RateRoll;
RateCalibrationPitch += RatePitch;
RateCalibrationYaw += RateYaw;
delay(1);
}
RateCalibrationRoll /= 2000;
RateCalibrationPitch /= 2000;
RateCalibrationYaw /= 2000;
// checking to see if throttle stick is in lowest position below
//while (ReceiverValue[2] < 1050){
read_receiver();
delay(4);
//}
}
void loop() {
// Changing the Rate variables from gyroscope to calibrate
gyro_signals();
RateRoll -= RateCalibrationRoll;
RatePitch -= RateCalibrationPitch;
RateYaw -= RateCalibrationYaw;
read_receiver();
// Mapping desired variables to reciever values below
DesiredRateRoll = 0.15 * (ReceiverValue[0] - 1500); DesiredRatePitch = 0.15 * (ReceiverValue[1] - 1500);
InputThrottle = ReceiverValue[2];
DesiredRateYaw = 0.15 * (ReceiverValue[3] - 1500);
// Calculating errors for the PID calculations below
ErrorRateRoll = DesiredRateRoll - RateRoll;
ErrorRatePitch = DesiredRatePitch - RatePitch;
ErrorRateYaw = DesiredRateYaw - RateYaw;
pid_equation(ErrorRateRoll, PRateRoll, IRateRoll, DRateRoll, PrevErrorRateRoll, PrevItermRateRoll);
InputRoll = PIDReturn[0];
PrevErrorRateRoll = PIDReturn[1];
PrevItermRateRoll = PIDReturn[2];
pid_equation(ErrorRatePitch, PRatePitch, IRatePitch, DRatePitch, PrevErrorRatePitch, PrevItermRatePitch);
InputPitch = PIDReturn[0];
PrevErrorRatePitch = PIDReturn[1];
PrevItermRatePitch = PIDReturn[2];
pid_equation(ErrorRateYaw, PRateYaw, IRateYaw, DRateYaw, PrevErrorRateYaw, PrevItermRateYaw);
InputYaw = PIDReturn[0];
PrevErrorRateYaw = PIDReturn[1];
PrevItermRateYaw = PIDReturn[2];
// Limiting throttle to 80 percent below because maximum throttle is 2000
if (InputThrottle > 1800){
InputThrottle = 1800;
}
// Calculating motor inputs below
MotorInput1 = 1.024 * ( InputThrottle - InputRoll - InputPitch - InputYaw);
MotorInput2 = 1.024 * (InputThrottle - InputRoll + InputPitch + InputYaw);
MotorInput3 = 1.024 * (InputThrottle + InputRoll + InputPitch - InputYaw);
MotorInput4 = 1.024 * (InputThrottle + InputRoll - InputPitch + InputYaw);
// Limiting maximum power going to motors below
if (MotorInput1 > 2000){
MotorInput1 = 1999;
}
if (MotorInput2 > 2000){
MotorInput2 = 1999;
}
if (MotorInput3 > 2000){
MotorInput3 = 1999;
}
if (MotorInput4 > 2000){
MotorInput4 = 1999;
}
// Setting motor to 18 percent to stop drone from crashing if the throttle stick is pushed down too low
int ThrottleIdle = 1180;
if (MotorInput1 < ThrottleIdle) {
MotorInput1 = ThrottleIdle;
}
if (MotorInput2 < ThrottleIdle) {
MotorInput2 = ThrottleIdle;
}
if (MotorInput3 < ThrottleIdle) {
MotorInput3 = ThrottleIdle;
}
if (MotorInput4 < ThrottleIdle) {
MotorInput4 = ThrottleIdle;
}
// if the throttle stick is set to its lowest position, the motors will turn off
int ThrottleCutOff = 1000;
if (ReceiverValue[2]<1050){
MotorInput1 = ThrottleCutOff;
MotorInput2 = ThrottleCutOff;
MotorInput3 = ThrottleCutOff;
MotorInput4 = ThrottleCutOff;
reset_pid();
}
//writing to the motors below
motor1.writeMicroseconds(MotorInput1);
motor2.writeMicroseconds(MotorInput2);
motor3.writeMicroseconds(MotorInput3);
motor4.writeMicroseconds(MotorInput4);
}
Right now, I'm just wondering if there is an issue within the code or if it is probably a hardware issue. When I run the code, the motor outputs seem to look correct(within a range between 1000 and 2000).
