Go Down

Topic: Creating a QuadCopter Controller and Code. roadblock, Need Help. (Read 573 times) previous topic - next topic

vortix2950

Hello everyone. I have been trying to create my own controller and quad copter and i hit a roadblock. The problem is that when i try to fly the quadcopter, it feels like its going to take off as your increase the throttle but once it gets to a point where its actually going to start taking off, it just goes berserk. it never takes off and it just starts going haywire. If i hold it with my hand from the buttom and try to do some basic tests, it seems to work. if you tilt towards a motor, that motor increases and power and if you tilt quickly, the motor reacts with faster speed.

Im not sure if im missing a step or something. i looked into a million equations and tried quite a lot of them, its not working.

here is what i have right now, the Code takes input from the controller and changes throttle speed. The Angles comes from the chip MPU 6050 using Jeff's library. as far is i know, the Library filters the Acc and Gyro and uses both to give you the Angles but im not sure.

No code for movement yet since i cant even take off vertically. Im Using arduino nano for the quad and uno for the controller. Right now, the leveling code is inside the Quad itself.


Frame:https://www.amazon.com/gp/product/B078SNZN87/ref=ppx_yo_dt_b_asin_title_o02_s03?ie=UTF8&psc=1

the MPU chip:https://www.amazon.com/gp/product/B07PY38BCB/ref=ppx_yo_dt_b_asin_image_o00_s00?ie=UTF8&psc=1

The ESC :https://www.amazon.com/gp/product/B07SQHCWQN/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1

Motors:
https://www.amazon.com/gp/product/B07KPDKV89/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1

Code: [Select]
Code:

//
float Porpotional_gain=3;
float Integral_gain=1.3;
float Derivative_gain=0.2;

PidTime=millis(); // we Read the Current time.
TimeError=(PidTime-LastPidTime)/1000;
CurrentReading_Yaw=ypr[0] * 180/M_PI;; // we read current Angles.
CurrentReading_Roll=ypr[2] * 180/M_PI;
CurrentReading_Pitch=ypr[1]* 180/M_PI ;

Desired_Roll=Initial_Roll;      //the initial Angle of the MPU when its flat on the ground
Desired_Pitch=Initial_Pitch;

Error_Pitch=Desired_Pitch-CurrentReading_Pitch;
Error_Roll=Desired_Roll-CurrentReading_Roll;

int_errorGain_Pitch+=(Error_Pitch*TimeError);
int_errorGain_Roll+=Error_Pitch*TimeError;

Integral_Pitch=Integral_gain*int_errorGain_Pitch;
Integral_Roll=Integral_gain*int_errorGain_Roll;

Derivative_Roll=Derivative_gain*(( Error_Roll - Prev_Error_Roll)/TimeError);
Derivative_Pitch=Derivative_gain*(( Error_Pitch - Prev_Error_Pitch)/TimeError);

Input_Pitch=(Porpotional_gain*Error_Pitch)+Integral_Pitch;
Input_Roll=(Porpotional_gain*Error_Roll)+Integral_Roll;


Motor_1_Speed=((MotorPower*MotorPower_Scaler)+MinMicroSeconds_Motor)-Input_Pitch;
Motor_3_Speed=((MotorPower*MotorPower_Scaler)+MinMicroSeconds_Motor)+Input_Pitch;
Motor_2_Speed=((MotorPower*MotorPower_Scaler)+MinMicroSeconds_Motor)-Input_Roll;
Motor_4_Speed=((MotorPower*MotorPower_Scaler)+MinMicroSeconds_Motor) +Input_Roll;

Prev_Error_Pitch=Error_Pitch; // update values that we need to carry for the next loop call.
Prev_Error_Roll=Error_Roll;
LastPidTime=PidTime;


Please, i just want to know if im missing something or is this just an "keep adjusting PID " type of problem. The MinMicroSeconds is that smallest value the motor can take which is 1000 milis.
MotorPower is Potentiometer reading from the controller and its scaled by 3.

there is very little that happens outside of this loop in terms of balancing the Quad. What else does this need to get stable flight?

MartinL

Hi vortix2950,

To achieve stable flight you first need to covert your roll, pitch and yaw pilot input into angular rate (speed), not angle. This can be in degrees per second, radians per second or whatever units you prefer.

