| View previous topic :: View next topic |
| Author |
Message |
mpthompson
Joined: 02 Jan 2006 Posts: 650 Location: San Carlos, CA
|
Posted: Fri Feb 02, 2007 7:08 pm Post subject: The PID Integrator - Experts Help Needed |
|
|
I wanted to start a thread specifically about the integrator in the PID algorithm. If you look at the PID implementation in the latest OpenServo code you'll see that I effectively removed the integrator from the PID calculation (as of 1/31/07). I did this because I couldn't get it working to my satisfaction and my previous integrator implementation actually detracted from operation of the OpenServo.
Based on my limited experience, I think that RC hobby servos probably only use the proportional and derivative component in their PID calculations. This is because a small servo that is designed to hold relatively light loads can get away without the integrator. Particularly with standard servo pulse control signaling which isn't particularly accurate. With the OpenServo we are setting a discrete 10 bit position value and the ability to query the current discrete position of the servo makes the lack of an integrator much more noticeable.
I'm sure that like me, most people using the OpenServo, when they command the servo to position 627 they want the servo at position 627 and not 619, 623 or even 625 just because the servo is fighting the heavy load such as lifting a weight. Normally, it is the integrator within the PID that will sense the load on the servo (by integrating positional error) to apply just the right amount of additional power to the motor to hold the command position. However, at a practical level I've found implementing the integrator hard to do. It's very easy to come up with an implementation that leads to oscillations in the servo which are worse than the problem the integrator is intended to fix.
In any case, I'm hoping an expert in implementing the PID algorithm will trip across this thread and tell me the magic code incantations needed to implement a nicely functioning integrator in the OpenServo. There is no monetary compensation, but I'm sure that the Creator will smile upon your generous contribution to the Open Source movement .
Until then I'll be chipping away at the problem and will certainly welcome entertain suggestions from other control newbies such as myself who may have ideas on the PID integrator.
-Mike |
|
| Back to top |
|
 |
