4
$\begingroup$

I'm trying to get a quad rotor to fly. The on board controller is an Ardupilot Mega 2.6, being programmed by Arduino 1.0.5.

I'm trying to fly it in simple autonomous mode, no Radio controller involved. I've done a thorough static weight balancing of the assembly (somewhat like this: http://www.youtube.com/watch?v=3nEvTeB2nX4) and the propellers are balanced correctly.

I'm trying to get the quadcopter to lift using this code:

#include <Servo.h>


int maxspeed = 155;
int minspeed = 0;

Servo motor1;
Servo motor2;
Servo motor3;
Servo motor4;

int val = 0;
int throttleCurveInitialGradient = 1;

void setup()
{


val = minspeed;

motor1.attach(7);
motor2.attach(8);
motor3.attach(11);
motor4.attach(12);


}


void loop()
{
setAllMotors(val);
delay(200);
val>maxspeed?true:val+=throttleCurveInitialGradient;
}

void setAllMotors(int val)
  {
    motor1.write(val);
    motor2.write(val);
    motor3.write(val);
    motor4.write(val);
  }

But the issue is, as soon as the quadcopter takes off, it tilts heavily in one direction and topples over.

It looks like one of the motor/propeller is not generating enough thrust for that arm to take-off. I've even tried offsetting the weight balance against the direction that fails to lift, but it doesn't work (and I snapped a few propellers in the process);

  • Is there something wrong with the way the ESCs are being fired using the Servo library?
  • If everything else fails, am I to assume there is something wrong with the motors?
  • Do I need to implement a PID controller for self-balancing the roll and pitch just to get this quadrotor to take off?

Edit 1: Thanks for all the replies.

I got the PID in place. Actually, it is still a PD controller with the integral gain set to zero.

Here's how I'm writing the angles to the servo:

motor1.write((int)(val + (kP * pError1) +(kI * iError1) +(kD * dError1)));  //front left
motor2.write((int)(val + (kP * pError2) +(kI * iError2) +(kD * dError2)));  //rear right
motor3.write((int)(val + (kP * pError3) +(kI * iError3) +(kD * dError3)));  //front right
motor4.write((int)(val + (kP * pError4) +(kI * iError4) +(kD * dError4)));  //rear left 

kI is zero, so I'll ignore that.

With the value of kP set somewhere between 0.00051 to 0.00070, I'm getting an oscillation of steady amplitude around a supposed mean value. But the problem is, the amplitude of oscillation is way too high. It is somewhere around +/- 160 degrees, which looks crazy even on a tightly constrained test rig.


[ Edit 2: How I calculate the term 'pError' - Simple linear thresholding.

I've a precomputed data of the average readings (mean and SD) coming out of the gyro when the IMU is steady. Based on the gyro reading, I classify any motion of the setup as left, right, forward or backward.

For each of these motion, I increase the pError term for two of the motors, i.e, for right tilt, I add pError terms to motors 2 & 3, for left tilt, I add pError term to motors 1 & 4 etc. (check the comment lines in the code snippet given above).

The magnitude of error I assign to the pError term is = abs(current gyro reading) - abs(mean steady-state gyro reading). This value is always positive, therefore the side that is dipping downwards will always have a positive increment in RPM. ]


As I crank up the derivative gain to around 0.0010 to 0.0015, the oscillation dampens rapidly and the drone comes to a relatively stable attitude hold, but not on the horizontal plane. The oscillation dies down (considerably, but not completely) only to give me a stable quadrotor tilted at 90 - 100 degrees with horizontal.

I'm using only the gyros for calculating the error. The gyros were self calibrated, hence I do expect a fair amount of noise and inaccuracy associated with the error values.

  • Do you think that is the primary reason for the high amplitude oscillation?

One other probable reason might be the low update frequency of the errors. I'm updating the errors 6 times a second.

  • Could that be a probable reason it is taking longer to stabilise the error?

And, for the steady state error after the wild oscillations dampen, is it necessary to fine tune the integral gain to get rid of that?

Please help.


Edit 3: I cranked up the frequency of operation to 150+ Hz and what I get now is a very controlled oscillation (within +/- 10 degrees).

I'm yet to tune the derivative gain, following which I plan to recompute the errors for the integral gain using a combination of gyro and accelerometer data.


Edit 4: I've tuned the P and D gain, resulting in +/- 5 degrees oscillation(approx). I can't get it to any lower than this, no matter how much I try.

There are two challenges about which I'm deeply concerned:

After 5 to 8 seconds of flight, the quadcopter is leaning into one side, albeit slowly.

A) Can this drift be controlled by tuning the integral gain?

B) Can the drift be controlled by using accelerometer + gyro fused data?