These three inputs are the setpoints for your roll, pitch and yaw rate PID loops. The 3-axis gyroscope outputs using the same units (for example degrees per second) act as your input to these control loops.

In these three control loops you simply subtract the gyroscope input value from the pilot setpoint and multiply by the proportional P gain:

PID output = (pilot setpoint - gyroscope input) * PGain

On a quadcopter the outputs from the roll, pitch and yaw control loops are superimposed on to the raw throttle level during motor mixing:

motor1 = throttlePulsewidth + rollRateOut + pitchRateOut + yawRateOut
motor2 = throttlePulsewidth - rollRateOut + pitchRateOut - yawRateOut
motor3 = throttlePulsewidth - rollRateOut - pitchRateOut + yawRateOut
motor4 = throttlePulsewidth + rollRateOut - pitchRateOut - yawRateOut

The additions and subractions may differ depending on your motor arrangement.

It's possible to sucessfully fly on P gain alone. Introduce the control loop derivative D and intergral I gains only once the aircraft is flying correctly.

You'll also need to activate the gyrosope/accelerometer Digital Low Pass Filter on the MPU6050, 20Hz is a good value to use initially.

Only move on to auto-level mode once you've first got the quadcopter successfully tuned and flying in rate mode.

vortix2950

Hi vortix2950,

To achieve stable flight you first need to covert your roll, pitch and yaw pilot input into angular rate (speed), not angle. This can be in degrees per second, radians per second or whatever units you prefer.

These three inputs are the setpoints for your roll, pitch and yaw rate PID loops. The 3-axis gyroscope outputs using the same units (for example degrees per second) act as your input to these control loops.

In these three control loops you simply subtract the gyroscope input value from the pilot setpoint and multiply by the proportional P gain:

PID output = (pilot setpoint - gyroscope input) * PGain

On a quadcopter the outputs from the roll, pitch and yaw control loops are superimposed on to the raw throttle level during motor mixing:

motor1 = throttlePulsewidth + rollRateOut + pitchRateOut + yawRateOut
motor2 = throttlePulsewidth - rollRateOut + pitchRateOut - yawRateOut
motor3 = throttlePulsewidth - rollRateOut - pitchRateOut + yawRateOut
motor4 = throttlePulsewidth + rollRateOut - pitchRateOut - yawRateOut

The additions and subractions may differ depending on your motor arrangement.

It's possible to sucessfully fly on P gain alone. Introduce the control loop derivative D and intergral I gains only once the aircraft is flying correctly.

You'll also need to activate the gyrosope/accelerometer Digital Low Pass Filter on the MPU6050, 20Hz is a good value to use initially.

Only move on to auto-level mode once you've first got the quadcopter successfully tuned and flying in rate mode.
thank you. i have a few questions just to make sure i understand you correctly. So what im suppose to do is convert the Angles from MPU 6050 to roll/yaw/pitch rates instead of angles and Then thats the Desired value
(or target value) of the PID control right? Then the current value(our current state) is just reading from the Gyro?

How do i turn the Angles into Rates?

also, im not sure what you mean by the Digtal Low Pass Filter? why do we need to do that? i only read about complimentary filters that are needed to merge the Acc and gyro and thats already done by the I2C dev library that returns the Yaw/pitch/roll.

Thank you!

MartinL

Hi vortix2950,

Quote
So what im suppose to do is convert the Angles from MPU 6050 to roll/yaw/pitch rates instead of angles and Then thats the Desired value
(or target value) of the PID control right?
Quote
How do i turn the Angles into Rates?
No, it's simpler than that. You just need the MPU6050's 3-axis gyroscope outputs that measure angular rate for roll, pitch and yaw. Convert these measuresurements, for sake of argument to say degrees per second.

For the moment you don't need any angle measurement, complimentary filter, or the MPU6050's accelerometer.

Regarding the pilot input, irrespective of what controller you're using, you just convert the roll (airelon), pitch (elevator) and yaw (rudder) inputs into degrees per second and set the minimum and maximum for a full stick throw. For example, I normally set the minimum and maximum roll and pitch to ±250°/s and yaw to ±450°/s.

The roll, pitch and yaw pilot input in degrees per second becomes the "setpoint" for your three corresponding PID control loops, while the gyroscope's output becomes the "input".

