笃行者的笔记 https://bbs.21ic.com/?581776 [收藏] [复制] [RSS]

日志

增量式PID C语言

已有 2533 次阅读2011-11-24 20:37 |系统分类:嵌入式系统| 增量式PID

最近在解决激光器恒功率控制问题,把PID部分代码拿出来分享一下。功能已经可以使用了,但还没有添加积分饱和处理,只在输出的时候做了范围限制。
Process_IPD.c 文件:
//==================================================================================================

//| 文件名称 | Mod_ProcessPID.c

//|--------- |--------------------------------------------------------------------------------------

//| 文件描述 | 过程PID 控制(增量式PID)

//|----------|--------------------------------------------------------------------------------------

//|  版本    |  时间       |  作者     | 描述

//|--------- |-------------|-----------|------------------------------------------------------------

//|  V1.0    | 2011.11.15  | 侯功   | 规范化

//==================================================================================================

#include "..\TypeDefine.h"

#include "..\F28335\DSP2833x_Device.h"

#include "..\F28335\DSP2833x_Examples.h"

 
#include "..\Driver\Drv_GpioDef.h"

#include "..\Driver\Drv_LTC1867.h"

#include "..\Driver\Drv_Dac124s085.h"

#include "..\Driver\Drv_ADC_OnChip.h"

#include "..\ProAPI\ProAPI_ANALOG.h"

#include "Mod_ProcessPID.h"

//激光器电流控制默认参数

#define kDefaultCurrent 50//默认50毫安电流

#define kDefaultPID_K    5//默认的增益为5倍

#define kDefaultPID_T   5//默认控制周期为5秒

#define kDefaultPID_Ti  25//默认积分时间为5秒

#define kDefaultPID_Td  30//默认的微分时间为30秒

#define kDefaultSet        0.4//默认0.4毫安

 
//函数名:增量式PID参数初始化

//参数:PID_STRU 指针

//返回值:void

//作者:侯功 2011-11-15

void LD_Ctrl_PID_Init(PID_STRU * p_pid)

{

    p_pid->set = kDefaultSet;//默认pd设置值0.2毫安 相当于激光器有50毫安驱动电流

    p_pid->output = kDefaultCurrent;//默认激光器电流

    p_pid->kp = kDefaultPID_K;//比例系数

    p_pid->ti = kDefaultPID_Ti;//积分时间

    p_pid->td = kDefaultPID_Td;//微分时间

    p_pid->t = kDefaultPID_T;//控制周期

 
}

//函数名:增量式PId控制

//参数:PID_STRU 指针

//返回值:void

//作者:侯功 2011-11-15

void PID_GetValue(PID_STRU * p_pid)

{

    INT16U i;

    static INT8U counter = 0;

    float err[3];

    //

    counter ++;

 
    p_pid->input[2] = p_pid->input[1];

    p_pid->input[1] = p_pid->input[0];

    p_pid->input[0] = GetLaserIntensVol();

    for(i=0;i<2;i++)

    {

        err = p_pid->set  - p_pid->input;

    }

    //

    if(counter > 2)

    {

        p_pid->output += p_pid->kp*(1+p_pid->ti/p_pid->t+p_pid->td/p_pid->t)*err[0];//比例项

        p_pid->output += p_pid->kp*(1+2*p_pid->td/p_pid->t)*err[1];//积分项

        //p_pid->output += p_pid->td*err[2]/p_pid->t;//微分项

    }

}

 
 Process_PID.h文件:
#ifndef MOD_PROCESSPID_H

#define MOD_PROCESSPID_H

     
     
    typedef struct 

    {

        float t;//采样周期

        float kp;//比例系数

        float ti;//积分时间

        float td;//微分时间

        float set;//设定值

        float input[4];//输入缓存

        float output;//输出

        unsigned char flag;// 正/反 作用

    }PID_STRU;

void LD_Ctrl_PID_Init(PID_STRU * p_pid);

void PID_GetValue(PID_STRU *);

 
#endif


使用步骤说明:
 
//step1 定义激光器控制参数

    PID_STRU ld_current_ctrl;

//step2 初始化PID参数

 
    LD_Ctrl_PID_Init(&ld_current_ctrl);

 
 
//step3 激光器电流PID控制主流程

 
void LD_CtrlProcess(void)

{

    //电流PID控制

    PID_GetValue(&ld_current_ctrl);

    //范围保护

    if(ld_current_ctrl.output < 5) 

    {

        ld_current_ctrl.output = 0;

    }

 
    if(ld_current_ctrl.output > 100)

    {

        ld_current_ctrl.output = 100;

    }

    //设置激光器电流

    SetLD_Current(ld_current_ctrl.output);

}

 
//step4 按照控制周期调用void LD_CtrlProcess(void) 函数

路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)