PID_v1.h 库的奇怪问题-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 7563|回复: 7

PID_v1.h 库的奇怪问题

[复制链接]
发表于 2016-4-14 21:42 | 显示全部楼层 |阅读模式
官方的代码:

#include <PID_v1.h>
double Setpoint,Input ,Output;

PID myPID(&Input,&Output,&Setpoint,2,5,1,DIRECT);
void setup() {
  
   Serial.begin(9600);
   Input=80;
   Setpoint=100;

  myPID.SetMode(AUTOMATIC);
}

void loop() {
  Input = 80;

  myPID.Compute();
  //analogWrite(3,Output);

  Serial.print("Output= ");
  Serial.println(Output);
  delay(500);
}

原代码的 Input 是读取 A0 口的模拟值 ( 有的代码里还会 map(val, 0 ,1023 , 0, 255)   类似这样的);

我这里把 Input 设置为一个固定值, setpoint 定为 100


为什么 OUTPUT 一开始是接近 setpoint  ,后面就一直向上,直到 255,就不变了,我觉得很纳闷,

到底这个 Input 有什么用?还是代码本身有什么问题?



发表于 2016-4-15 08:52 | 显示全部楼层
INPUT固定,程序认为调整无效,继续调整。主要是PID里的积分导致。
 楼主| 发表于 2016-4-15 13:40 | 显示全部楼层
开心咔咔 发表于 2016-4-15 08:52
INPUT固定,程序认为调整无效,继续调整。主要是PID里的积分导致。

听起来是有那么点道理,但是我昨晚做了试验,如果输入Input 比 Setpoint大(超过1),那么OUTPUT会趋于0,最终变成0,如果Setpoint 比 Input 大1,或是小1(在这个区间内变化),那么OUTPUT 会是一个常数,在一个小范围内变化(大概也是正负1左右的变化幅度) ,但是我的目的是要OUTPUT 跟 SETPOINT 变化,一样,或是不差太远,这不也是PID算法的最主要的作用吗?
发表于 2016-4-15 15:00 | 显示全部楼层
PID為閉迴路控制系統, 當PID output輸出後, 會再觀察input 和setpoint間的差值變化, 在計算下一步的輸出, 進而讓被控物達到目標(input-setpoint=0); 你的範例給定input為定值, 也就是說無論PID output如何輸出, 始終無法讓 input 與setpoint的差值為零 , 所以而積分控制項將驅動PID 輸出趨近於最大或最小;  至於你讓setpoint比Input在 +/-1區間做變化, PID輸出為常數, 有以下兩種可能 1) Ki 的值太小使PID output反應不出來; 2)在setpoint +/-1 之間有加filter提高PID控制器的穩定度
 楼主| 发表于 2016-4-15 17:43 | 显示全部楼层
qchi1983 发表于 2016-4-15 15:00
PID為閉迴路控制系統, 當PID output輸出後, 會再觀察input 和setpoint間的差值變化, 在計算下一步的輸出,  ...

其实我输入Input不是固定的,我是采用 测速输入的 ,码盘测速,20线 ,测出来是从 68 到 79之间变化的
 楼主| 发表于 2016-4-15 17:49 | 显示全部楼层
我的码盘是 20格的,Input 也是根据码盘测速来变化,speeds 测速是这样
volatile int scode = 0; //speed test

void setup() {
    attachInterrupt(digitalPinToInterrupt(OUT1),code,CHANGE );


}

void code() //interrputer
{
    scode = scode + 1;
}


void speedtest() {
    detachInterrupt(digitalPinToInterrupt(OUT1));
    oldtime = newtime;
    speeds = scode / 2;
    scode = 0;
    delay(1);
    attachInterrupt(digitalPinToInterrupt(OUT1), code, CHANGE);
}


void loop() {

newtime =newtime1= millis();
    if (newtime - oldtime > 1000) {
        Serial.println("begin test...");
        speedtest();
        speedtest1();
       // Setpoint=speeds1;         // 曾经把 Setpoint 放在这里,试图用另外一边轮子的速度作为标准 ,但是OUTPUT值不是趋向于0就是趋向于255
    }



   Input =speeds;
    myPID.Compute();


}
发表于 2016-4-15 22:57 | 显示全部楼层
你的Ki=5,对于+-1来说太大,用小于1的值试试。pid得参数要自己搭配找到最合适的值。
 楼主| 发表于 2016-4-16 08:46 | 显示全部楼层
开心咔咔 发表于 2016-4-15 22:57
你的Ki=5,对于+-1来说太大,用小于1的值试试。pid得参数要自己搭配找到最合适的值。 ...

输出并不是确定的,有时候是+-1,有时候也有更大的值,我试过更换其他Ki ,但是好像总是变成0,或是255(当speed为0的时候)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-11-28 13:46 , Processed in 0.150867 second(s), 15 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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