PID算法完全讲解-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

楼主: 对折之内

PID算法完全讲解

  [复制链接]
发表于 2017-2-15 16:05 | 显示全部楼层
LZ   有个问题想要请教下,我这边在做电机位置环控制(电机转动,利用编码盘计数,形成计数,比如N步,达到电机来回只走N步),目前就是多少有点误差(例如20线编码盘转一圈,有19,20,21的个数),然后就想利用PID控制,但是,不知道如何建模,入手,能讲解下?
发表于 2017-3-31 13:07 来自手机 | 显示全部楼层
厉害
发表于 2017-6-20 09:18 | 显示全部楼层
你好,PID的计算 有几个问题 想请教一下你。可以加QQ吗?
11594570
发表于 2017-7-13 23:01 | 显示全部楼层
最近做了一個平台放置要讓他做到平衡,但我在kp、ki、kd這個方面,總是做不到平衡。
#include<Servo.h>
#include<PID_v1.h>
const int servoPin = 9;                                               //Servo Pin
float Kp = 2.5;                                                  //Initial Proportional Gain
float Ki = 0.1;                                                      //Initial Integral Gain
float Kd = 1.1;                                                    //Intitial Derivative Gain
double Setpoint, Input, Output, ServoOutput;                                       
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);           //Initialize PID object, which is in the class PID.                                                                                                                                                                                                                                                                                   
Servo myServo;                                                       //Initialize Servo.

void setup() {

  Serial.begin(9600);                                                //Begin Serial
  myServo.attach(servoPin);                                          //Attach Servo
  Input = readPosition();                                            //Calls function readPosition() and sets the balls                                                                     //  position as the input to the PID algorithm                                                                  
  myPID.SetMode(AUTOMATIC);                                          //Set PID object myPID to AUTOMATIC
  myPID.SetOutputLimits(-40,40);                                     //Set Output limits to -80 and 80 degrees.
}

void loop()
{

  Setpoint = 20;
  Input = readPosition();                                            

  myPID.Compute();                                                   //computes Output in range of -80 to 80 degrees
myServo.write(100+ Output);                                         //Writes value of Output to servo
  
  
}

float readPosition() {
  delay(10);                                                            //Don't set too low or echos will run into eachother.      
  
  
const int pingPin = 11;
const int pingPin2 = 12;

long duration, cm;
unsigned long now = millis();
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);


  pinMode(pingPin2, INPUT);
  duration = pulseIn(pingPin2, HIGH);

  cm = duration/(29*2);
  
  
  if(cm > 50)     // 30 cm is the maximum position for the ball
  {cm=50;}
  
  
  Serial.println(cm);

  return cm;                                          //Returns distance value.

}


发表于 2017-7-22 14:19 | 显示全部楼层
题主,你好~
尝试着重新打了一遍您的代码。发现,在Timer_ISR()中使用了 uiCounter 的静态变量。中断1次,uiCounter +1.当等于 100 时,意味着,已经运行了 100 *0.1s。此时, pid 的运行标志g_bPIDRunFlag 置1.

而在,PID_output 函数中,用pid 的运行标志,来判断。其中又用到了 uCounter 的变量。里头写到,挚友uCounter 执行100次,才开始运行 PID_Operation(),开始pid 的计算。

那么,总的时间应该是:100 * 100 * 0.1s。和注释中写到的,100 * 0.1s 不符。

不知道是不是因为,单片机的时钟频率没有提及,造成了我的误解。
盼复~
再次感谢题主的帮助。
发表于 2018-1-7 09:29 | 显示全部楼层
谢谢!受益匪浅。十分感谢知识的分享。谢谢了。
发表于 2018-2-2 14:53 | 显示全部楼层
最后给的程序有问题吧iTemp = PID.iPriVal;后面iiTemp --没意义啊。
发表于 2018-4-2 22:52 来自手机 | 显示全部楼层
十分形象,通俗易懂
发表于 2018-8-7 10:16 | 显示全部楼层
理解了很多,赞一个
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 04:53 , Processed in 0.140547 second(s), 12 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表