C) Given that my drone still shows +/- 5 degrees oscillation, can I consider this the optimal set point for the proportional and derivative gains? Or do I need to search more? (In which case, I'm really at my wits end here!)

$\endgroup$
6
  • $\begingroup$ Possibly related: robotics.stackexchange.com/a/1216/350 $\endgroup$
    – Ian
    Commented Dec 25, 2013 at 18:53
  • 1
    $\begingroup$ You will have to provide more information on how exactly are you calculating term pError. In most of the cases although PID is good enough, oscillation are due to poor physical setup. So make sure that your physical setup is perfect in terms of propeller are perfectly balanced and gyros are isolated using vibration dampening material such as foam pads. $\endgroup$
    – nikhil
    Commented Dec 26, 2013 at 21:36
  • $\begingroup$ @nikhil: Please check 'edit 2' for a summary of how I'm computing pError. Physical setup is definitely not 'perfect', I'm sure. However, we've tried to do our best - yes, the propellors are balanced (one of the prop shows a slight dent in the root, but the weight balance is fine), static weight balancing of the entire setup is decent and there is a styrofoam pad glued under the IMU. $\endgroup$
    – metsburg
    Commented Dec 27, 2013 at 5:06
  • $\begingroup$ Are you using any filer for gyro data? Gyro usually show drift over time which you have to correct by applying filer. You should use Accelerometer along with gyro to achieve horizontal stability as gyro alone will never be able to perform up to your expectation. 6Hz is very low update rate. I would recommend at least 100Hz of update rate. More update rate will result in better performance. $\endgroup$
    – nikhil
    Commented Dec 27, 2013 at 13:01
  • 1
    $\begingroup$ A perfectly tuned kalaman will give you best result. You can also use simpler complimentary filter as explained in stackoverflow.com/questions/15490990/… Here are few more references starlino.com/imu_kalman_arduino.html x-io.co.uk/res/doc/madgwick_internal_report.pdf ieeexplore.ieee.org/stamp/… $\endgroup$
    – nikhil
    Commented Dec 28, 2013 at 10:20

5 Answers 5

7
$\begingroup$

Even very small errors can bother the balancing. Small errors such as:

  1. Weight of the quadcopter is unbalanced.
  2. One motor is rotating faster/slower than others due to manufacturing or your power-source.
  3. Air resistance and wind.
  4. Unbalanced propellers due to manufacturing.
  5. Strong magnetic forces.

You simple can not send the same motor speed to all motors and expect it to hover. You do need a sensor which can read the tilting of the robot and adjust the motor speeds based on the tilt angles. To do that you need to implement a PID controller (The simplest method).

As far as I know there are some PID controller for arudino. But you could always write your own simple version of a PID controller.

$\endgroup$
4
  • $\begingroup$ Yeh, there are plenty of PID controllers for arduino. I was hoping to develop one myself. $\endgroup$
    – metsburg
    Commented Dec 20, 2013 at 5:37
  • $\begingroup$ "Weight of the quadcopter is unbalanced" is not a factor here, because the Integral component of the PID controller will compensate for the imbalance. $\endgroup$
    – Ian
    Commented Jan 15, 2014 at 14:45
  • $\begingroup$ Thats correct Ian. Therefore I wrote that he needs the PID. $\endgroup$
    – nFu9DT
    Commented Jan 15, 2014 at 19:43
  • $\begingroup$ Oh OK. I thought you were talking about the PID he was already using, but you weren't. (It looks like this question has been heavily updated.) $\endgroup$
    – Ian
    Commented Jan 16, 2014 at 14:34
4
$\begingroup$

Quadcopter is inherently unstable system. So you have to apply some feedback controller (eg. PID) to keep it airborne. Even if you apply some basic PID using angular rates and angles, you still have to provide manual correction for drift till PID gains are perfectly set. So using radio control for manual control is really helpful during initial development stage.

$\endgroup$
4
$\begingroup$

I read the code but it looks like it is for the first attempt where you tried to hover "open loop" that can't work. So now you tried a PID control based straight off the raw IMU data. Tha't better but you are going to need one more step between the two. Will I say this assuming you are using a low-cost IMU, the kind that just breaks out the chip.

First off it would be ideal if you could measure the speed of each motor, and not just assume it rotates at a speed proportionate to the commanded value. Likely it does not. The BEST way to to place an encoder on the motor shaft that sends a few pluses per revolution. Then you replace "motor2.write(val)" with something like "motor.setspeed(rotationVelocity); and the set speed method runs a PID loop just ontheat one motor's speed, sending whatever PWM value is required. OK, lacking an encoder, get a hand held propeller tachometer. And plot RPM vs PWM for a tried vehicle fixed to a stand at some hight from the ground.

NEXT YOU NEED TO KNOW HOW TO RELATE RPM TO THRUST. One problem with yourPID control is it assume PWM value (voltage) is LINEARLY related to force in the vertical direction is is NOT because 1) If the vehicle is tilted the foxed is no longer down and is smaller be the cosine of the tilt and.. 2) force is NEVER linearly replaced to voltage. It think(???) there is a cubed relationship the is power cubed = force.

