一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

PID調(diào)節(jié)C語言解析

 咖啡屋2016 2019-01-04

PID調(diào)節(jié)C語言解析

2018年03月15日 22:32:34 彼時(shí)思默 閱讀數(shù):456
版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。 https://blog.csdn.net/qq_37258787/article/details/79575215

前言

老師布置了個(gè)任務(wù),用編程實(shí)現(xiàn)PID調(diào)節(jié),鑒于我們專業(yè)都學(xué)過C語言和VB,于是我就想拿Kotlin練練手.
上網(wǎng)搜索一番別人怎么用C實(shí)現(xiàn)的,找到個(gè)比較詳細(xì)的,但是展示了太多數(shù)據(jù),我這里整理一下基礎(chǔ)知識(shí).
Kotlin的實(shí)現(xiàn)在這里

簡要解析

參考資料,來自這里
通過誤差信號(hào)控制被控量,而控制器本身就是比例、積分、微分三個(gè)環(huán)節(jié)的加和。這里我們規(guī)定(在t時(shí)刻):

  • 輸入量為rin(t);
  • 輸出量為rout(t);
  • 偏差量為err(t)=rin(t)-rout(t);
  • 如果偏差為0,則比例環(huán)節(jié)不起作用,只有存在偏差時(shí),比例環(huán)節(jié)才起作用。
  • 而微分信號(hào)則反應(yīng)了偏差信號(hào)的變化規(guī)律,或者說是變化趨勢(shì),根據(jù)偏差信號(hào)的變化趨勢(shì)來進(jìn)行超前調(diào)節(jié),從而增加了系統(tǒng)的快速性。。

位置型PID的C語言實(shí)現(xiàn)

第一步:定義PID變量結(jié)構(gòu)體,代碼如下:

struct _pid{
    float SetSpeed;            //定義設(shè)定值
    float ActualSpeed;        //定義實(shí)際值
    float err;                //定義偏差值
    float err_last;            //定義上一個(gè)偏差值
    float Kp,Ki,Kd;            //定義比例、積分、微分系數(shù)
    float voltage;          //定義電壓值(控制執(zhí)行器的變量)
    float integral;            //定義積分值
}pid;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

控制算法中所需要用到的參數(shù)在一個(gè)結(jié)構(gòu)體中統(tǒng)一定義,方便后面的使用。

第二部:初始化變量,代碼如下:

void PID_init(){
    printf("PID_init begin \n");
    pid.SetSpeed=0.0;
    pid.ActualSpeed=0.0;
    pid.err=0.0;
    pid.err_last=0.0;
    pid.voltage=0.0;
    pid.integral=0.0;
    pid.Kp=0.2;
    pid.Ki=0.015;
    pid.Kd=0.2;
    printf("PID_init end \n");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

統(tǒng)一初始化變量,尤其是Kp,Ki,Kd三個(gè)參數(shù),調(diào)試過程當(dāng)中,對(duì)于要求的控制效果,可以通過調(diào)節(jié)這三個(gè)量直接進(jìn)行調(diào)節(jié)。

第三步:編寫控制算法,代碼如下:

float PID_realize(float speed){
    pid.SetSpeed=speed;
    pid.err=pid.SetSpeed-pid.ActualSpeed;
    pid.integral+=pid.err;
    pid.voltage=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);
    pid.err_last=pid.err;
    pid.ActualSpeed=pid.voltage*1.0;
    return pid.ActualSpeed;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

注意:這里用了最基本的算法實(shí)現(xiàn)形式,沒有考慮死區(qū)問題,沒有設(shè)定上下限,只是對(duì)公式的一種直接的實(shí)現(xiàn),后面的介紹當(dāng)中還會(huì)逐漸的對(duì)此改進(jìn)。

到此為止,PID的基本實(shí)現(xiàn)部分就初步完成了。下面是測(cè)試代碼:

int main(){
    printf("System begin \n");
    PID_init();
    int count=0;
    while(count<1000)
    {
        float speed=PID_realize(200.0);
        printf("%f\n",speed);
        count++;
    }
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

增量型PID的C語言實(shí)現(xiàn)

這就是離散化PID的增量式表示方式,由公式可以看出,增量式的表達(dá)結(jié)果和最近三次的偏差有關(guān),這樣就大大提高了系統(tǒng)的穩(wěn)定性。需要注意的是最終的輸出結(jié)果應(yīng)該為

   u(K)+增量調(diào)節(jié)值;
  • 1
include<stdio.h>
struct _pid{
    float SetSpeed;           //定義設(shè)定值
    float ActualSpeed;        //定義實(shí)際值
    float err;                //定義偏差值
    float err_next;           //定義上一個(gè)偏差值
    float err_last;           //定義最上前的偏差值
    float Kp,Ki,Kd;           //定義比例、積分、微分系數(shù)
}pid;

void PID_init(){
    pid.SetSpeed=0.0;
    pid.ActualSpeed=0.0;
    pid.err=0.0;
    pid.err_last=0.0;
    pid.err_next=0.0;
    pid.Kp=0.2;
    pid.Ki=0.015;
    pid.Kd=0.2;
}

float PID_realize(float speed){
    pid.SetSpeed=speed;
    pid.err=pid.SetSpeed-pid.ActualSpeed;
    float incrementSpeed=pid.Kp*(pid.err-pid.err_next)+pid.Ki*pid.err+pid.Kd*(pid.err-2*pid.err_next+pid.err_last);
    pid.ActualSpeed+=incrementSpeed;
    pid.err_last=pid.err_next;
    pid.err_next=pid.err;
    return pid.ActualSpeed;
}

int main(){
    PID_init();
    int count=0;
    while(count<1000)
    {
        float speed=PID_realize(200.0);
        printf("%f\n",speed);
        count++;
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

總結(jié):系統(tǒng)的穩(wěn)定性大大提高

積分分離的PID控制算法C語言實(shí)現(xiàn)

在普通PID控制中,引入積分環(huán)節(jié)的目的,主要是為了消除靜差,提高控制精度。但是在啟動(dòng)、結(jié)束或大幅度增減設(shè)定時(shí),短時(shí)間內(nèi)系統(tǒng)輸出有很大的偏差,會(huì)造成PID運(yùn)算的積分積累,導(dǎo)致控制量超過執(zhí)行機(jī)構(gòu)可能允許的最大動(dòng)作范圍對(duì)應(yīng)極限控制量,從而引起較大的超調(diào),甚至是震蕩,這是絕對(duì)不允許的。

為了克服這一問題,引入了積分分離的概念,其基本思路是 當(dāng)被控量與設(shè)定值偏差較大時(shí),取消積分作用; 當(dāng)被控量接近給定值時(shí),引入積分控制,以消除靜差,提高精度。其具體實(shí)現(xiàn)代碼如下:

pid.Kp=0.2;
pid.Ki=0.04;
pid.Kd=0.2;  //初始化過程
if(abs(pid.err)>200)
{
    index=0;
    }else{
    index=1;
    pid.integral+=pid.err;
}
    pid.voltage=pid.Kp*pid.err+index*pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);    //算法具體實(shí)現(xiàn)過程
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

總結(jié):系統(tǒng)的快速性得到了提高。

抗積分飽和的PID控制算法C語言實(shí)現(xiàn)

所謂的積分飽和現(xiàn)象是指如果系統(tǒng)存在一個(gè)方向的偏差,PID控制器的輸出由于積分作用的不斷累加而加大,從而導(dǎo)致執(zhí)行機(jī)構(gòu)達(dá)到極限位置,若控制器輸出U(k)繼續(xù)增大,執(zhí)行器開度不可能再增大,此時(shí)計(jì)算機(jī)輸出控制量超出了正常運(yùn)行范圍而進(jìn)入飽和區(qū)。一旦系統(tǒng)出現(xiàn)反向偏差,u(k)逐漸從飽和區(qū)退出。進(jìn)入飽和區(qū)越深則退出飽和區(qū)時(shí)間越長。在這段時(shí)間里,執(zhí)行機(jī)構(gòu)仍然停留在極限位置而不隨偏差反向而立即做出相應(yīng)的改變,這時(shí)系統(tǒng)就像失控一樣,造成控制性能惡化,這種現(xiàn)象稱為積分飽和現(xiàn)象或積分失控現(xiàn)象。
防止積分飽和的方法之一就是抗積分飽和法,該方法的思路是在計(jì)算u(k)時(shí),首先判斷上一時(shí)刻的控制量u(k-1)是否已經(jīng)超出了極限范圍: 如果u(k-1)>umax,則只累加負(fù)偏差; 如果u(k-1)<umin,則只累加正偏差。從而避免控制量長時(shí)間停留在飽和區(qū)。

struct _pid{
    float SetSpeed;           //定義設(shè)定值
    float ActualSpeed;        //定義實(shí)際值
    float err;                //定義偏差值
    float err_last;           //定義上一個(gè)偏差值
    float Kp,Ki,Kd;           //定義比例、積分、微分系數(shù)
    float voltage;            //定義電壓值(控制執(zhí)行器的變量)
    float integral;           //定義積分值
    float umax;
    float umin;
}pid;

void PID_init(){
    printf("PID_init begin \n");
    pid.SetSpeed=0.0;
    pid.ActualSpeed=0.0;
    pid.err=0.0;
    pid.err_last=0.0;
    pid.voltage=0.0;
    pid.integral=0.0;
    pid.Kp=0.2;
    pid.Ki=0.1;       //注意,和上幾次相比,這里加大了積分環(huán)節(jié)的值
    pid.Kd=0.2;
    pid.umax=400;
    pid.umin=-200;
    printf("PID_init end \n");
}
float PID_realize(float speed){
    int index;
    pid.SetSpeed=speed;
    pid.err=pid.SetSpeed-pid.ActualSpeed;

   if(pid.ActualSpeed>pid.umax)  //灰色底色表示抗積分飽和的實(shí)現(xiàn)
    {

       if(abs(pid.err)>200)      //藍(lán)色標(biāo)注為積分分離過程
        {
            index=0;
        }else{
            index=1;
            if(pid.err<0)
            {
              pid.integral+=pid.err;
            }
        }
    }else if(pid.ActualSpeed<pid.umin){
        if(abs(pid.err)>200)      //積分分離過程
        {
            index=0;
        }else{
            index=1;
            if(pid.err>0)
            {
	            pid.integral+=pid.err;
            }
        }
    }else{
        if(abs(pid.err)>200)                    //積分分離過程
        {
            index=0;
        }else{
            index=1;
            pid.integral+=pid.err;
        }
    }

    pid.voltage=pid.Kp*pid.err+index*pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);

    pid.err_last=pid.err;
    pid.ActualSpeed=pid.voltage*1.0;
    return pid.ActualSpeed;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

總結(jié):系統(tǒng)的穩(wěn)定時(shí)間相對(duì)前幾次來講縮短了不少。

梯形積分的PID控制算法C語言實(shí)現(xiàn)

先看一下梯形算法的積分環(huán)節(jié)公式
作為PID控制律的積分項(xiàng),其作用是消除余差,為了盡量減小余差,應(yīng)提高積分項(xiàng)運(yùn)算精度,為此可以將矩形積分改為梯形積分,具體實(shí)現(xiàn)的語句為:

pid.voltage=pid.Kp*pid.err+index*pid.Ki*pid.integral/2+pid.Kd*(pid.err-pid.err_last);  //梯形積分
  • 1

總結(jié):精度進(jìn)一步提高。

變積分的PID控制算法C語言實(shí)現(xiàn)

變積分PID可以看成是積分分離的PID算法的更一般的形式。在普通的PID控制算法中,由于積分系數(shù)ki是常數(shù),所以在整個(gè)控制過程中,積分增量是不變的。但是,系統(tǒng)對(duì)于積分項(xiàng)的要求是,系統(tǒng)偏差大時(shí),積分作用應(yīng)該減弱甚至是全無,而在偏差小時(shí),則應(yīng)該加強(qiáng)。積分系數(shù)取大了會(huì)產(chǎn)生超調(diào),甚至積分飽和,取小了又不能短時(shí)間內(nèi)消除靜差。因此,根據(jù)系統(tǒng)的偏差大小改變積分速度是有必要的。
變積分PID的基本思想是設(shè)法改變積分項(xiàng)的累加速度,使其與偏差大小相對(duì)應(yīng):偏差越大,積分越慢; 偏差越小,積分越快。

這里給積分系數(shù)前加上一個(gè)比例值index:

當(dāng)abs(err)<180時(shí),index=1;

當(dāng)180<abs(err)<200時(shí),index=(200-abs(err))/20;

當(dāng)abs(err)>200時(shí),index=0;
  • 1
  • 2
  • 3
  • 4
  • 5

最終的比例環(huán)節(jié)的比例系數(shù)值為ki*index;
具體PID實(shí)現(xiàn)代碼如下:

pid.Kp=0.4;
pid.Ki=0.2;    //增加了積分系數(shù)
pid.Kd=0.2;

float PID_realize(float speed){
	float index;
    pid.SetSpeed=speed;
    pid.err=pid.SetSpeed-pid.ActualSpeed;

    if(abs(pid.err)>200)           //變積分過程
    {
	    index=0.0;
    }else if(abs(pid.err)<180){
	    index=1.0;
	    pid.integral+=pid.err;
    }else{
	    index=(200-abs(pid.err))/20;
	    pid.integral+=pid.err;
    }
    pid.voltage=pid.Kp*pid.err+index*pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);

    pid.err_last=pid.err;
    pid.ActualSpeed=pid.voltage*1.0;
    return pid.ActualSpeed;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

總結(jié):系統(tǒng)的穩(wěn)定速度非???/strong>
我在另一篇博客https://blog.csdn.net/qq_37258787/article/details/79603352使用Kotlin語言實(shí)現(xiàn)上述功能,并進(jìn)行了簡單的數(shù)據(jù)可視化展示.

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    国产女高清在线看免费观看| 中文字幕人妻av不卡| 欧美亚洲另类久久久精品| 日韩欧美二区中文字幕| 插进她的身体里在线观看骚| 欧美人妻盗摄日韩偷拍| 不卡中文字幕在线视频| 在线免费不卡亚洲国产| 亚洲专区中文字幕在线| 亚洲伦片免费偷拍一区| 五月婷婷综合激情啪啪| 视频在线免费观看你懂的 | 国产亚洲成av人在线观看| 色好吊视频这里只有精| 欧美日韩高清不卡在线播放| 欧美不雅视频午夜福利| 日韩欧美在线看一卡一卡| 色婷婷视频免费在线观看| 色婷婷视频在线精品免费观看| 国产美女网红精品演绎| 91超频在线视频中文字幕| 大香蕉网国产在线观看av| 成人精品一区二区三区综合| 99热在线精品视频观看| 99久热只有精品视频最新| 欧美成人国产精品高清| 老司机精品福利视频在线播放 | 国产精品午夜性色视频| 日韩精品第一区二区三区| 一区二区在线激情视频| 日本高清不卡在线一区| 国产一级一片内射视频在线| 国产又黄又爽又粗视频在线| 欧美乱码精品一区二区三| 亚洲国产av国产av| 国产一级内射麻豆91| 亚洲一区在线观看蜜桃| 欧美在线观看视频免费不卡| 色婷婷久久五月中文字幕| 六月丁香六月综合缴情| 超薄丝袜足一区二区三区|