![]() |
PID control loops - feedback is our friend!!!
I've been talking (ranting:c) about this topic on and off on CD for a while, and a couple people have asked questions about it.
I went into some detail in a thread about castors, but thought this subject desirves its own thread. Feedback is one of the most power tools you learn about in engineering - I stuck this thread here because it involves SW and HW and your controller and sensors, and it can get pretty technical. I started talking about it in this thread: http://www.chiefdelphi.com/forums/sh...751#post212751 but for the sake of the rest of the forum, I like to continue the discussion here - it applies to more than just using castors on your robot - it can be used if you turn your wheels to steer, to postion a robot arm, to control your robots speed, how fast it turns - you could even set up a control algorythm to drive your bot with a steering wheel, so that, when you turn the wheel ten degrees, your bot turns ten degrees... if you take engineering in college you will learn about feedback and PID control systems - but I think we can use enough of a subset for what we do in FIRST to really make a difference in how well your bot responds to your drivers commands. (PS. I searched before I posted this, the only threads I could find on PID loops were from previous years, and they are closed now) |
Re: PID control loops - closed loop feedback
For another site that may prove interesting, you can try here [barello.net]. It includes an implementation of PID control in C, along with a description about it, for those interested.
|
Re: PID control loops - feedback is our friend!!!
|
Re: PID control loops - feedback is our friend!!!
PID control loops.... ahh. They seem to make sense sometimes but other times they don't... Here is the control loop that I have written up. Please take a look at it and critique it. The constants have not been tuned at all. I finally got to plug it into our second arm (with working pots!!) and somehow it was outputting numbers in the 400's....
Any help??? The two scaled values are pot values, one from our arm and one from the model. They are both scaled from 0 to 255 and are declared as unsigned longs... (don't ask, it has to do with how we scale them...) sint = signed int THIS IS WHERE IT IS CALLED: //call the control loop to set the pwm values Arm_Upper_Out = PID(scaled_highjoint_req, scaled_highjoint_act, lasthighjoint_act, sint_highjoint_errorsum); //keep track of the error for the control loop sint_highjoint_errorsum = sint_highjoint_errorsum + (scaled_highjoint_req - scaled_highjoint_act); //keep track of the last position to be able to tell how fast it is moving for the control loop lasthighjoint_act = scaled_highjoint_act; THIS IS THE CONTROL LOOP: unsigned char PID(signed int request, signed int actual, signed int lastactual, signed int sumerror) { #define PID_PROP 2 #define PID_DER 1 #define PID_INT 1 signed int pid, error; request = request - 127; actual = actual - 127; lastactual = lastactual - 127; pid = request; error = request - actual; //find the difference of the two values pid = pid + (error/PID_PROP); //add the proportional part of the error pid = pid + ((actual - lastactual)/PID_DER); // add the derivative part of the error pid = pid + (sumerror/PID_INT); //integral part of the pid pid = pid + 127; return(pid); } |
Re: PID control loops - feedback is our friend!!!
This might be the problem (it had been screwing up a lot of my code 'till I realized it).
Try casting all your constants to (signed int). Also, try casting your return value to (unsigned char) both in the return statement and in calling code. |
Re: PID control loops - feedback is our friend!!!
So like:
#define (signed int) PID_PROP 2 ? |
Re: PID control loops - feedback is our friend!!!
Quote:
|
Re: PID control loops - feedback is our friend!!!
Quote:
|
Re: PID control loops - feedback is our friend!!!
Yeah. I read up on that and I think I'm safe there.
I'm able to print out the scaled and pre-scaled actual pot values from the arm and they output correctly/as expected, so I don't think I have a problem there. |
Re: PID control loops - closed loop feedback
Have you made sure that you're calling the PID function at a consistent time interval? If there's code that occurs before that in the main loop that might vary in execution time, you might want to consider using an interrupt-driven timing scheme to make sure you're calling the function at precisely the right time interval. Are the excessive output values appearing as soon as the control loop starts, or are they occurring gradually? If they're occurring after you move the arm, particularly if you move it rapidly, try reducing Ki to make sure you're not saturating the integral term of the PID equation.
|
Re: PID control loops - closed loop feedback
What kind of time interval would you recommend? Every 25 ms or so?
|
Re: PID control loops - feedback is our friend!!!
Quote:
Also, you might want to add overflow checking, just in case. |
Re: PID control loops - feedback is our friend!!!
Quote:
|
Re: PID control loops - feedback is our friend!!!
So I should initially set pid to zero?
After testing the code this evening I found that the arm model that we are using was behaving more like a joystick than a model. I'd move it forward and the arm would move forward - but never stop at a certain place, move it back to neutral and it would stop, move it backward from neutral and the arm would go the opposite direction - once again not stopping at the desired position. Any pointers? |
Re: PID control loops - closed loop feedback
I believe the integral control portion should offset the initial setting of pid, but I would set it to 0, as this will most likely reduce settling time, overshoot, etc.
As for the digital response, my team saw something similar until we realized we were reading the wrong potentiometer value on the robot. We were reading a centered potentiometer, so when the input was neutral, the motor would not move. When the input was forward, the arm went forward, but the feedback wasn't in place to slow the arm down as it approached it's desired position because we were monitoring the wrong joint. I would recommend adding some debugging code to display both your arm pot value and your joystick value - this will also help you check to make sure the scaling is the same. It may also be a function of the gain settings. One suggestion is to comment out the integral and derivative control inputs, leaving only the proportional control effort and attempt to tune it so that it's satisfactory. This is the simplest loop, and often is enough to get the job done well. If you find you have error that can not be overcome (due to gravity, etc.), then you may have to add in integral control back in, or go back to a full PID. Either way, I try to start as simple as possible and add in complexity only as needed. Hope this helps. |
Re: PID control loops - feedback is our friend!!!
All the code for PID feedback loops i have seen posted on CD has used only the current and last measured values for the derivative and integral part. Has anyone tried using 3 or more frames? Is the result better?
|
Re: PID control loops - closed loop feedback
going back more than 2 loops is only useful for the intergral part - if the arm is not moving you keep adding a small part of the error - so the control signal can actually build up over several loops before the motor move enough to eliminate the error
but for the differential part you only want this reading and the last one - the D is like giving the system a swift kick for a loop or two, so it needs to be very responsive to the most recent action of the system. There is another type of PID control that does keep track of several previous commands and positions- its an adaptive algorythm - one that responsed differently if the mass of the system changes (like if you pick up a ball with your arm) or it the friction of the system changes (like if you move from carpet to smooth surface) and it adjusts the gains of the feedback accordingly. But I think thats really too fancy for what we need. so far on our drivetrain and our arm motion, we are only using proportional feedback this year - its works well so we dont want to get lost in complexity. |
Re: PID control loops - closed loop feedback
For the typical low performance robot (I think FIRST robots count here), PD is needed for position control (proportional/derivative) and PI is needed for velocity control.
Usually with positioning servos, the control is sloppy and there is a lot of friction, so you can get away with just P term. Adding the D term allows stiffer snappier control, but, again, with the typical chain driven arm snappy isn't the image that comes to mind. W/velocity control, often folks get away with just the I term. Something like: output += SomeFudgeFactor * VelocityError; So if you are slow, the output is built up until you are at the right speed, etc. Team #492 had a arm for manipulating the 2x ball which was pretty sloppy and oscillated terribly when overhead (chain slop). So we simply checked for range and divided the output by 16 (or some other large number) when overhead. Worked great. That is an example of "gain scheduling" where you change the gain based upon position (or some other external factor). |
Re: PID control loops - closed loop feedback
Quote:
|
Re: PID control loops - closed loop feedback
Quote:
Quote:
|
Re: PID control loops - closed loop feedback
We use 2 PI loops to maintain target velocities on our 2 arm joints. The integral is essential for our loop because it is what keeps the arms from falling due to gravity. For the proportional to work, it needs to have a speed error. So in order for the proportional to prevent the arm from dropping, the arm needs to drop a little first. The integral is non-zero when the arm is stationary, which is what keeps the motor at stall torque.
Here's the code for the PI loop for our elbow. Code:
//Joystick dead zoneBy the way, our P and I constants are both 1 / 8 on our competition robot, and our elbow loop runs at 10 Hz. Oh we also have a target position mode which feeds a target velocity into our PI loop. That's the RepositionElbow() function that you see in there. |
Re: PID control loops - closed loop feedback
thats pretty cool - I dont see any obvious mistakes in it.
have you been able to test it on your bot? the one thing Im curious about, why did you close the loop on arm velocity instead of arm position? for our arm control we integrate the joystick input and it creates a desired arm position - then we use a straight proportional desired-actual postion with a gain constant to create the motor drive the arm sags a little bit if its holding a ball, but thats a function of the gain- the more gain you use, the less it will sag (before the error signal is enough to hold it) closing the loop on position makes it easier to deal with the up and down limits - you just dont let the desired position exceed the limits. |
Re: PID control loops - closed loop feedback
Yeah the elbow loop works really well. It took us a lot of testing to get the right constants but 1/8 and 1/8 works best for us.
The wrist loop was a little more difficult to get working because of chain slack. Our wrist chain runs from the base of the robot up 5 ft to the joint so we can maintain a low CG by keeping all the motors in the base. What happened was when we moved the arm down it would overshoot a lot and be really bouncy, even though it worked perfectly on the way up. To fix that we reduced the constants on the way down. We did target velocity because that's basically what was coming out of the joysticks -- a target velocity. With target position, if something is holding back your arm, and your joystick is full forward, your target position is changing, but the actual position never changes. Then if you bring the joystick back to neutral and allow the arm to move again, it will shoot forward to its target position, even though that isn't necessarily what you wanted. Our arms sag a little bit when a ball is placed in them, but not much and the integral adjusts accordingly pretty quickly. In fact, we tested once with the robot at 90 deg (we were hanging from the bar) and the arm fully extended to 10 feet, and we placed a ball in it and it sagged about 3 inches with a huge lever arm before the integral picked up the change. |
Re: PID control loops - closed loop feedback
The PI loop on the wrist was immensely successful for us (I ran the arms at the Sacramento regional this weekend). The only problem it has, other than the bounciness on the way down Jay described (in actuallity that is a small problem, we only *fold* the arm once or twice in a match, to stow a ball or to stow when hanging), is that it can be slow to react when holding a ball. The integral has to get pretty high to move the arm up from extended to vertical (say, when we pick up a ball from a goal), and until I learned to correct, it would overshoot vertical (if thats when I moved the joystick to neutral) and fly down the other side. After about four rounds on Friday, though, I got that worked out and it worked really well for the rest of the tournament.
We had tried to build a PID loop earlier in the year, and didn't really end up with a workable solution. The important thing, it seems, was the engineer who came down and helped us map out the logic of the process. Once we knew what we wanted to do, it was actually only took about a half hour to write the function (and update as needed later). By the way, you can see the pictures of the arm straight out on our website, in my signature =). edit: The Reposition functions for the arms came from our old code for the arm, before we implemented the PI loop. It takes the distance from the desired position to generate a velocity. Pretty much, we only use it for the preset buttons on our control box and autonomous mode. |
Re: PID control loops - closed loop feedback
wow that arm looks huge - now that you mention it, we did the same thing with our arm - used a much smaller gain going down than up - didnt want the arm to slam into the roller on the front of our bot.
if your arm goes over the top and down the other side, that does make it tricky. In general the way to get a feedback loop working is to start with low gains and increase them until you start getting overshoot - then back off a little. (or goto engineering school for 4 years and learn all the math :c) |
Re: PID control loops - closed loop feedback
Quote:
|
Re: PID control loops - closed loop feedback
Quote:
e.g. Foo += Something is equivalent to Foo = Foo + Something; Therefore Foo is accumulating the integral of Something. You are correct that the integral is needed to drive the error term to zero, but for position stuff that is rarely needed (particularly in low performance systems like what we are working on). WHat is really needed is to drive the servo *close* enough to the correct position that you don't care about the residual error. Integral terms are hard to get right and lead to a lot of instability and are really useless in a dynamic environment as they are fighting your ability to change the setpoint. They only make sense if your servo is relatively static or has a constant force in one direction that needs to be compensated for with the integral term. But if the error amount is dynamic and changing sign, the integral term just gets in the way. |
Re: PID control loops - closed loop feedback
Quote:
|
Re: PID control loops - closed loop feedback
Quote:
You state you are controlling velocity, yet what you are really controlling is position, but by a round-about way. Velocity is the first derivative of position. Your code takes the velocity error + the integral of the velocity error. Well, that can also read as: The first derivative of position error + Position error. Hence, in fact, you have a classic PD controller for position. As your controller integrates the velocity error, you get, essentially, an error term that grows as the position error grows. That is the "proportional" error term. Cheers! |
Re: PID control loops - closed loop feedback
Quote:
.... on second though, that isnt really a problem as the integral term isn't needed when the error is large. And i was presumptious enough to think that years of science and engineering could be faulty.... :) So what this means is that if one limits the integral each iteration, one can integrate for the entire time the robot functions? I understand this would work now, but it still seems a little odd, id rather just integrate for a shorter period of time. Is this common practice? |
Re: PID control loops - closed loop feedback
Before we limited the integral, we found that it could wind itself up into the thousands if we weren't *very* careful. That could happen if the OI was off, the robot was on, and the arm moved, or if a velocity went in and the arm was held down. An integral that high means that when the arm is allowed to move, it will smash all the way over and ram into itself, or do other nasty things to itself.
We found that the integral never actually gets higher than 30-50, and thats very rare too. Usually it is under 20. We run the elbow loop at 10hz, and the wrist loop at 5hz. That leaves enough time to create a speed error we can actually work with...too much faster and we get mostly 0 speed with intermittant high speed as it actually moves. Very bad. edit: To the above poster: You're right. The proportional is supposed to be the major factor when the speed error is large, and the integral builds up to balance it out and hold steady as the speed error decreases (ie the integral maintains the speed the proportional generates). It just so happened that the arm worked best for us when the proportional and integral were both 1/8. It took a lot of testing and frustration to find the right values. |
Re: PID control loops - closed loop feedback
Quote:
The best way to think of the integral term is that it, eventually, will compensate for all those unknown things that prevent you from getting to your goal (position or velocity). The problem is that if your position setpoint is moving all the time (plus & minus, typical for an arm) the integral needed going forward is precisely the wrong thing for moving in reverse! Best to just leave out. |
Re: PID control loops - closed loop feedback
Quote:
Without an integral in our program there would be no way for us to control our arm, much less control it with a ball. The integral needs to build up to maintain zero velocity when the lever arm and torque is great, or the arm will simply fall. There really is no way to manage it dynamically otherwise. We suggest you use the PID loop to control velocity, because that's what's coming out of your joystick. Position may be very tricky, and as Jay and I said, the position system just generates its own velocity value. Don't knock PI loops until you've tried them! We would never have done so well without it. |
Re: PID control loops - closed loop feedback
Quote:
The PI algorithm that we use for everything uses a data element we invented called a CSStack for the I term. Its basically a dynamic variable lenght mutable circular buffer. It seems to me that response could be improved by dropping certian old values from the buffer in times of rapid w change. What about dynamically changing Ki according to the derivitave of w? Any input? What other sorts of optimizations have people made to the basic PID algorithm? Is anybody using somethign other than some variation of a PID controller? |
Re: PID control loops - closed loop feedback
Quote:
|
Re: PID control loops - closed loop feedback
If you start dropping values off of your integral, you are going to have a hard time keeping a steady state (ie velocity = 0) for any amount of time. You won't have a speed error, and so your integral won't change, but you still want it to hold still.
Rick is probably right in that you can increase your performance by dropping values off during times of high theta change (high omega), but the complexity of performing that may become difficult in C--I would think an object oriented language would assist much more in this (dynamically sized queues are also really difficult to program on our tiny little memory block on the robot...). Conceivably you could make another PID loop feed into your main one to change the constant's values, but just the straight loop works quite well with a little driver knowledge. I think that inputting another loop or trying to dynamically drop values will either make it far too jumpy or unstable. One last (though possibly minor) problem is drawing too hard on the battery and overheating the motors. We considered zeroing the integral if the direction of the motion was opposite the target direction but concluded it would draw too hard and be harder to control in the long run. |
Re: PID control loops - closed loop feedback
Quote:
Btw, you say you have been doing research on variable coeff algorithms, do you have any links? Any books i might read? I have wanted to learn more about feedback control loops, particulary adaptive ones, but havn't really known where to look. A freind of mine gave me a book on feedback control, but its more about analyzing the effectiveness of control loops rather than designing them. |
Re: PID control loops - closed loop feedback
any college library would have a shelf full of books on control systems - only problem is they require you to understand the math they use - most of it is worked out in the frequency domain - convolution - imaginary numbers
lots of fun at first, but once you get your head into that way of thinking it becomes intuitive. another good source is to seach the web for companies that sell control system hardware - stepper motors and servo motors - linear amps and feedback sensors - lots of them put out application books and white papers on how to use their stuff- and its all based on PID control loops. |
Re: PID control loops - closed loop feedback
Because this thread is so long, I haven't had a chance to read it all, but I see some common themes coming up... some people fighting for using PID... some people fighting to understand the math behind it... some people just looking for examples. I do a great deal of linear and non-linear control applications when I'm not doing FIRST, so I was thrilled this year to have some time to help the team build in some simple feedback controls systems to control not only our drive train but a two-jointed articulated arm.
And so I want to comment on a few things... But first, as a reference, if you would like some examples of PID (actually PIID, notice the second I) feedback loops as well as some other important modifications, take a look at our code for this year's Pittsburgh regional: http://www.osufirst.org/twiki/bin/vi...04RegionalCode To give some background, the robot is driven by one joystick out of the box, a number of buttons and switches, and a mock-up of our actual two-jointed arm. This mock-up has potentiometers built into each joint just like our big arm. Our big arm tracks the position of the small arm. Additionally, our drive train wheels have Banner sensors encoding every 36 degrees of their rotations into "ticks" that can be handled by interrupt handlers tied to digital inputs 1 and 2. If we had our ticks spaced correctly, we could run the Banner "normally closed" input into two more digital inputs to get double the resolution. There are some other software tricks to increase resolution, but they need speed first... and we need speed first anyway... Use Speed Control for Actual Motor Control Whenever Possible So my first comment is on speed control. Because motors inherently output speed and not position, even though you have position sensors (effectively), it's much easier to control speed. However, it's not trivial to calculate speed on such a robot with all of these quantization issues. For example, it's tempting to calculate speed by counting the number of ticks that pass by your encoder in a particular time. If you have lots and lots of ticks and are not sampling that fast, this works fine. However, if you're sampling fast with respect to the tick changes and you don't have that much resolution so the ticks take a long time to get noticed, you need a new way to calculate speed. How to Calculate Speed in Software Quickly On our robot, we have a clock running that keeps track of the number of 100ths of a second (centiseconds) that have passed. This is an "elapsedTime" variable. This is setup using interrupts, as is explained on IFI as well as many places here. Now, the interesting part is that our interrupt handler that catches the tick transitions of each wheel doesn't just increment a counter; it also calculates the time difference between the current tick and the last tick and also stores the current time. This time difference allows for the current speed to be easily calculated (in our code, in inches per second), except the problem is that if the robot stops turning, it will never register that we've slowed down to 0. So in our fast code, we calculate the difference between the current time and the previous tick time, and if that grows too large for our slowest speed (slowest speed is found by ramping up input until the robot moves and recording that speed), then we assume we've stopped. Calculate Acceleration Too: This is Important Later At each tick, calculate a new acceleration based on the change in speed over the time it took to move from tick to tick. This is much simpler than the speed calculation, but you should do it here rather than anywhere else so that it stays constant from tick to tick. Again, you should have some way of bringing the acceleration to 0 if the robot is stopped. Use Constant Time Sampling It doesn't always pay to do things as fast as you can. In these applications, sampling your actual data at 100 times a second is probably enough. So even though you are calculating speed very quickly from those interrupt handlers, actually create "speed samples" that will be known to be constant over the whole sample. This will become more important later when implementing the PID controller. System Identification: Keep It Linear! While a great deal in engineering is random, unknown, and often unsolvable, nothing in engineering is black magic. Once you can capture speed being outputted each 100th of a second to the program port, it is easy to characterize your system (or a linear approximation of it). This can be done by software encoding an input which sits at 0 for a small time and then immediately jumps up to some value (otherwise known as a "step" input). The input speed from the wheel turning due to such an input can actually give you the PID coefficients almost directly. (REMEMBER TO USE CONSTANT TIME SAMPLING!!) If you are not familiar with this compensation process or have no one around you who is familiar with root locus and/or Ziegler-Nichols methods, then you can bypass this section entirely. However, if you do do system identification on your robot, be sure that your step is not too large!! Having your robot jump into a speed that is approaching its saturation point will unfortunately cause your response to characterize a particular point on a very non-linear side of the motor. If you want to approximate your motor as a simple second-order linear time-invariant system, you probably should do it in the region where the change in output over change in input is still fairly constant. Note that in the 1014 code, we actually took a step and implemented it, but unfortunately our drive train changed substantially after the step was taken and we weren't able to use our optimized coefficients in time for competition. We resulted to setting these coefficients heuristically, and things worked very well during competition. Before Implementing: Condition Inputs and Outputs Create functions that will take in a value from -128 to 127 and output a PWM signal that has had a dead-zone applied (and possibly a hold-over zone) that goes from 0 to 255. Keeping your code in terms of -128 to 127 will simplify things GREATLY. This makes things all "linear" rather than "affine." The Basic PID Controller PID is simple to implement. The basic pseudocode goes something like this. Keep in mind the last note about conditioning inputs and outputs to be centered around 0. Also remember that both actual_seed and actual_accel are available as they have been calculated already. NOTICE THE USE OF Ts. This is the time between samples. If you sample 100 times a second, this is thus 0.01. THIS IS VERY IMPORTANT. It will help make your Ki gains much more reasonable. It is needed to approximate an integrator. It is the "width" of each rectangle that is being integrated. error = desired_speed - actual_seed; output = Kp * error + Ki * Ts * sum_error + Kd * actual_accel; sum_error += error; // Don't actually do this!!! SEE NEXT NOTE!!! The goal is then to set the Kp, Ki, and Kd coefficients properly. If you have identified your system, this is easy to do. If you have not, keep this in mind, and BE CAREFUL as you can EASILY CREATE OSCILLATIONS: Kp: Proportional Gain - Sets the shape of the output to generally match the input Ki: Creates a lag in the output that helps smooth transitions. This also causes overshoot due to this lag. However, a great thing it does is that it gaurantees no steady-state error. After some sufficiently long period of time, if enough of this term is added in, the output will match the input exactly. Kd: Speeds up the response. This reduces the lag caused by the Ki control. However, not only does it couple in lots of noise into the system, but it can actually cause steady-state error problems (because derivatives of constants are 0). Dealing with Integer Overflow: SATURATE If that sum_error term just keeps getting added to over and over again, it will very quickly overflow. This will turn a VERY LARGE POSITIVE NUMBER quickly into a VERY LARGE NEGATIVE NUMBER. Integral control can on its own cause nasty oscillations just due to its delay/lag. However, adding this fun roll-over effect creates even worse ones. To fix this, wrap something around the addition that prevents it from ever rolling over. Something like: sum_error = safe_add( sum_error, error ); Where safe_add makes sure that if a positive is added to a positive, a positive comes out, and if a negative is added to a negative, a negative comes out. You can see our PIID code in user_routines_fast.c. There is an additional integrator to allow us the freedom to tune our second order (ramp) input response. There are reasons for this additional I, but I am placing them outside the scope of this message. This controller does show all of the points above, including some more. Be Careful: Literals are BYTES by Default In this process, if you use ANY literals, be sure you explicitly cast them as, for example, int if they are negative or over 127. Otherwise your 255 looks like a -1 to the PIC. In general, be careful about your signed/unsigned conversions. Things may not be as you think they seem. Use State Machines in Autonomous Mode Once Good Controllers are Built Once good speed and position controllers are built (position controllers can be built on top of speed controllers), use state machines to move from one state (motors driving forward) to another state (motors turning robot left) to another state (motors driving forward again) to...... The only time you should have to look at your feedback in autonomous mode is thus when to CHANGE STATES. Otherwise, you let the speed controller do all the hard work for you. See the 1014 code for an example of this. Additionally, it is possible to build "steering controllers" that are PID based in themselves. These can take angles and forward velocities and turn them into left and right motor CONTROLS which then get fed into the left and right motor PID controllers which then turn them into motor commands. Some Simple Benefits (and Cons) of Feedback Control Being able to count on a controller to deliver a very simple task is so important. This allows the driver to simply "suggest" a speed with his or her joystick and the robot will handle all the rest. The driver can then get up the step at a slow speed, for example. Rather than running straight into the step, the driver holds the joystick constant and the feedback controller figures out how to get up the step to maintain its own speed. Additionally, for that same reason, a real feedback controller actually makes the torque-speed curve of a motor almost entirely horizontal (within a certain range). This actually can be dangerous because the robot will perform CONSISTENTLY under ANY BATTERY POWER and it may be easy to forget to monitor it's battery life. Plus, these controllers are extremely robust. People spend hours dealing with open-loop filters on joystick inputs and often come up with odd non-linear controllers which have no easy way to optimize. The linear feedback control system uses the motors own natural low-pass effects to smooth out its own input. The linear feedback control system needs very little tweaking to be operational, and will do its hardest to perform as close to optimally as possible even on a low battery or when facing an odd load. However, there is a much stronger dependence on hardware. There is a tremendous increase in complexity. There simply are costs for all the things that the feedback gains you. Anyway, I hope that code might help some people. I'm afraid my post might be too long to help pepole directly, but hopefully some will read it. The system works great on our robot; I hope it can help yours. |
Re: PID control loops - closed loop feedback
Wow, great post!
A few questions, though: first, how high a resolution encoder are you using? You spoke about sampling at 100hz, which is *much* higher than our sample rate (5 and 10hz)--we found that anything higher didn't allow for much change at all during one tick and as a result operated inproperly. We use a potentiometer on the motor with 1024 ticks on it (10 turns), using about 900 in the actual arm scope. Two, just as general practice, make sure to use 254 instead of 255 (and -127 instead of -128, or you're adding too much); you can get into trouble with the speed controllers with 255. Three, what circumstances are you dealing with integer overflow? We've never had anything close to that high an integral, much less wanted it (it would cause the motor to swing all the way over and jam the arm into the robot...). Perhaps we have radically different output systems, but our integral never really gets higher than 30-50 (and that can be dangerous). Hey but thanks for this! Now I gotta sit down and try to understand the part about linearizing it... :ahh: |
Re: PID control loops - closed loop feedback
Great post by TedP - only thing I would add is the motor speed is not the only way to go
for our auton mode we were more concerned with robot heading, so using a yaw rate sensor was the easiest solution - for most driving situtaions getting the robot pointed in the right direction is the trick, how fast it move (preciesly) is of less concern you can calculate how fast your bot is turning by having speed sensors on both wheels, but its much simpler to plant a yaw rate sensor on your frame somewhere and read it directly. BTW - if anyone is wondering if this stuff is worth the trouble- yes! our auton mode worked very well when our team coach remembered which 'left' to set the switch to (left or the other left) and at Buckeye our team won the Johnson & Johnson quality in controls award - I think not so much because of the PID closed loop feedback we had on our steering, arm elevation and arm extension, and the use of IR sensors - but because our students could explain so well to the judges how it all works. sophestication is good - understanding is excellent :^) |
Re: PID control loops - closed loop feedback
1 Attachment(s)
I am very cuious, why do you use the double integration? What was the issue with leaving it out?
For team #492, we only used PI for our velocity control and PD for our arm had excellent results. Attached is our servo code. It is considerably different from the typical examples and I will be publishing (sometime) a white paper on the subject out at http://www.titanrobotics.net on the subject. Highlights: 1. we modeled the drive motors and compensated for the back-EMF with some posative velocity driven feedback. By moving this large, known error, outside of the control loop, we were able to remove most of the integral term and vastly improve the stability of the system while keeping tight control. When properly implemented, back-EMF compensation (when in "torque" control mode) makes the robot feels "frictionless". Very cool to be able to push the robot and have it glide across the floor... In fact, that is how I tuned it: pushed the robot back and forth and adjusted the kemf values (left, right, forward, reverse) until the robot glided without speeding up or slowing down, in a straight line. This has obvious control implications: speed errors generate a torque command, when up to speed, the torque command goes to zero (no integral term needed!) yet the robot continues to zoom along. 2. We used gain scheduling on our arm. Actually, all we did was divide the K term by 16 when overhead because of the drive slop and lack of gravity keeping things taut. Still, gain scheduling sounds cooler :) 3. We also limited the maximum torque (current) to our motors. Rather than using the FIRST supplied current sensors (which would have been the precise way to do this) we used the back-EMF technique. Anyway, by limiting the maximum torque we avoided all issues of overheating our motors and popping circuit breakers. With a dual motor, simple gearbox (no shifting) design we still had plenty of power to push goals and robots around :D |
Re: PID control loops - closed loop feedback
Quote:
In the code I posted (above), we have a torque limit and stop accumulating the integral error when that has been hit. Cheers! |
Re: PID control loops - closed loop feedback
Quote:
To answer your question directly, we only had TEN ticks per revolution on our drive wheels (unfortunately that was about 4 to 5 inches per tick) and our maximum velocity for this robot wasn't any higher than around 50 inches per second. So we were ticking very very slowly... But we didn't calculate speed every sampling period, we calculated it every tick by recording time rather than recording ticks. Quote:
Quote:
For one, an uncompensated steady state output may simply have an output offset. As you sit "still" you'll sit there and churn integral error. The integrator is what brings you back to 0. The otherwise, in very slow moving systems, the error adds up VERY quickly since it takes you so long to get to your set point. In other words, IF YOUR SYSTEM ALREADY HAS LOTS OF LAG, then your integral term, which is supposed to ADD LAG, will explode. Of course, we saturate when we get too high. This protection is built into the code. It's a standard technique. Additionally, the reason you may not see much of that integral term is because you may multiply by your sampling time period immediately during the sum. We sum without that factor (0.01) and then multiply the whole sum later. And regardless, this is hardly dangerous. If the integral term gets large, that's fine. Just make sure your integral coefficient is set moderately correctly. Quote:
To understand where the non-linearities come from, I'll give two examples. The drive train moves from stopped to moderately slow in appoximately a straight line. That is, a little change in input causes a change in output proportional to that change in input, and that proportion doesn't change as long as you're moving moderately slow. Note that there is a jump from 0 to some velocity that is a non-linear jump, but I'm assuming we're over that hump. But eventually those motors have to saturate. Eventually they can't drive your robot any faster. This may happen when your joystick is only halfway through its travel. Even though your joystick can increase the signal going out to the motor, the motor simply cannot turn any faster. This is probably going to an extreme, but the point is that even a large change in input won't necessarily cause a large change in output. I know I see this with our robot as it easily moves from 0 to 45 inches per second and then creeps up toward 50 or 55 inches per second at a much slower rate. This sort of non-linearity causes all sorts of problems. However, without getting into them, the biggest issue is that your robot USUALLY is in the linear range. Your compensator should be built for the slower range where changes in input ACTUALLY CAUSE changes in output. If you build a compensator EXPECTING a very STUBBORN motor, then it will be FAR TOO HARSH during the rest of the motor's travel. It's better for the compensator to be gentle than harsh. The other non-linearity, a much more interesting one, involves our two-jointed articulated arm. Assuming the shoulder is holding the arm straight up into the air, the elbow joint may be moving the arm with gravity or against gravity depending on its direction AND its position. As it crosses vertical, the role of gravity will switch. In fact, as it moves toward vertical, the role of gravity drastically changes. Additionally, as weight is added onto the end of the arm when it picks up a ball, things change quite a bit. On top of this, the shoulder's position greatly affects how gravity will affect the elbow. If the shoulder is near horiztonal, we expect different gravity effects at the elbow based on its position. So in short, now position is a major variable in the control. However, things get more complicated when you consider shoulder movement. The shoulder has a gravity component too, but its own center of gravity changes depending on the elbow position, and that changes how fast it can move along with all the problems associated with the elbow joint. So now the elbow joint's dynamics are coupled to both its position and the shoulder's position and the SHOULDER'S DYNAMICS, and the shoulder's dynamics are coupled to the elbow's position, the shoulder's position, and the elbow's dynamics (is the elbow moving or not? and where is the elbow while it's moving?). This is a much more complicated system, and traditional approaches to the two-jointed arm problem involve forms of gravitational linearizing and other methods. However, our arm was so slow and had such a major gear reduction from motor to output joint (1250 reduction on the shoulder), we were able to use the simple PID controller on both joints fairly well. BUT... we did add an integral term to both joints. We didn't want to slow things down, but we wanted to make sure that as the robot sat idle, it would correct any offset errors which were produced during its movement. The topic of linear time-invariant systems is worth a whole career. The top of linear controllers fits into there. However, non-linear systems is an entirely different topic, and often does not benefit at all from linear system theory. Lukcilly, most FIRST systems are simple enough to not require such sophistication. And, of course, the thing that won our Engineering Inspiration Award in Pittsburgh was less of the technical stuff we did here, but more of the ability of our students to use it to aid in their understanding of engineering. When our STUDENTS said that we had no error because the integral term compensated for it, the judges really appreciated that. When our students explained that a system can be characterized by its ideal PID coefficients and thus the PID coefficients need to be traded off from one to the other to find the right equilibirum, that's what impressed the judges. How well we did enforced that, and that we were able to help other teams with similar mechanical systems but very different controls surely helped... but I hope it's what the students portrayed that got us recognized. |
Re: PID control loops - closed loop feedback
Quote:
The current system still uses the 2x255 but hides it from you by "adjusting" 255 to 254 before sending it to the control processor. We discovered this when trying to send telemetry data back. We were using some of the unused PWM slots for the dashport, so we could get data back each cycle. Well, no such luck. So we limited the data to 7 bits and used two slots to pass 14 bits of data back. (it was gyro angle in .1 deg so it needed to be an int). Now that IFI has given us a real processor, it is time to give a real radio without these limitations. |
Re: PID control loops - closed loop feedback
I am planning to use PID on the arm for our end of year mini-game bot
(we make a mini game w/ the robotic class (sadly only 7 students one being a moderator) split into 2 teams w/ a 2X2X3' 80 lbs robot its really cool) any ways for ours (i'm not sure if this will work) I will basically just put a gyro on the arm and compare the "wanted speed" to the real speed and then just add a bit to the PWM (dependent on how close real is to wanted) to calibrate it just move the gyro away from or closer to the joint! to get the real speed i'm just going to multiply the accel*time/looptime + previous...that should probly give me speed.. Will this work? Also i'm using the PBasic controller so i'll have to learn that a bit... do i have to keep loop time constant or not...does it really matter that mucH? This part really bugs me out because i read about everyone keeping loop times constant and what not but on the Edubot controller I just wrote the code...heck to loop time and everything worked (for our little autonomous gyro guidance thing) IF it does matter a LOT i might take a educontroller and connect it to the maincontroller so it can receive gyro inputs and then simply output the amount to add to the PWM through dig_out which plugs into dig in on the RC Also can someone explain why it matters so much (in reality ) do the loop times really vary by so much that it would greatly affect operation (i imagine if it loops so quickly it wouldn't matter...the differences would be averaged out to a menial number??) Thanks! |
Re: PID control loops - closed loop feedback
if you are matching rotational speed then the amount of time the loop takes doenst matter
its when you are integrating it to get angles that the loop time alters the output - and even that averages out if the loop is not the same every time I wouldnt worry about the loop speed - PID loops always have some trial and error testing to get the constants right sounds like fun. |
Re: PID control loops - closed loop feedback
Also...this is kind of a side question...if i integrate twice...wouldn't i get a 0-254 value? (from the gyro) ...that is Total V? ....i guess it wouldn't be so hard to convert to an angle given that its 150 deg/sec...but i don't really trust that so I'm thinking i'll not convert to degrees (useless anyways)...
just wondeing... |
Re: PID control loops - closed loop feedback
Im not sure what you mean by integrating the sensor twice?
the output of a yaw rate sensor is degrees/second when you integrate its somewhat like multipling by seconds, so you end up with degrees (in units that do not directly read out in degrees, you would need a constant added in if you want actually degrees, or radians, or whatever standard unit you want but if you integrate that again? Im not sure what that gives you? degreeSeconds?! I dont know what that would be measuring? |
Re: PID control loops - closed loop feedback
degree seconds? i thought it would give the degree angle of the arm ...like a potentiometer... (degree/seconds * seconds = degrees ) right?
btw this is the actual code it hasn't been compiled or tested yet just theory...just notepad: Code:
p2_y=armin;but why integrate the error....i don't get this and how it works ? i read some stuff about how it is an automatic reset which doesn't quite make sense to me...... Also can someone explain the derivative...part... :) |
Re: PID control loops - closed loop feedback
OKay...nevermind...i figured out what it does......now for the derivative ....the longer an error has stayed the more it adds... :cool:
|
Re: PID control loops - closed loop feedback
I think I understand your statements now.
when you intergrate the sensor output you are changing the 'signal' from degrees/second to degrees so now you can create an error signal by subtracting that from what the operator is commanding (desired angle) and do a PID feedback with intergral, proprotional and deriviative (or differentail) components so you would not really be intergating the sensor single twice - you would be integrating it once to get the angle then if you wanted tight feedback you could integrate the error signal over time. |
Re: PID control loops - closed loop feedback
yeah...i know i'm not gonna integrate twice...just once..(see code) but i was just wondering...
I've tweaked the code to include an integral term, now i'm wondering how to do the derivative...its hard because i'm trying to read ahead in the textbook...(we haven't learned derivitves yet!) ..... and then apply it to this....all the articles I find on PID are a bit too complex... btw... we also did the whole tape interpolation thing for autonomous..we didn't use it because we didn't need the precision, we used a gyro to track heading, then tape for distance, we didn't have a legal gyro at times so i also implemented a timer that would measure time between the tape being seen and calculate dist to a much finer degree then 1/6 wheel circumfrence...alot like what u did... |
Re: PID control loops - closed loop feedback
derivative is easy. its the delta or change since the last loop
create a new variable to keep track of the 'last_error' signal - then compair the current error signal to the last one - thats the derivate - you are interested in how fast the error signal is changing which can be due to the driver making a sudden change, or the bot moving suddenly. |
Re: PID control loops - closed loop feedback
okay....i get it now
Thanks! |
Re: PID control loops - closed loop feedback
Heres our PID code so far...the constants u multiply by really have to be tweaked once the actual robot is built :D! ... P+I+D should not be over 127 or under -127...so i'll have to definitely calibrate it A LOT
IF( any one spots obvious mistakes ...(not like syntax error type mistakes) ){please tell me...} Code:
////get joystick input/////////////// Am I doing the Proportional correctly? It says Gain= Input / Ouput ... but in stead i just compare the target to the actual...thats not exactly the same but should give me the result i'm looking for (to lower speed when target is closer to actual)?? Correct me if i'm wrong please.... |
Re: PID control loops - closed loop feedback
Quote:
|
| All times are GMT -5. The time now is 14:04. |
Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi