![]() |
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. |
| All times are GMT -5. The time now is 10:50. |
Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi