Go Down

Topic: Controlling an animatronics bust (Read 5 times) previous topic - next topic

PeterH

#20
Feb 07, 2013, 06:38 pm Last Edit: Feb 07, 2013, 06:45 pm by PeterH Reason: 1

Is error in your terms equal to currpos - setpos?


Yes, in the context of a closed loop feedback system the difference between the actual and required output is termed the error.

The notes you quoted are broadly along the right lines but don't account for time correctly, so don't put too much trust in them as an explanation of how PID works.


I am using structures instead of classes. I am really unfamiliar with the concept of classes just yet.


Structures let you hold the set of data associated with a servo but don't give you the ability to associate behaviour with it and don't (without a lot of work) enable you to deal with similar but not identical things.

Classes enable a much more comprehensive solution. You can define a simple common interface to a servo and then provide multiple different implementations that look the same from the outside but behave differently. So you could have some servos that use a potentiometer for feedback, and some that use an encoder to track movement, and some that are implemented using stepper motors, and some that are standard RC servos controlled by PWM, and fro the point of view of your control logic these would all behave the same.

It would be well worth your time researching the concepts of abstract typing, polymorphism and inheritance because they are key to using classes effectively, and will make your solution much, much simpler.
I only provide help via the forum - please do not contact me for private consultancy.

laadams85

#21
Feb 07, 2013, 06:40 pm Last Edit: Feb 07, 2013, 06:42 pm by laadams85 Reason: 1
The typical definition of error is expected response - actual response.  With servos its input position - actual position.  The definition that you have is the output of the PID, with P being the error, I being the integral of the error and D being the derivative of the error.

Edit:  As Peter said you are missing the dt term

Here is some pseudo code from wiki

previous_error = 0
integral = 0
start:
  error = setpoint - measured_value
  integral = integral + error*dt
  derivative = (error - previous_error)/dt
  output = Kp*error + Ki*integral + Kd*derivative
  previous_error = error
  wait(dt)
goto start

For the arduino instead of setting the dt value and the looping you would instead loop and then measure the dt.

Retroplayer

Is the arduino millis() function good source for determining dt? So something along the lines of this:

Code: [Select]
int PIDcalc(){

I = 0;
dt = millis() - prev_millis;

error = setPos - currPos;


I = I +error*dt;
D = (error-prev_error)/dt;

output = (error * Kp + I * Ki + D * Kd);

prev_error = error;

prev_millis = millis();
return output;

}


Or since I am calling this in a timed loop, would it be smarter to just make dt equal the amount of time that changed between calls?

The million dollar dumb question is: what do I do with output now to determine forward or reverse and speed? Should I just have that calculation done right in this routine?
Finally, what variables do I need to keep track of outside of this routine for handling the several motors?

Thanks!

laadams85

Quote
Is the arduino millis() function good source for determining dt?

Its the best you will get without using an outside timer.
This method isn't exactly correct, but it is a good approximation.  What you are trying to do is figure out what the error will be in the future based on the current slope of the error.  So dt should technically be the time step between now and the next step.  If your time steps are more or less uniform this isn't a problem.  If they are all over the place then you are gonna have problems.

Quote
The million dollar dumb question is: what do I do with output now to determine forward or reverse and speed? Should I just have that calculation done right in this routine?

The PID routine takes care of direction.  If you have overshot then the output will be in the opposite direction from before because your error will of the opposite sign from before.  You set your output to the output variable of your function

Quote
Finally, what variables do I need to keep track of outside of this routine for handling the several motors?

You should make your PID a function in which you pass it the set_position, the current_position, the previous_milli, and the previous_error with previous_milli and previous_error being reference variables so that you can set them in the function.

You should really look at the code in the PID library, it will answer a lot of your questions.  One thing I'm not so sure if is why they subtract the D term.
Code: [Select]
/* Compute() **********************************************************************
*     This, as they say, is where the magic happens.  this function should be called
*   every time "void loop()" executes.  the function will decide for itself whether a new
*   pid Output needs to be computed.  returns true when the output is computed,
*   false when nothing has been done.
**********************************************************************************/
bool PID::Compute()
{
   if(!inAuto) return false;
   unsigned long now = millis();
   unsigned long timeChange = (now - lastTime);
   if(timeChange>=SampleTime)
   {
      /*Compute all the working error variables*/
  double input = *myInput;
      double error = *mySetpoint - input;
      ITerm+= (ki * error);
      if(ITerm > outMax) ITerm= outMax;
      else if(ITerm < outMin) ITerm= outMin;
      double dInput = (input - lastInput);

      /*Compute PID Output*/
      double output = kp * error + ITerm- kd * dInput;
     
  if(output > outMax) output = outMax;
      else if(output < outMin) output = outMin;
  *myOutput = output;
 
      /*Remember some variables for next time*/
      lastInput = input;
      lastTime = now;
  return true;
   }
   else return false;
}

laadams85

Also followed the links on the library page an stumbled on this.  Might be explanatory.
http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/

Go Up