electromech
Joined: 05 Dec 2006 Posts: 6 Location: Oh Canada!
|
Posted: Sun Feb 04, 2007 2:52 pm Post subject: |
|
|
Mike,
I took a look at your recent videos. Congratulations on getting things working more to your satisfaction.
I'm no expert in PID but I have had some success with it in the past. Before I make any comments let post a link to an interactive PID simulation. With this simulation you can see how each component P, I, and D contribute to the output. Take a look at
http://www.control.lth.se/education/interactive/PIDcontrol.html
When adding the derivative and integral terms into the PID controller we subject ourselves to two problems. From you comments and changes you realized that filtering would improve your derivative term. The derivative tries to combat any instantaneous change in the load. However, if there is noise in the system this appear as a load. This can cause the system to be unstable. The easiest way to take care of this is to filter the data which you have done. Be careful how much you filter the data though because filtering adds delay into the system and delay leads to instability as well. With that said lets just say that the derivate term acts to changes in a very short amount of time.
The integral term on the other hand tries to compensate for errors over a long period of time. It tries to bring the system to zero error. This is not easy to do with P and D terms alone. The integral term as you know is the sum of all errors that occured in the past multiplied by a constant. In an analog system you would have a capacitor in an op amp circuit to perform the integration. The nice thing about this is that the op amp will saturate to the supply voltage. There introduces a limit to the summing behaviour. In digital systems we don't have this effect unless we increment past the range of our integer in which case we are really screwed because we overflow and return to zero!
So when we try to implement an integrator we must not let our value grow to large. This is known as wind up. It will grow large if we don't reach the desired position in a long period of time. Again time is the enemy, because we are summing over all history. Threre are a number of tricks to throw at this problem. Each with it's own poison.
1. First of all we can control how much the integrator can contribute to the output. You could limit it to 25% or 50% of the output. This works in some situations. (By the way I've seen this done on the derivative term as well)
2. You could also reset it when you have a new position requested that is far away from the current position. In this circumstance we don't really care about the history of time. It's kind of like dragging bad memories around at this point.
3. The last thing you could do if turn off the integrator if the proportional term has saturated the output. This is similar to item number 2.
The idea in all of these is not to let the integrator grow without bound. Again back to the analog comparison you will find the term leaky integrator used. Which means that a method to discharge the capacitor is created.
I don't think you need help with the algorithm. You appear to excel in this. Try out these suggestions and see what you can come up with. If you get it working great. If not I will try to help out more.
If you do get stuck take a look at www.koders.com and do a keyword search for PID. You will find a project named EMC. They have implemented a couple of these items in their project.
Cheers,
Electro |
|
| Back to top |
|
 |
mpthompson
Joined: 02 Jan 2006 Posts: 650 Location: San Carlos, CA
|
Posted: Sun Feb 04, 2007 5:11 pm Post subject: |
|
|
Electro, thanks for the detailed feedback. I'll ponder your suggestions for a few days and then hopefully attack the problem again with a fresh perspective.
With regards to my use of a filter on the derivative term, I did have to be very careful with the amount of filtering. In my testing it felt like I was walking a fine line between just enough filtering to quiet the noise, but not so much as to introduce oscillations in the system. I purposely erred on the side of leaving more noise on the input.
In an unrelated project I'm working to implement a Kaman filter to fuse accelerometer data with gyroscopic data for accurate roll and pitch information from an IMU unit purchased from SparkFun. I need to create an integrator for the gyroscope information so perhaps I'll gain some insight from that project as well. I'm also now finally starting to understand to some degree Stefan's state estimator and state regulator for control of the servo.
-Mike |
|
| Back to top |
|
 |
Zeddicus
Joined: 21 May 2006 Posts: 109
|
Posted: Tue Feb 06, 2007 7:46 pm Post subject: |
|
|
Hi,
I agree with electromech's explanations. I'd like to add that, in my experience, the use of the derivative term leads to more problems than it's worth (due to noise), so I usually stick to a PI controller. The integral term is absolutely essential to remove the longterm error, and get the servo positioned to where you really want it to be.
On a side note, I now have a glorious 7 days of boss-not-here time to finish my openservo simulator
Anyone know how to write a digital noise generator to simulate the noise on the motor position? guess I could just use a random number generator, but that seems kind of lame...
Cheers,
ZZZ |
|
| Back to top |
|
 |
mpthompson
Joined: 02 Jan 2006 Posts: 650 Location: San Carlos, CA
|
Posted: Tue Feb 06, 2007 9:43 pm Post subject: |
|
|
I never wrote a noise generator, but if you do a Google Search for ""Gaussian Noise Generator"" you may find some algorithms that are simple and better than a random number generator.
-Mike |
|
| Back to top |
|
 |
mpthompson
Joined: 02 Jan 2006 Posts: 650 Location: San Carlos, CA
|
Posted: Wed Feb 07, 2007 1:58 am Post subject: |
|
|
Zed, I've been thinking about what you said above regarding the derivative term. My experience has been that the servo would be very hard to control without a derivative term.
With my understanding of PID, the proportional term and derivative are both important to control the motor as it sweeps from one position to another. For an analogous physical system think of a car suspension system. The proportional term works very similar to the suspension spring where the more the suspension strut is brought out of position the stronger the pull of the spring to return the strut back to it's neutral position. The derivative term works like the shock absorber in the suspension system. It functions as drag and opposes velocity in whatever direction the suspension is moving. Without a shock absorber in the suspension (the derivative term to oppose the inertia of the car) the car would feel very bouncy and tend oscillate with every bump in a road. Like a car, a servo has internal inertia and external inertia as well as drag within the gearing. If the servo gearing has enough friction it will function in place of the derivative term, but my in experience artificial drag is needed in the form of the derivative term for good servo control. This is particularly important when there is a lot mass on the servo and the internal friction is overwhelmed by the inertial mass.
Hopefully my example makes sense. On the OpenServo it is very easy to play around with the P and D gains and see how the system responds.
I have heard of PID systems where the derivative is omitted, but I haven't actually seen an example of this with respect to motor control. If anything, I would like to understand this further to better my overall understanding of the PID algorithm.
-Mike |
|
| Back to top |
|
 |
electromech
Joined: 05 Dec 2006 Posts: 6 Location: Oh Canada!
|
Posted: Wed Feb 07, 2007 2:27 am Post subject: |
|
|
Mike,
I agree with you 100% about the derivative term. It is almost imposible to slow down the servo without it. What I've found is that I need to have two values for the D Term though. I have a larger value when far away from the target and a small value when I am close. This helps to eliminate the jitter. This is how I do it
| Code: |
// Calculate Dterm
// Two different calculations are performed depending on the current error
// We use a larger Dterm when farther away from the target to give us some extra brakes
// A smaller value is used when we are close to the target to avoid oscillations or hunting
if (abs(error) < 30)
{
// In close range
d_term = pid_st->D_Factor * pid_st->dErr ;
}
else
{
// Far away
d_term = (pid_st->D_Factor * pid_st->dErr) * 3 ;
}
|
You might want to try this as well if you still have some jitter.
Cheers,
Electro |
|
| Back to top |
|
 |
mpthompson
Joined: 02 Jan 2006 Posts: 650 Location: San Carlos, CA
|
Posted: Wed Feb 07, 2007 5:12 am Post subject: |
|
|
Hmmm. Certainly an approach worth trying. It rubs me a bit the wrong way to choose an arbitrary point where the derivative function changes, but it certainly is practical. I wonder if there is a mathematical function that is easy to evaluate on the 8 bit AVR that would transition between two functions more smoothly?
-Mike |
|
| Back to top |
|
 |
mpthompson
Joined: 02 Jan 2006 Posts: 650 Location: San Carlos, CA
|
|
| Back to top |
|
 |
Zeddicus
Joined: 21 May 2006 Posts: 109
|
Posted: Wed Feb 07, 2007 11:03 pm Post subject: |
|
|
My experience is with a pressurized tank, where you have to control the liquid level, and the pressure of the air mass above it. Both processes are linked, so that a change in one influences the other. This is a VERY hard system to control, because on top of everything, the system is nonlinear with respect to the pressure.
I used 4 PID controllers, one for each water level and air pressure, and one for the cross influences. This is where I came to the conclusion that the the derivative term causes a lot of problems. While it is true that the derivative term slows the movement down, in presence of noise it makes it oscillate wildly and can cause the controller to become unstable. You have to remember that the integrative term will force a zero error in steady state, and will also function as a low pass filter for the noise. The derivative term, however, will differentiate the noise, causing even more noise on the output.
But then again, I haven't really experimented with the openservo yet, so maybe the process is too different from what I've had to control in the past. My vacation is over, and I'm clearing out my infinite todo list, so I shouldn't be spread so thin anyore in the upcoming weeks
Cheers,
ZZZ |
|
| Back to top |
|
 |
mpthompson
Joined: 02 Jan 2006 Posts: 650 Location: San Carlos, CA
|
Posted: Thu Feb 08, 2007 1:38 am Post subject: |
|
|
Hey Zed, when you do get a chance to play with the OpenServo I'll be interested in your observations. I'll be away for two weeks, but when I get back I hope to take a stab at finally getting the integral working as it should.
-Mike |
|
| Back to top |
|
 |
|