You might just kip all the math and measure the force as a function of PWM and make a lookup table. Better to use encoders and

You over all PID loop will work much better when have a linear relationship.

Next idea: You CAN make a quad more stable. What if you tilt the plane of each door inwards just a little. Each is slightly non-horizonal, now if one side dips it will generate more lift.

Last idea: The IMU is a noisy device. The accelerometer has high frequency noise on it becise of random vibrations and the gyro has drift. The "standard" why to address this is with a Kalman Filter. The math is not easy but you can find MANY examples of Kalman filters on-line.

Summary: 1) Use good filter model to correct the IMU data. The raw data is not good. 2) Create a method (function) that takes llefting force as input then sets the PWM slue as required.
3) Used a top layer PID to drive the error to zero

What this does is address the basic flaw of all PID controller, they don't "see" inside the black box. They don't know the gyro drift and accelerometer is noisy and that PWM has a non-linear relationship to lift.

Next you get into moving flight and you need to make your aerodynamic model better to account for the fixed pitch props

$\endgroup$
5
  • $\begingroup$ Thanks for the well thought answer. I've, infact, already implemented some of the things you suggest here. Check this question: robotics.stackexchange.com/questions/2297/… which I posted a few days ago. This question specifically shows where I stand now. I seriously need to incorporate the non-linear property of the thrust vector. That is why I found the proportional gains to be different under different steady RPMs. The proportional gain also varies with battery voltage. Please check my new question and respond, if you wish. Thanks. $\endgroup$
    – metsburg
    Commented Jan 15, 2014 at 10:28
  • $\begingroup$ Why would you need to know the motor speed. That's irrelevant. If you were in open-loop, then yes, you'd need to know precisely the relationship between thrust and PWM input. But the whole point of PID control is that you don't need to know this! $\endgroup$
    – dm76
    Commented Jan 15, 2014 at 16:37
  • $\begingroup$ Ok, I understand what you're saying, makes sense. But I was just wondering, suppose if my PWM input vs output thrust response is an exponential curve (say)... is it not likely that the value of P/I/D for the linear part of the curve (slope of 1) will be different from the value for the more horizontal part (slope ~ 0) of the curve? Is it not better to confine my operation to a range where the input vs output characteristics are more or less similar? $\endgroup$
    – metsburg
    Commented Jan 16, 2014 at 4:54
  • $\begingroup$ You're right, for non-linear systems, different PID gains will be need for different part of the curve. You said you needed different P gain for different RPMs... what is the variation there? You'll have to choose the smallest P gain within your operating range of RPMs, trading off for somewhat slower settling-time. $\endgroup$
    – dm76
    Commented Jan 16, 2014 at 12:19
  • $\begingroup$ Nonetheless, it would be interesting to measure this non-linearity. One way, perhaps, instead of using encoders, would be to measure the audio spectrum of the motors (Any smart phone can do that), see the frequencies that comes up when the motors are on. Then you'd to relate frequencies with RPMs. See blog post: blog.pistuffing.co.uk/?p=2342 $\endgroup$
    – dm76
    Commented Jan 16, 2014 at 12:26
2
$\begingroup$

I can see several mistakes in your approach.

The biggest red flag for me is that you are treating the motors as individually-controlled PIDs when in fact they need to work in pairs. I'm talking about this line that you posted:

motor1.write((int)(val + (kP * pError1) +(kI * iError1) +(kD * dError1)));  //front left

The output of your PID should be the desired roll or pitch force -- the correction to the current pitch or roll vs what is desired. The desired roll or pitch force will then be translated into the thrust ratio between the 2 motors that can effect that force.

The second problem I see is that you are using a PD controller instead of a PID controller and wondering why it appears to be imbalanced. The integral term is precisely what you are missing -- it compensates for any (static) imbalance in the quadcopter itself.

The third (potential) problem that I see is that you might not be properly mapping the motor speed to the desired thrust -- that relationship may not be linear.

$\endgroup$
1
1
$\begingroup$

Is it always the same side that topples? If so, one obvious thing to try to eliminate the possibility that one of your motors is faulty, is to simply switch motor positions and see if the side that topples changes.

$\endgroup$
1
  • $\begingroup$ No, it doesn't topple on the same side (with the PD controller). Even without switching motors, it topples whimsically. $\endgroup$
    – metsburg
    Commented Dec 26, 2013 at 8:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.