Quote
also, im not sure what you mean by the Digtal Low Pass Filter? why do we need to do that?
The MPU6050 has an on-chip anti-aliasing filter that helps prevent sampling harmonic frequencies and noise from corrupting your gyroscope/accelerometer signals and entering your PID control loops.

To activate this filter for 20Hz using Jeff Rowberg's library:

Code: [Select]
accelgyro.setDLPFMode(MPU6050_DLPF_BW_20);
Using the stick input to control angular rate gives provides a similar experience to flying a fixed wing aircraft. This is what is known as rate/gyro/acro mode and is the mode preferred by most RC pilots.

Rate mode is the basis of flight stability. Auto-level builds on this, but it's necessary to get your aircraft flying in rate mode first.

vortix2950

Hi vortix2950,

No, it's simpler than that. You just need the MPU6050's 3-axis gyroscope outputs that measure angular rate for roll, pitch and yaw. Convert these measuresurements, for sake of argument to say degrees per second.

For the moment you don't need any angle measurement, complimentary filter, or the MPU6050's accelerometer.

Regarding the pilot input, irrespective of what controller you're using, you just convert the roll (airelon), pitch (elevator) and yaw (rudder) inputs into degrees per second and set the minimum and maximum for a full stick throw. For example, I normally set the minimum and maximum roll and pitch to ±250°/s and yaw to ±450°/s.

The roll, pitch and yaw pilot input in degrees per second becomes the "setpoint" for your three corresponding PID control loops, while the gyroscope's output becomes the "input".

The MPU6050 has an on-chip anti-aliasing filter that helps prevent sampling harmonic frequencies and noise from corrupting your gyroscope/accelerometer signals and entering your PID control loops.

To activate this filter for 20Hz using Jeff Rowberg's library:

Code: [Select]
accelgyro.setDLPFMode(MPU6050_DLPF_BW_20);
Using the stick input to control angular rate gives provides a similar experience to flying a fixed wing aircraft. This is what is known as rate/gyro/acro mode and is the mode preferred by most RC pilots.

Rate mode is the basis of flight stability. Auto-level builds on this, but it's necessary to get your aircraft flying in rate mode first.

i have done that now. It doesnt go berserk but still wont fly. as i increase the throttle, it starts Yawing to one side but never really takes off. still no flight. How do i fix that? Note that even though i have the Code written to PID, I and D are both zero as you suggested.

New Code Below :

Code: [Select]

  
maxInput=250;
minInput=-250;

maxInput_Yaw=450;
minInput_Yaw=-450;

Porpotional_gain=0.07;

accelgyro.getRotation(&gx, &gy, &gz);
    
    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;}


    PidTime=millis();
    TimeError=(PidTime-LastPidTime)/1000;
    
    CurrentReading_Yaw=gz;;
    CurrentReading_Roll=gx;
    CurrentReading_Pitch=gy;
    
    //
    Desired_Roll=0.0;
    Desired_Pitch=0.0;
    Desired_Yaw=0.0;
    
    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_Pitch=Derivative_gain*((Error_Pitch-Prev_Error_Pitch)/TimeError);
    Derivative_Roll=Derivative_gain*((Error_Roll-Prev_Error_Roll)/TimeError);
    Derivative_Yaw=Derivative_gain*((Error_Yaw-Prev_Error_Yaw)/TimeError);
    
    Input_Pitch=(Porpotional_gain*Error_Pitch)+Integral_Pitch;
    Input_Roll=(Porpotional_gain*Error_Roll)+Integral_Roll;
    Input_Yaw=(Porpotional_gain*Error_Yaw)+Integral_Yaw;
    




i also added the Line " accelgyro.setDLPFMode(MPU6050_DLPF_BW_20);" right before the loop calls the accelgyro for the gyro outputs.

like before, the controller doesn't have code to change rates through the controller for now, only the throttle. but that shouldn't be an issue to at least somewhat take off.
i Also wonder if it would work better or differently if my quad was bigger. right now this is a 2inch blades build. its a small quad. is there anything that needs change due to quad size?






MartinL

Hi vortix2950,

The flight controller project is best broken down into smaller mini projects:

1. Pilot input
2. Gyroscope output
3. PID control loops
4. Motor mixing and motor output

Each part needs to be independently developed and tested, before integrating them into a complete system. I also find it useful to think of the system in terms of the measurement, processing and flow of information.

Pilot Input

Normally in a traditional RC fixed wing aircraft the throttle, airelon, elevator and rudder signals directly drive the propeller and servo operated control surfaces. These signals are in the 1000us to 2000us range and repeat every 22ms or so.

In a quadcopter you've got a similar system except that the servo operated control surfaces have been repaced with additional motors. There's a flight controller placed between the receiver and the motors, to provide flight stability.

Whatever type of transmitter/receiver you're using this information ultimately needs to be converted into values that  your Electronic Speed Controllers (ESCs) and motors understand. If you're using brushless motors then the ESCs will expect a similar 1000us to 2000us signal. In the case of a RC transmitter/receiver, the throttle signal can be allowed to pass through directly to the motors, while the roll (airelon), pitch (elevator) and yaw (rudder) pulses must be converted to value that can be compared with the gyroscope in the PID control loops. The output from PID control loops being superimposed on to the throttle during motor mixing.

Whatever control information is produced by your transmitter/receiver they can be coverted to values your ESCs and PID control loops understand, by using the Arduino "map" and "constrain" macros.

Gyroscope Output

This is pretty straightforward, the gyroscope should generate roll, pitch and yaw information converted to your units of choice, for example degrees per second. Bear in mind that on the MPU6050 it's also possible to change the measurement range to: ±250°/s, ±500°/s, ±1000°/s and ±2000°/s.

PID Control Loops

There are three PID control loops for roll, pitch and yaw. The pilot input is the "setpoint" and the gyroscope the "input" to your system, these need to be in the same measurement units, for example degrees per second.

The other thing to note is that the PID control loop's output has no units, it's just a value that can be magnified with the proportional P gain and passed on to the motor mixer. In this case, the PID output is just the number of microseconds that are be added and subtracted from the throttle.

To determine the control loop's integral I and derivative D gains, it's better to use micros() rather than millis(). Even using floating point PID control loops, your Arduino Nano's loop time should be around 4ms or so.

Motor Mixing and Motor Output

The motor mixing has already been described above. The only other thing to note is that if you're using brushless motor ESCs it's necessary to use the analogWrite() function to generate a 490Hz PWM signal on pins 3, 11, 9 and 10 on the Arduino Nano. The servo library isn't suitable for quadcopter control.

vortix2950

Hi vortix2950,

The flight controller project is best broken down into smaller mini projects:

1. Pilot input
2. Gyroscope output
3. PID control loops
4. Motor mixing and motor output

Each part needs to be independently developed and tested, before integrating them into a complete system. I also find it useful to think of the system in terms of the measurement, processing and flow of information.

Pilot Input

Normally in a traditional RC fixed wing aircraft the throttle, airelon, elevator and rudder signals directly drive the propeller and servo operated control surfaces. These signals are in the 1000us to 2000us range and repeat every 22ms or so.

In a quadcopter you've got a similar system except that the servo operated control surfaces have been repaced with additional motors. There's a flight controller placed between the receiver and the motors, to provide flight stability.

Whatever type of transmitter/receiver you're using this information ultimately needs to be converted into values that  your Electronic Speed Controllers (ESCs) and motors understand. If you're using brushless motors then the ESCs will expect a similar 1000us to 2000us signal. In the case of a RC transmitter/receiver, the throttle signal can be allowed to pass through directly to the motors, while the roll (airelon), pitch (elevator) and yaw (rudder) pulses must be converted to value that can be compared with the gyroscope in the PID control loops. The output from PID control loops being superimposed on to the throttle during motor mixing.

Whatever control information is produced by your transmitter/receiver they can be coverted to values your ESCs and PID control loops understand, by using the Arduino "map" and "constrain" macros.

Gyroscope Output

This is pretty straightforward, the gyroscope should generate roll, pitch and yaw information converted to your units of choice, for example degrees per second. Bear in mind that on the MPU6050 it's also possible to change the measurement range to: ±250°/s, ±500°/s, ±1000°/s and ±2000°/s.

PID Control Loops

There are three PID control loops for roll, pitch and yaw. The pilot input is the "setpoint" and the gyroscope the "input" to your system, these need to be in the same measurement units, for example degrees per second.

The other thing to note is that the PID control loop's output has no units, it's just a value that can be magnified with the proportional P gain and passed on to the motor mixer. In this case, the PID output is just the number of microseconds that are be added and subtracted from the throttle.

