There also to discuss here but generally, everything is global. i know that's a bad idea structurally and i plan to change that at some point. the part where pretty much everything happens is the adjust() method. it does the reading of the gyro, the pid and the motors write. so after we read a message and figure out what we do with it, the message goes to adjust. Few things to note:
1. i limited the cycle of the calling to adjust by a timer of 4 milis. so we only adjust motor speed and do PID once every 4 milis. i personally don't know why thats needed but it seems that its needed at least according to the articles i read.
2. right now, the message coming from the transmitter effects the "desired value" of the Pid with the range of -250 to 250 degrees per second. the Value subtracted to it is the Raw gyro Value taking into account the offset of the Gyro. as far is i have seen, this should be enough to fly in "rate mode" which is what the Angle mode would build on. if something is missing, please to tell me since needless to say, this doesn't fly and i dont know what im missing.
3. Motor 1 seem to lag behind all other motors by a flat 150. if i dont write 150u+ , then it doesn't even start. its the same motor thats shutting of when turning the power too high. im beginning to think that it maybe the ESC and i should replace it.
4. any questions or suspicions, please do tell. i appreciate any type of input. thank you.
5. there is a word limit in the Forum but the way i communicate with the MPU is using jeff's library. google "MPU 6050 jeff" and it comes right up. his code is not included in this segment. only my code.
MPU6050 mpu;
MPU6050 accelgyro;
int16_t ax, ay, az;
int16_t gx, gy, gz;
void setup() {
Serial.begin(115200);
pinMode(LedPin,OUTPUT);
pinMode(LedPin2,OUTPUT);
pinMode(Motor1ESC,OUTPUT);
pinMode(Motor2ESC,OUTPUT);
pinMode(Motor3ESC,OUTPUT);
pinMode(Motor4ESC,OUTPUT);
digitalWrite(LedPin,LOW);
digitalWrite(LedPin2,LOW);
ESC.attach(Motor1ESC , 1000 , 2000); //3
ESC2.attach(Motor2ESC , 1000 , 2000);//
ESC3.attach(Motor3ESC , 1000 , 2000);
ESC4.attach(Motor4ESC , 1000 , 2000);
ReadInitialAccValues=true;
}
void loop() {
//Read the Incomeing Message.
ReadMessage();
MessTime=millis();
HandleMessage(Data);
HandleMessage_AnglesAndLED(Data);
if (SignalEnd==true) {
SignalEnd=false;
}
if(ReadInitialAccValues==false){
SetMotorsSpeed();
}
if(MessTime>interval && ReadInitialAccValues==true){
digitalWrite(LedPin,HIGH);
ReadInitialAccValues=false;
ReadInitial_Yaw_Pitch_Roll();
}
}
///////////////// This method reads message from the controller one char at a time.
void ReadMessage(){
char character;
//read a char if you recieve one.
while(Serial.available()>0){
SignalEnd=false; // we recieved a signal.
character = Serial.read(); //read the char
if(character=='-' ){ // "-" is the char we determined to be the end signal char. it can be anything we want but we are used "-".
SignalEnd=true; // meessage ended
RecievedMessage[MessagePosition]='\0'; //end the array with the \0 . its a needed char in the C language.
MessagePosition=0; // reset message position
strncpy(Buff,RecievedMessage,5); // write the message in a buffer.
Data=atoi(Buff); // change the type of data from A char string to an int.
}
else{RecievedMessage[MessagePosition]=character; // save current char in the buffer.
MessagePosition++; // move the position counter one step so that we dont overwrite our previously saved char.
}
}
}
//========== Set the Motor Speed =============
void SetMotorsSpeed(){
MessTime2=millis();
if(MessTime2-HoldTime2>interval2){
HoldTime2=MessTime2;
Adjust();
}
}
//============ Handle Messages Recieved From From Master========
//This handles the Data after its received. All Data is changed from char array to int. Depending on the int, we determine the appropriate action by the Quad.
void HandleMessage(int RecievedData){
if(RecievedData>=1000 && RecievedData<2000){
MotorPower_Throttle=RecievedData;
}
else if( RecievedData==1000){
Data=1000;
MotorPower_Throttle=1000;
SignalEnd=false;
}
}
void HandleMessage_AnglesAndLED(int RecievedData){
if(RecievedData>190 && RecievedData<280){
if(digitalRead(LedPin2)==HIGH){
digitalWrite(LedPin2,LOW);
}
else{digitalWrite(LedPin2,HIGH);}
}
if(RecievedData>=400 && RecievedData<500){
RCx=(RecievedData-400)*2;
}
else if(RecievedData>=500 && RecievedData<600){
RCx=(RecievedData-500)*-2;
}
else if(RecievedData>=600 && RecievedData<700){
RCy=(RecievedData-600)*-2;
}
else if(RecievedData>=700 && RecievedData<800){
RCy=(RecievedData-700)*2;
}
else if(RecievedData>=800 && RecievedData<900){
RCy=0.0;
}
else if( RecievedData>=900){
RCx=0.0;
}
else if(RecievedData>=200 && RecievedData<300){
RCz=(RecievedData-200)*-2;
}
else if(RecievedData>=300 && RecievedData<400){
RCz=(RecievedData-300)*2;
}
}
void Adjust(){
PidTime=micros();
accelgyro.getRotation(&gx, &gy, &gz); // This line reads the Gyro value from the MPU 6050
gx=((gx/131)* 180/M_PI);
gy=((gy/131)* 180/M_PI);
gz=((gz/131)* 180/M_PI);
if(gx<minInput){gx=minInput;}
if(gy<minInput){gy=minInput;}
if(gz<minInput){gz=minInput;}
if(gx>maxInput){gx=maxInput;}
if(gy>maxInput){gy=maxInput;}
if(gz>maxInput){gz=maxInput;}
TimeError=(PidTime-LastPidTime)/1000000;
CurrentReading_Yaw=gz;;
CurrentReading_Roll=gx;
CurrentReading_Pitch=gy;
Desired_Roll=RCx; // this is values from the transmitter
Desired_Pitch=RCy;
Desired_Yaw=RCz;
Desired_Yaw=map(Desired_Yaw,-180,180,-350,350);
Desired_Roll=map(Desired_Roll,-180,180,-250,250);
Desired_Pitch=map(Desired_Pitch,-180,180,-250,250);
Error_Pitch=Desired_Pitch-CurrentReading_Pitch;
Error_Roll=Desired_Roll-CurrentReading_Roll;
Error_Yaw=Desired_Yaw-CurrentReading_Yaw;
int_errorGain_Pitch+=(Error_Pitch*TimeError);
int_errorGain_Roll+=Error_Roll*TimeError;
int_errorGain_Yaw+=Error_Yaw*TimeError;
Integral_Pitch=Integral_gain*int_errorGain_Pitch;
Integral_Roll=Integral_gain*int_errorGain_Roll;
Integral_Yaw=Integral_gain*int_errorGain_Yaw;
Derivative_Roll=Derivative_gain*((Error_Roll-Prev_Error_Roll)/TimeError);
Derivative_Pitch=Derivative_gain*((Error_Pitch-Prev_Error_Pitch)/TimeError);
Derivative_Yaw=Derivative_gain*((Error_Yaw-Prev_Error_Yaw)/TimeError);
Input_Pitch=(Porpotional_gain*Error_Pitch)+Integral_Pitch; // no derivative gain cus it seems unnecessary according to multiple sources..
Input_Roll=(Porpotional_gain*Error_Roll)+Integral_Roll;
Input_Yaw=(Porpotional_gain*Error_Yaw)+Integral_Yaw;
Motor_1_Speed=(MotorPower_Throttle)+Input_Roll+Input_Pitch+Input_Yaw;
Motor_3_Speed=(MotorPower_Throttle)-Input_Roll+Input_Pitch-Input_Yaw;
Motor_2_Speed=(MotorPower_Throttle)-Input_Roll-Input_Pitch+Input_Yaw;
Motor_4_Speed=(MotorPower_Throttle) +Input_Roll-Input_Pitch-Input_Yaw;
int MotorMin=1000;
int MotorMax=2000;
if(Motor_1_Speed<MotorMin){Motor_1_Speed=MotorMin;}
if(Motor_2_Speed<MotorMin){Motor_2_Speed=MotorMin;}
if(Motor_3_Speed<MotorMin){Motor_3_Speed=MotorMin;}
if(Motor_4_Speed<MotorMin){Motor_4_Speed=MotorMin;}
if(Motor_1_Speed>MotorMax){Motor_1_Speed=MotorMax;}
if(Motor_2_Speed>MotorMax){Motor_2_Speed=MotorMax;}
if(Motor_3_Speed>MotorMax){Motor_3_Speed=MotorMax;}
if(Motor_4_Speed>MotorMax){Motor_4_Speed=MotorMax;}
Serial.print("1 : ");Serial.println(Motor_1_Speed);
Serial.print(" 2: ");Serial.print(Motor_2_Speed);
Serial.print(" 3: ");Serial.print(Motor_3_Speed);//
Serial.print(" 4: ");Serial.println(Motor_4_Speed);
ESC.writeMicroseconds(Motor_1_Speed+150); // Why +150? i which i know. that same motor doesnt start unless its getting 150u more than others.
ESC2.writeMicroseconds(Motor_2_Speed);
ESC3.writeMicroseconds(Motor_3_Speed);
ESC4.writeMicroseconds(Motor_4_Speed);
Prev_Error_Pitch=Error_Pitch; // update values that we neeed to carry for the next loop call.
Prev_Error_Roll=Error_Roll;
LastPidTime=PidTime;
}
void ReadInitial_Yaw_Pitch_Roll(){
LastPidTime=micros();
Initial_Yaw =0.0;
Initial_Roll=0.0;
Initial_Pitch=0.0;
}