1.自整定的过程大致分为以下步骤:
①稳定为先:先用一个无需非常完美的PID参数调整系统,使系统的被调量和输出都达到稳态,并且被调量近似达到设定值。
②强行震荡:再暂时禁用PID调节,使控制器将一个矩形波状的控制作用力作用于系统,当被调量低于设定值时,控制输出产生一个正的阶跃信号,迫使被调量向高处转变,当被调量高于设定值时,控制输出产生一个负的阶跃信号,迫使被调量向低处转变,由此强行使系统产生震荡。
③分析波形:分析以上过程产生的波形的特征,根据需要计算出相应的PID参数
投入使用:将自整定得到的参数投入PID调节器中,即可让系统实现较好的PID调节效果。
完成波形分析后,仅需将得到的峰峰值和周期带到PID前辈们推导出的公式中,计算得到相应的PID参数,再将PID参数更新投入使用,PID自整定便大功告成!
2.部分代码
2.1 主函数main.c文件:
由于main主函数里面会一直循环做别的控制,为了自整定的需要,需要在main的whlie循环里
#define Auto_PID 1 //设置为1则进入自动整定状态(注意这时需要关闭另外的PID加热功能)if(Auto_PID){//用于PID自整定//测试AC_EN_Open;SetTextFloat(Page_13, 16, (Start == 124) ? (PT100_Temp1):(PT100_Temp2), 1, 1);//三目运算(显示当前通道温度)Handle_PID_AT((Start == 124) ? 1: 2);//三目运算(确定哪一路加热进行自整定)//判断自整定结束,结束则退出if(PID_AutoTune.State==STATE_End){Start=0;PID_AutoTune.State=0;switch (Auto_PID){case 1:PID1.kp=PID_AutoTune.Proportion;PID1.ki=PID_AutoTune.Integration;PID1.kd=PID_AutoTune.Differentiation;break;}}HAL_IWDG_Refresh(&hiwdg);//喂狗HAL_Delay(500);HAL_IWDG_Refresh(&hiwdg);//喂狗}
2.2 PID_Auto.h文件:
#ifndef __PID_AUTO_H
#define __PID_AUTO_H#include "hmi_driver.h"
#include "EEPROM.h"struct PID_Auto{uint16_t Timing; //自整定计时器uint16_t TempSet; //自整定设置温度uint16_t TempCheck[10]; //检测点 uint16_t TempPeakRecord[2][3]; //温度峰值记录[0]=时间,[1]=温度; uint8_t State; //处于阶段uint8_t State_History; //历史阶段uint8_t Channel; //测温通道uint8_t PWM_out;uint16_t Pu;uint16_t A; float Ku;float Proportion; // 比例常数Proportional Constfloat Integration; // 积分常数Integral Constfloat Differentiation; // 微分常数Derivative Const
};#define STATE_Init 0 //初始化阶段
#define STATE_PreHeat 1 //预加热阶段
#define STATE_Inertia 2 //惯性升温阶段
#define STATE_PreShake 3 //预振荡阶段
#define STATE_Shake 4 //继电器振荡阶段
#define STATE_Analyse 5 //整定结束分析阶段
#define STATE_End 6 //整定结束#define PID_AT_PreStop 5 //温度预停止点
#define MAX_PWM_VALUE 40 //PID运行最大输出值,代表最大功率#define _SCREEN_PidSet 13 //PID自整定页面
#define _TXTDISPLAY_PidSet_PID_AutoTune_Timing 45 //自整定计时
#define _TXTDISPLAY_PidSet_Pu 38 //周期
#define _TXTDISPLAY_PidSet_A 27 //差值#define Set(A,B,C) HAL_GPIO_WritePin(A,B,C)#define AC220_1_Open Set(AC220_1_GPIO_Port,AC220_1_Pin,RESET); //固态继电器1
#define AC220_1_Stop Set(AC220_1_GPIO_Port,AC220_1_Pin,SET); //固态继电器1#define AC220_2_Open Set(AC220_2_GPIO_Port,AC220_2_Pin,RESET); //固态继电器2
#define AC220_2_Stop Set(AC220_2_GPIO_Port,AC220_2_Pin,SET); //固态继电器2#define AC220_3_Open Set(AC220_3_GPIO_Port,AC220_3_Pin,RESET); //固态继电器3
#define AC220_3_Stop Set(AC220_3_GPIO_Port,AC220_3_Pin,SET); //固态继电器3void Clear_PID_AT_HMI(void);
void Handle_PID_AT(uint8_t channel);#endif
2.3 PID_Auto.c文件:
#include "PID_Auto.h"
#include "PID.h"struct PID_Auto PID_AutoTune; //定义自整定结构体
struct PID PID3; //定义PID结构体#define PWM_OutH 40 //PWM高值
#define PWM_OutL 0 //PWM低值uint16_t Temp[3]; //缓存的温度数据
extern uint16_t number13_10; //设置的自整定温度
extern float PT100_Temp1; //采集的温度值1
extern float PT100_Temp2; //采集的温度值2//页面上数据置0
void Clear_PID_AT_HMI(void){SetTextFloat(_SCREEN_PidSet, 16, 0, 1, 1);HAL_Delay(20);SetTextInt32(_SCREEN_PidSet, 31, 0, 0, 1);HAL_Delay(20);SetTextInt32(_SCREEN_PidSet, 45, 0, 0, 1);HAL_Delay(20);SetTextInt32(_SCREEN_PidSet, 22, 0, 0, 1);HAL_Delay(20);SetTextInt32(_SCREEN_PidSet, 18, 0, 0, 1);HAL_Delay(20);SetTextInt32(_SCREEN_PidSet, 25, 0, 0, 1);HAL_Delay(20);SetTextInt32(_SCREEN_PidSet, 19, 0, 0, 1);HAL_Delay(20);SetTextInt32(_SCREEN_PidSet, 30, 0, 0, 1);HAL_Delay(20);SetTextInt32(_SCREEN_PidSet, 28, 0, 0, 1);HAL_Delay(20);SetTextInt32(_SCREEN_PidSet, 38, 0, 0, 1);HAL_Delay(20);SetTextInt32(_SCREEN_PidSet, 27, 0, 0, 1);HAL_Delay(20);
}//自整定函数
void Handle_PID_AT(uint8_t channel){static uint16_t flag_n = 0;Temp[1]=(uint16_t)(PT100_Temp1*10); //温度取一个小数Temp[2]=(uint16_t)(PT100_Temp2*10); //温度取一个小数PID_AutoTune.TempSet=number13_10*10; //设置的自整定温度取一个小数PID_AutoTune.Channel=channel;//选取整定通道(改)/缓存的10个近期温度数据(第0位最新的)/PID_AutoTune.TempCheck[9] = PID_AutoTune.TempCheck[8]; PID_AutoTune.TempCheck[8] = PID_AutoTune.TempCheck[7];PID_AutoTune.TempCheck[7] = PID_AutoTune.TempCheck[6];PID_AutoTune.TempCheck[6] = PID_AutoTune.TempCheck[5];PID_AutoTune.TempCheck[5] = PID_AutoTune.TempCheck[4]; PID_AutoTune.TempCheck[4] = PID_AutoTune.TempCheck[3];PID_AutoTune.TempCheck[3] = PID_AutoTune.TempCheck[2];PID_AutoTune.TempCheck[2] = PID_AutoTune.TempCheck[1];PID_AutoTune.TempCheck[1] = PID_AutoTune.TempCheck[0];PID_AutoTune.TempCheck[0] = Temp[PID_AutoTune.Channel];/ 历史阶段 or 现在阶段不同时,31处显示自整定阶段 ///if(PID_AutoTune.State != PID_AutoTune.State_History){ SetTextInt32(_SCREEN_PidSet, 31, PID_AutoTune.State, 0, 1);//整定阶段显示PID_AutoTune.State_History = PID_AutoTune.State;}//判断State在哪个阶段switch(PID_AutoTune.State){//********************初始化阶段(关闭全部加热,数据清除)case STATE_Init:{AC220_1_Stop;//关闭加热AC220_2_Stop;//关闭加热PID_AutoTune.Timing = 0; //自整定计时器清零PID_AutoTune.TempSet = 0; //清零//清除温度检测数据for (uint8_t n=0; n<10; n++){PID_AutoTune.TempCheck[n]=0;}//清除峰值记录数据for (uint8_t n=0; n<3; n++){PID_AutoTune.TempPeakRecord[0][n] = 0;PID_AutoTune.TempPeakRecord[1][n] = 0;}PID_AutoTune.State = 0; //清零PID_AutoTune.State_History = 0; //清零PID_AutoTune.Ku = 0; //清除PIDPID_AutoTune.Pu = 0; //清除PIDPID_AutoTune.A = 0; //清除PIDClear_PID_AT_HMI(); //清空右下角全部的数值PID_AutoTune.State = STATE_PreHeat;//进入下一个阶段}break;//********************预加热阶段1case STATE_PreHeat:{//到达预终止点前,一直加热 if((Temp[PID_AutoTune.Channel]+PID_AT_PreStop*10) < PID_AutoTune.TempSet){PID_Init(&PID3, 12, 1.1, 120, 25, 100);PID_AutoTune.PWM_out=PID_Calc(&PID3,PID_AutoTune.TempSet/10,Temp[PID_AutoTune.Channel]/10);SetControlVisiable(_SCREEN_PidSet,46,1);//显示加热图标}else{PID_AutoTune.PWM_out=0;SetControlVisiable(_SCREEN_PidSet,46,0);//隐藏加热图标PID_AutoTune.State = STATE_Inertia;//进入下一个阶段}}break;//**********************惯性升温2(惯性升温后,降温开始则跳入下一阶段)case STATE_Inertia:{//检测温度是否处于跌落状态 (惯性升温后,降温开始则跳入下一阶段)if(PID_AutoTune.TempCheck[0] < PID_AutoTune.TempCheck[9]){ //检测5秒flag_n = 0;PID_AutoTune.State = STATE_PreShake;//进入下一个阶段}}break; //**********************预振荡阶段3case STATE_PreShake:{if(Temp[PID_AutoTune.Channel] < PID_AutoTune.TempSet){//加热引脚打开,进行加热PID_AutoTune.PWM_out=PWM_OutH;SetControlVisiable(_SCREEN_PidSet,46,1);//显示加热图标//判断是否到波谷if(flag_n==1) flag_n=2;}else{//加热引脚关闭,不加热PID_AutoTune.PWM_out=PWM_OutL;SetControlVisiable(_SCREEN_PidSet,46,0);//隐藏加热图标switch(flag_n){case 0: flag_n = 1; break; //第一次到波峰case 2: //经过一个预振荡周期,过设置温度,进入振荡阶段flag_n = 0;PID_AutoTune.Timing = 0;PID_AutoTune.State = STATE_Shake;//进入下一个阶段break;}}}break;//*************************振荡阶段4case STATE_Shake:{PID_AutoTune.Timing++; //计时if(Temp[PID_AutoTune.Channel] < PID_AutoTune.TempSet){//加热引脚打开,进行加热PID_AutoTune.PWM_out=PWM_OutH;SetControlVisiable(_SCREEN_PidSet,46,1);//显示加热图标if(flag_n==0){//显示上个记录值SetTextInt32( _SCREEN_PidSet, 22, PID_AutoTune.TempPeakRecord[0][flag_n], 0, 1);SetTextFloat( _SCREEN_PidSet, 18, ((float)PID_AutoTune.TempPeakRecord[1][flag_n])/10, 1, 1);flag_n=1;PID_AutoTune.TempPeakRecord[0][flag_n] = PID_AutoTune.Timing;PID_AutoTune.TempPeakRecord[1][flag_n] = Temp[PID_AutoTune.Channel];}//检测波谷波形if(Temp[PID_AutoTune.Channel] < PID_AutoTune.TempPeakRecord[1][flag_n]){PID_AutoTune.TempPeakRecord[0][flag_n] = PID_AutoTune.Timing;PID_AutoTune.TempPeakRecord[1][flag_n] = Temp[PID_AutoTune.Channel];}}else{//加热引脚关闭,不加热PID_AutoTune.PWM_out=PWM_OutL;SetControlVisiable(_SCREEN_PidSet,46,0);//隐藏加热图标if(flag_n==1){//显示上个记录值SetTextInt32(_SCREEN_PidSet, 25, PID_AutoTune.TempPeakRecord[0][flag_n], 0, 1);SetTextFloat(_SCREEN_PidSet, 19, ((float)PID_AutoTune.TempPeakRecord[1][flag_n])/10, 1, 1);flag_n=2;PID_AutoTune.TempPeakRecord[0][flag_n] = PID_AutoTune.Timing;PID_AutoTune.TempPeakRecord[1][flag_n] = Temp[PID_AutoTune.Channel];}//检测波峰波形if(Temp[PID_AutoTune.Channel] > PID_AutoTune.TempPeakRecord[1][flag_n]){PID_AutoTune.TempPeakRecord[0][flag_n] = PID_AutoTune.Timing;PID_AutoTune.TempPeakRecord[1][flag_n] = Temp[PID_AutoTune.Channel];}//完成两个波峰和一个波谷的检测则退出振荡if(flag_n==2){//检测温度是否处于跌落状态 (升温后,降温开始则跳入下一阶段)if(PID_AutoTune.TempCheck[0] < PID_AutoTune.TempCheck[9]){ //检测5秒//显示上个记录值SetTextInt32(_SCREEN_PidSet, 30, PID_AutoTune.TempPeakRecord[0][flag_n], 0, 1);SetTextFloat(_SCREEN_PidSet, 28, ((float)PID_AutoTune.TempPeakRecord[1][flag_n])/10, 1, 1);PID_AutoTune.State = STATE_Analyse;//进入下一个阶段}}}}break;//*********************************分析阶段5case STATE_Analyse:{。。。。。。PID_AutoTune.State = STATE_End;//进入下一个阶段 }break; }//显示计时秒数SetTextInt32(_SCREEN_PidSet, _TXTDISPLAY_PidSet_PID_AutoTune_Timing, PID_AutoTune.Timing, 0, 1);}
3.完整代码
下载链接:https://download.csdn.net/download/qq_26043945/87839384
4.参考网址
参考链接:http://t.csdn.cn/Qp9Nd