To determine the control loop's integral I and derivative D gains, it's better to use micros() rather than millis(). Even using floating point PID control loops, your Arduino Nano's loop time should be around 4ms or so.

Motor Mixing and Motor Output

The motor mixing has already been described above. The only other thing to note is that if you're using brushless motor ESCs it's necessary to use the analogWrite() function to generate a 490Hz PWM signal on pins 3, 11, 9 and 10 on the Arduino Nano. The servo library isn't suitable for quadcopter control.
alright ill give it a try. Im assuming that i need to convert the output from the 1000us to 2000us range to analogwrite range which is 0 to 255 right?  the Servo has a write micro seconds function but the AnalogWrite doesnt.

MartinL

Quote
Im assuming that i need to convert the output from the 1000us to 2000us range to analogwrite range which is 0 to 255 right?  the Servo has a write micro seconds function but the AnalogWrite doesnt.
The issue is that servo library works at around 50Hz, whereas the analogWrite() function operates at 490Hz.

In the dim and distant past before multi-rotor specific ESCs were available, it was necessary to use ESCs designed for aeroplanes and helicopters. Traditionally these ESCs operated at 50Hz and used input filtering, however in order make them more responsive and to overcome the input filter, quacopters flight controllers used a faster update rate of 490Hz PWM instead. Nowadays there are multi-rotor specific ESC that support a whole host of protocols.

Yes that's right, if you're using the Arduino Uno or Nano it's necessary to map the resolution from 0 - 2000 down to 0 - 255 when using analogWrite(). This is because the Uno/Nano's Atmega 328P has only one 16-bit timer (timer 1) with two outputs, while the other timers (timers 0 and 2) are 8-bit.

vortix2950

Hi vortix2950,

The flight controller project is best broken down into smaller mini projects:

1. Pilot input
2. Gyroscope output
3. PID control loops
4. Motor mixing and motor output

Each part needs to be independently developed and tested, before integrating them into a complete system. I also find it useful to think of the system in terms of the measurement, processing and flow of information.

Pilot Input

Normally in a traditional RC fixed wing aircraft the throttle, airelon, elevator and rudder signals directly drive the propeller and servo operated control surfaces. These signals are in the 1000us to 2000us range and repeat every 22ms or so.

In a quadcopter you've got a similar system except that the servo operated control surfaces have been repaced with additional motors. There's a flight controller placed between the receiver and the motors, to provide flight stability.

Whatever type of transmitter/receiver you're using this information ultimately needs to be converted into values that  your Electronic Speed Controllers (ESCs) and motors understand. If you're using brushless motors then the ESCs will expect a similar 1000us to 2000us signal. In the case of a RC transmitter/receiver, the throttle signal can be allowed to pass through directly to the motors, while the roll (airelon), pitch (elevator) and yaw (rudder) pulses must be converted to value that can be compared with the gyroscope in the PID control loops. The output from PID control loops being superimposed on to the throttle during motor mixing.

Whatever control information is produced by your transmitter/receiver they can be coverted to values your ESCs and PID control loops understand, by using the Arduino "map" and "constrain" macros.

Gyroscope Output

This is pretty straightforward, the gyroscope should generate roll, pitch and yaw information converted to your units of choice, for example degrees per second. Bear in mind that on the MPU6050 it's also possible to change the measurement range to: ±250°/s, ±500°/s, ±1000°/s and ±2000°/s.

PID Control Loops

There are three PID control loops for roll, pitch and yaw. The pilot input is the "setpoint" and the gyroscope the "input" to your system, these need to be in the same measurement units, for example degrees per second.

The other thing to note is that the PID control loop's output has no units, it's just a value that can be magnified with the proportional P gain and passed on to the motor mixer. In this case, the PID output is just the number of microseconds that are be added and subtracted from the throttle.

To determine the control loop's integral I and derivative D gains, it's better to use micros() rather than millis(). Even using floating point PID control loops, your Arduino Nano's loop time should be around 4ms or so.

Motor Mixing and Motor Output

The motor mixing has already been described above. The only other thing to note is that if you're using brushless motor ESCs it's necessary to use the analogWrite() function to generate a 490Hz PWM signal on pins 3, 11, 9 and 10 on the Arduino Nano. The servo library isn't suitable for quadcopter control.
ok so i did all of that and i converted to 0 to 255. multiplied the Gyros by 1000,000 for micro and this might work but One new problem came out of nowhere.
since i switched from Servos to analogWrite, the motors have been having quite a problem with the signals they are getting so i couldn't test if it flys. all motors are using the 3,9,10,11 pins But as i try to send them the signal, they just dont sync up together. they start making syncing sounds but some start while others just dont.
if you continue increasing throttle, they all start but as you approach the throttle that would take the quad to flight, one(and some times 2) motors stop completely while the other two keep going. they still respond to controller but two motors  just stop until you bring throttle down and they start making noises again. note that im using analogWrite() and tested the output and at that stick position, the motors didn't receive more than 20-25 in  analog write.

Battery seems half full so i dont think its the battery. Its a complete mess. they keep turning on and off and making syncing sounds like its a disco party. almost feels like random.its not that they work a little then stop working, they start doing this from the very beginning.
one thing i noticed is that the Motors dont actually start untill you write about 7 to 10 in analogwrite. an when they do start, its rather strong for whats suppose to be the minimum.

Also, should i still attach the motors to servo? or is that not necessary now?

i dont even have the faintest idea of whats wrong.

MartinL

Hi vortix2950,

Starting with the Pilot Input:

You mention that you're using an Arduino Uno for your controller, I presume this is the transmitter?

What control signals is your Nano flight controller receiving for throttle, roll, pitch and yaw channels?

How are you mapping these inputs into values that can be used as your PID control loops' "setpoints".

For example using an RC transmitter/receiver you'll get roughly a 1ms to 2ms pulse on each of the receiver's channels. The flight controller needs to determine the pulse width of each of these channels without the program blocking (waiting) for each pulse to occur.

Here's how I mapped the airelon (roll) pulse to ±180°/s with using the Arduino "map" macro:

Code: [Select]
rxRoll = map(airelonPulsewidth, 1076, 1872, -180, 180);
The 1076 and 1872 are receivers microsecond minimum and maximum values, as I mentioned the received pulse widths are only roughly 1000us to 2000us.

Once this is established it's possible to move on the the Gyroscope Output.


MartinL

My apologies for starting from the pilot input, but it's better than working on the motors only to find that the issue actually occurs somewhere further upstream.

vortix2950

My apologies for starting from the pilot input, but it's better than working on the motors only to find that the issue actually occurs somewhere further upstream.

its all good, i appreciate the help.

Hi vortix2950,

Starting with the Pilot Input:

You mention that your using an Arduino Uno for your controller, I presume this is the transmitter?

What control signals is your Nano flight controller receiving for throttle, roll, pitch and yaw channels?

How are you mapping these inputs into values that can be used as your PID control loops' "setpoints".

For example using an RC transmitter/receiver you'll get roughly a 1ms to 2ms pulse on each of the receiver's channels. The flight controller needs to determine the pulse width of each of these channels without the program blocking (waiting) for each pulse to occur.

Here's how I mapped the airelon (roll) pulse to ±180°/s with using the Arduino "map" macro:

Code: [Select]
rxRoll = map(airelonPulsewidth, 1076, 1872, -180, 180);
The 1076 and 1872 are receivers microsecond minimum and maximum values, as I mentioned the received pulse widths are only roughly 1000us to 2000us.

Once this is established it's possible to move on the the Gyroscope Output.


the controller only sends potentiometer reading from 0 to 180. once that is received, i multiply it by a thousand For the throttle.
The Yaw,pitch, and roll are set to 0.0 automatically for now. No controller involvement for that. The reason for that is because i wanted to wait for it to be able to take off the ground first before trying to  move it front an back and so on.I think that taking off vertically takes priority since i assume the rest off the controls wont work even if implemented correctly.

here is the Code lines:

Code: [Select]

  
 MotorPower=RecievedData; // this is the quad getting the Data from the controller.

  accelgyro.getRotation(&gx, &gy, &gz);
    gx=((gx/131)* 180/M_PI)*1000000;
    gy=((gy/131)* 180/M_PI)*1000000;
    gz=((gz/131)* 180/M_PI)*1000000;

if(gx<minInput){gx=minInput*1000000;}
if(gy<minInput){gy=minInput*1000000;}
if(gz<minInput){gz=minInput*1000000;}


if(gx>maxInput){gx=maxInput*1000000;}
if(gy>maxInput){gy=maxInput*1000000;}
if(gz>maxInput){gz=maxInput*1000000;}


   PidTime=micros();
    TimeError=(PidTime-LastPidTime);

    
    //
    Desired_Roll=0.0;
    Desired_Pitch=0.0;
    Desired_Yaw=0.0;

//Do same PID loop// Look Code in comment Above

//Here we use the data from controller which is pot reading 0-180 then multiply by 1000 and add adjustment to that.
    Motor_1_Speed=((MotorPower*MotorPower_Scaler)+MinMicroSeconds_Motor)+Input_Roll+Input_Pitch+Input_Yaw;
    Motor_3_Speed=((MotorPower*MotorPower_Scaler)+MinMicroSeconds_Motor)-Input_Roll+Input_Pitch-Input_Yaw;
    Motor_2_Speed=((MotorPower*MotorPower_Scaler)+MinMicroSeconds_Motor)-Input_Roll-Input_Pitch+Input_Yaw;
    Motor_4_Speed=((MotorPower*MotorPower_Scaler)+MinMicroSeconds_Motor) +Input_Roll-Input_Pitch-Input_Yaw;




    Motor_1_Speed=map(Motor_1_Speed,1000000,2000000,0,255);
    Motor_2_Speed=map(Motor_2_Speed,1000000,2000000,0,255);
    Motor_3_Speed=map(Motor_3_Speed,1000000,2000000,0,255);
    Motor_4_Speed=map(Motor_4_Speed,1000000,2000000,0,255);


    analogWrite(Motor1Analog_1,Motor_1_Speed);
    analogWrite(Motor1Analog_2,Motor_2_Speed);
    analogWrite(Motor1Analog_3,Motor_3_Speed);
    analogWrite(Motor1Analog_4,Motor_4_Speed);




MartinL

Hi vortix2950,

You're going to need to also get the roll, pitch and yaw channels working in addition to the throttle, as the aircraft won't just simply take off vertically with these channels set to zero. The aircraft will require corrective input from the pilot.

By the way, using micros() instead of millis() relates to the I and D gain terms of the PID loop and not the gyroscope, therefore it isn't necessary to multiply the gyro values by 1,000,000.

vortix2950

Alright Done.

 Now the Controller Sends Values from -90 to 90 which is multiplied by 2 when received by quad copter giving the -180 to 180 input(similar to the map that you did) for roll and pitch. I don't know how to send yaw through. what i dont understand is how to use the controller to change it. the 10$ helicopters that i have seen have a tiny pot that changes the yaw angle slightly when moved.Not sure if thats best idea though but its easily done if thats whats needed.

secondly, is there a preferable message rate from controller? the nano doesn't seem to handle sending lots of messages well so i use a timer to limit the  messages speed. using millis() hope that's not an issue. it seems to respond to change faster when i limit the messages.

Code:
Code: [Select]

float RCx=0.0;
float RCy=0.0;
float RCz=0.0;

 
//this section changes the int to the value that we really want. depending on which number it was, x/y could be negative or positive. first digit tell us the sign, the rest of the number tells us the X and Y position and we multiply by 2 cus it goes from -90 to 90 and we want from -180 angles to 180


    else 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;
       }


    accelgyro.getRotation(&gx, &gy, &gz);
    gx=((gx/131)* 180/M_PI);
    gy=((gy/131)* 180/M_PI);
    gz=((gz/131)* 180/M_PI);

   
  Desired_Roll=RCx;
   Desired_Pitch=RCy;
    Desired_Yaw=RCz;
   
 // Rest of PID Control.....






So what do i do now? i hope i didn't misunderstand you or anything, tryin my best.

MartinL

Hi vortix2950,

You seem to have two projects on the go here, both a transmitter/receiver system and a quadcopter flight controller.

Building your own quadcopter flight controller is a great project, but it's also quite a difficult challenge and takes time, we're talking months of development. It's a project in which the amount of code or sketch size is actually relatively small, but it's the concepts that take a while to understand.

As I mentioned, you need to break the system down into smaller more manageable tasks, while maintaining a clear idea of what information is passed between them.

Before you proceed, I feel that you need to answer the questions you pose regarding the pilot input. Sometimes it's worth stepping back and reassessing the situation. Might it not be easier to use an existing transmitter/receiver system?

Go Up