PID output limits calculation

Hi, the following code is written by electronoobs.com, i dont understand how he got the number 150 on line 67.
For example, the kp value is given as 8 on line 29 and the set point is 21 on line 32. If you calculate the distance_error given on line 52, it can have a value from -21 to +21 and with this if you calculate PID_p on line 53,the value would be from -168 to +168. So even with just kp value, the PID total would be more than 150 or less than -150. So how did he come up with the number 150?? :slight_smile:

/* PID balance code with ping pong ball and distance sensor sharp 2y0a21
 *  by ELECTRONOOBS: https://www.youtube.com/channel/UCjiVhIvGmRZixSzupD0sS9Q
 *  Tutorial: http://electronoobs.com/eng_arduino_tut100.php
 *  Code: http://electronoobs.com/eng_arduino_tut100_code1.php
 *  Scheamtic: http://electronoobs.com/eng_arduino_tut100_sch1.php 
 *  3D parts: http://electronoobs.com/eng_arduino_tut100_stl1.php   
 */
#include <Wire.h>
#include <Servo.h>



///////////////////////Inputs/outputs///////////////////////
int Analog_in = A0;
Servo myservo;  // create servo object to control a servo, later attatched to D9
///////////////////////////////////////////////////////


////////////////////////Variables///////////////////////
int Read = 0;
float distance = 0.0;
float elapsedTime, time, timePrev;        //Variables for time control
float distance_previous_error, distance_error;
int period = 50;  //Refresh rate period of the loop is 50ms
///////////////////////////////////////////////////////


///////////////////PID constants///////////////////////
float kp=8; //Mine was 8
float ki=0.2; //Mine was 0.2
float kd=3100; //Mine was 3100
float distance_setpoint = 21;           //Should be the distance from sensor to the middle of the bar in mm
float PID_p, PID_i, PID_d, PID_total;
///////////////////////////////////////////////////////



void setup() {
  //analogReference(EXTERNAL);
  Serial.begin(9600);  
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  myservo.write(125); //Put the servco at angle 125, so the balance is in the middle
  pinMode(Analog_in,INPUT);  
  time = millis();
}

void loop() {
  if (millis() > time+period)
  {
    time = millis();    
    distance = get_dist(100);   
    distance_error = distance_setpoint - distance;   
    PID_p = kp * distance_error;
    float dist_diference = distance_error - distance_previous_error;     
    PID_d = kd*((distance_error - distance_previous_error)/period);
      
    if(-3 < distance_error && distance_error < 3)
    {
      PID_i = PID_i + (ki * distance_error);
    }
    else
    {
      PID_i = 0;
    }
  
    PID_total = PID_p + PID_i + PID_d;  
    PID_total = map(PID_total, -150, 150, 0, 150);
  
    if(PID_total < 20){PID_total = 20;}
    if(PID_total > 160) {PID_total = 160; } 
  
    myservo.write(PID_total+30);  
    distance_previous_error = distance_error;
  }
}




float get_dist(int n)
{
  long sum=0;
  for(int i=0;i<n;i++)
  {
    sum=sum+analogRead(Analog_in);
  }  
  float adc=sum/n;
  //float volts = analogRead(adc)*0.0048828125;  // value from sensor * (5/1024)
  //float volts = sum*0.003222656;  // value from sensor * (3.3/1024) EXTERNAL analog refference

  float distance_cm = 17569.7 * pow(adc, -1.2062);
  //float distance_cm = 13*pow(volts, -1); 
  return(distance_cm);
}

Ask him.

PID implementations often require arbitrary choices. The calculated value of OUTPUT can be impossible, considering the limitations of the equipment (e.g. PWM value negative, or exceeding 255 on Arduino), so you may have to impose arbitrary constraints on it.

Don't worry. The map() function will extend the output range if you exceed the input range. If you put in a value below -150 you will get an answer below 0. If you put in a value above 150 you will get an answer above 150. The result is then truncated to the 20 to 160 range so values below -110 become 20 and values above 170 become 160.

Thanks for the reply. I understood what you wrote. But how did the author know the PID total is -150 to 150?

how did the author know the total would be between the -150 to 150?

See post #2.

See: Heuristic

You should not want your output to hit limits.
It will disturb proper response.
It would be ok for situations that your hardware cannot handle. For example when a motor is stalled and may burn out otherwise. Or when a motor needs minimum input to start running.
Or

Maybe it was empirical and when he tried it he found that all the values he got were between -150 and 150. As I pointed out, it doesn't matter.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.